diff options
author | teravus | 2012-11-15 10:05:16 -0500 |
---|---|---|
committer | teravus | 2012-11-15 10:05:16 -0500 |
commit | e9153e1d1aae50024d8cd05fe14a9bce34343a0e (patch) | |
tree | bc111d34f95a26b99c7e34d9e495dc14d1802cc3 /OpenSim/Region | |
parent | Merge master into teravuswork (diff) | |
download | opensim-SC_OLD-e9153e1d1aae50024d8cd05fe14a9bce34343a0e.zip opensim-SC_OLD-e9153e1d1aae50024d8cd05fe14a9bce34343a0e.tar.gz opensim-SC_OLD-e9153e1d1aae50024d8cd05fe14a9bce34343a0e.tar.bz2 opensim-SC_OLD-e9153e1d1aae50024d8cd05fe14a9bce34343a0e.tar.xz |
Revert "Merge master into teravuswork", it should have been avination, not master.
This reverts commit dfac269032300872c4d0dc507f4f9062d102b0f4, reversing
changes made to 619c39e5144f15aca129d6d999bcc5c34133ee64.
Diffstat (limited to '')
159 files changed, 6037 insertions, 14925 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs b/OpenSim/Framework/PacketPool.cs index 9f22fb4..41d17c5 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs +++ b/OpenSim/Framework/PacketPool.cs | |||
@@ -31,10 +31,10 @@ 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; | ||
35 | 34 | ||
36 | namespace OpenSim.Region.ClientStack.LindenUDP | 35 | namespace OpenSim.Framework |
37 | { | 36 | { |
37 | |||
38 | public sealed class PacketPool | 38 | public sealed class PacketPool |
39 | { | 39 | { |
40 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 40 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
@@ -44,32 +44,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
44 | private bool packetPoolEnabled = true; | 44 | private bool packetPoolEnabled = true; |
45 | private bool dataBlockPoolEnabled = true; | 45 | private bool dataBlockPoolEnabled = true; |
46 | 46 | ||
47 | private PercentageStat m_packetsReusedStat = new PercentageStat( | ||
48 | "PacketsReused", | ||
49 | "Packets reused", | ||
50 | "Number of packets reused out of all requests to the packet pool", | ||
51 | "clientstack", | ||
52 | "packetpool", | ||
53 | StatType.Push, | ||
54 | null, | ||
55 | StatVerbosity.Debug); | ||
56 | |||
57 | private PercentageStat m_blocksReusedStat = new PercentageStat( | ||
58 | "PacketDataBlocksReused", | ||
59 | "Packet data blocks reused", | ||
60 | "Number of data blocks reused out of all requests to the packet pool", | ||
61 | "clientstack", | ||
62 | "packetpool", | ||
63 | StatType.Push, | ||
64 | null, | ||
65 | StatVerbosity.Debug); | ||
66 | |||
67 | /// <summary> | ||
68 | /// Pool of packets available for reuse. | ||
69 | /// </summary> | ||
70 | private readonly Dictionary<PacketType, Stack<Packet>> pool = new Dictionary<PacketType, Stack<Packet>>(); | 47 | private readonly Dictionary<PacketType, Stack<Packet>> pool = new Dictionary<PacketType, Stack<Packet>>(); |
71 | 48 | ||
72 | private static Dictionary<Type, Stack<Object>> DataBlocks = new Dictionary<Type, Stack<Object>>(); | 49 | private static Dictionary<Type, Stack<Object>> DataBlocks = |
50 | new Dictionary<Type, Stack<Object>>(); | ||
51 | |||
52 | static PacketPool() | ||
53 | { | ||
54 | } | ||
73 | 55 | ||
74 | public static PacketPool Instance | 56 | public static PacketPool Instance |
75 | { | 57 | { |
@@ -88,45 +70,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
88 | get { return dataBlockPoolEnabled; } | 70 | get { return dataBlockPoolEnabled; } |
89 | } | 71 | } |
90 | 72 | ||
91 | private PacketPool() | ||
92 | { | ||
93 | StatsManager.RegisterStat(m_packetsReusedStat); | ||
94 | StatsManager.RegisterStat(m_blocksReusedStat); | ||
95 | |||
96 | StatsManager.RegisterStat( | ||
97 | new Stat( | ||
98 | "PacketsPoolCount", | ||
99 | "Objects within the packet pool", | ||
100 | "The number of objects currently stored within the packet pool", | ||
101 | "", | ||
102 | "clientstack", | ||
103 | "packetpool", | ||
104 | StatType.Pull, | ||
105 | stat => { lock (pool) { stat.Value = pool.Count; } }, | ||
106 | StatVerbosity.Debug)); | ||
107 | |||
108 | StatsManager.RegisterStat( | ||
109 | new Stat( | ||
110 | "PacketDataBlocksPoolCount", | ||
111 | "Objects within the packet data block pool", | ||
112 | "The number of objects currently stored within the packet data block pool", | ||
113 | "", | ||
114 | "clientstack", | ||
115 | "packetpool", | ||
116 | StatType.Pull, | ||
117 | stat => { lock (DataBlocks) { stat.Value = DataBlocks.Count; } }, | ||
118 | StatVerbosity.Debug)); | ||
119 | } | ||
120 | |||
121 | /// <summary> | ||
122 | /// Gets a packet of the given type. | ||
123 | /// </summary> | ||
124 | /// <param name='type'></param> | ||
125 | /// <returns>Guaranteed to always return a packet, whether from the pool or newly constructed.</returns> | ||
126 | public Packet GetPacket(PacketType type) | 73 | public Packet GetPacket(PacketType type) |
127 | { | 74 | { |
128 | m_packetsReusedStat.Consequent++; | ||
129 | |||
130 | Packet packet; | 75 | Packet packet; |
131 | 76 | ||
132 | if (!packetPoolEnabled) | 77 | if (!packetPoolEnabled) |
@@ -136,19 +81,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
136 | { | 81 | { |
137 | if (!pool.ContainsKey(type) || pool[type] == null || (pool[type]).Count == 0) | 82 | if (!pool.ContainsKey(type) || pool[type] == null || (pool[type]).Count == 0) |
138 | { | 83 | { |
139 | // m_log.DebugFormat("[PACKETPOOL]: Building {0} packet", type); | ||
140 | |||
141 | // Creating a new packet if we cannot reuse an old package | 84 | // Creating a new packet if we cannot reuse an old package |
142 | packet = Packet.BuildPacket(type); | 85 | packet = Packet.BuildPacket(type); |
143 | } | 86 | } |
144 | else | 87 | else |
145 | { | 88 | { |
146 | // m_log.DebugFormat("[PACKETPOOL]: Pulling {0} packet", type); | ||
147 | |||
148 | // Recycle old packages | 89 | // Recycle old packages |
149 | m_packetsReusedStat.Antecedent++; | 90 | packet = (pool[type]).Pop(); |
150 | |||
151 | packet = pool[type].Pop(); | ||
152 | } | 91 | } |
153 | } | 92 | } |
154 | 93 | ||
@@ -197,7 +136,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
197 | { | 136 | { |
198 | PacketType type = GetType(bytes); | 137 | PacketType type = GetType(bytes); |
199 | 138 | ||
200 | // Array.Clear(zeroBuffer, 0, zeroBuffer.Length); | 139 | Array.Clear(zeroBuffer, 0, zeroBuffer.Length); |
201 | 140 | ||
202 | int i = 0; | 141 | int i = 0; |
203 | Packet packet = GetPacket(type); | 142 | Packet packet = GetPacket(type); |
@@ -244,7 +183,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
244 | switch (packet.Type) | 183 | switch (packet.Type) |
245 | { | 184 | { |
246 | // List pooling packets here | 185 | // List pooling packets here |
247 | case PacketType.AgentUpdate: | ||
248 | case PacketType.PacketAck: | 186 | case PacketType.PacketAck: |
249 | case PacketType.ObjectUpdate: | 187 | case PacketType.ObjectUpdate: |
250 | case PacketType.ImprovedTerseObjectUpdate: | 188 | case PacketType.ImprovedTerseObjectUpdate: |
@@ -259,9 +197,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
259 | 197 | ||
260 | if ((pool[type]).Count < 50) | 198 | if ((pool[type]).Count < 50) |
261 | { | 199 | { |
262 | // m_log.DebugFormat("[PACKETPOOL]: Pushing {0} packet", type); | 200 | (pool[type]).Push(packet); |
263 | |||
264 | pool[type].Push(packet); | ||
265 | } | 201 | } |
266 | } | 202 | } |
267 | break; | 203 | break; |
@@ -273,21 +209,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
273 | } | 209 | } |
274 | } | 210 | } |
275 | 211 | ||
276 | public T GetDataBlock<T>() where T: new() | 212 | public static T GetDataBlock<T>() where T: new() |
277 | { | 213 | { |
278 | lock (DataBlocks) | 214 | lock (DataBlocks) |
279 | { | 215 | { |
280 | m_blocksReusedStat.Consequent++; | ||
281 | |||
282 | Stack<Object> s; | 216 | Stack<Object> s; |
283 | 217 | ||
284 | if (DataBlocks.TryGetValue(typeof(T), out s)) | 218 | if (DataBlocks.TryGetValue(typeof(T), out s)) |
285 | { | 219 | { |
286 | if (s.Count > 0) | 220 | if (s.Count > 0) |
287 | { | ||
288 | m_blocksReusedStat.Antecedent++; | ||
289 | return (T)s.Pop(); | 221 | return (T)s.Pop(); |
290 | } | ||
291 | } | 222 | } |
292 | else | 223 | else |
293 | { | 224 | { |
@@ -298,7 +229,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
298 | } | 229 | } |
299 | } | 230 | } |
300 | 231 | ||
301 | public void ReturnDataBlock<T>(T block) where T: new() | 232 | public static void ReturnDataBlock<T>(T block) where T: new() |
302 | { | 233 | { |
303 | if (block == null) | 234 | if (block == null) |
304 | return; | 235 | return; |
@@ -313,4 +244,4 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
313 | } | 244 | } |
314 | } | 245 | } |
315 | } | 246 | } |
316 | } \ No newline at end of file | 247 | } |
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index 5f07272..6255515 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs | |||
@@ -35,7 +35,6 @@ using System.Text; | |||
35 | using System.Text.RegularExpressions; | 35 | using System.Text.RegularExpressions; |
36 | using System.Timers; | 36 | using System.Timers; |
37 | using log4net; | 37 | using log4net; |
38 | using NDesk.Options; | ||
39 | using Nini.Config; | 38 | using Nini.Config; |
40 | using OpenMetaverse; | 39 | using OpenMetaverse; |
41 | using OpenSim.Framework; | 40 | using OpenSim.Framework; |
@@ -254,14 +253,8 @@ namespace OpenSim | |||
254 | m_console.Commands.AddCommand("Debug", false, "debug teleport", "debug teleport", "Toggle teleport route debugging", Debug); | 253 | m_console.Commands.AddCommand("Debug", false, "debug teleport", "debug teleport", "Toggle teleport route debugging", Debug); |
255 | 254 | ||
256 | m_console.Commands.AddCommand("Debug", false, "debug scene", | 255 | m_console.Commands.AddCommand("Debug", false, "debug scene", |
257 | "debug scene active|collisions|physics|scripting|teleport true|false", | 256 | "debug scene <scripting> <collisions> <physics>", |
258 | "Turn on scene debugging.", | 257 | "Turn on scene debugging", Debug); |
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); | ||
265 | 258 | ||
266 | m_console.Commands.AddCommand("General", false, "change region", | 259 | m_console.Commands.AddCommand("General", false, "change region", |
267 | "change region <region name>", | 260 | "change region <region name>", |
@@ -298,7 +291,7 @@ namespace OpenSim | |||
298 | 291 | ||
299 | m_console.Commands.AddCommand("Archiving", false, "save oar", | 292 | m_console.Commands.AddCommand("Archiving", false, "save oar", |
300 | //"save oar [-v|--version=<N>] [-p|--profile=<url>] [<OAR path>]", | 293 | //"save oar [-v|--version=<N>] [-p|--profile=<url>] [<OAR path>]", |
301 | "save oar [-h|--home=<url>] [--noassets] [--publish] [--perm=<permissions>] [--all] [<OAR path>]", | 294 | "save oar [-h|--home=<url>] [--noassets] [--publish] [--perm=<permissions>] [<OAR path>]", |
302 | "Save a region's data to an OAR archive.", | 295 | "Save a region's data to an OAR archive.", |
303 | // "-v|--version=<N> generates scene objects as per older versions of the serialization (e.g. -v=0)" + Environment.NewLine | 296 | // "-v|--version=<N> generates scene objects as per older versions of the serialization (e.g. -v=0)" + Environment.NewLine |
304 | "-h|--home=<url> adds the url of the profile service to the saved user information.\n" | 297 | "-h|--home=<url> adds the url of the profile service to the saved user information.\n" |
@@ -308,7 +301,6 @@ namespace OpenSim | |||
308 | + " this is useful if you're making oars generally available that might be reloaded to the same grid from which you published\n" | 301 | + " this is useful if you're making oars generally available that might be reloaded to the same grid from which you published\n" |
309 | + "--perm=<permissions> stops objects with insufficient permissions from being saved to the OAR.\n" | 302 | + "--perm=<permissions> stops objects with insufficient permissions from being saved to the OAR.\n" |
310 | + " <permissions> can contain one or more of these characters: \"C\" = Copy, \"T\" = Transfer\n" | 303 | + " <permissions> can contain one or more of these characters: \"C\" = Copy, \"T\" = Transfer\n" |
311 | + "--all saves all the regions in the simulator, instead of just the current region.\n" | ||
312 | + "The OAR path must be a filesystem path." | 304 | + "The OAR path must be a filesystem path." |
313 | + " If this is not given then the oar is saved to region.oar in the current directory.", | 305 | + " If this is not given then the oar is saved to region.oar in the current directory.", |
314 | SaveOar); | 306 | SaveOar); |
@@ -318,11 +310,8 @@ namespace OpenSim | |||
318 | "Change the scale of a named prim", HandleEditScale); | 310 | "Change the scale of a named prim", HandleEditScale); |
319 | 311 | ||
320 | m_console.Commands.AddCommand("Users", false, "kick user", | 312 | m_console.Commands.AddCommand("Users", false, "kick user", |
321 | "kick user <first> <last> [--force] [message]", | 313 | "kick user <first> <last> [message]", |
322 | "Kick a user off the simulator", | 314 | "Kick a user off the simulator", KickUserCommand); |
323 | "The --force option will kick the user without any checks to see whether it's already in the process of closing\n" | ||
324 | + "Only use this option if you are sure the avatar is inactive and a normal kick user operation does not removed them", | ||
325 | KickUserCommand); | ||
326 | 315 | ||
327 | m_console.Commands.AddCommand("Users", false, "show users", | 316 | m_console.Commands.AddCommand("Users", false, "show users", |
328 | "show users [full]", | 317 | "show users [full]", |
@@ -339,6 +328,10 @@ namespace OpenSim | |||
339 | "show circuits", | 328 | "show circuits", |
340 | "Show agent circuit data", HandleShow); | 329 | "Show agent circuit data", HandleShow); |
341 | 330 | ||
331 | m_console.Commands.AddCommand("Comms", false, "show http-handlers", | ||
332 | "show http-handlers", | ||
333 | "Show all registered http handlers", HandleShow); | ||
334 | |||
342 | m_console.Commands.AddCommand("Comms", false, "show pending-objects", | 335 | m_console.Commands.AddCommand("Comms", false, "show pending-objects", |
343 | "show pending-objects", | 336 | "show pending-objects", |
344 | "Show # of objects on the pending queues of all scene viewers", HandleShow); | 337 | "Show # of objects on the pending queues of all scene viewers", HandleShow); |
@@ -423,7 +416,6 @@ namespace OpenSim | |||
423 | { | 416 | { |
424 | RunCommandScript(m_shutdownCommandsFile); | 417 | RunCommandScript(m_shutdownCommandsFile); |
425 | } | 418 | } |
426 | |||
427 | base.ShutdownSpecific(); | 419 | base.ShutdownSpecific(); |
428 | } | 420 | } |
429 | 421 | ||
@@ -461,17 +453,11 @@ namespace OpenSim | |||
461 | /// <param name="cmdparams">name of avatar to kick</param> | 453 | /// <param name="cmdparams">name of avatar to kick</param> |
462 | private void KickUserCommand(string module, string[] cmdparams) | 454 | private void KickUserCommand(string module, string[] cmdparams) |
463 | { | 455 | { |
464 | bool force = false; | 456 | if (cmdparams.Length < 4) |
465 | |||
466 | OptionSet options = new OptionSet().Add("f|force", delegate (string v) { force = v != null; }); | ||
467 | |||
468 | List<string> mainParams = options.Parse(cmdparams); | ||
469 | |||
470 | if (mainParams.Count < 4) | ||
471 | return; | 457 | return; |
472 | 458 | ||
473 | string alert = null; | 459 | string alert = null; |
474 | if (mainParams.Count > 4) | 460 | if (cmdparams.Length > 4) |
475 | alert = String.Format("\n{0}\n", String.Join(" ", cmdparams, 4, cmdparams.Length - 4)); | 461 | alert = String.Format("\n{0}\n", String.Join(" ", cmdparams, 4, cmdparams.Length - 4)); |
476 | 462 | ||
477 | IList agents = SceneManager.GetCurrentSceneAvatars(); | 463 | IList agents = SceneManager.GetCurrentSceneAvatars(); |
@@ -480,8 +466,8 @@ namespace OpenSim | |||
480 | { | 466 | { |
481 | RegionInfo regionInfo = presence.Scene.RegionInfo; | 467 | RegionInfo regionInfo = presence.Scene.RegionInfo; |
482 | 468 | ||
483 | if (presence.Firstname.ToLower().Contains(mainParams[2].ToLower()) && | 469 | if (presence.Firstname.ToLower().Contains(cmdparams[2].ToLower()) && |
484 | presence.Lastname.ToLower().Contains(mainParams[3].ToLower())) | 470 | presence.Lastname.ToLower().Contains(cmdparams[3].ToLower())) |
485 | { | 471 | { |
486 | MainConsole.Instance.Output( | 472 | MainConsole.Instance.Output( |
487 | String.Format( | 473 | String.Format( |
@@ -494,7 +480,7 @@ namespace OpenSim | |||
494 | else | 480 | else |
495 | presence.ControllingClient.Kick("\nYou have been logged out by an administrator.\n"); | 481 | presence.ControllingClient.Kick("\nYou have been logged out by an administrator.\n"); |
496 | 482 | ||
497 | presence.Scene.IncomingCloseAgent(presence.UUID, force); | 483 | presence.Scene.IncomingCloseAgent(presence.UUID); |
498 | } | 484 | } |
499 | } | 485 | } |
500 | 486 | ||
@@ -936,8 +922,7 @@ namespace OpenSim | |||
936 | } | 922 | } |
937 | else | 923 | else |
938 | { | 924 | { |
939 | MainConsole.Instance.Output( | 925 | MainConsole.Instance.Output("Usage: debug scene scripting|collisions|physics|teleport true|false"); |
940 | "Usage: debug scene active|scripting|collisions|physics|teleport true|false"); | ||
941 | } | 926 | } |
942 | 927 | ||
943 | break; | 928 | break; |
@@ -1017,6 +1002,33 @@ namespace OpenSim | |||
1017 | HandleShowCircuits(); | 1002 | HandleShowCircuits(); |
1018 | break; | 1003 | break; |
1019 | 1004 | ||
1005 | case "http-handlers": | ||
1006 | System.Text.StringBuilder handlers = new System.Text.StringBuilder("Registered HTTP Handlers:\n"); | ||
1007 | |||
1008 | handlers.AppendFormat("* XMLRPC:\n"); | ||
1009 | foreach (String s in HttpServer.GetXmlRpcHandlerKeys()) | ||
1010 | handlers.AppendFormat("\t{0}\n", s); | ||
1011 | |||
1012 | handlers.AppendFormat("* HTTP:\n"); | ||
1013 | List<String> poll = HttpServer.GetPollServiceHandlerKeys(); | ||
1014 | foreach (String s in HttpServer.GetHTTPHandlerKeys()) | ||
1015 | handlers.AppendFormat("\t{0} {1}\n", s, (poll.Contains(s) ? "(poll service)" : string.Empty)); | ||
1016 | |||
1017 | handlers.AppendFormat("* Agent:\n"); | ||
1018 | foreach (String s in HttpServer.GetAgentHandlerKeys()) | ||
1019 | handlers.AppendFormat("\t{0}\n", s); | ||
1020 | |||
1021 | handlers.AppendFormat("* LLSD:\n"); | ||
1022 | foreach (String s in HttpServer.GetLLSDHandlerKeys()) | ||
1023 | handlers.AppendFormat("\t{0}\n", s); | ||
1024 | |||
1025 | handlers.AppendFormat("* StreamHandlers ({0}):\n", HttpServer.GetStreamHandlerKeys().Count); | ||
1026 | foreach (String s in HttpServer.GetStreamHandlerKeys()) | ||
1027 | handlers.AppendFormat("\t{0}\n", s); | ||
1028 | |||
1029 | MainConsole.Instance.Output(handlers.ToString()); | ||
1030 | break; | ||
1031 | |||
1020 | case "modules": | 1032 | case "modules": |
1021 | MainConsole.Instance.Output("The currently loaded shared modules are:"); | 1033 | MainConsole.Instance.Output("The currently loaded shared modules are:"); |
1022 | foreach (IRegionModule module in m_moduleLoader.GetLoadedSharedModules) | 1034 | foreach (IRegionModule module in m_moduleLoader.GetLoadedSharedModules) |
@@ -1111,7 +1123,7 @@ namespace OpenSim | |||
1111 | aCircuit.Name, | 1123 | aCircuit.Name, |
1112 | aCircuit.child ? "child" : "root", | 1124 | aCircuit.child ? "child" : "root", |
1113 | aCircuit.circuitcode.ToString(), | 1125 | aCircuit.circuitcode.ToString(), |
1114 | aCircuit.IPAddress != null ? aCircuit.IPAddress.ToString() : "not set", | 1126 | aCircuit.IPAddress.ToString(), |
1115 | aCircuit.Viewer); | 1127 | aCircuit.Viewer); |
1116 | }); | 1128 | }); |
1117 | 1129 | ||
diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index 7232383..d107b7a 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs | |||
@@ -232,6 +232,8 @@ namespace OpenSim | |||
232 | 232 | ||
233 | base.StartupSpecific(); | 233 | base.StartupSpecific(); |
234 | 234 | ||
235 | m_stats = StatsManager.SimExtraStats; | ||
236 | |||
235 | // Create a ModuleLoader instance | 237 | // Create a ModuleLoader instance |
236 | m_moduleLoader = new ModuleLoader(m_config.Source); | 238 | m_moduleLoader = new ModuleLoader(m_config.Source); |
237 | 239 | ||
@@ -247,51 +249,51 @@ namespace OpenSim | |||
247 | plugin.PostInitialise(); | 249 | plugin.PostInitialise(); |
248 | } | 250 | } |
249 | 251 | ||
250 | if (m_console != null) | 252 | AddPluginCommands(); |
251 | { | ||
252 | StatsManager.RegisterConsoleCommands(m_console); | ||
253 | AddPluginCommands(m_console); | ||
254 | } | ||
255 | } | 253 | } |
256 | 254 | ||
257 | protected virtual void AddPluginCommands(CommandConsole console) | 255 | protected virtual void AddPluginCommands() |
258 | { | 256 | { |
259 | List<string> topics = GetHelpTopics(); | 257 | // If console exists add plugin commands. |
260 | 258 | if (m_console != null) | |
261 | foreach (string topic in topics) | ||
262 | { | 259 | { |
263 | string capitalizedTopic = char.ToUpper(topic[0]) + topic.Substring(1); | 260 | List<string> topics = GetHelpTopics(); |
264 | 261 | ||
265 | // This is a hack to allow the user to enter the help command in upper or lowercase. This will go | 262 | foreach (string topic in topics) |
266 | // away at some point. | 263 | { |
267 | console.Commands.AddCommand(capitalizedTopic, false, "help " + topic, | 264 | string capitalizedTopic = char.ToUpper(topic[0]) + topic.Substring(1); |
268 | "help " + capitalizedTopic, | ||
269 | "Get help on plugin command '" + topic + "'", | ||
270 | HandleCommanderHelp); | ||
271 | console.Commands.AddCommand(capitalizedTopic, false, "help " + capitalizedTopic, | ||
272 | "help " + capitalizedTopic, | ||
273 | "Get help on plugin command '" + topic + "'", | ||
274 | HandleCommanderHelp); | ||
275 | 265 | ||
276 | ICommander commander = null; | 266 | // 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. | ||
268 | m_console.Commands.AddCommand(capitalizedTopic, false, "help " + topic, | ||
269 | "help " + capitalizedTopic, | ||
270 | "Get help on plugin command '" + topic + "'", | ||
271 | HandleCommanderHelp); | ||
272 | m_console.Commands.AddCommand(capitalizedTopic, false, "help " + capitalizedTopic, | ||
273 | "help " + capitalizedTopic, | ||
274 | "Get help on plugin command '" + topic + "'", | ||
275 | HandleCommanderHelp); | ||
277 | 276 | ||
278 | Scene s = SceneManager.CurrentOrFirstScene; | 277 | ICommander commander = null; |
279 | 278 | ||
280 | if (s != null && s.GetCommanders() != null) | 279 | Scene s = SceneManager.CurrentOrFirstScene; |
281 | { | ||
282 | if (s.GetCommanders().ContainsKey(topic)) | ||
283 | commander = s.GetCommanders()[topic]; | ||
284 | } | ||
285 | 280 | ||
286 | if (commander == null) | 281 | if (s != null && s.GetCommanders() != null) |
287 | continue; | 282 | { |
283 | if (s.GetCommanders().ContainsKey(topic)) | ||
284 | commander = s.GetCommanders()[topic]; | ||
285 | } | ||
288 | 286 | ||
289 | foreach (string command in commander.Commands.Keys) | 287 | if (commander == null) |
290 | { | 288 | continue; |
291 | console.Commands.AddCommand(capitalizedTopic, false, | 289 | |
292 | topic + " " + command, | 290 | foreach (string command in commander.Commands.Keys) |
293 | topic + " " + commander.Commands[command].ShortHelp(), | 291 | { |
294 | String.Empty, HandleCommanderCommand); | 292 | m_console.Commands.AddCommand(capitalizedTopic, false, |
293 | topic + " " + command, | ||
294 | topic + " " + commander.Commands[command].ShortHelp(), | ||
295 | String.Empty, HandleCommanderCommand); | ||
296 | } | ||
295 | } | 297 | } |
296 | } | 298 | } |
297 | } | 299 | } |
@@ -621,7 +623,7 @@ namespace OpenSim | |||
621 | if (account == null) | 623 | if (account == null) |
622 | { | 624 | { |
623 | m_log.ErrorFormat( | 625 | m_log.ErrorFormat( |
624 | "[OPENSIM]: Unable to store account. If this simulator is connected to a grid, you must create the estate owner account first at the grid level."); | 626 | "[OPENSIM]: Unable to store account. If this simulator is connected to a grid, you must create the estate owner account first."); |
625 | } | 627 | } |
626 | else | 628 | else |
627 | { | 629 | { |
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs index f6146a9..650cd50 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs | |||
@@ -241,8 +241,8 @@ namespace OpenSim.Region.ClientStack.Linden | |||
241 | m_HostCapsObj.RegisterHandler( | 241 | m_HostCapsObj.RegisterHandler( |
242 | "SEED", new RestStreamHandler("POST", capsBase + m_requestPath, SeedCapRequest, "SEED", null)); | 242 | "SEED", new RestStreamHandler("POST", capsBase + m_requestPath, SeedCapRequest, "SEED", null)); |
243 | 243 | ||
244 | // m_log.DebugFormat( | 244 | m_log.DebugFormat( |
245 | // "[CAPS]: Registered seed capability {0} for {1}", capsBase + m_requestPath, m_HostCapsObj.AgentID); | 245 | "[CAPS]: Registered seed capability {0} for {1}", capsBase + m_requestPath, m_HostCapsObj.AgentID); |
246 | 246 | ||
247 | //m_capsHandlers["MapLayer"] = | 247 | //m_capsHandlers["MapLayer"] = |
248 | // new LLSDStreamhandler<OSDMapRequest, OSDMapLayerResponse>("POST", | 248 | // new LLSDStreamhandler<OSDMapRequest, OSDMapLayerResponse>("POST", |
@@ -337,12 +337,11 @@ namespace OpenSim.Region.ClientStack.Linden | |||
337 | public string SeedCapRequest(string request, string path, string param, | 337 | public string SeedCapRequest(string request, string path, string param, |
338 | IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) | 338 | IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) |
339 | { | 339 | { |
340 | m_log.DebugFormat( | 340 | // m_log.Debug("[CAPS]: Seed Caps Request in region: " + m_regionName); |
341 | "[CAPS]: Received SEED caps request in {0} for agent {1}", m_regionName, m_HostCapsObj.AgentID); | ||
342 | 341 | ||
343 | if (!m_Scene.CheckClient(m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint)) | 342 | if (!m_Scene.CheckClient(m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint)) |
344 | { | 343 | { |
345 | m_log.WarnFormat( | 344 | m_log.DebugFormat( |
346 | "[CAPS]: Unauthorized CAPS client {0} from {1}", | 345 | "[CAPS]: Unauthorized CAPS client {0} from {1}", |
347 | m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint); | 346 | m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint); |
348 | 347 | ||
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs index 5bbdce8..e113c60 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,7 +102,6 @@ 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 | |||
106 | scene.EventManager.OnMakeChildAgent += MakeChildAgent; | 105 | scene.EventManager.OnMakeChildAgent += MakeChildAgent; |
107 | scene.EventManager.OnRegisterCaps += OnRegisterCaps; | 106 | scene.EventManager.OnRegisterCaps += OnRegisterCaps; |
108 | 107 | ||
@@ -111,10 +110,10 @@ namespace OpenSim.Region.ClientStack.Linden | |||
111 | false, | 110 | false, |
112 | "debug eq", | 111 | "debug eq", |
113 | "debug eq [0|1|2]", | 112 | "debug eq [0|1|2]", |
114 | "Turn on event queue debugging\n" | 113 | "Turn on event queue debugging" |
115 | + " <= 0 - turns off all event queue logging\n" | 114 | + "<= 0 - turns off all event queue logging" |
116 | + " >= 1 - turns on outgoing event logging\n" | 115 | + ">= 1 - turns on outgoing event logging" |
117 | + " >= 2 - turns on poll notification", | 116 | + ">= 2 - turns on poll notification", |
118 | HandleDebugEq); | 117 | HandleDebugEq); |
119 | } | 118 | } |
120 | else | 119 | else |
@@ -227,6 +226,16 @@ namespace OpenSim.Region.ClientStack.Linden | |||
227 | 226 | ||
228 | #endregion | 227 | #endregion |
229 | 228 | ||
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 | |||
230 | private void ClientClosed(UUID agentID, Scene scene) | 239 | private void ClientClosed(UUID agentID, Scene scene) |
231 | { | 240 | { |
232 | // m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", agentID, m_scene.RegionInfo.RegionName); | 241 | // m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", agentID, m_scene.RegionInfo.RegionName); |
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs index d604cf6..cd70410 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs | |||
@@ -94,7 +94,7 @@ namespace OpenSim.Region.ClientStack.Linden.Tests | |||
94 | UUID spId = TestHelpers.ParseTail(0x1); | 94 | UUID spId = TestHelpers.ParseTail(0x1); |
95 | 95 | ||
96 | SceneHelpers.AddScenePresence(m_scene, spId); | 96 | SceneHelpers.AddScenePresence(m_scene, spId); |
97 | m_scene.IncomingCloseAgent(spId, false); | 97 | m_scene.IncomingCloseAgent(spId); |
98 | 98 | ||
99 | // TODO: Add more assertions for the other aspects of event queues | 99 | // TODO: Add more assertions for the other aspects of event queues |
100 | Assert.That(MainServer.Instance.GetPollServiceHandlerKeys().Count, Is.EqualTo(0)); | 100 | Assert.That(MainServer.Instance.GetPollServiceHandlerKeys().Count, Is.EqualTo(0)); |
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs index fcac182..0a5ad0f 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs | |||
@@ -109,7 +109,7 @@ namespace OpenSim.Region.ClientStack.Linden | |||
109 | 109 | ||
110 | UUID capID = UUID.Random(); | 110 | UUID capID = UUID.Random(); |
111 | 111 | ||
112 | // m_log.DebugFormat("[REGION CONSOLE]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName); | 112 | m_log.DebugFormat("[REGION CONSOLE]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName); |
113 | caps.RegisterHandler( | 113 | caps.RegisterHandler( |
114 | "SimConsoleAsync", | 114 | "SimConsoleAsync", |
115 | new ConsoleHandler("/CAPS/" + capID + "/", "SimConsoleAsync", agentID, this, m_scene)); | 115 | new ConsoleHandler("/CAPS/" + capID + "/", "SimConsoleAsync", agentID, this, m_scene)); |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs b/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs index e22670b..1b8535c 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs | |||
@@ -45,12 +45,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
45 | public Packet Packet; | 45 | public Packet Packet; |
46 | 46 | ||
47 | /// <summary> | 47 | /// <summary> |
48 | /// No arg constructor. | 48 | /// Default constructor |
49 | /// </summary> | ||
50 | public IncomingPacket() {} | ||
51 | |||
52 | /// <summary> | ||
53 | /// Constructor | ||
54 | /// </summary> | 49 | /// </summary> |
55 | /// <param name="client">Reference to the client this packet came from</param> | 50 | /// <param name="client">Reference to the client this packet came from</param> |
56 | /// <param name="packet">Packet data</param> | 51 | /// <param name="packet">Packet data</param> |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index c9aa4ca..ae9ed7f 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | |||
@@ -47,7 +47,6 @@ 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; | ||
51 | using Nini.Config; | 50 | using Nini.Config; |
52 | 51 | ||
53 | using System.IO; | 52 | using System.IO; |
@@ -356,17 +355,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
356 | private bool m_deliverPackets = true; | 355 | private bool m_deliverPackets = true; |
357 | private int m_animationSequenceNumber = 1; | 356 | private int m_animationSequenceNumber = 1; |
358 | private bool m_SendLogoutPacketWhenClosing = true; | 357 | private bool m_SendLogoutPacketWhenClosing = true; |
359 | 358 | private AgentUpdateArgs lastarg; | |
360 | /// <summary> | ||
361 | /// We retain a single AgentUpdateArgs so that we can constantly reuse it rather than construct a new one for | ||
362 | /// every single incoming AgentUpdate. Every client sends 10 AgentUpdate UDP messages per second, even if it | ||
363 | /// is doing absolutely nothing. | ||
364 | /// </summary> | ||
365 | /// <remarks> | ||
366 | /// This does mean that agent updates must be processed synchronously, at least for each client, and called methods | ||
367 | /// cannot retain a reference to it outside of that method. | ||
368 | /// </remarks> | ||
369 | private AgentUpdateArgs m_lastAgentUpdateArgs; | ||
370 | 359 | ||
371 | protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>(); | 360 | protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>(); |
372 | protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers | 361 | protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers |
@@ -521,18 +510,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
521 | /// </summary> | 510 | /// </summary> |
522 | public void Close() | 511 | public void Close() |
523 | { | 512 | { |
524 | Close(true, false); | 513 | Close(true); |
525 | } | 514 | } |
526 | 515 | ||
527 | public void Close(bool sendStop, bool force) | 516 | /// <summary> |
517 | /// Shut down the client view | ||
518 | /// </summary> | ||
519 | public void Close(bool sendStop) | ||
528 | { | 520 | { |
529 | // We lock here to prevent race conditions between two threads calling close simultaneously (e.g. | 521 | // We lock here to prevent race conditions between two threads calling close simultaneously (e.g. |
530 | // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection. | 522 | // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection. |
531 | lock (CloseSyncLock) | 523 | lock (CloseSyncLock) |
532 | { | 524 | { |
533 | // We still perform a force close inside the sync lock since this is intended to attempt close where | 525 | if (!IsActive) |
534 | // there is some unidentified connection problem, not where we have issues due to deadlock | ||
535 | if (!IsActive && !force) | ||
536 | return; | 526 | return; |
537 | 527 | ||
538 | IsActive = false; | 528 | IsActive = false; |
@@ -847,9 +837,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
847 | OutPacket(mov, ThrottleOutPacketType.Unknown); | 837 | OutPacket(mov, ThrottleOutPacketType.Unknown); |
848 | } | 838 | } |
849 | 839 | ||
850 | public void SendChatMessage( | 840 | public void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName, |
851 | string message, byte type, Vector3 fromPos, string fromName, | 841 | UUID fromAgentID, byte source, byte audible) |
852 | UUID fromAgentID, UUID ownerID, byte source, byte audible) | ||
853 | { | 842 | { |
854 | ChatFromSimulatorPacket reply = (ChatFromSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.ChatFromSimulator); | 843 | ChatFromSimulatorPacket reply = (ChatFromSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.ChatFromSimulator); |
855 | reply.ChatData.Audible = audible; | 844 | reply.ChatData.Audible = audible; |
@@ -858,7 +847,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
858 | reply.ChatData.SourceType = source; | 847 | reply.ChatData.SourceType = source; |
859 | reply.ChatData.Position = fromPos; | 848 | reply.ChatData.Position = fromPos; |
860 | reply.ChatData.FromName = Util.StringToBytes256(fromName); | 849 | reply.ChatData.FromName = Util.StringToBytes256(fromName); |
861 | reply.ChatData.OwnerID = ownerID; | 850 | reply.ChatData.OwnerID = fromAgentID; |
862 | reply.ChatData.SourceID = fromAgentID; | 851 | reply.ChatData.SourceID = fromAgentID; |
863 | 852 | ||
864 | OutPacket(reply, ThrottleOutPacketType.Unknown); | 853 | OutPacket(reply, ThrottleOutPacketType.Unknown); |
@@ -3996,8 +3985,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3996 | { | 3985 | { |
3997 | List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value; | 3986 | List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value; |
3998 | 3987 | ||
3999 | ImprovedTerseObjectUpdatePacket packet | 3988 | ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); |
4000 | = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); | ||
4001 | packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; | 3989 | packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; |
4002 | packet.RegionData.TimeDilation = timeDilation; | 3990 | packet.RegionData.TimeDilation = timeDilation; |
4003 | packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; | 3991 | packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; |
@@ -4042,9 +4030,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4042 | { | 4030 | { |
4043 | List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value; | 4031 | List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value; |
4044 | 4032 | ||
4045 | ImprovedTerseObjectUpdatePacket packet | 4033 | ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); |
4046 | = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket( | ||
4047 | PacketType.ImprovedTerseObjectUpdate); | ||
4048 | packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; | 4034 | packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; |
4049 | packet.RegionData.TimeDilation = timeDilation; | 4035 | packet.RegionData.TimeDilation = timeDilation; |
4050 | packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; | 4036 | packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; |
@@ -4052,7 +4038,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4052 | for (int i = 0; i < blocks.Count; i++) | 4038 | for (int i = 0; i < blocks.Count; i++) |
4053 | packet.ObjectData[i] = blocks[i]; | 4039 | packet.ObjectData[i] = blocks[i]; |
4054 | 4040 | ||
4055 | OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); }); | 4041 | OutPacket(packet, ThrottleOutPacketType.Task, true); |
4056 | } | 4042 | } |
4057 | 4043 | ||
4058 | #endregion Packet Sending | 4044 | #endregion Packet Sending |
@@ -4549,7 +4535,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4549 | { | 4535 | { |
4550 | returnblock[j] = new EstateOwnerMessagePacket.ParamListBlock(); | 4536 | returnblock[j] = new EstateOwnerMessagePacket.ParamListBlock(); |
4551 | } | 4537 | } |
4552 | j = 0; | 4538 | j = 0; |
4553 | 4539 | ||
4554 | returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++; | 4540 | returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++; |
4555 | returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++; | 4541 | returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++; |
@@ -5053,9 +5039,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
5053 | Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Y, -64.0f, 64.0f), data, pos); pos += 2; | 5039 | Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Y, -64.0f, 64.0f), data, pos); pos += 2; |
5054 | Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Z, -64.0f, 64.0f), data, pos); pos += 2; | 5040 | Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Z, -64.0f, 64.0f), data, pos); pos += 2; |
5055 | 5041 | ||
5056 | ImprovedTerseObjectUpdatePacket.ObjectDataBlock block | 5042 | ImprovedTerseObjectUpdatePacket.ObjectDataBlock block = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock(); |
5057 | = PacketPool.Instance.GetDataBlock<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>(); | ||
5058 | |||
5059 | block.Data = data; | 5043 | block.Data = data; |
5060 | 5044 | ||
5061 | if (textureEntry != null && textureEntry.Length > 0) | 5045 | if (textureEntry != null && textureEntry.Length > 0) |
@@ -5305,18 +5289,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
5305 | protected virtual void RegisterLocalPacketHandlers() | 5289 | protected virtual void RegisterLocalPacketHandlers() |
5306 | { | 5290 | { |
5307 | AddLocalPacketHandler(PacketType.LogoutRequest, HandleLogout); | 5291 | AddLocalPacketHandler(PacketType.LogoutRequest, HandleLogout); |
5308 | |||
5309 | // If AgentUpdate is ever handled asynchronously, then we will also need to construct a new AgentUpdateArgs | ||
5310 | // for each AgentUpdate packet. | ||
5311 | AddLocalPacketHandler(PacketType.AgentUpdate, HandleAgentUpdate, false); | 5292 | AddLocalPacketHandler(PacketType.AgentUpdate, HandleAgentUpdate, false); |
5312 | |||
5313 | AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect, false); | 5293 | AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect, false); |
5314 | AddLocalPacketHandler(PacketType.AgentCachedTexture, HandleAgentTextureCached, false); | 5294 | AddLocalPacketHandler(PacketType.AgentCachedTexture, HandleAgentTextureCached, false); |
5315 | AddLocalPacketHandler(PacketType.MultipleObjectUpdate, HandleMultipleObjUpdate, false); | 5295 | AddLocalPacketHandler(PacketType.MultipleObjectUpdate, HandleMultipleObjUpdate, false); |
5316 | AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest, false); | 5296 | AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest, false); |
5317 | AddLocalPacketHandler(PacketType.ParcelBuy, HandleParcelBuyRequest, false); | 5297 | AddLocalPacketHandler(PacketType.ParcelBuy, HandleParcelBuyRequest, false); |
5318 | AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest); | 5298 | AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest, false); |
5319 | AddLocalPacketHandler(PacketType.ObjectGroup, HandleObjectGroupRequest); | 5299 | AddLocalPacketHandler(PacketType.ObjectGroup, HandleObjectGroupRequest, false); |
5320 | AddLocalPacketHandler(PacketType.GenericMessage, HandleGenericMessage); | 5300 | AddLocalPacketHandler(PacketType.GenericMessage, HandleGenericMessage); |
5321 | AddLocalPacketHandler(PacketType.AvatarPropertiesRequest, HandleAvatarPropertiesRequest); | 5301 | AddLocalPacketHandler(PacketType.AvatarPropertiesRequest, HandleAvatarPropertiesRequest); |
5322 | AddLocalPacketHandler(PacketType.ChatFromViewer, HandleChatFromViewer); | 5302 | AddLocalPacketHandler(PacketType.ChatFromViewer, HandleChatFromViewer); |
@@ -5538,84 +5518,81 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
5538 | 5518 | ||
5539 | #region Scene/Avatar | 5519 | #region Scene/Avatar |
5540 | 5520 | ||
5541 | private bool HandleAgentUpdate(IClientAPI sener, Packet packet) | 5521 | private bool HandleAgentUpdate(IClientAPI sener, Packet Pack) |
5542 | { | 5522 | { |
5543 | if (OnAgentUpdate != null) | 5523 | if (OnAgentUpdate != null) |
5544 | { | 5524 | { |
5545 | AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet; | 5525 | bool update = false; |
5526 | AgentUpdatePacket agenUpdate = (AgentUpdatePacket)Pack; | ||
5546 | 5527 | ||
5547 | #region Packet Session and User Check | 5528 | #region Packet Session and User Check |
5548 | if (agentUpdate.AgentData.SessionID != SessionId || agentUpdate.AgentData.AgentID != AgentId) | 5529 | if (agenUpdate.AgentData.SessionID != SessionId || agenUpdate.AgentData.AgentID != AgentId) |
5549 | { | ||
5550 | PacketPool.Instance.ReturnPacket(packet); | ||
5551 | return false; | 5530 | return false; |
5552 | } | ||
5553 | #endregion | 5531 | #endregion |
5554 | 5532 | ||
5555 | bool update = false; | 5533 | AgentUpdatePacket.AgentDataBlock x = agenUpdate.AgentData; |
5556 | AgentUpdatePacket.AgentDataBlock x = agentUpdate.AgentData; | 5534 | |
5535 | // We can only check when we have something to check | ||
5536 | // against. | ||
5557 | 5537 | ||
5558 | if (m_lastAgentUpdateArgs != null) | 5538 | if (lastarg != null) |
5559 | { | 5539 | { |
5560 | // These should be ordered from most-likely to | ||
5561 | // least likely to change. I've made an initial | ||
5562 | // guess at that. | ||
5563 | update = | 5540 | update = |
5564 | ( | 5541 | ( |
5565 | (x.BodyRotation != m_lastAgentUpdateArgs.BodyRotation) || | 5542 | (x.BodyRotation != lastarg.BodyRotation) || |
5566 | (x.CameraAtAxis != m_lastAgentUpdateArgs.CameraAtAxis) || | 5543 | (x.CameraAtAxis != lastarg.CameraAtAxis) || |
5567 | (x.CameraCenter != m_lastAgentUpdateArgs.CameraCenter) || | 5544 | (x.CameraCenter != lastarg.CameraCenter) || |
5568 | (x.CameraLeftAxis != m_lastAgentUpdateArgs.CameraLeftAxis) || | 5545 | (x.CameraLeftAxis != lastarg.CameraLeftAxis) || |
5569 | (x.CameraUpAxis != m_lastAgentUpdateArgs.CameraUpAxis) || | 5546 | (x.CameraUpAxis != lastarg.CameraUpAxis) || |
5570 | (x.ControlFlags != m_lastAgentUpdateArgs.ControlFlags) || | 5547 | (x.ControlFlags != lastarg.ControlFlags) || |
5571 | (x.ControlFlags != 0) || | 5548 | (x.ControlFlags != 0) || |
5572 | (x.Far != m_lastAgentUpdateArgs.Far) || | 5549 | (x.Far != lastarg.Far) || |
5573 | (x.Flags != m_lastAgentUpdateArgs.Flags) || | 5550 | (x.Flags != lastarg.Flags) || |
5574 | (x.State != m_lastAgentUpdateArgs.State) || | 5551 | (x.State != lastarg.State) || |
5575 | (x.HeadRotation != m_lastAgentUpdateArgs.HeadRotation) || | 5552 | (x.HeadRotation != lastarg.HeadRotation) || |
5576 | (x.SessionID != m_lastAgentUpdateArgs.SessionID) || | 5553 | (x.SessionID != lastarg.SessionID) || |
5577 | (x.AgentID != m_lastAgentUpdateArgs.AgentID) | 5554 | (x.AgentID != lastarg.AgentID) |
5578 | ); | 5555 | ); |
5579 | } | 5556 | } |
5580 | else | 5557 | else |
5581 | { | 5558 | { |
5582 | m_lastAgentUpdateArgs = new AgentUpdateArgs(); | ||
5583 | update = true; | 5559 | update = true; |
5584 | } | 5560 | } |
5585 | 5561 | ||
5562 | // These should be ordered from most-likely to | ||
5563 | // least likely to change. I've made an initial | ||
5564 | // guess at that. | ||
5565 | |||
5586 | if (update) | 5566 | if (update) |
5587 | { | 5567 | { |
5588 | // m_log.DebugFormat("[LLCLIENTVIEW]: Triggered AgentUpdate for {0}", sener.Name); | 5568 | // m_log.DebugFormat("[LLCLIENTVIEW]: Triggered AgentUpdate for {0}", sener.Name); |
5589 | 5569 | ||
5590 | m_lastAgentUpdateArgs.AgentID = x.AgentID; | 5570 | AgentUpdateArgs arg = new AgentUpdateArgs(); |
5591 | m_lastAgentUpdateArgs.BodyRotation = x.BodyRotation; | 5571 | arg.AgentID = x.AgentID; |
5592 | m_lastAgentUpdateArgs.CameraAtAxis = x.CameraAtAxis; | 5572 | arg.BodyRotation = x.BodyRotation; |
5593 | m_lastAgentUpdateArgs.CameraCenter = x.CameraCenter; | 5573 | arg.CameraAtAxis = x.CameraAtAxis; |
5594 | m_lastAgentUpdateArgs.CameraLeftAxis = x.CameraLeftAxis; | 5574 | arg.CameraCenter = x.CameraCenter; |
5595 | m_lastAgentUpdateArgs.CameraUpAxis = x.CameraUpAxis; | 5575 | arg.CameraLeftAxis = x.CameraLeftAxis; |
5596 | m_lastAgentUpdateArgs.ControlFlags = x.ControlFlags; | 5576 | arg.CameraUpAxis = x.CameraUpAxis; |
5597 | m_lastAgentUpdateArgs.Far = x.Far; | 5577 | arg.ControlFlags = x.ControlFlags; |
5598 | m_lastAgentUpdateArgs.Flags = x.Flags; | 5578 | arg.Far = x.Far; |
5599 | m_lastAgentUpdateArgs.HeadRotation = x.HeadRotation; | 5579 | arg.Flags = x.Flags; |
5600 | m_lastAgentUpdateArgs.SessionID = x.SessionID; | 5580 | arg.HeadRotation = x.HeadRotation; |
5601 | m_lastAgentUpdateArgs.State = x.State; | 5581 | arg.SessionID = x.SessionID; |
5602 | 5582 | arg.State = x.State; | |
5603 | UpdateAgent handlerAgentUpdate = OnAgentUpdate; | 5583 | UpdateAgent handlerAgentUpdate = OnAgentUpdate; |
5604 | UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate; | 5584 | UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate; |
5605 | 5585 | lastarg = arg; // save this set of arguments for nexttime | |
5606 | if (handlerPreAgentUpdate != null) | 5586 | if (handlerPreAgentUpdate != null) |
5607 | OnPreAgentUpdate(this, m_lastAgentUpdateArgs); | 5587 | OnPreAgentUpdate(this, arg); |
5608 | |||
5609 | if (handlerAgentUpdate != null) | 5588 | if (handlerAgentUpdate != null) |
5610 | OnAgentUpdate(this, m_lastAgentUpdateArgs); | 5589 | OnAgentUpdate(this, arg); |
5611 | 5590 | ||
5612 | handlerAgentUpdate = null; | 5591 | handlerAgentUpdate = null; |
5613 | handlerPreAgentUpdate = null; | 5592 | handlerPreAgentUpdate = null; |
5614 | } | 5593 | } |
5615 | } | 5594 | } |
5616 | 5595 | ||
5617 | PacketPool.Instance.ReturnPacket(packet); | ||
5618 | |||
5619 | return true; | 5596 | return true; |
5620 | } | 5597 | } |
5621 | 5598 | ||
@@ -5987,8 +5964,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
5987 | msgpack.MessageBlock.ID, | 5964 | msgpack.MessageBlock.ID, |
5988 | msgpack.MessageBlock.Offline != 0 ? true : false, | 5965 | msgpack.MessageBlock.Offline != 0 ? true : false, |
5989 | msgpack.MessageBlock.Position, | 5966 | msgpack.MessageBlock.Position, |
5990 | msgpack.MessageBlock.BinaryBucket, | 5967 | msgpack.MessageBlock.BinaryBucket); |
5991 | true); | ||
5992 | 5968 | ||
5993 | handlerInstantMessage(this, im); | 5969 | handlerInstantMessage(this, im); |
5994 | } | 5970 | } |
@@ -9275,9 +9251,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
9275 | } | 9251 | } |
9276 | #endregion | 9252 | #endregion |
9277 | 9253 | ||
9278 | string method = Utils.BytesToString(messagePacket.MethodData.Method); | 9254 | switch (Utils.BytesToString(messagePacket.MethodData.Method)) |
9279 | |||
9280 | switch (method) | ||
9281 | { | 9255 | { |
9282 | case "getinfo": | 9256 | case "getinfo": |
9283 | if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) | 9257 | if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) |
@@ -9593,17 +9567,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
9593 | return true; | 9567 | return true; |
9594 | 9568 | ||
9595 | default: | 9569 | default: |
9596 | m_log.WarnFormat( | 9570 | m_log.Error("EstateOwnerMessage: Unknown method requested\n" + messagePacket); |
9597 | "[LLCLIENTVIEW]: EstateOwnerMessage: Unknown method {0} requested for {1} in {2}", | ||
9598 | method, Name, Scene.Name); | ||
9599 | |||
9600 | for (int i = 0; i < messagePacket.ParamList.Length; i++) | ||
9601 | { | ||
9602 | EstateOwnerMessagePacket.ParamListBlock block = messagePacket.ParamList[i]; | ||
9603 | string data = (string)Utils.BytesToString(block.Parameter); | ||
9604 | m_log.DebugFormat("[LLCLIENTVIEW]: Param {0}={1}", i, data); | ||
9605 | } | ||
9606 | |||
9607 | return true; | 9571 | return true; |
9608 | } | 9572 | } |
9609 | 9573 | ||
@@ -11996,7 +11960,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
11996 | logPacket = false; | 11960 | logPacket = false; |
11997 | 11961 | ||
11998 | if (DebugPacketLevel <= 50 | 11962 | if (DebugPacketLevel <= 50 |
11999 | && (packet.Type == PacketType.ImprovedTerseObjectUpdate || packet.Type == PacketType.ObjectUpdate)) | 11963 | & (packet.Type == PacketType.ImprovedTerseObjectUpdate || packet.Type == PacketType.ObjectUpdate)) |
12000 | logPacket = false; | 11964 | logPacket = false; |
12001 | 11965 | ||
12002 | if (DebugPacketLevel <= 25 && packet.Type == PacketType.ObjectPropertiesFamily) | 11966 | if (DebugPacketLevel <= 25 && packet.Type == PacketType.ObjectPropertiesFamily) |
@@ -12070,6 +12034,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
12070 | 12034 | ||
12071 | if (!ProcessPacketMethod(packet)) | 12035 | if (!ProcessPacketMethod(packet)) |
12072 | m_log.Warn("[CLIENT]: unhandled packet " + packet.Type); | 12036 | m_log.Warn("[CLIENT]: unhandled packet " + packet.Type); |
12037 | |||
12038 | PacketPool.Instance.ReturnPacket(packet); | ||
12073 | } | 12039 | } |
12074 | 12040 | ||
12075 | private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket) | 12041 | private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket) |
@@ -12238,7 +12204,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
12238 | { | 12204 | { |
12239 | Kick(reason); | 12205 | Kick(reason); |
12240 | Thread.Sleep(1000); | 12206 | Thread.Sleep(1000); |
12241 | Disconnect(); | 12207 | Close(); |
12242 | } | 12208 | } |
12243 | 12209 | ||
12244 | public void Disconnect() | 12210 | public void Disconnect() |
@@ -12526,10 +12492,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
12526 | ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f); | 12492 | ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f); |
12527 | 12493 | ||
12528 | 12494 | ||
12529 | ImprovedTerseObjectUpdatePacket packet | 12495 | ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); |
12530 | = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket( | ||
12531 | PacketType.ImprovedTerseObjectUpdate); | ||
12532 | |||
12533 | packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; | 12496 | packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; |
12534 | packet.RegionData.TimeDilation = timeDilation; | 12497 | packet.RegionData.TimeDilation = timeDilation; |
12535 | packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1]; | 12498 | 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 b8951d9..d6513c5 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | |||
@@ -37,7 +37,6 @@ using log4net; | |||
37 | using Nini.Config; | 37 | using Nini.Config; |
38 | using OpenMetaverse.Packets; | 38 | using OpenMetaverse.Packets; |
39 | using OpenSim.Framework; | 39 | using OpenSim.Framework; |
40 | using OpenSim.Framework.Console; | ||
41 | using OpenSim.Framework.Monitoring; | 40 | using OpenSim.Framework.Monitoring; |
42 | using OpenSim.Region.Framework.Scenes; | 41 | using OpenSim.Region.Framework.Scenes; |
43 | using OpenMetaverse; | 42 | using OpenMetaverse; |
@@ -101,11 +100,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
101 | 100 | ||
102 | /// <summary>The measured resolution of Environment.TickCount</summary> | 101 | /// <summary>The measured resolution of Environment.TickCount</summary> |
103 | public readonly float TickCountResolution; | 102 | public readonly float TickCountResolution; |
104 | |||
105 | /// <summary>Number of prim updates to put on the queue each time the | 103 | /// <summary>Number of prim updates to put on the queue each time the |
106 | /// OnQueueEmpty event is triggered for updates</summary> | 104 | /// OnQueueEmpty event is triggered for updates</summary> |
107 | public readonly int PrimUpdatesPerCallback; | 105 | public readonly int PrimUpdatesPerCallback; |
108 | |||
109 | /// <summary>Number of texture packets to put on the queue each time the | 106 | /// <summary>Number of texture packets to put on the queue each time the |
110 | /// OnQueueEmpty event is triggered for textures</summary> | 107 | /// OnQueueEmpty event is triggered for textures</summary> |
111 | public readonly int TextureSendLimit; | 108 | public readonly int TextureSendLimit; |
@@ -127,37 +124,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
127 | 124 | ||
128 | /// <summary>Manages authentication for agent circuits</summary> | 125 | /// <summary>Manages authentication for agent circuits</summary> |
129 | private AgentCircuitManager m_circuitManager; | 126 | private AgentCircuitManager m_circuitManager; |
130 | |||
131 | /// <summary>Reference to the scene this UDP server is attached to</summary> | 127 | /// <summary>Reference to the scene this UDP server is attached to</summary> |
132 | protected Scene m_scene; | 128 | protected Scene m_scene; |
133 | |||
134 | /// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary> | 129 | /// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary> |
135 | private Location m_location; | 130 | private Location m_location; |
136 | |||
137 | /// <summary>The size of the receive buffer for the UDP socket. This value | 131 | /// <summary>The size of the receive buffer for the UDP socket. This value |
138 | /// is passed up to the operating system and used in the system networking | 132 | /// is passed up to the operating system and used in the system networking |
139 | /// stack. Use zero to leave this value as the default</summary> | 133 | /// stack. Use zero to leave this value as the default</summary> |
140 | private int m_recvBufferSize; | 134 | private int m_recvBufferSize; |
141 | |||
142 | /// <summary>Flag to process packets asynchronously or synchronously</summary> | 135 | /// <summary>Flag to process packets asynchronously or synchronously</summary> |
143 | private bool m_asyncPacketHandling; | 136 | private bool m_asyncPacketHandling; |
144 | |||
145 | /// <summary>Tracks whether or not a packet was sent each round so we know | 137 | /// <summary>Tracks whether or not a packet was sent each round so we know |
146 | /// whether or not to sleep</summary> | 138 | /// whether or not to sleep</summary> |
147 | private bool m_packetSent; | 139 | private bool m_packetSent; |
148 | 140 | ||
149 | /// <summary>Environment.TickCount of the last time that packet stats were reported to the scene</summary> | 141 | /// <summary>Environment.TickCount of the last time that packet stats were reported to the scene</summary> |
150 | private int m_elapsedMSSinceLastStatReport = 0; | 142 | private int m_elapsedMSSinceLastStatReport = 0; |
151 | |||
152 | /// <summary>Environment.TickCount of the last time the outgoing packet handler executed</summary> | 143 | /// <summary>Environment.TickCount of the last time the outgoing packet handler executed</summary> |
153 | private int m_tickLastOutgoingPacketHandler; | 144 | private int m_tickLastOutgoingPacketHandler; |
154 | |||
155 | /// <summary>Keeps track of the number of elapsed milliseconds since the last time the outgoing packet handler looped</summary> | 145 | /// <summary>Keeps track of the number of elapsed milliseconds since the last time the outgoing packet handler looped</summary> |
156 | private int m_elapsedMSOutgoingPacketHandler; | 146 | private int m_elapsedMSOutgoingPacketHandler; |
157 | |||
158 | /// <summary>Keeps track of the number of 100 millisecond periods elapsed in the outgoing packet handler executed</summary> | 147 | /// <summary>Keeps track of the number of 100 millisecond periods elapsed in the outgoing packet handler executed</summary> |
159 | private int m_elapsed100MSOutgoingPacketHandler; | 148 | private int m_elapsed100MSOutgoingPacketHandler; |
160 | |||
161 | /// <summary>Keeps track of the number of 500 millisecond periods elapsed in the outgoing packet handler executed</summary> | 149 | /// <summary>Keeps track of the number of 500 millisecond periods elapsed in the outgoing packet handler executed</summary> |
162 | private int m_elapsed500MSOutgoingPacketHandler; | 150 | private int m_elapsed500MSOutgoingPacketHandler; |
163 | 151 | ||
@@ -171,9 +159,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
171 | protected bool m_sendPing; | 159 | protected bool m_sendPing; |
172 | 160 | ||
173 | private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>(); | 161 | private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>(); |
174 | private Pool<IncomingPacket> m_incomingPacketPool; | ||
175 | |||
176 | private Stat m_incomingPacketPoolStat; | ||
177 | 162 | ||
178 | private int m_defaultRTO = 0; | 163 | private int m_defaultRTO = 0; |
179 | private int m_maxRTO = 0; | 164 | private int m_maxRTO = 0; |
@@ -195,9 +180,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
195 | /// </summary> | 180 | /// </summary> |
196 | private IClientAPI m_currentIncomingClient; | 181 | private IClientAPI m_currentIncomingClient; |
197 | 182 | ||
198 | public LLUDPServer( | 183 | public LLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager) |
199 | IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, | ||
200 | IConfigSource configSource, AgentCircuitManager circuitManager) | ||
201 | : base(listenIP, (int)port) | 184 | : base(listenIP, (int)port) |
202 | { | 185 | { |
203 | #region Environment.TickCount Measurement | 186 | #region Environment.TickCount Measurement |
@@ -219,7 +202,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
219 | 202 | ||
220 | m_circuitManager = circuitManager; | 203 | m_circuitManager = circuitManager; |
221 | int sceneThrottleBps = 0; | 204 | int sceneThrottleBps = 0; |
222 | bool usePools = false; | ||
223 | 205 | ||
224 | IConfig config = configSource.Configs["ClientStack.LindenUDP"]; | 206 | IConfig config = configSource.Configs["ClientStack.LindenUDP"]; |
225 | if (config != null) | 207 | if (config != null) |
@@ -245,16 +227,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
245 | m_pausedAckTimeout = 1000 * 300; // 5 minutes | 227 | m_pausedAckTimeout = 1000 * 300; // 5 minutes |
246 | } | 228 | } |
247 | 229 | ||
248 | // FIXME: This actually only needs to be done once since the PacketPool is shared across all servers. | ||
249 | // However, there is no harm in temporarily doing it multiple times. | ||
250 | IConfig packetConfig = configSource.Configs["PacketPool"]; | ||
251 | if (packetConfig != null) | ||
252 | { | ||
253 | PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true); | ||
254 | PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true); | ||
255 | usePools = packetConfig.GetBoolean("RecycleBaseUDPPackets", usePools); | ||
256 | } | ||
257 | |||
258 | #region BinaryStats | 230 | #region BinaryStats |
259 | config = configSource.Configs["Statistics.Binary"]; | 231 | config = configSource.Configs["Statistics.Binary"]; |
260 | m_shouldCollectStats = false; | 232 | m_shouldCollectStats = false; |
@@ -282,28 +254,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
282 | 254 | ||
283 | m_throttle = new TokenBucket(null, sceneThrottleBps); | 255 | m_throttle = new TokenBucket(null, sceneThrottleBps); |
284 | ThrottleRates = new ThrottleRates(configSource); | 256 | ThrottleRates = new ThrottleRates(configSource); |
285 | |||
286 | if (usePools) | ||
287 | EnablePools(); | ||
288 | } | 257 | } |
289 | 258 | ||
290 | public void Start() | 259 | public void Start() |
291 | { | 260 | { |
292 | StartInbound(); | 261 | if (m_scene == null) |
293 | StartOutbound(); | 262 | throw new InvalidOperationException("[LLUDPSERVER]: Cannot LLUDPServer.Start() without an IScene reference"); |
294 | 263 | ||
295 | m_elapsedMSSinceLastStatReport = Environment.TickCount; | ||
296 | } | ||
297 | |||
298 | private void StartInbound() | ||
299 | { | ||
300 | m_log.InfoFormat( | 264 | m_log.InfoFormat( |
301 | "[LLUDPSERVER]: Starting inbound packet processing for the LLUDP server in {0} mode with UsePools = {1}", | 265 | "[LLUDPSERVER]: Starting the LLUDP server in {0} mode", |
302 | m_asyncPacketHandling ? "asynchronous" : "synchronous", UsePools); | 266 | m_asyncPacketHandling ? "asynchronous" : "synchronous"); |
303 | 267 | ||
304 | base.StartInbound(m_recvBufferSize, m_asyncPacketHandling); | 268 | base.Start(m_recvBufferSize, m_asyncPacketHandling); |
305 | 269 | ||
306 | // This thread will process the packets received that are placed on the packetInbox | 270 | // Start the packet processing threads |
307 | Watchdog.StartThread( | 271 | Watchdog.StartThread( |
308 | IncomingPacketHandler, | 272 | IncomingPacketHandler, |
309 | string.Format("Incoming Packets ({0})", m_scene.RegionInfo.RegionName), | 273 | string.Format("Incoming Packets ({0})", m_scene.RegionInfo.RegionName), |
@@ -312,13 +276,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
312 | true, | 276 | true, |
313 | GetWatchdogIncomingAlarmData, | 277 | GetWatchdogIncomingAlarmData, |
314 | Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS); | 278 | Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS); |
315 | } | ||
316 | |||
317 | private new void StartOutbound() | ||
318 | { | ||
319 | m_log.Info("[LLUDPSERVER]: Starting outbound packet processing for the LLUDP server"); | ||
320 | |||
321 | base.StartOutbound(); | ||
322 | 279 | ||
323 | Watchdog.StartThread( | 280 | Watchdog.StartThread( |
324 | OutgoingPacketHandler, | 281 | OutgoingPacketHandler, |
@@ -328,57 +285,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
328 | true, | 285 | true, |
329 | GetWatchdogOutgoingAlarmData, | 286 | GetWatchdogOutgoingAlarmData, |
330 | Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS); | 287 | Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS); |
331 | } | ||
332 | |||
333 | public void Stop() | ||
334 | { | ||
335 | m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName); | ||
336 | base.StopOutbound(); | ||
337 | base.StopInbound(); | ||
338 | } | ||
339 | 288 | ||
340 | protected override bool EnablePools() | 289 | m_elapsedMSSinceLastStatReport = Environment.TickCount; |
341 | { | ||
342 | if (!UsePools) | ||
343 | { | ||
344 | base.EnablePools(); | ||
345 | |||
346 | m_incomingPacketPool = new Pool<IncomingPacket>(() => new IncomingPacket(), 500); | ||
347 | |||
348 | m_incomingPacketPoolStat | ||
349 | = new Stat( | ||
350 | "IncomingPacketPoolCount", | ||
351 | "Objects within incoming packet pool", | ||
352 | "The number of objects currently stored within the incoming packet pool", | ||
353 | "", | ||
354 | "clientstack", | ||
355 | "packetpool", | ||
356 | StatType.Pull, | ||
357 | stat => stat.Value = m_incomingPacketPool.Count, | ||
358 | StatVerbosity.Debug); | ||
359 | |||
360 | StatsManager.RegisterStat(m_incomingPacketPoolStat); | ||
361 | |||
362 | return true; | ||
363 | } | ||
364 | |||
365 | return false; | ||
366 | } | ||
367 | |||
368 | protected override bool DisablePools() | ||
369 | { | ||
370 | if (UsePools) | ||
371 | { | ||
372 | base.DisablePools(); | ||
373 | |||
374 | StatsManager.DeregisterStat(m_incomingPacketPoolStat); | ||
375 | |||
376 | // We won't null out the pool to avoid a race condition with code that may be in the middle of using it. | ||
377 | |||
378 | return true; | ||
379 | } | ||
380 | |||
381 | return false; | ||
382 | } | 290 | } |
383 | 291 | ||
384 | /// <summary> | 292 | /// <summary> |
@@ -403,6 +311,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
403 | m_currentOutgoingClient != null ? m_currentOutgoingClient.Name : "none"); | 311 | m_currentOutgoingClient != null ? m_currentOutgoingClient.Name : "none"); |
404 | } | 312 | } |
405 | 313 | ||
314 | public new void Stop() | ||
315 | { | ||
316 | m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName); | ||
317 | base.Stop(); | ||
318 | } | ||
319 | |||
406 | public void AddScene(IScene scene) | 320 | public void AddScene(IScene scene) |
407 | { | 321 | { |
408 | if (m_scene != null) | 322 | if (m_scene != null) |
@@ -419,117 +333,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
419 | 333 | ||
420 | m_scene = (Scene)scene; | 334 | m_scene = (Scene)scene; |
421 | m_location = new Location(m_scene.RegionInfo.RegionHandle); | 335 | m_location = new Location(m_scene.RegionInfo.RegionHandle); |
422 | |||
423 | MainConsole.Instance.Commands.AddCommand( | ||
424 | "Debug", | ||
425 | false, | ||
426 | "debug lludp start", | ||
427 | "debug lludp start <in|out|all>", | ||
428 | "Control LLUDP packet processing.", | ||
429 | "No effect if packet processing has already started.\n" | ||
430 | + "in - start inbound processing.\n" | ||
431 | + "out - start outbound processing.\n" | ||
432 | + "all - start in and outbound processing.\n", | ||
433 | HandleStartCommand); | ||
434 | |||
435 | MainConsole.Instance.Commands.AddCommand( | ||
436 | "Debug", | ||
437 | false, | ||
438 | "debug lludp stop", | ||
439 | "debug lludp stop <in|out|all>", | ||
440 | "Stop LLUDP packet processing.", | ||
441 | "No effect if packet processing has already stopped.\n" | ||
442 | + "in - stop inbound processing.\n" | ||
443 | + "out - stop outbound processing.\n" | ||
444 | + "all - stop in and outbound processing.\n", | ||
445 | HandleStopCommand); | ||
446 | |||
447 | MainConsole.Instance.Commands.AddCommand( | ||
448 | "Debug", | ||
449 | false, | ||
450 | "debug lludp pool", | ||
451 | "debug lludp pool <on|off>", | ||
452 | "Turn object pooling within the lludp component on or off.", | ||
453 | HandlePoolCommand); | ||
454 | |||
455 | MainConsole.Instance.Commands.AddCommand( | ||
456 | "Debug", | ||
457 | false, | ||
458 | "debug lludp status", | ||
459 | "debug lludp status", | ||
460 | "Return status of LLUDP packet processing.", | ||
461 | HandleStatusCommand); | ||
462 | } | ||
463 | |||
464 | private void HandleStartCommand(string module, string[] args) | ||
465 | { | ||
466 | if (args.Length != 4) | ||
467 | { | ||
468 | MainConsole.Instance.Output("Usage: debug lludp start <in|out|all>"); | ||
469 | return; | ||
470 | } | ||
471 | |||
472 | string subCommand = args[3]; | ||
473 | |||
474 | if (subCommand == "in" || subCommand == "all") | ||
475 | StartInbound(); | ||
476 | |||
477 | if (subCommand == "out" || subCommand == "all") | ||
478 | StartOutbound(); | ||
479 | } | ||
480 | |||
481 | private void HandleStopCommand(string module, string[] args) | ||
482 | { | ||
483 | if (args.Length != 4) | ||
484 | { | ||
485 | MainConsole.Instance.Output("Usage: debug lludp stop <in|out|all>"); | ||
486 | return; | ||
487 | } | ||
488 | |||
489 | string subCommand = args[3]; | ||
490 | |||
491 | if (subCommand == "in" || subCommand == "all") | ||
492 | StopInbound(); | ||
493 | |||
494 | if (subCommand == "out" || subCommand == "all") | ||
495 | StopOutbound(); | ||
496 | } | ||
497 | |||
498 | private void HandlePoolCommand(string module, string[] args) | ||
499 | { | ||
500 | if (args.Length != 4) | ||
501 | { | ||
502 | MainConsole.Instance.Output("Usage: debug lludp pool <on|off>"); | ||
503 | return; | ||
504 | } | ||
505 | |||
506 | string enabled = args[3]; | ||
507 | |||
508 | if (enabled == "on") | ||
509 | { | ||
510 | if (EnablePools()) | ||
511 | MainConsole.Instance.OutputFormat("Packet pools enabled on {0}", m_scene.Name); | ||
512 | } | ||
513 | else if (enabled == "off") | ||
514 | { | ||
515 | if (DisablePools()) | ||
516 | MainConsole.Instance.OutputFormat("Packet pools disabled on {0}", m_scene.Name); | ||
517 | } | ||
518 | else | ||
519 | { | ||
520 | MainConsole.Instance.Output("Usage: debug lludp pool <on|off>"); | ||
521 | } | ||
522 | } | ||
523 | |||
524 | private void HandleStatusCommand(string module, string[] args) | ||
525 | { | ||
526 | MainConsole.Instance.OutputFormat( | ||
527 | "IN LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningInbound ? "enabled" : "disabled"); | ||
528 | |||
529 | MainConsole.Instance.OutputFormat( | ||
530 | "OUT LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningOutbound ? "enabled" : "disabled"); | ||
531 | |||
532 | MainConsole.Instance.OutputFormat("LLUDP pools in {0} are {1}", m_scene.Name, UsePools ? "on" : "off"); | ||
533 | } | 336 | } |
534 | 337 | ||
535 | public bool HandlesRegion(Location x) | 338 | public bool HandlesRegion(Location x) |
@@ -613,8 +416,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
613 | byte[] data = packet.ToBytes(); | 416 | byte[] data = packet.ToBytes(); |
614 | SendPacketData(udpClient, data, packet.Type, category, method); | 417 | SendPacketData(udpClient, data, packet.Type, category, method); |
615 | } | 418 | } |
616 | |||
617 | PacketPool.Instance.ReturnPacket(packet); | ||
618 | } | 419 | } |
619 | 420 | ||
620 | /// <summary> | 421 | /// <summary> |
@@ -899,7 +700,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
899 | LLUDPClient udpClient = null; | 700 | LLUDPClient udpClient = null; |
900 | Packet packet = null; | 701 | Packet packet = null; |
901 | int packetEnd = buffer.DataLength - 1; | 702 | int packetEnd = buffer.DataLength - 1; |
902 | IPEndPoint endPoint = (IPEndPoint)buffer.RemoteEndPoint; | 703 | IPEndPoint address = (IPEndPoint)buffer.RemoteEndPoint; |
903 | 704 | ||
904 | #region Decoding | 705 | #region Decoding |
905 | 706 | ||
@@ -909,7 +710,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
909 | // "[LLUDPSERVER]: Dropping undersized packet with {0} bytes received from {1} in {2}", | 710 | // "[LLUDPSERVER]: Dropping undersized packet with {0} bytes received from {1} in {2}", |
910 | // buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName); | 711 | // buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName); |
911 | 712 | ||
912 | return; // Drop undersized packet | 713 | return; // Drop undersizd packet |
913 | } | 714 | } |
914 | 715 | ||
915 | int headerLen = 7; | 716 | int headerLen = 7; |
@@ -932,13 +733,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
932 | 733 | ||
933 | try | 734 | try |
934 | { | 735 | { |
935 | // packet = Packet.BuildPacket(buffer.Data, ref packetEnd, | 736 | packet = Packet.BuildPacket(buffer.Data, ref packetEnd, |
936 | // // Only allocate a buffer for zerodecoding if the packet is zerocoded | ||
937 | // ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); | ||
938 | // If OpenSimUDPBase.UsePool == true (which is currently separate from the PacketPool) then we | ||
939 | // assume that packet construction does not retain a reference to byte[] buffer.Data (instead, all | ||
940 | // bytes are copied out). | ||
941 | packet = PacketPool.Instance.GetPacket(buffer.Data, ref packetEnd, | ||
942 | // Only allocate a buffer for zerodecoding if the packet is zerocoded | 737 | // Only allocate a buffer for zerodecoding if the packet is zerocoded |
943 | ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); | 738 | ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); |
944 | } | 739 | } |
@@ -953,13 +748,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
953 | 748 | ||
954 | return; // Drop short packet | 749 | return; // Drop short packet |
955 | } | 750 | } |
956 | catch (Exception e) | 751 | catch(Exception e) |
957 | { | 752 | { |
958 | if (m_malformedCount < 100) | 753 | if (m_malformedCount < 100) |
959 | m_log.DebugFormat("[LLUDPSERVER]: Dropped malformed packet: " + e.ToString()); | 754 | m_log.DebugFormat("[LLUDPSERVER]: Dropped malformed packet: " + e.ToString()); |
960 | |||
961 | m_malformedCount++; | 755 | m_malformedCount++; |
962 | |||
963 | if ((m_malformedCount % 100000) == 0) | 756 | if ((m_malformedCount % 100000) == 0) |
964 | m_log.DebugFormat("[LLUDPSERVER]: Received {0} malformed packets so far, probable network attack.", m_malformedCount); | 757 | m_log.DebugFormat("[LLUDPSERVER]: Received {0} malformed packets so far, probable network attack.", m_malformedCount); |
965 | } | 758 | } |
@@ -979,7 +772,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
979 | 772 | ||
980 | // If there is already a client for this endpoint, don't process UseCircuitCode | 773 | // If there is already a client for this endpoint, don't process UseCircuitCode |
981 | IClientAPI client = null; | 774 | IClientAPI client = null; |
982 | if (!m_scene.TryGetClient(endPoint, out client) || !(client is LLClientView)) | 775 | if (!m_scene.TryGetClient(address, out client)) |
983 | { | 776 | { |
984 | // UseCircuitCode handling | 777 | // UseCircuitCode handling |
985 | if (packet.Type == PacketType.UseCircuitCode) | 778 | if (packet.Type == PacketType.UseCircuitCode) |
@@ -987,15 +780,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
987 | // And if there is a UseCircuitCode pending, also drop it | 780 | // And if there is a UseCircuitCode pending, also drop it |
988 | lock (m_pendingCache) | 781 | lock (m_pendingCache) |
989 | { | 782 | { |
990 | if (m_pendingCache.Contains(endPoint)) | 783 | if (m_pendingCache.Contains(address)) |
991 | return; | 784 | return; |
992 | 785 | ||
993 | m_pendingCache.AddOrUpdate(endPoint, new Queue<UDPPacketBuffer>(), 60); | 786 | m_pendingCache.AddOrUpdate(address, new Queue<UDPPacketBuffer>(), 60); |
994 | } | 787 | } |
995 | 788 | ||
996 | // We need to copy the endpoint so that it doesn't get changed when another thread reuses the | 789 | object[] array = new object[] { buffer, packet }; |
997 | // buffer. | ||
998 | object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; | ||
999 | 790 | ||
1000 | Util.FireAndForget(HandleUseCircuitCode, array); | 791 | Util.FireAndForget(HandleUseCircuitCode, array); |
1001 | 792 | ||
@@ -1007,7 +798,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1007 | lock (m_pendingCache) | 798 | lock (m_pendingCache) |
1008 | { | 799 | { |
1009 | Queue<UDPPacketBuffer> queue; | 800 | Queue<UDPPacketBuffer> queue; |
1010 | if (m_pendingCache.TryGetValue(endPoint, out queue)) | 801 | if (m_pendingCache.TryGetValue(address, out queue)) |
1011 | { | 802 | { |
1012 | //m_log.DebugFormat("[LLUDPSERVER]: Enqueued a {0} packet into the pending queue", packet.Type); | 803 | //m_log.DebugFormat("[LLUDPSERVER]: Enqueued a {0} packet into the pending queue", packet.Type); |
1013 | queue.Enqueue(buffer); | 804 | queue.Enqueue(buffer); |
@@ -1043,10 +834,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1043 | // Handle appended ACKs | 834 | // Handle appended ACKs |
1044 | if (packet.Header.AppendedAcks && packet.Header.AckList != null) | 835 | if (packet.Header.AppendedAcks && packet.Header.AckList != null) |
1045 | { | 836 | { |
1046 | // m_log.DebugFormat( | ||
1047 | // "[LLUDPSERVER]: Handling {0} appended acks from {1} in {2}", | ||
1048 | // packet.Header.AckList.Length, client.Name, m_scene.Name); | ||
1049 | |||
1050 | for (int i = 0; i < packet.Header.AckList.Length; i++) | 837 | for (int i = 0; i < packet.Header.AckList.Length; i++) |
1051 | udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent); | 838 | udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent); |
1052 | } | 839 | } |
@@ -1056,10 +843,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1056 | { | 843 | { |
1057 | PacketAckPacket ackPacket = (PacketAckPacket)packet; | 844 | PacketAckPacket ackPacket = (PacketAckPacket)packet; |
1058 | 845 | ||
1059 | // m_log.DebugFormat( | ||
1060 | // "[LLUDPSERVER]: Handling {0} packet acks for {1} in {2}", | ||
1061 | // ackPacket.Packets.Length, client.Name, m_scene.Name); | ||
1062 | |||
1063 | for (int i = 0; i < ackPacket.Packets.Length; i++) | 846 | for (int i = 0; i < ackPacket.Packets.Length; i++) |
1064 | udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent); | 847 | udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent); |
1065 | 848 | ||
@@ -1073,10 +856,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1073 | 856 | ||
1074 | if (packet.Header.Reliable) | 857 | if (packet.Header.Reliable) |
1075 | { | 858 | { |
1076 | // m_log.DebugFormat( | ||
1077 | // "[LLUDPSERVER]: Adding ack request for {0} {1} from {2} in {3}", | ||
1078 | // packet.Type, packet.Header.Sequence, client.Name, m_scene.Name); | ||
1079 | |||
1080 | udpClient.PendingAcks.Enqueue(packet.Header.Sequence); | 859 | udpClient.PendingAcks.Enqueue(packet.Header.Sequence); |
1081 | 860 | ||
1082 | // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out, | 861 | // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out, |
@@ -1123,8 +902,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1123 | 902 | ||
1124 | if (packet.Type == PacketType.StartPingCheck) | 903 | if (packet.Type == PacketType.StartPingCheck) |
1125 | { | 904 | { |
1126 | // m_log.DebugFormat("[LLUDPSERVER]: Handling ping from {0} in {1}", client.Name, m_scene.Name); | ||
1127 | |||
1128 | // We don't need to do anything else with ping checks | 905 | // We don't need to do anything else with ping checks |
1129 | StartPingCheckPacket startPing = (StartPingCheckPacket)packet; | 906 | StartPingCheckPacket startPing = (StartPingCheckPacket)packet; |
1130 | CompletePing(udpClient, startPing.PingID.PingID); | 907 | CompletePing(udpClient, startPing.PingID.PingID); |
@@ -1144,25 +921,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1144 | 921 | ||
1145 | #endregion Ping Check Handling | 922 | #endregion Ping Check Handling |
1146 | 923 | ||
1147 | IncomingPacket incomingPacket; | ||
1148 | |||
1149 | // Inbox insertion | 924 | // Inbox insertion |
1150 | if (UsePools) | 925 | if (packet.Type == PacketType.AgentUpdate || |
1151 | { | 926 | packet.Type == PacketType.ChatFromViewer) |
1152 | incomingPacket = m_incomingPacketPool.GetObject(); | 927 | packetInbox.EnqueueHigh(new IncomingPacket((LLClientView)client, packet)); |
1153 | incomingPacket.Client = (LLClientView)client; | ||
1154 | incomingPacket.Packet = packet; | ||
1155 | } | ||
1156 | else | ||
1157 | { | ||
1158 | incomingPacket = new IncomingPacket((LLClientView)client, packet); | ||
1159 | } | ||
1160 | |||
1161 | if (incomingPacket.Packet.Type == PacketType.AgentUpdate || | ||
1162 | incomingPacket.Packet.Type == PacketType.ChatFromViewer) | ||
1163 | packetInbox.EnqueueHigh(incomingPacket); | ||
1164 | else | 928 | else |
1165 | packetInbox.EnqueueLow(incomingPacket); | 929 | packetInbox.EnqueueLow(new IncomingPacket((LLClientView)client, packet)); |
930 | // packetInbox.Enqueue(new IncomingPacket((LLClientView)client, packet)); | ||
1166 | } | 931 | } |
1167 | 932 | ||
1168 | #region BinaryStats | 933 | #region BinaryStats |
@@ -1248,19 +1013,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1248 | 1013 | ||
1249 | private void HandleUseCircuitCode(object o) | 1014 | private void HandleUseCircuitCode(object o) |
1250 | { | 1015 | { |
1251 | IPEndPoint endPoint = null; | 1016 | IPEndPoint remoteEndPoint = null; |
1252 | IClientAPI client = null; | 1017 | IClientAPI client = null; |
1253 | 1018 | ||
1254 | try | 1019 | try |
1255 | { | 1020 | { |
1256 | // DateTime startTime = DateTime.Now; | 1021 | // DateTime startTime = DateTime.Now; |
1257 | object[] array = (object[])o; | 1022 | object[] array = (object[])o; |
1258 | endPoint = (IPEndPoint)array[0]; | 1023 | UDPPacketBuffer buffer = (UDPPacketBuffer)array[0]; |
1259 | UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1]; | 1024 | UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1]; |
1260 | 1025 | ||
1261 | m_log.DebugFormat( | 1026 | m_log.DebugFormat( |
1262 | "[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} to {1} from IP {2}", | 1027 | "[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} to {1} from IP {2}", |
1263 | uccp.CircuitCode.Code, m_scene.RegionInfo.RegionName, endPoint); | 1028 | uccp.CircuitCode.Code, m_scene.RegionInfo.RegionName, buffer.RemoteEndPoint); |
1029 | |||
1030 | remoteEndPoint = (IPEndPoint)buffer.RemoteEndPoint; | ||
1264 | 1031 | ||
1265 | AuthenticateResponse sessionInfo; | 1032 | AuthenticateResponse sessionInfo; |
1266 | if (IsClientAuthorized(uccp, out sessionInfo)) | 1033 | if (IsClientAuthorized(uccp, out sessionInfo)) |
@@ -1271,13 +1038,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1271 | uccp.CircuitCode.Code, | 1038 | uccp.CircuitCode.Code, |
1272 | uccp.CircuitCode.ID, | 1039 | uccp.CircuitCode.ID, |
1273 | uccp.CircuitCode.SessionID, | 1040 | uccp.CircuitCode.SessionID, |
1274 | endPoint, | 1041 | remoteEndPoint, |
1275 | sessionInfo); | 1042 | sessionInfo); |
1276 | 1043 | ||
1277 | // Send ack straight away to let the viewer know that the connection is active. | 1044 | // Send ack straight away to let the viewer know that the connection is active. |
1278 | // The client will be null if it already exists (e.g. if on a region crossing the client sends a use | 1045 | // The client will be null if it already exists (e.g. if on a region crossing the client sends a use |
1279 | // circuit code to the existing child agent. This is not particularly obvious. | 1046 | // circuit code to the existing child agent. This is not particularly obvious. |
1280 | SendAckImmediate(endPoint, uccp.Header.Sequence); | 1047 | SendAckImmediate(remoteEndPoint, uccp.Header.Sequence); |
1281 | 1048 | ||
1282 | // We only want to send initial data to new clients, not ones which are being converted from child to root. | 1049 | // We only want to send initial data to new clients, not ones which are being converted from child to root. |
1283 | if (client != null) | 1050 | if (client != null) |
@@ -1291,12 +1058,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1291 | 1058 | ||
1292 | lock (m_pendingCache) | 1059 | lock (m_pendingCache) |
1293 | { | 1060 | { |
1294 | if (!m_pendingCache.TryGetValue(endPoint, out queue)) | 1061 | if (!m_pendingCache.TryGetValue(remoteEndPoint, out queue)) |
1295 | { | 1062 | { |
1296 | m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present"); | 1063 | m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present"); |
1297 | return; | 1064 | return; |
1298 | } | 1065 | } |
1299 | m_pendingCache.Remove(endPoint); | 1066 | m_pendingCache.Remove(remoteEndPoint); |
1300 | } | 1067 | } |
1301 | 1068 | ||
1302 | m_log.DebugFormat("[LLUDPSERVER]: Client created, processing pending queue, {0} entries", queue.Count); | 1069 | m_log.DebugFormat("[LLUDPSERVER]: Client created, processing pending queue, {0} entries", queue.Count); |
@@ -1314,9 +1081,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1314 | // Don't create clients for unauthorized requesters. | 1081 | // Don't create clients for unauthorized requesters. |
1315 | m_log.WarnFormat( | 1082 | m_log.WarnFormat( |
1316 | "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", | 1083 | "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", |
1317 | uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint); | 1084 | uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, remoteEndPoint); |
1318 | lock (m_pendingCache) | 1085 | lock (m_pendingCache) |
1319 | m_pendingCache.Remove(endPoint); | 1086 | m_pendingCache.Remove(remoteEndPoint); |
1320 | } | 1087 | } |
1321 | 1088 | ||
1322 | // m_log.DebugFormat( | 1089 | // m_log.DebugFormat( |
@@ -1328,7 +1095,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1328 | { | 1095 | { |
1329 | m_log.ErrorFormat( | 1096 | m_log.ErrorFormat( |
1330 | "[LLUDPSERVER]: UseCircuitCode handling from endpoint {0}, client {1} {2} failed. Exception {3}{4}", | 1097 | "[LLUDPSERVER]: UseCircuitCode handling from endpoint {0}, client {1} {2} failed. Exception {3}{4}", |
1331 | endPoint != null ? endPoint.ToString() : "n/a", | 1098 | remoteEndPoint != null ? remoteEndPoint.ToString() : "n/a", |
1332 | client != null ? client.Name : "unknown", | 1099 | client != null ? client.Name : "unknown", |
1333 | client != null ? client.AgentId.ToString() : "unknown", | 1100 | client != null ? client.AgentId.ToString() : "unknown", |
1334 | e.Message, | 1101 | e.Message, |
@@ -1393,20 +1160,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1393 | { | 1160 | { |
1394 | IClientAPI client = null; | 1161 | IClientAPI client = null; |
1395 | 1162 | ||
1396 | // We currently synchronize this code across the whole scene to avoid issues such as | 1163 | // In priciple there shouldn't be more than one thread here, ever. |
1397 | // http://opensimulator.org/mantis/view.php?id=5365 However, once locking per agent circuit can be done | 1164 | // But in case that happens, we need to synchronize this piece of code |
1398 | // consistently, this lock could probably be removed. | 1165 | // because it's too important |
1399 | lock (this) | 1166 | lock (this) |
1400 | { | 1167 | { |
1401 | if (!m_scene.TryGetClient(agentID, out client)) | 1168 | if (!m_scene.TryGetClient(agentID, out client)) |
1402 | { | 1169 | { |
1403 | LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); | 1170 | LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); |
1404 | 1171 | ||
1405 | client = new LLClientView(m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); | 1172 | client = new LLClientView(m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); |
1406 | client.OnLogout += LogoutHandler; | 1173 | client.OnLogout += LogoutHandler; |
1407 | 1174 | ||
1408 | ((LLClientView)client).DisableFacelights = m_disableFacelights; | 1175 | ((LLClientView)client).DisableFacelights = m_disableFacelights; |
1409 | 1176 | ||
1410 | client.Start(); | 1177 | client.Start(); |
1411 | } | 1178 | } |
1412 | } | 1179 | } |
@@ -1445,7 +1212,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1445 | // on to en-US to avoid number parsing issues | 1212 | // on to en-US to avoid number parsing issues |
1446 | Culture.SetCurrentCulture(); | 1213 | Culture.SetCurrentCulture(); |
1447 | 1214 | ||
1448 | while (IsRunningInbound) | 1215 | while (base.IsRunning) |
1449 | { | 1216 | { |
1450 | m_scene.ThreadAlive(1); | 1217 | m_scene.ThreadAlive(1); |
1451 | try | 1218 | try |
@@ -1461,12 +1228,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1461 | } | 1228 | } |
1462 | 1229 | ||
1463 | if (packetInbox.Dequeue(100, ref incomingPacket)) | 1230 | if (packetInbox.Dequeue(100, ref incomingPacket)) |
1464 | { | ||
1465 | ProcessInPacket(incomingPacket);//, incomingPacket); Util.FireAndForget(ProcessInPacket, incomingPacket); | 1231 | ProcessInPacket(incomingPacket);//, incomingPacket); Util.FireAndForget(ProcessInPacket, incomingPacket); |
1466 | |||
1467 | if (UsePools) | ||
1468 | m_incomingPacketPool.ReturnObject(incomingPacket); | ||
1469 | } | ||
1470 | } | 1232 | } |
1471 | catch (Exception ex) | 1233 | catch (Exception ex) |
1472 | { | 1234 | { |
@@ -1493,7 +1255,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1493 | // Action generic every round | 1255 | // Action generic every round |
1494 | Action<IClientAPI> clientPacketHandler = ClientOutgoingPacketHandler; | 1256 | Action<IClientAPI> clientPacketHandler = ClientOutgoingPacketHandler; |
1495 | 1257 | ||
1496 | while (base.IsRunningOutbound) | 1258 | while (base.IsRunning) |
1497 | { | 1259 | { |
1498 | m_scene.ThreadAlive(2); | 1260 | m_scene.ThreadAlive(2); |
1499 | try | 1261 | try |
@@ -1761,7 +1523,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1761 | if (!client.IsLoggingOut) | 1523 | if (!client.IsLoggingOut) |
1762 | { | 1524 | { |
1763 | client.IsLoggingOut = true; | 1525 | client.IsLoggingOut = true; |
1764 | client.Close(false, false); | 1526 | client.Close(false); |
1765 | } | 1527 | } |
1766 | } | 1528 | } |
1767 | } | 1529 | } |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs index 8bd3461..cfe7c9d 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs | |||
@@ -30,8 +30,6 @@ using System.Net; | |||
30 | using System.Net.Sockets; | 30 | using System.Net.Sockets; |
31 | using System.Threading; | 31 | using System.Threading; |
32 | using log4net; | 32 | using log4net; |
33 | using OpenSim.Framework; | ||
34 | using OpenSim.Framework.Monitoring; | ||
35 | 33 | ||
36 | namespace OpenMetaverse | 34 | namespace OpenMetaverse |
37 | { | 35 | { |
@@ -60,31 +58,17 @@ namespace OpenMetaverse | |||
60 | /// <summary>Flag to process packets asynchronously or synchronously</summary> | 58 | /// <summary>Flag to process packets asynchronously or synchronously</summary> |
61 | private bool m_asyncPacketHandling; | 59 | private bool m_asyncPacketHandling; |
62 | 60 | ||
63 | /// <summary> | 61 | /// <summary>The all important shutdown flag</summary> |
64 | /// Pool to use for handling data. May be null if UsePools = false; | 62 | private volatile bool m_shutdownFlag = true; |
65 | /// </summary> | ||
66 | protected OpenSim.Framework.Pool<UDPPacketBuffer> m_pool; | ||
67 | |||
68 | /// <summary> | ||
69 | /// Are we to use object pool(s) to reduce memory churn when receiving data? | ||
70 | /// </summary> | ||
71 | public bool UsePools { get; protected set; } | ||
72 | |||
73 | /// <summary>Returns true if the server is currently listening for inbound packets, otherwise false</summary> | ||
74 | public bool IsRunningInbound { get; private set; } | ||
75 | 63 | ||
76 | /// <summary>Returns true if the server is currently sending outbound packets, otherwise false</summary> | 64 | /// <summary>Returns true if the server is currently listening, otherwise false</summary> |
77 | /// <remarks>If IsRunningOut = false, then any request to send a packet is simply dropped.</remarks> | 65 | public bool IsRunning { get { return !m_shutdownFlag; } } |
78 | public bool IsRunningOutbound { get; private set; } | ||
79 | |||
80 | private Stat m_poolCountStat; | ||
81 | 66 | ||
82 | /// <summary> | 67 | /// <summary> |
83 | /// Default constructor | 68 | /// Default constructor |
84 | /// </summary> | 69 | /// </summary> |
85 | /// <param name="bindAddress">Local IP address to bind the server to</param> | 70 | /// <param name="bindAddress">Local IP address to bind the server to</param> |
86 | /// <param name="port">Port to listening for incoming UDP packets on</param> | 71 | /// <param name="port">Port to listening for incoming UDP packets on</param> |
87 | /// /// <param name="usePool">Are we to use an object pool to get objects for handing inbound data?</param> | ||
88 | public OpenSimUDPBase(IPAddress bindAddress, int port) | 72 | public OpenSimUDPBase(IPAddress bindAddress, int port) |
89 | { | 73 | { |
90 | m_localBindAddress = bindAddress; | 74 | m_localBindAddress = bindAddress; |
@@ -92,7 +76,7 @@ namespace OpenMetaverse | |||
92 | } | 76 | } |
93 | 77 | ||
94 | /// <summary> | 78 | /// <summary> |
95 | /// Start inbound UDP packet handling. | 79 | /// Start the UDP server |
96 | /// </summary> | 80 | /// </summary> |
97 | /// <param name="recvBufferSize">The size of the receive buffer for | 81 | /// <param name="recvBufferSize">The size of the receive buffer for |
98 | /// the UDP socket. This value is passed up to the operating system | 82 | /// the UDP socket. This value is passed up to the operating system |
@@ -107,11 +91,11 @@ namespace OpenMetaverse | |||
107 | /// manner (not throwing an exception when the remote side resets the | 91 | /// manner (not throwing an exception when the remote side resets the |
108 | /// connection). This call is ignored on Mono where the flag is not | 92 | /// connection). This call is ignored on Mono where the flag is not |
109 | /// necessary</remarks> | 93 | /// necessary</remarks> |
110 | public void StartInbound(int recvBufferSize, bool asyncPacketHandling) | 94 | public void Start(int recvBufferSize, bool asyncPacketHandling) |
111 | { | 95 | { |
112 | m_asyncPacketHandling = asyncPacketHandling; | 96 | m_asyncPacketHandling = asyncPacketHandling; |
113 | 97 | ||
114 | if (!IsRunningInbound) | 98 | if (m_shutdownFlag) |
115 | { | 99 | { |
116 | const int SIO_UDP_CONNRESET = -1744830452; | 100 | const int SIO_UDP_CONNRESET = -1744830452; |
117 | 101 | ||
@@ -139,7 +123,8 @@ namespace OpenMetaverse | |||
139 | 123 | ||
140 | m_udpSocket.Bind(ipep); | 124 | m_udpSocket.Bind(ipep); |
141 | 125 | ||
142 | IsRunningInbound = true; | 126 | // we're not shutting down, we're starting up |
127 | m_shutdownFlag = false; | ||
143 | 128 | ||
144 | // kick off an async receive. The Start() method will return, the | 129 | // kick off an async receive. The Start() method will return, the |
145 | // actual receives will occur asynchronously and will be caught in | 130 | // actual receives will occur asynchronously and will be caught in |
@@ -149,84 +134,28 @@ namespace OpenMetaverse | |||
149 | } | 134 | } |
150 | 135 | ||
151 | /// <summary> | 136 | /// <summary> |
152 | /// Start outbound UDP packet handling. | 137 | /// Stops the UDP server |
153 | /// </summary> | 138 | /// </summary> |
154 | public void StartOutbound() | 139 | public void Stop() |
155 | { | ||
156 | IsRunningOutbound = true; | ||
157 | } | ||
158 | |||
159 | public void StopInbound() | ||
160 | { | 140 | { |
161 | if (IsRunningInbound) | 141 | if (!m_shutdownFlag) |
162 | { | 142 | { |
163 | // wait indefinitely for a writer lock. Once this is called, the .NET runtime | 143 | // wait indefinitely for a writer lock. Once this is called, the .NET runtime |
164 | // will deny any more reader locks, in effect blocking all other send/receive | 144 | // will deny any more reader locks, in effect blocking all other send/receive |
165 | // threads. Once we have the lock, we set IsRunningInbound = false to inform the other | 145 | // threads. Once we have the lock, we set shutdownFlag to inform the other |
166 | // threads that the socket is closed. | 146 | // threads that the socket is closed. |
167 | IsRunningInbound = false; | 147 | m_shutdownFlag = true; |
168 | m_udpSocket.Close(); | 148 | m_udpSocket.Close(); |
169 | } | 149 | } |
170 | } | 150 | } |
171 | 151 | ||
172 | public void StopOutbound() | ||
173 | { | ||
174 | IsRunningOutbound = false; | ||
175 | } | ||
176 | |||
177 | protected virtual bool EnablePools() | ||
178 | { | ||
179 | if (!UsePools) | ||
180 | { | ||
181 | m_pool = new Pool<UDPPacketBuffer>(() => new UDPPacketBuffer(), 500); | ||
182 | |||
183 | m_poolCountStat | ||
184 | = new Stat( | ||
185 | "UDPPacketBufferPoolCount", | ||
186 | "Objects within the UDPPacketBuffer pool", | ||
187 | "The number of objects currently stored within the UDPPacketBuffer pool", | ||
188 | "", | ||
189 | "clientstack", | ||
190 | "packetpool", | ||
191 | StatType.Pull, | ||
192 | stat => stat.Value = m_pool.Count, | ||
193 | StatVerbosity.Debug); | ||
194 | |||
195 | StatsManager.RegisterStat(m_poolCountStat); | ||
196 | |||
197 | UsePools = true; | ||
198 | |||
199 | return true; | ||
200 | } | ||
201 | |||
202 | return false; | ||
203 | } | ||
204 | |||
205 | protected virtual bool DisablePools() | ||
206 | { | ||
207 | if (UsePools) | ||
208 | { | ||
209 | UsePools = false; | ||
210 | StatsManager.DeregisterStat(m_poolCountStat); | ||
211 | |||
212 | // We won't null out the pool to avoid a race condition with code that may be in the middle of using it. | ||
213 | |||
214 | return true; | ||
215 | } | ||
216 | |||
217 | return false; | ||
218 | } | ||
219 | |||
220 | private void AsyncBeginReceive() | 152 | private void AsyncBeginReceive() |
221 | { | 153 | { |
222 | UDPPacketBuffer buf; | 154 | // allocate a packet buffer |
223 | 155 | //WrappedObject<UDPPacketBuffer> wrappedBuffer = Pool.CheckOut(); | |
224 | if (UsePools) | 156 | UDPPacketBuffer buf = new UDPPacketBuffer(); |
225 | buf = m_pool.GetObject(); | ||
226 | else | ||
227 | buf = new UDPPacketBuffer(); | ||
228 | 157 | ||
229 | if (IsRunningInbound) | 158 | if (!m_shutdownFlag) |
230 | { | 159 | { |
231 | try | 160 | try |
232 | { | 161 | { |
@@ -279,7 +208,7 @@ namespace OpenMetaverse | |||
279 | { | 208 | { |
280 | // Asynchronous receive operations will complete here through the call | 209 | // Asynchronous receive operations will complete here through the call |
281 | // to AsyncBeginReceive | 210 | // to AsyncBeginReceive |
282 | if (IsRunningInbound) | 211 | if (!m_shutdownFlag) |
283 | { | 212 | { |
284 | // Asynchronous mode will start another receive before the | 213 | // Asynchronous mode will start another receive before the |
285 | // callback for this packet is even fired. Very parallel :-) | 214 | // callback for this packet is even fired. Very parallel :-) |
@@ -288,6 +217,8 @@ namespace OpenMetaverse | |||
288 | 217 | ||
289 | // get the buffer that was created in AsyncBeginReceive | 218 | // get the buffer that was created in AsyncBeginReceive |
290 | // this is the received data | 219 | // this is the received data |
220 | //WrappedObject<UDPPacketBuffer> wrappedBuffer = (WrappedObject<UDPPacketBuffer>)iar.AsyncState; | ||
221 | //UDPPacketBuffer buffer = wrappedBuffer.Instance; | ||
291 | UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState; | 222 | UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState; |
292 | 223 | ||
293 | try | 224 | try |
@@ -304,8 +235,7 @@ namespace OpenMetaverse | |||
304 | catch (ObjectDisposedException) { } | 235 | catch (ObjectDisposedException) { } |
305 | finally | 236 | finally |
306 | { | 237 | { |
307 | if (UsePools) | 238 | //wrappedBuffer.Dispose(); |
308 | m_pool.ReturnObject(buffer); | ||
309 | 239 | ||
310 | // Synchronous mode waits until the packet callback completes | 240 | // Synchronous mode waits until the packet callback completes |
311 | // before starting the receive to fetch another packet | 241 | // before starting the receive to fetch another packet |
@@ -318,7 +248,7 @@ namespace OpenMetaverse | |||
318 | 248 | ||
319 | public void AsyncBeginSend(UDPPacketBuffer buf) | 249 | public void AsyncBeginSend(UDPPacketBuffer buf) |
320 | { | 250 | { |
321 | if (IsRunningOutbound) | 251 | if (!m_shutdownFlag) |
322 | { | 252 | { |
323 | try | 253 | try |
324 | { | 254 | { |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs index 556df30..109a8e1 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 : OpenSimTestCase | 46 | public class BasicCircuitTests |
47 | { | 47 | { |
48 | private Scene m_scene; | 48 | private Scene m_scene; |
49 | private TestLLUDPServer m_udpServer; | 49 | private TestLLUDPServer m_udpServer; |
@@ -65,9 +65,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests | |||
65 | } | 65 | } |
66 | 66 | ||
67 | [SetUp] | 67 | [SetUp] |
68 | public override void SetUp() | 68 | public void SetUp() |
69 | { | 69 | { |
70 | base.SetUp(); | ||
71 | m_scene = new SceneHelpers().SetupScene(); | 70 | m_scene = new SceneHelpers().SetupScene(); |
72 | } | 71 | } |
73 | 72 | ||
@@ -144,7 +143,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests | |||
144 | public void TestAddClient() | 143 | public void TestAddClient() |
145 | { | 144 | { |
146 | TestHelpers.InMethod(); | 145 | TestHelpers.InMethod(); |
147 | // TestHelpers.EnableLogging(); | 146 | // XmlConfigurator.Configure(); |
148 | 147 | ||
149 | AddUdpServer(); | 148 | AddUdpServer(); |
150 | 149 | ||
diff --git a/OpenSim/Region/ClientStack/RegionApplicationBase.cs b/OpenSim/Region/ClientStack/RegionApplicationBase.cs index 853b72d..4672f8a 100644 --- a/OpenSim/Region/ClientStack/RegionApplicationBase.cs +++ b/OpenSim/Region/ClientStack/RegionApplicationBase.cs | |||
@@ -76,7 +76,7 @@ namespace OpenSim.Region.ClientStack | |||
76 | 76 | ||
77 | protected override void StartupSpecific() | 77 | protected override void StartupSpecific() |
78 | { | 78 | { |
79 | SceneManager = SceneManager.Instance; | 79 | SceneManager = new SceneManager(); |
80 | m_clientStackManager = CreateClientStackManager(); | 80 | m_clientStackManager = CreateClientStackManager(); |
81 | 81 | ||
82 | Initialize(); | 82 | Initialize(); |
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs index da1ff2e..8a4fd8f 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs | |||
@@ -57,36 +57,39 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
57 | } | 57 | } |
58 | 58 | ||
59 | /// <summary> | 59 | /// <summary> |
60 | /// Return the xfer uploader for the given transaction. | 60 | /// Return a xfer uploader if one does not already exist. |
61 | /// </summary> | 61 | /// </summary> |
62 | /// <remarks> | ||
63 | /// If an uploader does not already exist for this transaction then it is created, otherwise the existing | ||
64 | /// uploader is returned. | ||
65 | /// </remarks> | ||
66 | /// <param name="transactionID"></param> | 62 | /// <param name="transactionID"></param> |
67 | /// <returns>The asset xfer uploader</returns> | 63 | /// <param name="assetID"> |
68 | public AssetXferUploader RequestXferUploader(UUID transactionID) | 64 | /// We must transfer the new asset ID into the uploader on creation, otherwise |
65 | /// we can see race conditions with other threads which can retrieve an item before it is updated with the new | ||
66 | /// asset id. | ||
67 | /// </param> | ||
68 | /// <returns> | ||
69 | /// The xfer uploader requested. Null if one is already in existence. | ||
70 | /// FIXME: This is a bizarre thing to do, and is probably meant to signal an error condition if multiple | ||
71 | /// transfers are made. Needs to be corrected. | ||
72 | /// </returns> | ||
73 | public AssetXferUploader RequestXferUploader(UUID transactionID, UUID assetID) | ||
69 | { | 74 | { |
70 | AssetXferUploader uploader; | ||
71 | |||
72 | lock (XferUploaders) | 75 | lock (XferUploaders) |
73 | { | 76 | { |
74 | if (!XferUploaders.ContainsKey(transactionID)) | 77 | if (!XferUploaders.ContainsKey(transactionID)) |
75 | { | 78 | { |
76 | uploader = new AssetXferUploader(this, m_Scene, transactionID, m_dumpAssetsToFile); | 79 | AssetXferUploader uploader = new AssetXferUploader(this, m_Scene, assetID, m_dumpAssetsToFile); |
77 | 80 | ||
78 | // m_log.DebugFormat( | 81 | // m_log.DebugFormat( |
79 | // "[AGENT ASSETS TRANSACTIONS]: Adding asset xfer uploader {0} since it didn't previously exist", transactionID); | 82 | // "[AGENT ASSETS TRANSACTIONS]: Adding asset xfer uploader {0} since it didn't previously exist", transactionID); |
80 | 83 | ||
81 | XferUploaders.Add(transactionID, uploader); | 84 | XferUploaders.Add(transactionID, uploader); |
82 | } | 85 | |
83 | else | 86 | return uploader; |
84 | { | ||
85 | uploader = XferUploaders[transactionID]; | ||
86 | } | 87 | } |
87 | } | 88 | } |
88 | 89 | ||
89 | return uploader; | 90 | m_log.WarnFormat("[AGENT ASSETS TRANSACTIONS]: Ignoring request for asset xfer uploader {0} since it already exists", transactionID); |
91 | |||
92 | return null; | ||
90 | } | 93 | } |
91 | 94 | ||
92 | public void HandleXfer(ulong xferID, uint packetID, byte[] data) | 95 | public void HandleXfer(ulong xferID, uint packetID, byte[] data) |
@@ -148,30 +151,117 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
148 | string description, string name, sbyte invType, | 151 | string description, string name, sbyte invType, |
149 | sbyte type, byte wearableType, uint nextOwnerMask) | 152 | sbyte type, byte wearableType, uint nextOwnerMask) |
150 | { | 153 | { |
151 | AssetXferUploader uploader = RequestXferUploader(transactionID); | 154 | AssetXferUploader uploader = null; |
155 | |||
156 | lock (XferUploaders) | ||
157 | { | ||
158 | if (XferUploaders.ContainsKey(transactionID)) | ||
159 | uploader = XferUploaders[transactionID]; | ||
160 | } | ||
152 | 161 | ||
153 | uploader.RequestCreateInventoryItem( | 162 | if (uploader != null) |
154 | remoteClient, folderID, callbackID, | 163 | { |
155 | description, name, invType, type, wearableType, nextOwnerMask); | 164 | uploader.RequestCreateInventoryItem( |
165 | remoteClient, transactionID, folderID, | ||
166 | callbackID, description, name, invType, type, | ||
167 | wearableType, nextOwnerMask); | ||
156 | 168 | ||
157 | return true; | 169 | return true; |
170 | } | ||
171 | |||
172 | return false; | ||
173 | } | ||
174 | |||
175 | /// <summary> | ||
176 | /// Get an uploaded asset. If the data is successfully retrieved, | ||
177 | /// the transaction will be removed. | ||
178 | /// </summary> | ||
179 | /// <param name="transactionID"></param> | ||
180 | /// <returns>The asset if the upload has completed, null if it has not.</returns> | ||
181 | private AssetBase GetTransactionAsset(UUID transactionID) | ||
182 | { | ||
183 | lock (XferUploaders) | ||
184 | { | ||
185 | if (XferUploaders.ContainsKey(transactionID)) | ||
186 | { | ||
187 | AssetXferUploader uploader = XferUploaders[transactionID]; | ||
188 | AssetBase asset = uploader.GetAssetData(); | ||
189 | RemoveXferUploader(transactionID); | ||
190 | |||
191 | return asset; | ||
192 | } | ||
193 | } | ||
194 | |||
195 | return null; | ||
158 | } | 196 | } |
159 | 197 | ||
160 | public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient, | 198 | public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient, |
161 | SceneObjectPart part, UUID transactionID, | 199 | SceneObjectPart part, UUID transactionID, |
162 | TaskInventoryItem item) | 200 | TaskInventoryItem item) |
163 | { | 201 | { |
164 | AssetXferUploader uploader = RequestXferUploader(transactionID); | 202 | AssetXferUploader uploader = null; |
203 | |||
204 | lock (XferUploaders) | ||
205 | { | ||
206 | if (XferUploaders.ContainsKey(transactionID)) | ||
207 | uploader = XferUploaders[transactionID]; | ||
208 | } | ||
209 | |||
210 | if (uploader != null) | ||
211 | { | ||
212 | AssetBase asset = GetTransactionAsset(transactionID); | ||
213 | |||
214 | // Only legacy viewers use this, and they prefer CAPS, which | ||
215 | // we have, so this really never runs. | ||
216 | // Allow it, but only for "safe" types. | ||
217 | if ((InventoryType)item.InvType != InventoryType.Notecard && | ||
218 | (InventoryType)item.InvType != InventoryType.LSL) | ||
219 | return; | ||
165 | 220 | ||
166 | uploader.RequestUpdateTaskInventoryItem(remoteClient, item); | 221 | if (asset != null) |
222 | { | ||
223 | // m_log.DebugFormat( | ||
224 | // "[AGENT ASSETS TRANSACTIONS]: Updating item {0} in {1} for transaction {2}", | ||
225 | // item.Name, part.Name, transactionID); | ||
226 | |||
227 | asset.FullID = UUID.Random(); | ||
228 | asset.Name = item.Name; | ||
229 | asset.Description = item.Description; | ||
230 | asset.Type = (sbyte)item.Type; | ||
231 | item.AssetID = asset.FullID; | ||
232 | |||
233 | m_Scene.AssetService.Store(asset); | ||
234 | } | ||
235 | } | ||
236 | else | ||
237 | { | ||
238 | m_log.ErrorFormat( | ||
239 | "[AGENT ASSET TRANSACTIONS]: Could not find uploader with transaction ID {0} when handling request to update task inventory item {1} in {2}", | ||
240 | transactionID, item.Name, part.Name); | ||
241 | } | ||
167 | } | 242 | } |
168 | 243 | ||
169 | public void RequestUpdateInventoryItem(IClientAPI remoteClient, | 244 | public void RequestUpdateInventoryItem(IClientAPI remoteClient, |
170 | UUID transactionID, InventoryItemBase item) | 245 | UUID transactionID, InventoryItemBase item) |
171 | { | 246 | { |
172 | AssetXferUploader uploader = RequestXferUploader(transactionID); | 247 | AssetXferUploader uploader = null; |
248 | |||
249 | lock (XferUploaders) | ||
250 | { | ||
251 | if (XferUploaders.ContainsKey(transactionID)) | ||
252 | uploader = XferUploaders[transactionID]; | ||
253 | } | ||
173 | 254 | ||
174 | uploader.RequestUpdateInventoryItem(remoteClient, item); | 255 | if (uploader != null) |
256 | { | ||
257 | uploader.RequestUpdateInventoryItem(remoteClient, transactionID, item); | ||
258 | } | ||
259 | else | ||
260 | { | ||
261 | m_log.ErrorFormat( | ||
262 | "[AGENT ASSET TRANSACTIONS]: Could not find uploader with transaction ID {0} when handling request to update inventory item {1} for {2}", | ||
263 | transactionID, item.Name, remoteClient.Name); | ||
264 | } | ||
175 | } | 265 | } |
176 | } | 266 | } |
177 | } | 267 | } |
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs index 4bb8986..441c4ff 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs | |||
@@ -215,7 +215,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
215 | IClientAPI remoteClient, SceneObjectPart part, UUID transactionID, TaskInventoryItem item) | 215 | IClientAPI remoteClient, SceneObjectPart part, UUID transactionID, TaskInventoryItem item) |
216 | { | 216 | { |
217 | m_log.DebugFormat( | 217 | m_log.DebugFormat( |
218 | "[ASSET TRANSACTION MODULE] Called HandleTaskItemUpdateFromTransaction with item {0} in {1} for {2} in {3}", | 218 | "[TRANSACTIONS MANAGER] Called HandleTaskItemUpdateFromTransaction with item {0} in {1} for {2} in {3}", |
219 | item.Name, part.Name, remoteClient.Name, m_Scene.RegionInfo.RegionName); | 219 | item.Name, part.Name, remoteClient.Name, m_Scene.RegionInfo.RegionName); |
220 | 220 | ||
221 | AgentAssetTransactions transactions = | 221 | AgentAssetTransactions transactions = |
@@ -274,8 +274,13 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
274 | } | 274 | } |
275 | 275 | ||
276 | AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); | 276 | AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); |
277 | AssetXferUploader uploader = transactions.RequestXferUploader(transaction); | 277 | AssetXferUploader uploader = transactions.RequestXferUploader(transaction, assetID); |
278 | uploader.StartUpload(remoteClient, assetID, transaction, type, data, storeLocal, tempFile); | 278 | |
279 | if (uploader != null) | ||
280 | { | ||
281 | uploader.Initialise(remoteClient, assetID, transaction, type, | ||
282 | data, storeLocal, tempFile); | ||
283 | } | ||
279 | } | 284 | } |
280 | 285 | ||
281 | /// <summary> | 286 | /// <summary> |
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs index f6dd5af..4cedfe6 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs | |||
@@ -49,75 +49,39 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
49 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 49 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
50 | 50 | ||
51 | /// <summary> | 51 | /// <summary> |
52 | /// Upload state. | ||
53 | /// </summary> | ||
54 | /// <remarks> | ||
55 | /// New -> Uploading -> Complete | ||
56 | /// </remarks> | ||
57 | private enum UploadState | ||
58 | { | ||
59 | New, | ||
60 | Uploading, | ||
61 | Complete | ||
62 | } | ||
63 | |||
64 | /// <summary> | ||
65 | /// Reference to the object that holds this uploader. Used to remove ourselves from it's list if we | 52 | /// Reference to the object that holds this uploader. Used to remove ourselves from it's list if we |
66 | /// are performing a delayed update. | 53 | /// are performing a delayed update. |
67 | /// </summary> | 54 | /// </summary> |
68 | AgentAssetTransactions m_transactions; | 55 | AgentAssetTransactions m_transactions; |
69 | 56 | ||
70 | private UploadState m_uploadState = UploadState.New; | ||
71 | |||
72 | private AssetBase m_asset; | 57 | private AssetBase m_asset; |
73 | private UUID InventFolder = UUID.Zero; | 58 | private UUID InventFolder = UUID.Zero; |
74 | private sbyte invType = 0; | 59 | private sbyte invType = 0; |
75 | 60 | ||
76 | private bool m_createItem; | 61 | private bool m_createItem = false; |
77 | private uint m_createItemCallback; | 62 | private uint m_createItemCallback = 0; |
78 | 63 | private bool m_updateItem = false; | |
79 | private bool m_updateItem; | ||
80 | private InventoryItemBase m_updateItemData; | 64 | private InventoryItemBase m_updateItemData; |
81 | 65 | ||
82 | private bool m_updateTaskItem; | ||
83 | private TaskInventoryItem m_updateTaskItemData; | ||
84 | |||
85 | private string m_description = String.Empty; | 66 | private string m_description = String.Empty; |
86 | private bool m_dumpAssetToFile; | 67 | private bool m_dumpAssetToFile; |
68 | private bool m_finished = false; | ||
87 | private string m_name = String.Empty; | 69 | private string m_name = String.Empty; |
88 | // private bool m_storeLocal; | 70 | private bool m_storeLocal; |
89 | private uint nextPerm = 0; | 71 | private uint nextPerm = 0; |
90 | private IClientAPI ourClient; | 72 | private IClientAPI ourClient; |
91 | 73 | private UUID TransactionID = UUID.Zero; | |
92 | private UUID m_transactionID; | ||
93 | |||
94 | private sbyte type = 0; | 74 | private sbyte type = 0; |
95 | private byte wearableType = 0; | 75 | private byte wearableType = 0; |
96 | private byte[] m_oldData = null; | 76 | private byte[] m_oldData = null; |
97 | public ulong XferID; | 77 | public ulong XferID; |
98 | private Scene m_Scene; | 78 | private Scene m_Scene; |
99 | 79 | ||
100 | /// <summary> | 80 | public AssetXferUploader(AgentAssetTransactions transactions, Scene scene, UUID assetID, bool dumpAssetToFile) |
101 | /// AssetXferUploader constructor | ||
102 | /// </summary> | ||
103 | /// <param name='transactions'>/param> | ||
104 | /// <param name='scene'></param> | ||
105 | /// <param name='transactionID'></param> | ||
106 | /// <param name='dumpAssetToFile'> | ||
107 | /// If true then when the asset is uploaded it is dumped to a file with the format | ||
108 | /// String.Format("{6}_{7}_{0:d2}{1:d2}{2:d2}_{3:d2}{4:d2}{5:d2}.dat", | ||
109 | /// now.Year, now.Month, now.Day, now.Hour, now.Minute, | ||
110 | /// now.Second, m_asset.Name, m_asset.Type); | ||
111 | /// for debugging purposes. | ||
112 | /// </param> | ||
113 | public AssetXferUploader( | ||
114 | AgentAssetTransactions transactions, Scene scene, UUID transactionID, bool dumpAssetToFile) | ||
115 | { | 81 | { |
116 | m_asset = new AssetBase(); | ||
117 | |||
118 | m_transactions = transactions; | 82 | m_transactions = transactions; |
119 | m_transactionID = transactionID; | ||
120 | m_Scene = scene; | 83 | m_Scene = scene; |
84 | m_asset = new AssetBase() { FullID = assetID }; | ||
121 | m_dumpAssetToFile = dumpAssetToFile; | 85 | m_dumpAssetToFile = dumpAssetToFile; |
122 | } | 86 | } |
123 | 87 | ||
@@ -163,50 +127,30 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
163 | } | 127 | } |
164 | 128 | ||
165 | /// <summary> | 129 | /// <summary> |
166 | /// Start asset transfer from the client | 130 | /// Initialise asset transfer from the client |
167 | /// </summary> | 131 | /// </summary> |
168 | /// <param name="remoteClient"></param> | 132 | /// <param name="xferID"></param> |
169 | /// <param name="assetID"></param> | 133 | /// <param name="packetID"></param> |
170 | /// <param name="transaction"></param> | 134 | /// <param name="data"></param> |
171 | /// <param name="type"></param> | 135 | public void Initialise(IClientAPI remoteClient, UUID assetID, |
172 | /// <param name="data"> | 136 | UUID transaction, sbyte type, byte[] data, bool storeLocal, |
173 | /// Optional data. If present then the asset is created immediately with this data | 137 | bool tempFile) |
174 | /// rather than requesting an upload from the client. The data must be longer than 2 bytes. | ||
175 | /// </param> | ||
176 | /// <param name="storeLocal"></param> | ||
177 | /// <param name="tempFile"></param> | ||
178 | public void StartUpload( | ||
179 | IClientAPI remoteClient, UUID assetID, UUID transaction, sbyte type, byte[] data, bool storeLocal, | ||
180 | bool tempFile) | ||
181 | { | 138 | { |
182 | // m_log.DebugFormat( | 139 | // m_log.DebugFormat( |
183 | // "[ASSET XFER UPLOADER]: Initialised xfer from {0}, asset {1}, transaction {2}, type {3}, storeLocal {4}, tempFile {5}, already received data length {6}", | 140 | // "[ASSET XFER UPLOADER]: Initialised xfer from {0}, asset {1}, transaction {2}, type {3}, storeLocal {4}, tempFile {5}, already received data length {6}", |
184 | // remoteClient.Name, assetID, transaction, type, storeLocal, tempFile, data.Length); | 141 | // remoteClient.Name, assetID, transaction, type, storeLocal, tempFile, data.Length); |
185 | 142 | ||
186 | lock (this) | ||
187 | { | ||
188 | if (m_uploadState != UploadState.New) | ||
189 | { | ||
190 | m_log.WarnFormat( | ||
191 | "[ASSET XFER UPLOADER]: Tried to start upload of asset {0}, transaction {1} for {2} but this is already in state {3}. Aborting.", | ||
192 | assetID, transaction, remoteClient.Name, m_uploadState); | ||
193 | |||
194 | return; | ||
195 | } | ||
196 | |||
197 | m_uploadState = UploadState.Uploading; | ||
198 | } | ||
199 | |||
200 | ourClient = remoteClient; | 143 | ourClient = remoteClient; |
201 | 144 | m_asset.Name = "blank"; | |
202 | m_asset.FullID = assetID; | 145 | m_asset.Description = "empty"; |
203 | m_asset.Type = type; | 146 | m_asset.Type = type; |
204 | m_asset.CreatorID = remoteClient.AgentId.ToString(); | 147 | m_asset.CreatorID = remoteClient.AgentId.ToString(); |
205 | m_asset.Data = data; | 148 | m_asset.Data = data; |
206 | m_asset.Local = storeLocal; | 149 | m_asset.Local = storeLocal; |
207 | m_asset.Temporary = tempFile; | 150 | m_asset.Temporary = tempFile; |
208 | 151 | ||
209 | // m_storeLocal = storeLocal; | 152 | TransactionID = transaction; |
153 | m_storeLocal = storeLocal; | ||
210 | 154 | ||
211 | if (m_asset.Data.Length > 2) | 155 | if (m_asset.Data.Length > 2) |
212 | { | 156 | { |
@@ -231,35 +175,36 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
231 | 175 | ||
232 | protected void SendCompleteMessage() | 176 | protected void SendCompleteMessage() |
233 | { | 177 | { |
178 | ourClient.SendAssetUploadCompleteMessage(m_asset.Type, true, | ||
179 | m_asset.FullID); | ||
180 | |||
234 | // We must lock in order to avoid a race with a separate thread dealing with an inventory item or create | 181 | // We must lock in order to avoid a race with a separate thread dealing with an inventory item or create |
235 | // message from other client UDP. | 182 | // message from other client UDP. |
236 | lock (this) | 183 | lock (this) |
237 | { | 184 | { |
238 | m_uploadState = UploadState.Complete; | 185 | m_finished = true; |
239 | |||
240 | ourClient.SendAssetUploadCompleteMessage(m_asset.Type, true, m_asset.FullID); | ||
241 | |||
242 | if (m_createItem) | 186 | if (m_createItem) |
243 | { | 187 | { |
244 | CompleteCreateItem(m_createItemCallback); | 188 | DoCreateItem(m_createItemCallback); |
245 | } | 189 | } |
246 | else if (m_updateItem) | 190 | else if (m_updateItem) |
247 | { | 191 | { |
248 | CompleteItemUpdate(m_updateItemData); | 192 | StoreAssetForItemUpdate(m_updateItemData); |
193 | |||
194 | // Remove ourselves from the list of transactions if completion was delayed until the transaction | ||
195 | // was complete. | ||
196 | // TODO: Should probably do the same for create item. | ||
197 | m_transactions.RemoveXferUploader(TransactionID); | ||
249 | } | 198 | } |
250 | else if (m_updateTaskItem) | 199 | else if (m_storeLocal) |
251 | { | 200 | { |
252 | CompleteTaskItemUpdate(m_updateTaskItemData); | 201 | m_Scene.AssetService.Store(m_asset); |
253 | } | 202 | } |
254 | // else if (m_storeLocal) | ||
255 | // { | ||
256 | // m_Scene.AssetService.Store(m_asset); | ||
257 | // } | ||
258 | } | 203 | } |
259 | 204 | ||
260 | m_log.DebugFormat( | 205 | m_log.DebugFormat( |
261 | "[ASSET XFER UPLOADER]: Uploaded asset {0} for transaction {1}", | 206 | "[ASSET XFER UPLOADER]: Uploaded asset {0} for transaction {1}", |
262 | m_asset.FullID, m_transactionID); | 207 | m_asset.FullID, TransactionID); |
263 | 208 | ||
264 | if (m_dumpAssetToFile) | 209 | if (m_dumpAssetToFile) |
265 | { | 210 | { |
@@ -287,37 +232,40 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
287 | } | 232 | } |
288 | 233 | ||
289 | public void RequestCreateInventoryItem(IClientAPI remoteClient, | 234 | public void RequestCreateInventoryItem(IClientAPI remoteClient, |
290 | UUID folderID, uint callbackID, | 235 | UUID transactionID, UUID folderID, uint callbackID, |
291 | string description, string name, sbyte invType, | 236 | string description, string name, sbyte invType, |
292 | sbyte type, byte wearableType, uint nextOwnerMask) | 237 | sbyte type, byte wearableType, uint nextOwnerMask) |
293 | { | 238 | { |
294 | InventFolder = folderID; | 239 | if (TransactionID == transactionID) |
295 | m_name = name; | ||
296 | m_description = description; | ||
297 | this.type = type; | ||
298 | this.invType = invType; | ||
299 | this.wearableType = wearableType; | ||
300 | nextPerm = nextOwnerMask; | ||
301 | m_asset.Name = name; | ||
302 | m_asset.Description = description; | ||
303 | m_asset.Type = type; | ||
304 | |||
305 | // We must lock to avoid a race with a separate thread uploading the asset. | ||
306 | lock (this) | ||
307 | { | 240 | { |
308 | if (m_uploadState == UploadState.Complete) | 241 | InventFolder = folderID; |
242 | m_name = name; | ||
243 | m_description = description; | ||
244 | this.type = type; | ||
245 | this.invType = invType; | ||
246 | this.wearableType = wearableType; | ||
247 | nextPerm = nextOwnerMask; | ||
248 | m_asset.Name = name; | ||
249 | m_asset.Description = description; | ||
250 | m_asset.Type = type; | ||
251 | |||
252 | // We must lock to avoid a race with a separate thread uploading the asset. | ||
253 | lock (this) | ||
309 | { | 254 | { |
310 | CompleteCreateItem(callbackID); | 255 | if (m_finished) |
311 | } | 256 | { |
312 | else | 257 | DoCreateItem(callbackID); |
313 | { | 258 | } |
314 | m_createItem = true; //set flag so the inventory item is created when upload is complete | 259 | else |
315 | m_createItemCallback = callbackID; | 260 | { |
261 | m_createItem = true; //set flag so the inventory item is created when upload is complete | ||
262 | m_createItemCallback = callbackID; | ||
263 | } | ||
316 | } | 264 | } |
317 | } | 265 | } |
318 | } | 266 | } |
319 | 267 | ||
320 | public void RequestUpdateInventoryItem(IClientAPI remoteClient, InventoryItemBase item) | 268 | public void RequestUpdateInventoryItem(IClientAPI remoteClient, UUID transactionID, InventoryItemBase item) |
321 | { | 269 | { |
322 | // We must lock to avoid a race with a separate thread uploading the asset. | 270 | // We must lock to avoid a race with a separate thread uploading the asset. |
323 | lock (this) | 271 | lock (this) |
@@ -332,9 +280,9 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
332 | item.AssetID = m_asset.FullID; | 280 | item.AssetID = m_asset.FullID; |
333 | m_Scene.InventoryService.UpdateItem(item); | 281 | m_Scene.InventoryService.UpdateItem(item); |
334 | 282 | ||
335 | if (m_uploadState == UploadState.Complete) | 283 | if (m_finished) |
336 | { | 284 | { |
337 | CompleteItemUpdate(item); | 285 | StoreAssetForItemUpdate(item); |
338 | } | 286 | } |
339 | else | 287 | else |
340 | { | 288 | { |
@@ -348,59 +296,20 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
348 | } | 296 | } |
349 | } | 297 | } |
350 | 298 | ||
351 | public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient, TaskInventoryItem taskItem) | ||
352 | { | ||
353 | // We must lock to avoid a race with a separate thread uploading the asset. | ||
354 | lock (this) | ||
355 | { | ||
356 | m_asset.Name = taskItem.Name; | ||
357 | m_asset.Description = taskItem.Description; | ||
358 | m_asset.Type = (sbyte)taskItem.Type; | ||
359 | taskItem.AssetID = m_asset.FullID; | ||
360 | |||
361 | if (m_uploadState == UploadState.Complete) | ||
362 | { | ||
363 | CompleteTaskItemUpdate(taskItem); | ||
364 | } | ||
365 | else | ||
366 | { | ||
367 | m_updateTaskItem = true; | ||
368 | m_updateTaskItemData = taskItem; | ||
369 | } | ||
370 | } | ||
371 | } | ||
372 | |||
373 | /// <summary> | 299 | /// <summary> |
374 | /// Store the asset for the given item when it has been uploaded. | 300 | /// Store the asset for the given item. |
375 | /// </summary> | 301 | /// </summary> |
376 | /// <param name="item"></param> | 302 | /// <param name="item"></param> |
377 | private void CompleteItemUpdate(InventoryItemBase item) | 303 | private void StoreAssetForItemUpdate(InventoryItemBase item) |
378 | { | 304 | { |
379 | // m_log.DebugFormat( | 305 | // m_log.DebugFormat( |
380 | // "[ASSET XFER UPLOADER]: Storing asset {0} for earlier item update for {1} for {2}", | 306 | // "[ASSET XFER UPLOADER]: Storing asset {0} for earlier item update for {1} for {2}", |
381 | // m_asset.FullID, item.Name, ourClient.Name); | 307 | // m_asset.FullID, item.Name, ourClient.Name); |
382 | 308 | ||
383 | m_Scene.AssetService.Store(m_asset); | 309 | m_Scene.AssetService.Store(m_asset); |
384 | |||
385 | m_transactions.RemoveXferUploader(m_transactionID); | ||
386 | } | ||
387 | |||
388 | /// <summary> | ||
389 | /// Store the asset for the given task item when it has been uploaded. | ||
390 | /// </summary> | ||
391 | /// <param name="taskItem"></param> | ||
392 | private void CompleteTaskItemUpdate(TaskInventoryItem taskItem) | ||
393 | { | ||
394 | // m_log.DebugFormat( | ||
395 | // "[ASSET XFER UPLOADER]: Storing asset {0} for earlier task item update for {1} for {2}", | ||
396 | // m_asset.FullID, taskItem.Name, ourClient.Name); | ||
397 | |||
398 | m_Scene.AssetService.Store(m_asset); | ||
399 | |||
400 | m_transactions.RemoveXferUploader(m_transactionID); | ||
401 | } | 310 | } |
402 | 311 | ||
403 | private void CompleteCreateItem(uint callbackID) | 312 | private void DoCreateItem(uint callbackID) |
404 | { | 313 | { |
405 | ValidateAssets(); | 314 | ValidateAssets(); |
406 | m_Scene.AssetService.Store(m_asset); | 315 | m_Scene.AssetService.Store(m_asset); |
@@ -430,8 +339,6 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
430 | ourClient.SendInventoryItemCreateUpdate(item, callbackID); | 339 | ourClient.SendInventoryItemCreateUpdate(item, callbackID); |
431 | else | 340 | else |
432 | ourClient.SendAlertMessage("Unable to create inventory item"); | 341 | ourClient.SendAlertMessage("Unable to create inventory item"); |
433 | |||
434 | m_transactions.RemoveXferUploader(m_transactionID); | ||
435 | } | 342 | } |
436 | 343 | ||
437 | private void ValidateAssets() | 344 | private void ValidateAssets() |
@@ -509,7 +416,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
509 | /// <returns>null if the asset has not finished uploading</returns> | 416 | /// <returns>null if the asset has not finished uploading</returns> |
510 | public AssetBase GetAssetData() | 417 | public AssetBase GetAssetData() |
511 | { | 418 | { |
512 | if (m_uploadState == UploadState.Complete) | 419 | if (m_finished) |
513 | { | 420 | { |
514 | ValidateAssets(); | 421 | ValidateAssets(); |
515 | return m_asset; | 422 | return m_asset; |
@@ -562,3 +469,4 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
562 | } | 469 | } |
563 | } | 470 | } |
564 | } | 471 | } |
472 | |||
diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index d1a563c..7d7176f 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs | |||
@@ -52,7 +52,7 @@ using OpenSim.Services.Interfaces; | |||
52 | [assembly: Addin("FlotsamAssetCache", "1.1")] | 52 | [assembly: Addin("FlotsamAssetCache", "1.1")] |
53 | [assembly: AddinDependency("OpenSim", "0.5")] | 53 | [assembly: AddinDependency("OpenSim", "0.5")] |
54 | 54 | ||
55 | namespace OpenSim.Region.CoreModules.Asset | 55 | namespace Flotsam.RegionModules.AssetCache |
56 | { | 56 | { |
57 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] | 57 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] |
58 | public class FlotsamAssetCache : ISharedRegionModule, IImprovedAssetCache, IAssetService | 58 | public class FlotsamAssetCache : ISharedRegionModule, IImprovedAssetCache, IAssetService |
@@ -107,6 +107,8 @@ namespace OpenSim.Region.CoreModules.Asset | |||
107 | private IAssetService m_AssetService; | 107 | private IAssetService m_AssetService; |
108 | private List<Scene> m_Scenes = new List<Scene>(); | 108 | private List<Scene> m_Scenes = new List<Scene>(); |
109 | 109 | ||
110 | private bool m_DeepScanBeforePurge; | ||
111 | |||
110 | public FlotsamAssetCache() | 112 | public FlotsamAssetCache() |
111 | { | 113 | { |
112 | m_InvalidChars.AddRange(Path.GetInvalidPathChars()); | 114 | m_InvalidChars.AddRange(Path.GetInvalidPathChars()); |
@@ -168,6 +170,8 @@ namespace OpenSim.Region.CoreModules.Asset | |||
168 | m_CacheDirectoryTierLen = assetConfig.GetInt("CacheDirectoryTierLength", m_CacheDirectoryTierLen); | 170 | m_CacheDirectoryTierLen = assetConfig.GetInt("CacheDirectoryTierLength", m_CacheDirectoryTierLen); |
169 | 171 | ||
170 | m_CacheWarnAt = assetConfig.GetInt("CacheWarnAt", m_CacheWarnAt); | 172 | m_CacheWarnAt = assetConfig.GetInt("CacheWarnAt", m_CacheWarnAt); |
173 | |||
174 | m_DeepScanBeforePurge = assetConfig.GetBoolean("DeepScanBeforePurge", m_DeepScanBeforePurge); | ||
171 | } | 175 | } |
172 | 176 | ||
173 | m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory {0}", m_CacheDirectory); | 177 | m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory {0}", m_CacheDirectory); |
@@ -515,10 +519,13 @@ namespace OpenSim.Region.CoreModules.Asset | |||
515 | // Purge all files last accessed prior to this point | 519 | // Purge all files last accessed prior to this point |
516 | DateTime purgeLine = DateTime.Now - m_FileExpiration; | 520 | DateTime purgeLine = DateTime.Now - m_FileExpiration; |
517 | 521 | ||
518 | // An asset cache may contain local non-temporary assets that are not in the asset service. Therefore, | 522 | // An optional deep scan at this point will ensure assets present in scenes, |
519 | // before cleaning up expired files we must scan the objects in the scene to make sure that we retain | 523 | // or referenced by objects in the scene, but not recently accessed |
520 | // such local assets if they have not been recently accessed. | 524 | // are not purged. |
521 | TouchAllSceneAssets(false); | 525 | if (m_DeepScanBeforePurge) |
526 | { | ||
527 | CacheScenes(); | ||
528 | } | ||
522 | 529 | ||
523 | foreach (string dir in Directory.GetDirectories(m_CacheDirectory)) | 530 | foreach (string dir in Directory.GetDirectories(m_CacheDirectory)) |
524 | { | 531 | { |
@@ -711,14 +718,11 @@ namespace OpenSim.Region.CoreModules.Asset | |||
711 | 718 | ||
712 | /// <summary> | 719 | /// <summary> |
713 | /// Iterates through all Scenes, doing a deep scan through assets | 720 | /// Iterates through all Scenes, doing a deep scan through assets |
714 | /// to update the access time of all assets present in the scene or referenced by assets | 721 | /// to cache all assets present in the scene or referenced by assets |
715 | /// in the scene. | 722 | /// in the scene |
716 | /// </summary> | 723 | /// </summary> |
717 | /// <param name="storeUncached"> | 724 | /// <returns></returns> |
718 | /// If true, then assets scanned which are not found in cache are added to the cache. | 725 | private int CacheScenes() |
719 | /// </param> | ||
720 | /// <returns>Number of distinct asset references found in the scene.</returns> | ||
721 | private int TouchAllSceneAssets(bool storeUncached) | ||
722 | { | 726 | { |
723 | UuidGatherer gatherer = new UuidGatherer(m_AssetService); | 727 | UuidGatherer gatherer = new UuidGatherer(m_AssetService); |
724 | 728 | ||
@@ -741,7 +745,7 @@ namespace OpenSim.Region.CoreModules.Asset | |||
741 | { | 745 | { |
742 | File.SetLastAccessTime(filename, DateTime.Now); | 746 | File.SetLastAccessTime(filename, DateTime.Now); |
743 | } | 747 | } |
744 | else if (storeUncached) | 748 | else |
745 | { | 749 | { |
746 | m_AssetService.Get(assetID.ToString()); | 750 | m_AssetService.Get(assetID.ToString()); |
747 | } | 751 | } |
@@ -869,14 +873,13 @@ namespace OpenSim.Region.CoreModules.Asset | |||
869 | 873 | ||
870 | break; | 874 | break; |
871 | 875 | ||
876 | |||
872 | case "assets": | 877 | case "assets": |
873 | m_log.Info("[FLOTSAM ASSET CACHE]: Ensuring assets are cached for all scenes."); | 878 | m_log.Info("[FLOTSAM ASSET CACHE]: Caching all assets, in all scenes."); |
874 | 879 | ||
875 | Util.FireAndForget(delegate { | 880 | Util.FireAndForget(delegate { |
876 | int assetReferenceTotal = TouchAllSceneAssets(true); | 881 | int assetsCached = CacheScenes(); |
877 | m_log.InfoFormat( | 882 | m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Completed Scene Caching, {0} assets found.", assetsCached); |
878 | "[FLOTSAM ASSET CACHE]: Completed check with {0} assets.", | ||
879 | assetReferenceTotal); | ||
880 | }); | 883 | }); |
881 | 884 | ||
882 | break; | 885 | break; |
diff --git a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs index 1c2bfd0..c91b25f 100644 --- a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs +++ b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs | |||
@@ -35,6 +35,7 @@ using Nini.Config; | |||
35 | using NUnit.Framework; | 35 | using NUnit.Framework; |
36 | using OpenMetaverse; | 36 | using OpenMetaverse; |
37 | using OpenMetaverse.Assets; | 37 | using OpenMetaverse.Assets; |
38 | using Flotsam.RegionModules.AssetCache; | ||
38 | using OpenSim.Framework; | 39 | using OpenSim.Framework; |
39 | using OpenSim.Region.Framework.Scenes; | 40 | using OpenSim.Region.Framework.Scenes; |
40 | using OpenSim.Region.Framework.Scenes.Serialization; | 41 | using OpenSim.Region.Framework.Scenes.Serialization; |
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index acd156e..951afd7 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs | |||
@@ -286,20 +286,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
286 | 286 | ||
287 | public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool temp) | 287 | public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool temp) |
288 | { | 288 | { |
289 | if (!Enabled) | ||
290 | return false; | ||
291 | |||
292 | if (AttachObjectInternal(sp, group, attachmentPt, silent, useAttachData, temp)) | ||
293 | { | ||
294 | m_scene.EventManager.TriggerOnAttach(group.LocalId, group.FromItemID, sp.UUID); | ||
295 | return true; | ||
296 | } | ||
297 | |||
298 | return false; | ||
299 | } | ||
300 | |||
301 | private bool AttachObjectInternal(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool temp) | ||
302 | { | ||
303 | lock (sp.AttachmentsSyncLock) | 289 | lock (sp.AttachmentsSyncLock) |
304 | { | 290 | { |
305 | // m_log.DebugFormat( | 291 | // m_log.DebugFormat( |
@@ -475,11 +461,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
475 | 461 | ||
476 | public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId) | 462 | public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId) |
477 | { | 463 | { |
478 | DetachSingleAttachmentToGround(sp, soLocalId, sp.AbsolutePosition, Quaternion.Identity); | ||
479 | } | ||
480 | |||
481 | public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId, Vector3 absolutePos, Quaternion absoluteRot) | ||
482 | { | ||
483 | if (!Enabled) | 464 | if (!Enabled) |
484 | return; | 465 | return; |
485 | 466 | ||
@@ -521,11 +502,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
521 | so.FromItemID = UUID.Zero; | 502 | so.FromItemID = UUID.Zero; |
522 | 503 | ||
523 | SceneObjectPart rootPart = so.RootPart; | 504 | SceneObjectPart rootPart = so.RootPart; |
524 | so.AbsolutePosition = absolutePos; | 505 | so.AbsolutePosition = sp.AbsolutePosition; |
525 | if (absoluteRot != Quaternion.Identity) | ||
526 | { | ||
527 | so.UpdateGroupRotationR(absoluteRot); | ||
528 | } | ||
529 | so.AttachedAvatar = UUID.Zero; | 506 | so.AttachedAvatar = UUID.Zero; |
530 | rootPart.SetParentLocalId(0); | 507 | rootPart.SetParentLocalId(0); |
531 | so.ClearPartAttachmentData(); | 508 | so.ClearPartAttachmentData(); |
@@ -639,9 +616,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
639 | 616 | ||
640 | if (grp.HasGroupChanged) | 617 | if (grp.HasGroupChanged) |
641 | { | 618 | { |
642 | m_log.DebugFormat( | 619 | // m_log.DebugFormat( |
643 | "[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}", | 620 | // "[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}", |
644 | grp.UUID, grp.AttachmentPoint); | 621 | // grp.UUID, grp.AttachmentPoint); |
645 | 622 | ||
646 | string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp, scriptedState); | 623 | string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp, scriptedState); |
647 | 624 | ||
@@ -885,7 +862,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
885 | // This will throw if the attachment fails | 862 | // This will throw if the attachment fails |
886 | try | 863 | try |
887 | { | 864 | { |
888 | AttachObjectInternal(sp, objatt, attachmentPt, false, false, false); | 865 | AttachObject(sp, objatt, attachmentPt, false, false, false); |
889 | } | 866 | } |
890 | catch (Exception e) | 867 | catch (Exception e) |
891 | { | 868 | { |
@@ -956,9 +933,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
956 | 933 | ||
957 | InventoryItemBase item = new InventoryItemBase(itemID, sp.UUID); | 934 | InventoryItemBase item = new InventoryItemBase(itemID, sp.UUID); |
958 | item = m_scene.InventoryService.GetItem(item); | 935 | item = m_scene.InventoryService.GetItem(item); |
959 | if (item == null) | ||
960 | return; | ||
961 | |||
962 | bool changed = sp.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID); | 936 | bool changed = sp.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID); |
963 | if (changed && m_scene.AvatarFactory != null) | 937 | if (changed && m_scene.AvatarFactory != null) |
964 | { | 938 | { |
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs index 4e9d3f9..d9a619d 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs | |||
@@ -62,10 +62,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests | |||
62 | public class AttachmentsModuleTests : OpenSimTestCase | 62 | public class AttachmentsModuleTests : OpenSimTestCase |
63 | { | 63 | { |
64 | private AutoResetEvent m_chatEvent = new AutoResetEvent(false); | 64 | private AutoResetEvent m_chatEvent = new AutoResetEvent(false); |
65 | // private OSChatMessage m_osChatMessageReceived; | 65 | private OSChatMessage m_osChatMessageReceived; |
66 | |||
67 | // Used to test whether the operations have fired the attach event. Must be reset after each test. | ||
68 | private int m_numberOfAttachEventsFired; | ||
69 | 66 | ||
70 | [TestFixtureSetUp] | 67 | [TestFixtureSetUp] |
71 | public void FixtureInit() | 68 | public void FixtureInit() |
@@ -86,7 +83,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests | |||
86 | { | 83 | { |
87 | // Console.WriteLine("Got chat [{0}]", oscm.Message); | 84 | // Console.WriteLine("Got chat [{0}]", oscm.Message); |
88 | 85 | ||
89 | // m_osChatMessageReceived = oscm; | 86 | m_osChatMessageReceived = oscm; |
90 | m_chatEvent.Set(); | 87 | m_chatEvent.Set(); |
91 | } | 88 | } |
92 | 89 | ||
@@ -102,8 +99,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests | |||
102 | "attachments-test-scene", TestHelpers.ParseTail(999), 1000, 1000, config); | 99 | "attachments-test-scene", TestHelpers.ParseTail(999), 1000, 1000, config); |
103 | SceneHelpers.SetupSceneModules(scene, config, modules.ToArray()); | 100 | SceneHelpers.SetupSceneModules(scene, config, modules.ToArray()); |
104 | 101 | ||
105 | scene.EventManager.OnAttach += (localID, itemID, avatarID) => m_numberOfAttachEventsFired++; | ||
106 | |||
107 | return scene; | 102 | return scene; |
108 | } | 103 | } |
109 | 104 | ||
@@ -186,8 +181,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests | |||
186 | TestHelpers.InMethod(); | 181 | TestHelpers.InMethod(); |
187 | // TestHelpers.EnableLogging(); | 182 | // TestHelpers.EnableLogging(); |
188 | 183 | ||
189 | m_numberOfAttachEventsFired = 0; | ||
190 | |||
191 | Scene scene = CreateTestScene(); | 184 | Scene scene = CreateTestScene(); |
192 | UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); | 185 | UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); |
193 | ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1); | 186 | ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1); |
@@ -196,7 +189,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests | |||
196 | 189 | ||
197 | SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID); | 190 | SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID); |
198 | 191 | ||
199 | m_numberOfAttachEventsFired = 0; | ||
200 | scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false, false); | 192 | scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false, false); |
201 | 193 | ||
202 | // Check status on scene presence | 194 | // Check status on scene presence |
@@ -224,8 +216,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests | |||
224 | 216 | ||
225 | Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); | 217 | Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); |
226 | 218 | ||
227 | // Check events | 219 | // TestHelpers.DisableLogging(); |
228 | Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); | ||
229 | } | 220 | } |
230 | 221 | ||
231 | /// <summary> | 222 | /// <summary> |
@@ -237,8 +228,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests | |||
237 | TestHelpers.InMethod(); | 228 | TestHelpers.InMethod(); |
238 | // TestHelpers.EnableLogging(); | 229 | // TestHelpers.EnableLogging(); |
239 | 230 | ||
240 | m_numberOfAttachEventsFired = 0; | ||
241 | |||
242 | Scene scene = CreateTestScene(); | 231 | Scene scene = CreateTestScene(); |
243 | UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); | 232 | UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); |
244 | ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1); | 233 | ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1); |
@@ -258,9 +247,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests | |||
258 | 247 | ||
259 | Assert.That(sp.HasAttachments(), Is.False); | 248 | Assert.That(sp.HasAttachments(), Is.False); |
260 | Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); | 249 | Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); |
261 | |||
262 | // Check events | ||
263 | Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0)); | ||
264 | } | 250 | } |
265 | 251 | ||
266 | [Test] | 252 | [Test] |
@@ -275,7 +261,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests | |||
275 | 261 | ||
276 | InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20); | 262 | InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20); |
277 | 263 | ||
278 | m_numberOfAttachEventsFired = 0; | ||
279 | scene.AttachmentsModule.RezSingleAttachmentFromInventory( | 264 | scene.AttachmentsModule.RezSingleAttachmentFromInventory( |
280 | sp, attItem.ID, (uint)AttachmentPoint.Chest); | 265 | sp, attItem.ID, (uint)AttachmentPoint.Chest); |
281 | 266 | ||
@@ -295,9 +280,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests | |||
295 | Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); | 280 | Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); |
296 | 281 | ||
297 | Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); | 282 | Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); |
298 | |||
299 | // Check events | ||
300 | Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); | ||
301 | } | 283 | } |
302 | 284 | ||
303 | /// <summary> | 285 | /// <summary> |
@@ -356,8 +338,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests | |||
356 | ISceneEntity so | 338 | ISceneEntity so |
357 | = scene.AttachmentsModule.RezSingleAttachmentFromInventory( | 339 | = scene.AttachmentsModule.RezSingleAttachmentFromInventory( |
358 | sp, attItem.ID, (uint)AttachmentPoint.Chest); | 340 | sp, attItem.ID, (uint)AttachmentPoint.Chest); |
359 | |||
360 | m_numberOfAttachEventsFired = 0; | ||
361 | scene.AttachmentsModule.DetachSingleAttachmentToGround(sp, so.LocalId); | 341 | scene.AttachmentsModule.DetachSingleAttachmentToGround(sp, so.LocalId); |
362 | 342 | ||
363 | // Check scene presence status | 343 | // Check scene presence status |
@@ -373,9 +353,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests | |||
373 | 353 | ||
374 | // Check object in scene | 354 | // Check object in scene |
375 | Assert.That(scene.GetSceneObjectGroup("att"), Is.Not.Null); | 355 | Assert.That(scene.GetSceneObjectGroup("att"), Is.Not.Null); |
376 | |||
377 | // Check events | ||
378 | Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); | ||
379 | } | 356 | } |
380 | 357 | ||
381 | [Test] | 358 | [Test] |
@@ -392,8 +369,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests | |||
392 | SceneObjectGroup so | 369 | SceneObjectGroup so |
393 | = (SceneObjectGroup)scene.AttachmentsModule.RezSingleAttachmentFromInventory( | 370 | = (SceneObjectGroup)scene.AttachmentsModule.RezSingleAttachmentFromInventory( |
394 | sp, attItem.ID, (uint)AttachmentPoint.Chest); | 371 | sp, attItem.ID, (uint)AttachmentPoint.Chest); |
395 | |||
396 | m_numberOfAttachEventsFired = 0; | ||
397 | scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, so); | 372 | scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, so); |
398 | 373 | ||
399 | // Check status on scene presence | 374 | // Check status on scene presence |
@@ -405,9 +380,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests | |||
405 | Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo(0)); | 380 | Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo(0)); |
406 | 381 | ||
407 | Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(0)); | 382 | Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(0)); |
408 | |||
409 | // Check events | ||
410 | Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); | ||
411 | } | 383 | } |
412 | 384 | ||
413 | /// <summary> | 385 | /// <summary> |
@@ -489,14 +461,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests | |||
489 | 461 | ||
490 | SceneObjectGroup rezzedAtt = presence.GetAttachments()[0]; | 462 | SceneObjectGroup rezzedAtt = presence.GetAttachments()[0]; |
491 | 463 | ||
492 | m_numberOfAttachEventsFired = 0; | 464 | scene.IncomingCloseAgent(presence.UUID); |
493 | scene.IncomingCloseAgent(presence.UUID, false); | ||
494 | 465 | ||
495 | // Check that we can't retrieve this attachment from the scene. | 466 | // Check that we can't retrieve this attachment from the scene. |
496 | Assert.That(scene.GetSceneObjectGroup(rezzedAtt.UUID), Is.Null); | 467 | Assert.That(scene.GetSceneObjectGroup(rezzedAtt.UUID), Is.Null); |
497 | |||
498 | // Check events | ||
499 | Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0)); | ||
500 | } | 468 | } |
501 | 469 | ||
502 | [Test] | 470 | [Test] |
@@ -512,8 +480,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests | |||
512 | AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID); | 480 | AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID); |
513 | acd.Appearance = new AvatarAppearance(); | 481 | acd.Appearance = new AvatarAppearance(); |
514 | acd.Appearance.SetAttachment((int)AttachmentPoint.Chest, attItem.ID, attItem.AssetID); | 482 | acd.Appearance.SetAttachment((int)AttachmentPoint.Chest, attItem.ID, attItem.AssetID); |
515 | |||
516 | m_numberOfAttachEventsFired = 0; | ||
517 | ScenePresence presence = SceneHelpers.AddScenePresence(scene, acd); | 483 | ScenePresence presence = SceneHelpers.AddScenePresence(scene, acd); |
518 | 484 | ||
519 | Assert.That(presence.HasAttachments(), Is.True); | 485 | Assert.That(presence.HasAttachments(), Is.True); |
@@ -536,9 +502,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests | |||
536 | Assert.That(presence.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); | 502 | Assert.That(presence.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); |
537 | 503 | ||
538 | Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); | 504 | Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); |
539 | |||
540 | // Check events. We expect OnAttach to fire on login. | ||
541 | Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); | ||
542 | } | 505 | } |
543 | 506 | ||
544 | [Test] | 507 | [Test] |
@@ -559,14 +522,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests | |||
559 | 522 | ||
560 | Vector3 newPosition = new Vector3(1, 2, 4); | 523 | Vector3 newPosition = new Vector3(1, 2, 4); |
561 | 524 | ||
562 | m_numberOfAttachEventsFired = 0; | ||
563 | scene.SceneGraph.UpdatePrimGroupPosition(attSo.LocalId, newPosition, sp.ControllingClient); | 525 | scene.SceneGraph.UpdatePrimGroupPosition(attSo.LocalId, newPosition, sp.ControllingClient); |
564 | 526 | ||
565 | Assert.That(attSo.AbsolutePosition, Is.EqualTo(sp.AbsolutePosition)); | 527 | Assert.That(attSo.AbsolutePosition, Is.EqualTo(sp.AbsolutePosition)); |
566 | Assert.That(attSo.RootPart.AttachedPos, Is.EqualTo(newPosition)); | 528 | Assert.That(attSo.RootPart.AttachedPos, Is.EqualTo(newPosition)); |
567 | |||
568 | // Check events | ||
569 | Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0)); | ||
570 | } | 529 | } |
571 | 530 | ||
572 | [Test] | 531 | [Test] |
@@ -615,7 +574,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests | |||
615 | Vector3 teleportPosition = new Vector3(10, 11, 12); | 574 | Vector3 teleportPosition = new Vector3(10, 11, 12); |
616 | Vector3 teleportLookAt = new Vector3(20, 21, 22); | 575 | Vector3 teleportLookAt = new Vector3(20, 21, 22); |
617 | 576 | ||
618 | m_numberOfAttachEventsFired = 0; | ||
619 | sceneA.RequestTeleportLocation( | 577 | sceneA.RequestTeleportLocation( |
620 | beforeTeleportSp.ControllingClient, | 578 | beforeTeleportSp.ControllingClient, |
621 | sceneB.RegionInfo.RegionHandle, | 579 | sceneB.RegionInfo.RegionHandle, |
@@ -658,9 +616,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests | |||
658 | Assert.That(actualSceneAAttachments.Count, Is.EqualTo(0)); | 616 | Assert.That(actualSceneAAttachments.Count, Is.EqualTo(0)); |
659 | 617 | ||
660 | Assert.That(sceneA.GetSceneObjectGroups().Count, Is.EqualTo(0)); | 618 | Assert.That(sceneA.GetSceneObjectGroups().Count, Is.EqualTo(0)); |
661 | |||
662 | // Check events | ||
663 | Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0)); | ||
664 | } | 619 | } |
620 | |||
621 | // I'm commenting this test because scene setup NEEDS InventoryService to | ||
622 | // be non-null | ||
623 | //[Test] | ||
624 | // public void T032_CrossAttachments() | ||
625 | // { | ||
626 | // TestHelpers.InMethod(); | ||
627 | // | ||
628 | // ScenePresence presence = scene.GetScenePresence(agent1); | ||
629 | // ScenePresence presence2 = scene2.GetScenePresence(agent1); | ||
630 | // presence2.AddAttachment(sog1); | ||
631 | // presence2.AddAttachment(sog2); | ||
632 | // | ||
633 | // ISharedRegionModule serialiser = new SerialiserModule(); | ||
634 | // SceneHelpers.SetupSceneModules(scene, new IniConfigSource(), serialiser); | ||
635 | // SceneHelpers.SetupSceneModules(scene2, new IniConfigSource(), serialiser); | ||
636 | // | ||
637 | // Assert.That(presence.HasAttachments(), Is.False, "Presence has attachments before cross"); | ||
638 | // | ||
639 | // //Assert.That(presence2.CrossAttachmentsIntoNewRegion(region1, true), Is.True, "Cross was not successful"); | ||
640 | // Assert.That(presence2.HasAttachments(), Is.False, "Presence2 objects were not deleted"); | ||
641 | // Assert.That(presence.HasAttachments(), Is.True, "Presence has not received new objects"); | ||
642 | // } | ||
665 | } | 643 | } |
666 | } | 644 | } |
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index e3bf997..4cb4370 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs | |||
@@ -533,7 +533,6 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
533 | // Ignore ruth's assets | 533 | // Ignore ruth's assets |
534 | if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID) | 534 | if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID) |
535 | continue; | 535 | continue; |
536 | |||
537 | InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID); | 536 | InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID); |
538 | baseItem = invService.GetItem(baseItem); | 537 | baseItem = invService.GetItem(baseItem); |
539 | 538 | ||
diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs index 4407e40..dbbb0ae 100644 --- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs | |||
@@ -197,7 +197,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat | |||
197 | string fromName = c.From; | 197 | string fromName = c.From; |
198 | string fromNamePrefix = ""; | 198 | string fromNamePrefix = ""; |
199 | UUID fromID = UUID.Zero; | 199 | UUID fromID = UUID.Zero; |
200 | UUID ownerID = UUID.Zero; | ||
201 | string message = c.Message; | 200 | string message = c.Message; |
202 | IScene scene = c.Scene; | 201 | IScene scene = c.Scene; |
203 | UUID destination = c.Destination; | 202 | UUID destination = c.Destination; |
@@ -225,16 +224,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat | |||
225 | fromNamePrefix = m_adminPrefix; | 224 | fromNamePrefix = m_adminPrefix; |
226 | } | 225 | } |
227 | destination = UUID.Zero; // Avatars cant "SayTo" | 226 | destination = UUID.Zero; // Avatars cant "SayTo" |
228 | ownerID = c.Sender.AgentId; | ||
229 | |||
230 | break; | 227 | break; |
231 | 228 | ||
232 | case ChatSourceType.Object: | 229 | case ChatSourceType.Object: |
233 | fromID = c.SenderUUID; | 230 | fromID = c.SenderUUID; |
234 | 231 | ||
235 | if (c.SenderObject != null && c.SenderObject is SceneObjectPart) | ||
236 | ownerID = ((SceneObjectPart)c.SenderObject).OwnerID; | ||
237 | |||
238 | break; | 232 | break; |
239 | } | 233 | } |
240 | 234 | ||
@@ -268,16 +262,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat | |||
268 | // objects on a parcel with access restrictions | 262 | // objects on a parcel with access restrictions |
269 | if (c.Sender == null || Presencecheck.IsEitherBannedOrRestricted(c.Sender.AgentId) != true) | 263 | if (c.Sender == null || Presencecheck.IsEitherBannedOrRestricted(c.Sender.AgentId) != true) |
270 | { | 264 | { |
271 | if (destination != UUID.Zero) | 265 | if (TrySendChatMessage(presence, fromPos, regionPos, fromID, fromNamePrefix + fromName, c.Type, message, sourceType)) |
272 | { | 266 | receiverIDs.Add(presence.UUID); |
273 | if (TrySendChatMessage(presence, fromPos, regionPos, fromID, ownerID, fromNamePrefix + fromName, c.Type, message, sourceType, true)) | ||
274 | receiverIDs.Add(presence.UUID); | ||
275 | } | ||
276 | else | ||
277 | { | ||
278 | if (TrySendChatMessage(presence, fromPos, regionPos, fromID, ownerID, fromNamePrefix + fromName, c.Type, message, sourceType, false)) | ||
279 | receiverIDs.Add(presence.UUID); | ||
280 | } | ||
281 | } | 267 | } |
282 | } | 268 | } |
283 | } | 269 | } |
@@ -338,7 +324,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat | |||
338 | (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId)) | 324 | (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId)) |
339 | return; | 325 | return; |
340 | 326 | ||
341 | client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID, fromID, | 327 | client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID, |
342 | (byte)sourceType, (byte)ChatAudibleLevel.Fully); | 328 | (byte)sourceType, (byte)ChatAudibleLevel.Fully); |
343 | receiverIDs.Add(client.AgentId); | 329 | receiverIDs.Add(client.AgentId); |
344 | } | 330 | } |
@@ -355,20 +341,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat | |||
355 | /// <param name="fromPos"></param> | 341 | /// <param name="fromPos"></param> |
356 | /// <param name="regionPos">/param> | 342 | /// <param name="regionPos">/param> |
357 | /// <param name="fromAgentID"></param> | 343 | /// <param name="fromAgentID"></param> |
358 | /// <param name='ownerID'> | ||
359 | /// Owner of the message. For at least some messages from objects, this has to be correctly filled with the owner's UUID. | ||
360 | /// This is the case for script error messages in viewer 3 since LLViewer change EXT-7762 | ||
361 | /// </param> | ||
362 | /// <param name="fromName"></param> | 344 | /// <param name="fromName"></param> |
363 | /// <param name="type"></param> | 345 | /// <param name="type"></param> |
364 | /// <param name="message"></param> | 346 | /// <param name="message"></param> |
365 | /// <param name="src"></param> | 347 | /// <param name="src"></param> |
366 | /// <returns>true if the message was sent to the receiver, false if it was not sent due to failing a | 348 | /// <returns>true if the message was sent to the receiver, false if it was not sent due to failing a |
367 | /// precondition</returns> | 349 | /// precondition</returns> |
368 | protected virtual bool TrySendChatMessage( | 350 | protected virtual bool TrySendChatMessage(ScenePresence presence, Vector3 fromPos, Vector3 regionPos, |
369 | ScenePresence presence, Vector3 fromPos, Vector3 regionPos, | 351 | UUID fromAgentID, string fromName, ChatTypeEnum type, |
370 | UUID fromAgentID, UUID ownerID, string fromName, ChatTypeEnum type, | 352 | string message, ChatSourceType src) |
371 | string message, ChatSourceType src, bool ignoreDistance) | ||
372 | { | 353 | { |
373 | // don't send chat to child agents | 354 | // don't send chat to child agents |
374 | if (presence.IsChildAgent) return false; | 355 | if (presence.IsChildAgent) return false; |
@@ -388,9 +369,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat | |||
388 | } | 369 | } |
389 | 370 | ||
390 | // TODO: should change so the message is sent through the avatar rather than direct to the ClientView | 371 | // TODO: should change so the message is sent through the avatar rather than direct to the ClientView |
391 | presence.ControllingClient.SendChatMessage( | 372 | presence.ControllingClient.SendChatMessage(message, (byte) type, fromPos, fromName, |
392 | message, (byte) type, fromPos, fromName, | 373 | fromAgentID, (byte)src, (byte)ChatAudibleLevel.Fully); |
393 | fromAgentID, ownerID, (byte)src, (byte)ChatAudibleLevel.Fully); | ||
394 | 374 | ||
395 | return true; | 375 | return true; |
396 | } | 376 | } |
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs index 5ec0ea9..d942e87 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs | |||
@@ -141,7 +141,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends | |||
141 | client.FirstName+" "+client.LastName, | 141 | client.FirstName+" "+client.LastName, |
142 | destID, (byte)211, false, | 142 | destID, (byte)211, false, |
143 | String.Empty, | 143 | String.Empty, |
144 | transactionID, false, new Vector3(), new byte[0], true), | 144 | transactionID, false, new Vector3(), new byte[0]), |
145 | delegate(bool success) {} ); | 145 | delegate(bool success) {} ); |
146 | } | 146 | } |
147 | } | 147 | } |
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index f1903c3..24ec435 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs | |||
@@ -28,7 +28,6 @@ | |||
28 | using System; | 28 | using System; |
29 | using System.Collections; | 29 | using System.Collections; |
30 | using System.Collections.Generic; | 30 | using System.Collections.Generic; |
31 | using System.Linq; | ||
32 | using System.Reflection; | 31 | using System.Reflection; |
33 | using System.Threading; | 32 | using System.Threading; |
34 | using log4net; | 33 | using log4net; |
@@ -483,9 +482,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends | |||
483 | Util.FireAndForget( | 482 | Util.FireAndForget( |
484 | delegate | 483 | delegate |
485 | { | 484 | { |
486 | // m_log.DebugFormat( | 485 | m_log.DebugFormat( |
487 | // "[FRIENDS MODULE]: Notifying {0} friends of {1} of online status {2}", | 486 | "[FRIENDS MODULE]: Notifying {0} friends of {1} of online status {2}", |
488 | // friendList.Count, agentID, online); | 487 | friendList.Count, agentID, online); |
489 | 488 | ||
490 | // Notify about this user status | 489 | // Notify about this user status |
491 | StatusNotify(friendList, agentID, online); | 490 | StatusNotify(friendList, agentID, online); |
@@ -496,36 +495,42 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends | |||
496 | 495 | ||
497 | protected virtual void StatusNotify(List<FriendInfo> friendList, UUID userID, bool online) | 496 | protected virtual void StatusNotify(List<FriendInfo> friendList, UUID userID, bool online) |
498 | { | 497 | { |
499 | List<string> friendStringIds = friendList.ConvertAll<string>(friend => friend.Friend); | 498 | foreach (FriendInfo friend in friendList) |
500 | List<string> remoteFriendStringIds = new List<string>(); | ||
501 | foreach (string friendStringId in friendStringIds) | ||
502 | { | 499 | { |
503 | UUID friendUuid; | 500 | UUID friendID; |
504 | if (UUID.TryParse(friendStringId, out friendUuid)) | 501 | if (UUID.TryParse(friend.Friend, out friendID)) |
505 | { | 502 | { |
506 | if (LocalStatusNotification(userID, friendUuid, online)) | 503 | // Try local |
504 | if (LocalStatusNotification(userID, friendID, online)) | ||
507 | continue; | 505 | continue; |
508 | 506 | ||
509 | remoteFriendStringIds.Add(friendStringId); | 507 | // The friend is not here [as root]. Let's forward. |
508 | PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() }); | ||
509 | if (friendSessions != null && friendSessions.Length > 0) | ||
510 | { | ||
511 | PresenceInfo friendSession = null; | ||
512 | foreach (PresenceInfo pinfo in friendSessions) | ||
513 | { | ||
514 | if (pinfo.RegionID != UUID.Zero) // let's guard against sessions-gone-bad | ||
515 | { | ||
516 | friendSession = pinfo; | ||
517 | break; | ||
518 | } | ||
519 | } | ||
520 | |||
521 | if (friendSession != null) | ||
522 | { | ||
523 | GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); | ||
524 | //m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName); | ||
525 | m_FriendsSimConnector.StatusNotify(region, userID, friendID, online); | ||
526 | } | ||
527 | } | ||
528 | |||
529 | // Friend is not online. Ignore. | ||
510 | } | 530 | } |
511 | else | 531 | else |
512 | { | 532 | { |
513 | m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friendStringId); | 533 | m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friend.Friend); |
514 | } | ||
515 | } | ||
516 | |||
517 | // We do this regrouping so that we can efficiently send a single request rather than one for each | ||
518 | // friend in what may be a very large friends list. | ||
519 | PresenceInfo[] friendSessions = PresenceService.GetAgents(remoteFriendStringIds.ToArray()); | ||
520 | |||
521 | foreach (PresenceInfo friendSession in friendSessions) | ||
522 | { | ||
523 | // let's guard against sessions-gone-bad | ||
524 | if (friendSession.RegionID != UUID.Zero) | ||
525 | { | ||
526 | GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); | ||
527 | //m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName); | ||
528 | m_FriendsSimConnector.StatusNotify(region, userID, friendSession.UserID, online); | ||
529 | } | 534 | } |
530 | } | 535 | } |
531 | } | 536 | } |
diff --git a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs index 82816d9..716cc69 100644 --- a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs | |||
@@ -206,7 +206,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods | |||
206 | transferModule.SendInstantMessage(new GridInstantMessage( | 206 | transferModule.SendInstantMessage(new GridInstantMessage( |
207 | m_scene, godID, "God", agentID, (byte)250, false, | 207 | m_scene, godID, "God", agentID, (byte)250, false, |
208 | Utils.BytesToString(reason), UUID.Zero, true, | 208 | Utils.BytesToString(reason), UUID.Zero, true, |
209 | new Vector3(), new byte[] {(byte)kickflags}, true), | 209 | new Vector3(), new byte[] {(byte)kickflags}), |
210 | delegate(bool success) {} ); | 210 | delegate(bool success) {} ); |
211 | } | 211 | } |
212 | return; | 212 | return; |
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs index d0e88f6..6587ead 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs | |||
@@ -166,7 +166,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
166 | 166 | ||
167 | if (options.ContainsKey("verbose")) | 167 | if (options.ContainsKey("verbose")) |
168 | m_log.InfoFormat( | 168 | m_log.InfoFormat( |
169 | "[INVENTORY ARCHIVER]: Saving item {0} {1} (asset UUID {2})", | 169 | "[INVENTORY ARCHIVER]: Saving item {0} {1} with asset {2}", |
170 | inventoryItem.ID, inventoryItem.Name, inventoryItem.AssetID); | 170 | inventoryItem.ID, inventoryItem.Name, inventoryItem.AssetID); |
171 | 171 | ||
172 | string filename = path + CreateArchiveItemName(inventoryItem); | 172 | string filename = path + CreateArchiveItemName(inventoryItem); |
@@ -337,14 +337,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
337 | { | 337 | { |
338 | m_log.DebugFormat("[INVENTORY ARCHIVER]: Saving {0} assets for items", m_assetUuids.Count); | 338 | m_log.DebugFormat("[INVENTORY ARCHIVER]: Saving {0} assets for items", m_assetUuids.Count); |
339 | 339 | ||
340 | AssetsRequest ar | 340 | new AssetsRequest( |
341 | = new AssetsRequest( | 341 | new AssetsArchiver(m_archiveWriter), |
342 | new AssetsArchiver(m_archiveWriter), | 342 | m_assetUuids, m_scene.AssetService, |
343 | m_assetUuids, m_scene.AssetService, | 343 | m_scene.UserAccountService, m_scene.RegionInfo.ScopeID, |
344 | m_scene.UserAccountService, m_scene.RegionInfo.ScopeID, | 344 | options, ReceivedAllAssets).Execute(); |
345 | options, ReceivedAllAssets); | ||
346 | |||
347 | Util.FireAndForget(o => ar.Execute()); | ||
348 | } | 345 | } |
349 | else | 346 | else |
350 | { | 347 | { |
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs index 765b960..7d1fe68 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs | |||
@@ -35,7 +35,6 @@ using Nini.Config; | |||
35 | using OpenMetaverse; | 35 | using OpenMetaverse; |
36 | using OpenSim.Framework; | 36 | using OpenSim.Framework; |
37 | using OpenSim.Framework.Communications; | 37 | using OpenSim.Framework.Communications; |
38 | using OpenSim.Framework.Console; | ||
39 | using OpenSim.Region.Framework.Interfaces; | 38 | using OpenSim.Region.Framework.Interfaces; |
40 | using OpenSim.Region.Framework.Scenes; | 39 | using OpenSim.Region.Framework.Scenes; |
41 | using OpenSim.Services.Interfaces; | 40 | using OpenSim.Services.Interfaces; |
@@ -210,9 +209,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
210 | Guid id, string firstName, string lastName, string invPath, string pass, string savePath, | 209 | Guid id, string firstName, string lastName, string invPath, string pass, string savePath, |
211 | Dictionary<string, object> options) | 210 | Dictionary<string, object> options) |
212 | { | 211 | { |
213 | // if (!ConsoleUtil.CheckFileDoesNotExist(MainConsole.Instance, savePath)) | ||
214 | // return false; | ||
215 | |||
216 | if (m_scenes.Count > 0) | 212 | if (m_scenes.Count > 0) |
217 | { | 213 | { |
218 | UserAccount userInfo = GetUserInfo(firstName, lastName, pass); | 214 | UserAccount userInfo = GetUserInfo(firstName, lastName, pass); |
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs index 00727a4..1056865 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs | |||
@@ -82,25 +82,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests | |||
82 | 82 | ||
83 | protected string m_item1Name = "Ray Gun Item"; | 83 | protected string m_item1Name = "Ray Gun Item"; |
84 | protected string m_coaItemName = "Coalesced Item"; | 84 | protected string m_coaItemName = "Coalesced Item"; |
85 | 85 | ||
86 | [TestFixtureSetUp] | ||
87 | public void FixtureSetup() | ||
88 | { | ||
89 | // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread. | ||
90 | Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest; | ||
91 | |||
92 | ConstructDefaultIarBytesForTestLoad(); | ||
93 | } | ||
94 | |||
95 | [TestFixtureTearDown] | ||
96 | public void TearDown() | ||
97 | { | ||
98 | // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple | ||
99 | // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression | ||
100 | // tests really shouldn't). | ||
101 | Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; | ||
102 | } | ||
103 | |||
104 | [SetUp] | 86 | [SetUp] |
105 | public override void SetUp() | 87 | public override void SetUp() |
106 | { | 88 | { |
@@ -108,6 +90,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests | |||
108 | m_iarStream = new MemoryStream(m_iarStreamBytes); | 90 | m_iarStream = new MemoryStream(m_iarStreamBytes); |
109 | } | 91 | } |
110 | 92 | ||
93 | [TestFixtureSetUp] | ||
94 | public void FixtureSetup() | ||
95 | { | ||
96 | ConstructDefaultIarBytesForTestLoad(); | ||
97 | } | ||
98 | |||
111 | protected void ConstructDefaultIarBytesForTestLoad() | 99 | protected void ConstructDefaultIarBytesForTestLoad() |
112 | { | 100 | { |
113 | // log4net.Config.XmlConfigurator.Configure(); | 101 | // log4net.Config.XmlConfigurator.Configure(); |
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs index 06f6e49..b112b6d 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs | |||
@@ -49,7 +49,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests | |||
49 | { | 49 | { |
50 | [TestFixture] | 50 | [TestFixture] |
51 | public class InventoryArchiverTests : InventoryArchiveTestCase | 51 | public class InventoryArchiverTests : InventoryArchiveTestCase |
52 | { | 52 | { |
53 | protected TestScene m_scene; | 53 | protected TestScene m_scene; |
54 | protected InventoryArchiverModule m_archiverModule; | 54 | protected InventoryArchiverModule m_archiverModule; |
55 | 55 | ||
@@ -69,7 +69,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests | |||
69 | public void TestLoadCoalesecedItem() | 69 | public void TestLoadCoalesecedItem() |
70 | { | 70 | { |
71 | TestHelpers.InMethod(); | 71 | TestHelpers.InMethod(); |
72 | // TestHelpers.EnableLogging(); | 72 | // log4net.Config.XmlConfigurator.Configure(); |
73 | 73 | ||
74 | UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL1, "password"); | 74 | UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL1, "password"); |
75 | m_archiverModule.DearchiveInventory(m_uaLL1.FirstName, m_uaLL1.LastName, "/", "password", m_iarStream); | 75 | m_archiverModule.DearchiveInventory(m_uaLL1.FirstName, m_uaLL1.LastName, "/", "password", m_iarStream); |
@@ -350,38 +350,38 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests | |||
350 | Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL1.PrincipalID)); | 350 | Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL1.PrincipalID)); |
351 | } | 351 | } |
352 | 352 | ||
353 | // /// <summary> | 353 | /// <summary> |
354 | // /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where | 354 | /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where |
355 | // /// an account exists with the same name as the creator, though not the same id. | 355 | /// an account exists with the same name as the creator, though not the same id. |
356 | // /// </summary> | 356 | /// </summary> |
357 | // [Test] | 357 | [Test] |
358 | // public void TestLoadIarV0_1SameNameCreator() | 358 | public void TestLoadIarV0_1SameNameCreator() |
359 | // { | 359 | { |
360 | // TestHelpers.InMethod(); | 360 | TestHelpers.InMethod(); |
361 | // TestHelpers.EnableLogging(); | 361 | // log4net.Config.XmlConfigurator.Configure(); |
362 | // | 362 | |
363 | // UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "meowfood"); | 363 | UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "meowfood"); |
364 | // UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL2, "hampshire"); | 364 | UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL2, "hampshire"); |
365 | // | 365 | |
366 | // m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream); | 366 | m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream); |
367 | // InventoryItemBase foundItem1 | 367 | InventoryItemBase foundItem1 |
368 | // = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name); | 368 | = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name); |
369 | // | 369 | |
370 | // Assert.That( | 370 | Assert.That( |
371 | // foundItem1.CreatorId, Is.EqualTo(m_uaLL2.PrincipalID.ToString()), | 371 | foundItem1.CreatorId, Is.EqualTo(m_uaLL2.PrincipalID.ToString()), |
372 | // "Loaded item non-uuid creator doesn't match original"); | 372 | "Loaded item non-uuid creator doesn't match original"); |
373 | // Assert.That( | 373 | Assert.That( |
374 | // foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL2.PrincipalID), | 374 | foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL2.PrincipalID), |
375 | // "Loaded item uuid creator doesn't match original"); | 375 | "Loaded item uuid creator doesn't match original"); |
376 | // Assert.That(foundItem1.Owner, Is.EqualTo(m_uaMT.PrincipalID), | 376 | Assert.That(foundItem1.Owner, Is.EqualTo(m_uaMT.PrincipalID), |
377 | // "Loaded item owner doesn't match inventory reciever"); | 377 | "Loaded item owner doesn't match inventory reciever"); |
378 | // | 378 | |
379 | // AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString()); | 379 | AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString()); |
380 | // string xmlData = Utils.BytesToString(asset1.Data); | 380 | string xmlData = Utils.BytesToString(asset1.Data); |
381 | // SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); | 381 | SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); |
382 | // | 382 | |
383 | // Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL2.PrincipalID)); | 383 | Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL2.PrincipalID)); |
384 | // } | 384 | } |
385 | 385 | ||
386 | /// <summary> | 386 | /// <summary> |
387 | /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where | 387 | /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where |
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs index e26beec..8176989 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs | |||
@@ -38,15 +38,15 @@ using OpenSim.Services.Interfaces; | |||
38 | 38 | ||
39 | namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer | 39 | namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer |
40 | { | 40 | { |
41 | public class InventoryTransferModule : ISharedRegionModule | 41 | public class InventoryTransferModule : IInventoryTransferModule, ISharedRegionModule |
42 | { | 42 | { |
43 | private static readonly ILog m_log | 43 | private static readonly ILog m_log |
44 | = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 44 | = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
45 | 45 | ||
46 | /// <summary> | 46 | /// <summary> |
47 | private List<Scene> m_Scenelist = new List<Scene>(); | 47 | private List<Scene> m_Scenelist = new List<Scene>(); |
48 | // private Dictionary<UUID, Scene> m_AgentRegions = | 48 | private Dictionary<UUID, Scene> m_AgentRegions = |
49 | // new Dictionary<UUID, Scene>(); | 49 | new Dictionary<UUID, Scene>(); |
50 | 50 | ||
51 | private IMessageTransferModule m_TransferModule = null; | 51 | private IMessageTransferModule m_TransferModule = null; |
52 | private bool m_Enabled = true; | 52 | private bool m_Enabled = true; |
@@ -76,12 +76,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer | |||
76 | 76 | ||
77 | m_Scenelist.Add(scene); | 77 | m_Scenelist.Add(scene); |
78 | 78 | ||
79 | // scene.RegisterModuleInterface<IInventoryTransferModule>(this); | 79 | scene.RegisterModuleInterface<IInventoryTransferModule>(this); |
80 | 80 | ||
81 | scene.EventManager.OnNewClient += OnNewClient; | 81 | scene.EventManager.OnNewClient += OnNewClient; |
82 | // scene.EventManager.OnClientClosed += ClientLoggedOut; | 82 | scene.EventManager.OnClientClosed += ClientLoggedOut; |
83 | scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; | 83 | scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; |
84 | // scene.EventManager.OnSetRootAgentScene += OnSetRootAgentScene; | 84 | scene.EventManager.OnSetRootAgentScene += OnSetRootAgentScene; |
85 | } | 85 | } |
86 | 86 | ||
87 | public void RegionLoaded(Scene scene) | 87 | public void RegionLoaded(Scene scene) |
@@ -96,9 +96,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer | |||
96 | 96 | ||
97 | m_Scenelist.Clear(); | 97 | m_Scenelist.Clear(); |
98 | scene.EventManager.OnNewClient -= OnNewClient; | 98 | scene.EventManager.OnNewClient -= OnNewClient; |
99 | // scene.EventManager.OnClientClosed -= ClientLoggedOut; | 99 | scene.EventManager.OnClientClosed -= ClientLoggedOut; |
100 | scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage; | 100 | scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage; |
101 | // scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene; | 101 | scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene; |
102 | } | 102 | } |
103 | } | 103 | } |
104 | } | 104 | } |
@@ -106,9 +106,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer | |||
106 | public void RemoveRegion(Scene scene) | 106 | public void RemoveRegion(Scene scene) |
107 | { | 107 | { |
108 | scene.EventManager.OnNewClient -= OnNewClient; | 108 | scene.EventManager.OnNewClient -= OnNewClient; |
109 | // scene.EventManager.OnClientClosed -= ClientLoggedOut; | 109 | scene.EventManager.OnClientClosed -= ClientLoggedOut; |
110 | scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage; | 110 | scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage; |
111 | // scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene; | 111 | scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene; |
112 | m_Scenelist.Remove(scene); | 112 | m_Scenelist.Remove(scene); |
113 | } | 113 | } |
114 | 114 | ||
@@ -138,10 +138,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer | |||
138 | client.OnInstantMessage += OnInstantMessage; | 138 | client.OnInstantMessage += OnInstantMessage; |
139 | } | 139 | } |
140 | 140 | ||
141 | // protected void OnSetRootAgentScene(UUID id, Scene scene) | 141 | protected void OnSetRootAgentScene(UUID id, Scene scene) |
142 | // { | 142 | { |
143 | // m_AgentRegions[id] = scene; | 143 | m_AgentRegions[id] = scene; |
144 | // } | 144 | } |
145 | 145 | ||
146 | private Scene FindClientScene(UUID agentId) | 146 | private Scene FindClientScene(UUID agentId) |
147 | { | 147 | { |
@@ -313,11 +313,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer | |||
313 | m_TransferModule.SendInstantMessage(im, delegate(bool success) {}); | 313 | m_TransferModule.SendInstantMessage(im, delegate(bool success) {}); |
314 | } | 314 | } |
315 | } | 315 | } |
316 | |||
317 | // XXX: This code was placed here to try and accomdate RLV which moves given folders named #RLV/~<name> | ||
318 | // to a folder called name in #RLV. However, this approach may not be ultimately correct - from analysis | ||
319 | // of Firestorm 4.2.2 on sending an InventoryOffered instead of TaskInventoryOffered (as was previously | ||
320 | // done), the viewer itself would appear to move and rename the folder, rather than the simulator doing it here. | ||
321 | else if (im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted) | 316 | else if (im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted) |
322 | { | 317 | { |
323 | UUID destinationFolderID = UUID.Zero; | 318 | UUID destinationFolderID = UUID.Zero; |
@@ -329,16 +324,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer | |||
329 | 324 | ||
330 | if (destinationFolderID != UUID.Zero) | 325 | if (destinationFolderID != UUID.Zero) |
331 | { | 326 | { |
332 | InventoryFolderBase destinationFolder = new InventoryFolderBase(destinationFolderID, client.AgentId); | ||
333 | if (destinationFolder == null) | ||
334 | { | ||
335 | m_log.WarnFormat( | ||
336 | "[INVENTORY TRANSFER]: TaskInventoryAccepted message from {0} in {1} specified folder {2} which does not exist", | ||
337 | client.Name, scene.Name, destinationFolderID); | ||
338 | |||
339 | return; | ||
340 | } | ||
341 | |||
342 | IInventoryService invService = scene.InventoryService; | 327 | IInventoryService invService = scene.InventoryService; |
343 | 328 | ||
344 | UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip | 329 | UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip |
@@ -346,11 +331,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer | |||
346 | InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId); | 331 | InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId); |
347 | item = invService.GetItem(item); | 332 | item = invService.GetItem(item); |
348 | InventoryFolderBase folder = null; | 333 | InventoryFolderBase folder = null; |
349 | UUID? previousParentFolderID = null; | ||
350 | 334 | ||
351 | if (item != null) // It's an item | 335 | if (item != null) // It's an item |
352 | { | 336 | { |
353 | previousParentFolderID = item.Folder; | ||
354 | item.Folder = destinationFolderID; | 337 | item.Folder = destinationFolderID; |
355 | 338 | ||
356 | invService.DeleteItems(item.Owner, new List<UUID>() { item.ID }); | 339 | invService.DeleteItems(item.Owner, new List<UUID>() { item.ID }); |
@@ -363,22 +346,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer | |||
363 | 346 | ||
364 | if (folder != null) // It's a folder | 347 | if (folder != null) // It's a folder |
365 | { | 348 | { |
366 | previousParentFolderID = folder.ParentID; | ||
367 | folder.ParentID = destinationFolderID; | 349 | folder.ParentID = destinationFolderID; |
368 | invService.MoveFolder(folder); | 350 | invService.MoveFolder(folder); |
369 | } | 351 | } |
370 | } | 352 | } |
371 | |||
372 | // Tell client about updates to original parent and new parent (this should probably be factored with existing move item/folder code). | ||
373 | if (previousParentFolderID != null) | ||
374 | { | ||
375 | InventoryFolderBase previousParentFolder | ||
376 | = new InventoryFolderBase((UUID)previousParentFolderID, client.AgentId); | ||
377 | previousParentFolder = invService.GetFolder(previousParentFolder); | ||
378 | scene.SendInventoryUpdate(client, previousParentFolder, true, true); | ||
379 | |||
380 | scene.SendInventoryUpdate(client, destinationFolder, true, true); | ||
381 | } | ||
382 | } | 353 | } |
383 | } | 354 | } |
384 | else if ( | 355 | else if ( |
@@ -399,11 +370,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer | |||
399 | InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId); | 370 | InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId); |
400 | item = invService.GetItem(item); | 371 | item = invService.GetItem(item); |
401 | InventoryFolderBase folder = null; | 372 | InventoryFolderBase folder = null; |
402 | UUID? previousParentFolderID = null; | ||
403 | 373 | ||
404 | if (item != null && trashFolder != null) | 374 | if (item != null && trashFolder != null) |
405 | { | 375 | { |
406 | previousParentFolderID = item.Folder; | ||
407 | item.Folder = trashFolder.ID; | 376 | item.Folder = trashFolder.ID; |
408 | 377 | ||
409 | // Diva comment: can't we just update this item??? | 378 | // Diva comment: can't we just update this item??? |
@@ -419,7 +388,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer | |||
419 | 388 | ||
420 | if (folder != null & trashFolder != null) | 389 | if (folder != null & trashFolder != null) |
421 | { | 390 | { |
422 | previousParentFolderID = folder.ParentID; | ||
423 | folder.ParentID = trashFolder.ID; | 391 | folder.ParentID = trashFolder.ID; |
424 | invService.MoveFolder(folder); | 392 | invService.MoveFolder(folder); |
425 | client.SendBulkUpdateInventory(folder); | 393 | client.SendBulkUpdateInventory(folder); |
@@ -440,16 +408,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer | |||
440 | client.SendAgentAlertMessage("Unable to delete "+ | 408 | client.SendAgentAlertMessage("Unable to delete "+ |
441 | "received inventory" + reason, false); | 409 | "received inventory" + reason, false); |
442 | } | 410 | } |
443 | // Tell client about updates to original parent and new parent (this should probably be factored with existing move item/folder code). | ||
444 | else if (previousParentFolderID != null) | ||
445 | { | ||
446 | InventoryFolderBase previousParentFolder | ||
447 | = new InventoryFolderBase((UUID)previousParentFolderID, client.AgentId); | ||
448 | previousParentFolder = invService.GetFolder(previousParentFolder); | ||
449 | scene.SendInventoryUpdate(client, previousParentFolder, true, true); | ||
450 | |||
451 | scene.SendInventoryUpdate(client, trashFolder, true, true); | ||
452 | } | ||
453 | 411 | ||
454 | if (im.dialog == (byte)InstantMessageDialog.InventoryDeclined) | 412 | if (im.dialog == (byte)InstantMessageDialog.InventoryDeclined) |
455 | { | 413 | { |
@@ -468,69 +426,69 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer | |||
468 | } | 426 | } |
469 | } | 427 | } |
470 | 428 | ||
471 | // public bool NeedSceneCacheClear(UUID agentID, Scene scene) | 429 | public bool NeedSceneCacheClear(UUID agentID, Scene scene) |
472 | // { | 430 | { |
473 | // if (!m_AgentRegions.ContainsKey(agentID)) | 431 | if (!m_AgentRegions.ContainsKey(agentID)) |
474 | // { | 432 | { |
475 | // // Since we can get here two ways, we need to scan | 433 | // Since we can get here two ways, we need to scan |
476 | // // the scenes here. This is somewhat more expensive | 434 | // the scenes here. This is somewhat more expensive |
477 | // // but helps avoid a nasty bug | 435 | // but helps avoid a nasty bug |
478 | // // | 436 | // |
479 | // | 437 | |
480 | // foreach (Scene s in m_Scenelist) | 438 | foreach (Scene s in m_Scenelist) |
481 | // { | 439 | { |
482 | // ScenePresence presence; | 440 | ScenePresence presence; |
483 | // | 441 | |
484 | // if (s.TryGetScenePresence(agentID, out presence)) | 442 | if (s.TryGetScenePresence(agentID, out presence)) |
485 | // { | 443 | { |
486 | // // If the agent is in this scene, then we | 444 | // If the agent is in this scene, then we |
487 | // // are being called twice in a single | 445 | // are being called twice in a single |
488 | // // teleport. This is wasteful of cycles | 446 | // teleport. This is wasteful of cycles |
489 | // // but harmless due to this 2nd level check | 447 | // but harmless due to this 2nd level check |
490 | // // | 448 | // |
491 | // // If the agent is found in another scene | 449 | // If the agent is found in another scene |
492 | // // then the list wasn't current | 450 | // then the list wasn't current |
493 | // // | 451 | // |
494 | // // If the agent is totally unknown, then what | 452 | // If the agent is totally unknown, then what |
495 | // // are we even doing here?? | 453 | // are we even doing here?? |
496 | // // | 454 | // |
497 | // if (s == scene) | 455 | if (s == scene) |
498 | // { | 456 | { |
499 | // //m_log.Debug("[INVTRANSFERMOD]: s == scene. Returning true in " + scene.RegionInfo.RegionName); | 457 | //m_log.Debug("[INVTRANSFERMOD]: s == scene. Returning true in " + scene.RegionInfo.RegionName); |
500 | // return true; | 458 | return true; |
501 | // } | 459 | } |
502 | // else | 460 | else |
503 | // { | 461 | { |
504 | // //m_log.Debug("[INVTRANSFERMOD]: s != scene. Returning false in " + scene.RegionInfo.RegionName); | 462 | //m_log.Debug("[INVTRANSFERMOD]: s != scene. Returning false in " + scene.RegionInfo.RegionName); |
505 | // return false; | 463 | return false; |
506 | // } | 464 | } |
507 | // } | 465 | } |
508 | // } | 466 | } |
509 | // //m_log.Debug("[INVTRANSFERMOD]: agent not in scene. Returning true in " + scene.RegionInfo.RegionName); | 467 | //m_log.Debug("[INVTRANSFERMOD]: agent not in scene. Returning true in " + scene.RegionInfo.RegionName); |
510 | // return true; | 468 | return true; |
511 | // } | 469 | } |
512 | // | 470 | |
513 | // // The agent is left in current Scene, so we must be | 471 | // The agent is left in current Scene, so we must be |
514 | // // going to another instance | 472 | // going to another instance |
515 | // // | 473 | // |
516 | // if (m_AgentRegions[agentID] == scene) | 474 | if (m_AgentRegions[agentID] == scene) |
517 | // { | 475 | { |
518 | // //m_log.Debug("[INVTRANSFERMOD]: m_AgentRegions[agentID] == scene. Returning true in " + scene.RegionInfo.RegionName); | 476 | //m_log.Debug("[INVTRANSFERMOD]: m_AgentRegions[agentID] == scene. Returning true in " + scene.RegionInfo.RegionName); |
519 | // m_AgentRegions.Remove(agentID); | 477 | m_AgentRegions.Remove(agentID); |
520 | // return true; | 478 | return true; |
521 | // } | 479 | } |
522 | // | 480 | |
523 | // // Another region has claimed the agent | 481 | // Another region has claimed the agent |
524 | // // | 482 | // |
525 | // //m_log.Debug("[INVTRANSFERMOD]: last resort. Returning false in " + scene.RegionInfo.RegionName); | 483 | //m_log.Debug("[INVTRANSFERMOD]: last resort. Returning false in " + scene.RegionInfo.RegionName); |
526 | // return false; | 484 | return false; |
527 | // } | 485 | } |
528 | // | 486 | |
529 | // public void ClientLoggedOut(UUID agentID, Scene scene) | 487 | public void ClientLoggedOut(UUID agentID, Scene scene) |
530 | // { | 488 | { |
531 | // if (m_AgentRegions.ContainsKey(agentID)) | 489 | if (m_AgentRegions.ContainsKey(agentID)) |
532 | // m_AgentRegions.Remove(agentID); | 490 | m_AgentRegions.Remove(agentID); |
533 | // } | 491 | } |
534 | 492 | ||
535 | /// <summary> | 493 | /// <summary> |
536 | /// | 494 | /// |
diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs index 9c369f6..92cf9d1 100644 --- a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs | |||
@@ -186,7 +186,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure | |||
186 | client.FirstName+" "+client.LastName, targetid, | 186 | client.FirstName+" "+client.LastName, targetid, |
187 | (byte)InstantMessageDialog.RequestTeleport, false, | 187 | (byte)InstantMessageDialog.RequestTeleport, false, |
188 | message, sessionID, false, presence.AbsolutePosition, | 188 | message, sessionID, false, presence.AbsolutePosition, |
189 | new Byte[0], true); | 189 | new Byte[0]); |
190 | m.RegionID = client.Scene.RegionInfo.RegionID.Guid; | 190 | m.RegionID = client.Scene.RegionInfo.RegionID.Guid; |
191 | 191 | ||
192 | m_log.DebugFormat("[HG LURE MODULE]: RequestTeleport sessionID={0}, regionID={1}, message={2}", m.imSessionID, m.RegionID, m.message); | 192 | m_log.DebugFormat("[HG LURE MODULE]: RequestTeleport sessionID={0}, regionID={1}, message={2}", m.imSessionID, m.RegionID, m.message); |
diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs index 1949459..a889984 100644 --- a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs | |||
@@ -173,7 +173,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure | |||
173 | client.FirstName+" "+client.LastName, targetid, | 173 | client.FirstName+" "+client.LastName, targetid, |
174 | (byte)InstantMessageDialog.GodLikeRequestTeleport, false, | 174 | (byte)InstantMessageDialog.GodLikeRequestTeleport, false, |
175 | message, dest, false, presence.AbsolutePosition, | 175 | message, dest, false, presence.AbsolutePosition, |
176 | new Byte[0], true); | 176 | new Byte[0]); |
177 | } | 177 | } |
178 | else | 178 | else |
179 | { | 179 | { |
@@ -181,7 +181,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure | |||
181 | client.FirstName+" "+client.LastName, targetid, | 181 | client.FirstName+" "+client.LastName, targetid, |
182 | (byte)InstantMessageDialog.RequestTeleport, false, | 182 | (byte)InstantMessageDialog.RequestTeleport, false, |
183 | message, dest, false, presence.AbsolutePosition, | 183 | message, dest, false, presence.AbsolutePosition, |
184 | new Byte[0], true); | 184 | new Byte[0]); |
185 | } | 185 | } |
186 | 186 | ||
187 | if (m_TransferModule != null) | 187 | if (m_TransferModule != null) |
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 31e6ce9..880b2cc 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs | |||
@@ -327,14 +327,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
327 | return; | 327 | return; |
328 | } | 328 | } |
329 | 329 | ||
330 | // Validate assorted conditions | ||
331 | string reason = string.Empty; | ||
332 | if (!ValidateGenericConditions(sp, reg, finalDestination, teleportFlags, out reason)) | ||
333 | { | ||
334 | sp.ControllingClient.SendTeleportFailed(reason); | ||
335 | return; | ||
336 | } | ||
337 | |||
338 | // | 330 | // |
339 | // This is it | 331 | // This is it |
340 | // | 332 | // |
@@ -366,13 +358,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
366 | } | 358 | } |
367 | } | 359 | } |
368 | 360 | ||
369 | // Nothing to validate here | ||
370 | protected virtual bool ValidateGenericConditions(ScenePresence sp, GridRegion reg, GridRegion finalDestination, uint teleportFlags, out string reason) | ||
371 | { | ||
372 | reason = String.Empty; | ||
373 | return true; | ||
374 | } | ||
375 | |||
376 | /// <summary> | 361 | /// <summary> |
377 | /// Determines whether this instance is within the max transfer distance. | 362 | /// Determines whether this instance is within the max transfer distance. |
378 | /// </summary> | 363 | /// </summary> |
@@ -488,11 +473,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
488 | // both regions | 473 | // both regions |
489 | if (sp.ParentID != (uint)0) | 474 | if (sp.ParentID != (uint)0) |
490 | sp.StandUp(); | 475 | sp.StandUp(); |
476 | |||
491 | else if (sp.Flying) | 477 | else if (sp.Flying) |
492 | teleportFlags |= (uint)TeleportFlags.IsFlying; | 478 | teleportFlags |= (uint)TeleportFlags.IsFlying; |
493 | 479 | ||
494 | // At least on LL 3.3.4, this is not strictly necessary - a teleport will succeed without sending this to | ||
495 | // the viewer. However, it might mean that the viewer does not see the black teleport screen (untested). | ||
496 | sp.ControllingClient.SendTeleportStart(teleportFlags); | 480 | sp.ControllingClient.SendTeleportStart(teleportFlags); |
497 | 481 | ||
498 | // the avatar.Close below will clear the child region list. We need this below for (possibly) | 482 | // the avatar.Close below will clear the child region list. We need this below for (possibly) |
@@ -568,11 +552,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
568 | // So let's wait | 552 | // So let's wait |
569 | Thread.Sleep(200); | 553 | Thread.Sleep(200); |
570 | 554 | ||
571 | // At least on LL 3.3.4 for teleports between different regions on the same simulator this appears | ||
572 | // unnecessary - teleport will succeed and SEED caps will be requested without it (though possibly | ||
573 | // only on TeleportFinish). This is untested for region teleport between different simulators | ||
574 | // though this probably also works. | ||
575 | m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath); | 555 | m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath); |
556 | |||
576 | } | 557 | } |
577 | else | 558 | else |
578 | { | 559 | { |
@@ -593,7 +574,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
593 | 574 | ||
594 | //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Updating agent..."); | 575 | //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Updating agent..."); |
595 | 576 | ||
596 | if (!UpdateAgent(reg, finalDestination, agent, sp)) | 577 | if (!UpdateAgent(reg, finalDestination, agent)) |
597 | { | 578 | { |
598 | // Region doesn't take it | 579 | // Region doesn't take it |
599 | m_log.WarnFormat( | 580 | m_log.WarnFormat( |
@@ -669,7 +650,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
669 | // an agent cannot teleport back to this region if it has teleported away. | 650 | // an agent cannot teleport back to this region if it has teleported away. |
670 | Thread.Sleep(3000); | 651 | Thread.Sleep(3000); |
671 | 652 | ||
672 | sp.Scene.IncomingCloseAgent(sp.UUID, false); | 653 | sp.Scene.IncomingCloseAgent(sp.UUID); |
673 | } | 654 | } |
674 | else | 655 | else |
675 | { | 656 | { |
@@ -677,14 +658,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
677 | sp.Reset(); | 658 | sp.Reset(); |
678 | } | 659 | } |
679 | 660 | ||
680 | // Commented pending deletion since this method no longer appears to do anything at all | 661 | // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! |
681 | // // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! | 662 | if (sp.Scene.NeedSceneCacheClear(sp.UUID)) |
682 | // if (sp.Scene.NeedSceneCacheClear(sp.UUID)) | 663 | { |
683 | // { | 664 | m_log.DebugFormat( |
684 | // m_log.DebugFormat( | 665 | "[ENTITY TRANSFER MODULE]: User {0} is going to another region, profile cache removed", |
685 | // "[ENTITY TRANSFER MODULE]: User {0} is going to another region, profile cache removed", | 666 | sp.UUID); |
686 | // sp.UUID); | 667 | } |
687 | // } | ||
688 | 668 | ||
689 | m_entityTransferStateMachine.ResetFromTransit(sp.UUID); | 669 | m_entityTransferStateMachine.ResetFromTransit(sp.UUID); |
690 | } | 670 | } |
@@ -721,7 +701,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
721 | return success; | 701 | return success; |
722 | } | 702 | } |
723 | 703 | ||
724 | protected virtual bool UpdateAgent(GridRegion reg, GridRegion finalDestination, AgentData agent, ScenePresence sp) | 704 | protected virtual bool UpdateAgent(GridRegion reg, GridRegion finalDestination, AgentData agent) |
725 | { | 705 | { |
726 | return Scene.SimulationService.UpdateAgent(finalDestination, agent); | 706 | return Scene.SimulationService.UpdateAgent(finalDestination, agent); |
727 | } | 707 | } |
@@ -1033,7 +1013,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1033 | Scene initiatingScene) | 1013 | Scene initiatingScene) |
1034 | { | 1014 | { |
1035 | Thread.Sleep(10000); | 1015 | Thread.Sleep(10000); |
1036 | |||
1037 | IMessageTransferModule im = initiatingScene.RequestModuleInterface<IMessageTransferModule>(); | 1016 | IMessageTransferModule im = initiatingScene.RequestModuleInterface<IMessageTransferModule>(); |
1038 | if (im != null) | 1017 | if (im != null) |
1039 | { | 1018 | { |
@@ -1046,22 +1025,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1046 | (uint)(int)position.X, | 1025 | (uint)(int)position.X, |
1047 | (uint)(int)position.Y, | 1026 | (uint)(int)position.Y, |
1048 | (uint)(int)position.Z); | 1027 | (uint)(int)position.Z); |
1049 | 1028 | GridInstantMessage m = new GridInstantMessage(initiatingScene, UUID.Zero, | |
1050 | GridInstantMessage m | 1029 | "Region", agent.UUID, |
1051 | = new GridInstantMessage( | 1030 | (byte)InstantMessageDialog.GodLikeRequestTeleport, false, |
1052 | initiatingScene, | 1031 | "", gotoLocation, false, new Vector3(127, 0, 0), |
1053 | UUID.Zero, | 1032 | new Byte[0]); |
1054 | "Region", | ||
1055 | agent.UUID, | ||
1056 | (byte)InstantMessageDialog.GodLikeRequestTeleport, | ||
1057 | false, | ||
1058 | "", | ||
1059 | gotoLocation, | ||
1060 | false, | ||
1061 | new Vector3(127, 0, 0), | ||
1062 | new Byte[0], | ||
1063 | false); | ||
1064 | |||
1065 | im.SendInstantMessage(m, delegate(bool success) | 1033 | im.SendInstantMessage(m, delegate(bool success) |
1066 | { | 1034 | { |
1067 | m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Client Initiating Teleport sending IM success = {0}", success); | 1035 | m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Client Initiating Teleport sending IM success = {0}", success); |
@@ -1223,11 +1191,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1223 | // the user may change their profile information in other region, | 1191 | // the user may change their profile information in other region, |
1224 | // so the userinfo in UserProfileCache is not reliable any more, delete it | 1192 | // so the userinfo in UserProfileCache is not reliable any more, delete it |
1225 | // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! | 1193 | // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! |
1226 | // if (agent.Scene.NeedSceneCacheClear(agent.UUID)) | 1194 | if (agent.Scene.NeedSceneCacheClear(agent.UUID)) |
1227 | // { | 1195 | { |
1228 | // m_log.DebugFormat( | 1196 | m_log.DebugFormat( |
1229 | // "[ENTITY TRANSFER MODULE]: User {0} is going to another region", agent.UUID); | 1197 | "[ENTITY TRANSFER MODULE]: User {0} is going to another region", agent.UUID); |
1230 | // } | 1198 | } |
1231 | 1199 | ||
1232 | //m_log.Debug("AFTER CROSS"); | 1200 | //m_log.Debug("AFTER CROSS"); |
1233 | //Scene.DumpChildrenSeeds(UUID); | 1201 | //Scene.DumpChildrenSeeds(UUID); |
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index b16c37a..3010b59 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs | |||
@@ -54,59 +54,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
54 | 54 | ||
55 | private GatekeeperServiceConnector m_GatekeeperConnector; | 55 | private GatekeeperServiceConnector m_GatekeeperConnector; |
56 | 56 | ||
57 | protected bool m_RestrictAppearanceAbroad; | ||
58 | protected string m_AccountName; | ||
59 | protected List<AvatarAppearance> m_ExportedAppearances; | ||
60 | protected List<AvatarAttachment> m_Attachs; | ||
61 | |||
62 | protected List<AvatarAppearance> ExportedAppearance | ||
63 | { | ||
64 | get | ||
65 | { | ||
66 | if (m_ExportedAppearances != null) | ||
67 | return m_ExportedAppearances; | ||
68 | |||
69 | m_ExportedAppearances = new List<AvatarAppearance>(); | ||
70 | m_Attachs = new List<AvatarAttachment>(); | ||
71 | |||
72 | string[] names = m_AccountName.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); | ||
73 | |||
74 | foreach (string name in names) | ||
75 | { | ||
76 | string[] parts = name.Trim().Split(); | ||
77 | if (parts.Length != 2) | ||
78 | { | ||
79 | m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Wrong user account name format {0}. Specify 'First Last'", name); | ||
80 | return null; | ||
81 | } | ||
82 | UserAccount account = Scene.UserAccountService.GetUserAccount(UUID.Zero, parts[0], parts[1]); | ||
83 | if (account == null) | ||
84 | { | ||
85 | m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unknown account {0}", m_AccountName); | ||
86 | return null; | ||
87 | } | ||
88 | AvatarAppearance a = Scene.AvatarService.GetAppearance(account.PrincipalID); | ||
89 | if (a != null) | ||
90 | m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Successfully retrieved appearance for {0}", name); | ||
91 | |||
92 | foreach (AvatarAttachment att in a.GetAttachments()) | ||
93 | { | ||
94 | InventoryItemBase item = new InventoryItemBase(att.ItemID, account.PrincipalID); | ||
95 | item = Scene.InventoryService.GetItem(item); | ||
96 | if (item != null) | ||
97 | a.SetAttachment(att.AttachPoint, att.ItemID, item.AssetID); | ||
98 | else | ||
99 | m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unable to retrieve item {0} from inventory {1}", att.ItemID, name); | ||
100 | } | ||
101 | |||
102 | m_ExportedAppearances.Add(a); | ||
103 | m_Attachs.AddRange(a.GetAttachments()); | ||
104 | } | ||
105 | |||
106 | return m_ExportedAppearances; | ||
107 | } | ||
108 | } | ||
109 | |||
110 | #region ISharedRegionModule | 57 | #region ISharedRegionModule |
111 | 58 | ||
112 | public override string Name | 59 | public override string Name |
@@ -125,18 +72,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
125 | { | 72 | { |
126 | IConfig transferConfig = source.Configs["EntityTransfer"]; | 73 | IConfig transferConfig = source.Configs["EntityTransfer"]; |
127 | if (transferConfig != null) | 74 | if (transferConfig != null) |
128 | { | ||
129 | m_levelHGTeleport = transferConfig.GetInt("LevelHGTeleport", 0); | 75 | m_levelHGTeleport = transferConfig.GetInt("LevelHGTeleport", 0); |
130 | 76 | ||
131 | m_RestrictAppearanceAbroad = transferConfig.GetBoolean("RestrictAppearanceAbroad", false); | ||
132 | if (m_RestrictAppearanceAbroad) | ||
133 | { | ||
134 | m_AccountName = transferConfig.GetString("AccountForAppearance", string.Empty); | ||
135 | if (m_AccountName == string.Empty) | ||
136 | m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: RestrictAppearanceAbroad is on, but no account has been given for avatar appearance!"); | ||
137 | } | ||
138 | } | ||
139 | |||
140 | InitialiseCommon(source); | 77 | InitialiseCommon(source); |
141 | m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: {0} enabled.", Name); | 78 | m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: {0} enabled.", Name); |
142 | } | 79 | } |
@@ -148,36 +85,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
148 | base.AddRegion(scene); | 85 | base.AddRegion(scene); |
149 | 86 | ||
150 | if (m_Enabled) | 87 | if (m_Enabled) |
151 | { | ||
152 | scene.RegisterModuleInterface<IUserAgentVerificationModule>(this); | 88 | scene.RegisterModuleInterface<IUserAgentVerificationModule>(this); |
153 | scene.EventManager.OnIncomingSceneObject += OnIncomingSceneObject; | ||
154 | } | ||
155 | } | ||
156 | |||
157 | void OnIncomingSceneObject(SceneObjectGroup so) | ||
158 | { | ||
159 | if (!so.IsAttachment) | ||
160 | return; | ||
161 | |||
162 | if (so.Scene.UserManagementModule.IsLocalGridUser(so.AttachedAvatar)) | ||
163 | return; | ||
164 | |||
165 | // foreign user | ||
166 | AgentCircuitData aCircuit = so.Scene.AuthenticateHandler.GetAgentCircuitData(so.AttachedAvatar); | ||
167 | if (aCircuit != null && (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0) | ||
168 | { | ||
169 | if (aCircuit.ServiceURLs != null && aCircuit.ServiceURLs.ContainsKey("AssetServerURI")) | ||
170 | { | ||
171 | string url = aCircuit.ServiceURLs["AssetServerURI"].ToString(); | ||
172 | m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Incoming attachement {0} for HG user {1} with asset server {2}", so.Name, so.AttachedAvatar, url); | ||
173 | Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>(); | ||
174 | HGUuidGatherer uuidGatherer = new HGUuidGatherer(so.Scene.AssetService, url); | ||
175 | uuidGatherer.GatherAssetUuids(so, ids); | ||
176 | |||
177 | foreach (KeyValuePair<UUID, AssetType> kvp in ids) | ||
178 | uuidGatherer.FetchAsset(kvp.Key); | ||
179 | } | ||
180 | } | ||
181 | } | 89 | } |
182 | 90 | ||
183 | protected override void OnNewClient(IClientAPI client) | 91 | protected override void OnNewClient(IClientAPI client) |
@@ -212,7 +120,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
212 | int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, region.RegionID); | 120 | 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); | 121 | m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: region {0} flags: {1}", region.RegionID, flags); |
214 | 122 | ||
215 | if ((flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0) | 123 | if ((flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0) |
216 | { | 124 | { |
217 | m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Destination region {0} is hyperlink", region.RegionID); | 125 | m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Destination region {0} is hyperlink", region.RegionID); |
218 | GridRegion real_destination = m_GatekeeperConnector.GetHyperlinkRegion(region, region.RegionID); | 126 | GridRegion real_destination = m_GatekeeperConnector.GetHyperlinkRegion(region, region.RegionID); |
@@ -232,7 +140,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
232 | return true; | 140 | return true; |
233 | 141 | ||
234 | int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID); | 142 | int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID); |
235 | if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0) | 143 | if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0) |
236 | return true; | 144 | return true; |
237 | 145 | ||
238 | return false; | 146 | return false; |
@@ -245,8 +153,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
245 | { | 153 | { |
246 | // Log them out of this grid | 154 | // Log them out of this grid |
247 | Scene.PresenceService.LogoutAgent(sp.ControllingClient.SessionId); | 155 | Scene.PresenceService.LogoutAgent(sp.ControllingClient.SessionId); |
248 | string userId = Scene.UserManagementModule.GetUserUUI(sp.UUID); | ||
249 | Scene.GridUserService.LoggedOut(userId, UUID.Zero, Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat); | ||
250 | } | 156 | } |
251 | } | 157 | } |
252 | 158 | ||
@@ -256,11 +162,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
256 | reason = string.Empty; | 162 | reason = string.Empty; |
257 | logout = false; | 163 | logout = false; |
258 | int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID); | 164 | int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID); |
259 | if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0) | 165 | if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0) |
260 | { | 166 | { |
261 | // this user is going to another grid | 167 | // this user is going to another grid |
262 | // for local users, check if HyperGrid teleport is allowed, based on user level | 168 | // check if HyperGrid teleport is allowed, based on user level |
263 | if (Scene.UserManagementModule.IsLocalGridUser(sp.UUID) && sp.UserLevel < m_levelHGTeleport) | 169 | if (sp.UserLevel < m_levelHGTeleport) |
264 | { | 170 | { |
265 | m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unable to HG teleport agent due to insufficient UserLevel."); | 171 | m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unable to HG teleport agent due to insufficient UserLevel."); |
266 | reason = "Hypergrid teleport not allowed"; | 172 | reason = "Hypergrid teleport not allowed"; |
@@ -294,124 +200,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
294 | TeleportHome(id, client); | 200 | TeleportHome(id, client); |
295 | } | 201 | } |
296 | 202 | ||
297 | protected override bool ValidateGenericConditions(ScenePresence sp, GridRegion reg, GridRegion finalDestination, uint teleportFlags, out string reason) | ||
298 | { | ||
299 | reason = "Please wear your grid's allowed appearance before teleporting to another grid"; | ||
300 | if (!m_RestrictAppearanceAbroad) | ||
301 | return true; | ||
302 | |||
303 | // The rest is only needed for controlling appearance | ||
304 | |||
305 | int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID); | ||
306 | if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0) | ||
307 | { | ||
308 | // this user is going to another grid | ||
309 | if (Scene.UserManagementModule.IsLocalGridUser(sp.UUID)) | ||
310 | { | ||
311 | m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: RestrictAppearanceAbroad is ON. Checking generic appearance"); | ||
312 | |||
313 | // Check wearables | ||
314 | for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++) | ||
315 | { | ||
316 | for (int j = 0; j < sp.Appearance.Wearables[i].Count; j++) | ||
317 | { | ||
318 | if (sp.Appearance.Wearables[i] == null) | ||
319 | continue; | ||
320 | |||
321 | bool found = false; | ||
322 | foreach (AvatarAppearance a in ExportedAppearance) | ||
323 | if (a.Wearables[i] != null) | ||
324 | { | ||
325 | found = true; | ||
326 | break; | ||
327 | } | ||
328 | |||
329 | if (!found) | ||
330 | { | ||
331 | m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Wearable not allowed to go outside {0}", i); | ||
332 | return false; | ||
333 | } | ||
334 | |||
335 | found = false; | ||
336 | foreach (AvatarAppearance a in ExportedAppearance) | ||
337 | if (sp.Appearance.Wearables[i][j].AssetID == a.Wearables[i][j].AssetID) | ||
338 | { | ||
339 | found = true; | ||
340 | break; | ||
341 | } | ||
342 | |||
343 | if (!found) | ||
344 | { | ||
345 | m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Wearable not allowed to go outside {0}", i); | ||
346 | return false; | ||
347 | } | ||
348 | } | ||
349 | } | ||
350 | |||
351 | // Check attachments | ||
352 | foreach (AvatarAttachment att in sp.Appearance.GetAttachments()) | ||
353 | { | ||
354 | bool found = false; | ||
355 | foreach (AvatarAttachment att2 in m_Attachs) | ||
356 | { | ||
357 | if (att2.AssetID == att.AssetID) | ||
358 | { | ||
359 | found = true; | ||
360 | break; | ||
361 | } | ||
362 | } | ||
363 | if (!found) | ||
364 | { | ||
365 | m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Attachment not allowed to go outside {0}", att.AttachPoint); | ||
366 | return false; | ||
367 | } | ||
368 | } | ||
369 | } | ||
370 | } | ||
371 | |||
372 | reason = string.Empty; | ||
373 | return true; | ||
374 | } | ||
375 | |||
376 | |||
377 | //protected override bool UpdateAgent(GridRegion reg, GridRegion finalDestination, AgentData agentData, ScenePresence sp) | ||
378 | //{ | ||
379 | // int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID); | ||
380 | // if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0) | ||
381 | // { | ||
382 | // // this user is going to another grid | ||
383 | // if (m_RestrictAppearanceAbroad && Scene.UserManagementModule.IsLocalGridUser(agentData.AgentID)) | ||
384 | // { | ||
385 | // // We need to strip the agent off its appearance | ||
386 | // m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: RestrictAppearanceAbroad is ON. Sending generic appearance"); | ||
387 | |||
388 | // // Delete existing npc attachments | ||
389 | // Scene.AttachmentsModule.DeleteAttachmentsFromScene(sp, false); | ||
390 | |||
391 | // // XXX: We can't just use IAvatarFactoryModule.SetAppearance() yet since it doesn't transfer attachments | ||
392 | // AvatarAppearance newAppearance = new AvatarAppearance(ExportedAppearance, true); | ||
393 | // sp.Appearance = newAppearance; | ||
394 | |||
395 | // // Rez needed npc attachments | ||
396 | // Scene.AttachmentsModule.RezAttachments(sp); | ||
397 | |||
398 | |||
399 | // IAvatarFactoryModule module = Scene.RequestModuleInterface<IAvatarFactoryModule>(); | ||
400 | // //module.SendAppearance(sp.UUID); | ||
401 | // module.RequestRebake(sp, false); | ||
402 | |||
403 | // Scene.AttachmentsModule.CopyAttachments(sp, agentData); | ||
404 | // agentData.Appearance = sp.Appearance; | ||
405 | // } | ||
406 | // } | ||
407 | |||
408 | // foreach (AvatarAttachment a in agentData.Appearance.GetAttachments()) | ||
409 | // m_log.DebugFormat("[XXX]: {0}-{1}", a.ItemID, a.AssetID); | ||
410 | |||
411 | |||
412 | // return base.UpdateAgent(reg, finalDestination, agentData, sp); | ||
413 | //} | ||
414 | |||
415 | public override bool TeleportHome(UUID id, IClientAPI client) | 203 | public override bool TeleportHome(UUID id, IClientAPI client) |
416 | { | 204 | { |
417 | m_log.DebugFormat( | 205 | m_log.DebugFormat( |
@@ -587,4 +375,4 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
587 | return region; | 375 | return region; |
588 | } | 376 | } |
589 | } | 377 | } |
590 | } | 378 | } \ No newline at end of file |
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs index f8ec6de..eaadc1b 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs | |||
@@ -71,19 +71,19 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
71 | 71 | ||
72 | #region Internal functions | 72 | #region Internal functions |
73 | 73 | ||
74 | public AssetMetadata FetchMetadata(string url, UUID assetID) | 74 | public AssetBase FetchAsset(string url, UUID assetID) |
75 | { | 75 | { |
76 | if (!url.EndsWith("/") && !url.EndsWith("=")) | 76 | if (!url.EndsWith("/") && !url.EndsWith("=")) |
77 | url = url + "/"; | 77 | url = url + "/"; |
78 | 78 | ||
79 | AssetMetadata meta = m_scene.AssetService.GetMetadata(url + assetID.ToString()); | 79 | AssetBase asset = m_scene.AssetService.Get(url + assetID.ToString()); |
80 | 80 | ||
81 | if (meta != null) | 81 | if (asset != null) |
82 | m_log.DebugFormat("[HG ASSET MAPPER]: Fetched metadata for asset {0} of type {1} from {2} ", assetID, meta.Type, url); | 82 | { |
83 | else | 83 | m_log.DebugFormat("[HG ASSET MAPPER]: Copied asset {0} from {1} to local asset server. ", asset.ID, url); |
84 | m_log.DebugFormat("[HG ASSET MAPPER]: Unable to fetched metadata for asset {0} from {1} ", assetID, url); | 84 | return asset; |
85 | 85 | } | |
86 | return meta; | 86 | return null; |
87 | } | 87 | } |
88 | 88 | ||
89 | public bool PostAsset(string url, AssetBase asset) | 89 | public bool PostAsset(string url, AssetBase asset) |
@@ -93,7 +93,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
93 | if (!url.EndsWith("/") && !url.EndsWith("=")) | 93 | if (!url.EndsWith("/") && !url.EndsWith("=")) |
94 | url = url + "/"; | 94 | url = url + "/"; |
95 | 95 | ||
96 | bool success = true; | ||
97 | // See long comment in AssetCache.AddAsset | 96 | // See long comment in AssetCache.AddAsset |
98 | if (!asset.Temporary || asset.Local) | 97 | if (!asset.Temporary || asset.Local) |
99 | { | 98 | { |
@@ -104,7 +103,14 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
104 | // not having a global naming infrastructure | 103 | // not having a global naming infrastructure |
105 | AssetBase asset1 = new AssetBase(asset.FullID, asset.Name, asset.Type, asset.Metadata.CreatorID); | 104 | AssetBase asset1 = new AssetBase(asset.FullID, asset.Name, asset.Type, asset.Metadata.CreatorID); |
106 | Copy(asset, asset1); | 105 | Copy(asset, asset1); |
107 | asset1.ID = url + asset.ID; | 106 | try |
107 | { | ||
108 | asset1.ID = url + asset.ID; | ||
109 | } | ||
110 | catch | ||
111 | { | ||
112 | m_log.Warn("[HG ASSET MAPPER]: Oops."); | ||
113 | } | ||
108 | 114 | ||
109 | AdjustIdentifiers(asset1.Metadata); | 115 | AdjustIdentifiers(asset1.Metadata); |
110 | if (asset1.Metadata.Type == (sbyte)AssetType.Object) | 116 | if (asset1.Metadata.Type == (sbyte)AssetType.Object) |
@@ -112,17 +118,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
112 | else | 118 | else |
113 | asset1.Data = asset.Data; | 119 | asset1.Data = asset.Data; |
114 | 120 | ||
115 | string id = m_scene.AssetService.Store(asset1); | 121 | m_scene.AssetService.Store(asset1); |
116 | if (id == string.Empty) | 122 | m_log.DebugFormat("[HG ASSET MAPPER]: Posted copy of asset {0} from local asset server to {1}", asset1.ID, url); |
117 | { | ||
118 | m_log.DebugFormat("[HG ASSET MAPPER]: Asset server {0} did not accept {1}", url, asset.ID); | ||
119 | success = false; | ||
120 | } | ||
121 | else | ||
122 | m_log.DebugFormat("[HG ASSET MAPPER]: Posted copy of asset {0} from local asset server to {1}", asset1.ID, url); | ||
123 | } | 123 | } |
124 | return success; | 124 | return true; |
125 | } | 125 | } |
126 | else | 126 | else |
127 | m_log.Warn("[HG ASSET MAPPER]: Tried to post asset to remote server, but asset not in local cache."); | 127 | m_log.Warn("[HG ASSET MAPPER]: Tried to post asset to remote server, but asset not in local cache."); |
128 | 128 | ||
@@ -222,17 +222,28 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
222 | 222 | ||
223 | public void Get(UUID assetID, UUID ownerID, string userAssetURL) | 223 | public void Get(UUID assetID, UUID ownerID, string userAssetURL) |
224 | { | 224 | { |
225 | // Get the item from the remote asset server onto the local AssetService | 225 | // Get the item from the remote asset server onto the local AssetCache |
226 | // and place an entry in m_assetMap | ||
227 | |||
228 | m_log.Debug("[HG ASSET MAPPER]: Fetching object " + assetID + " from asset server " + userAssetURL); | ||
229 | AssetBase asset = FetchAsset(userAssetURL, assetID); | ||
226 | 230 | ||
227 | AssetMetadata meta = FetchMetadata(userAssetURL, assetID); | 231 | if (asset != null) |
228 | if (meta == null) | 232 | { |
229 | return; | 233 | // OK, now fetch the inside. |
234 | Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>(); | ||
235 | HGUuidGatherer uuidGatherer = new HGUuidGatherer(this, m_scene.AssetService, userAssetURL); | ||
236 | uuidGatherer.GatherAssetUuids(asset.FullID, (AssetType)asset.Type, ids); | ||
237 | if (ids.ContainsKey(assetID)) | ||
238 | ids.Remove(assetID); | ||
239 | foreach (UUID uuid in ids.Keys) | ||
240 | FetchAsset(userAssetURL, uuid); | ||
230 | 241 | ||
231 | // The act of gathering UUIDs downloads the assets from the remote server | 242 | m_log.DebugFormat("[HG ASSET MAPPER]: Successfully fetched asset {0} from asset server {1}", asset.ID, userAssetURL); |
232 | Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>(); | ||
233 | HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, userAssetURL); | ||
234 | uuidGatherer.GatherAssetUuids(assetID, (AssetType)meta.Type, ids); | ||
235 | 243 | ||
244 | } | ||
245 | else | ||
246 | m_log.Warn("[HG ASSET MAPPER]: Could not fetch asset from remote asset server " + userAssetURL); | ||
236 | } | 247 | } |
237 | 248 | ||
238 | 249 | ||
@@ -246,23 +257,19 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
246 | if (asset != null) | 257 | if (asset != null) |
247 | { | 258 | { |
248 | Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>(); | 259 | Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>(); |
249 | HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, string.Empty); | 260 | HGUuidGatherer uuidGatherer = new HGUuidGatherer(this, m_scene.AssetService, string.Empty); |
250 | uuidGatherer.GatherAssetUuids(asset.FullID, (AssetType)asset.Type, ids); | 261 | uuidGatherer.GatherAssetUuids(asset.FullID, (AssetType)asset.Type, ids); |
251 | bool success = false; | ||
252 | foreach (UUID uuid in ids.Keys) | 262 | foreach (UUID uuid in ids.Keys) |
253 | { | 263 | { |
254 | asset = m_scene.AssetService.Get(uuid.ToString()); | 264 | asset = m_scene.AssetService.Get(uuid.ToString()); |
255 | if (asset == null) | 265 | if (asset == null) |
256 | m_log.DebugFormat("[HG ASSET MAPPER]: Could not find asset {0}", uuid); | 266 | m_log.DebugFormat("[HG ASSET MAPPER]: Could not find asset {0}", uuid); |
257 | else | 267 | else |
258 | success = PostAsset(userAssetURL, asset); | 268 | PostAsset(userAssetURL, asset); |
259 | } | 269 | } |
260 | 270 | ||
261 | // maybe all pieces got there... | 271 | // maybe all pieces got there... |
262 | if (!success) | 272 | m_log.DebugFormat("[HG ASSET MAPPER]: Successfully posted item {0} to asset server {1}", assetID, userAssetURL); |
263 | m_log.DebugFormat("[HG ASSET MAPPER]: Problems posting item {0} to asset server {1}", assetID, userAssetURL); | ||
264 | else | ||
265 | m_log.DebugFormat("[HG ASSET MAPPER]: Successfully posted item {0} to asset server {1}", assetID, userAssetURL); | ||
266 | 273 | ||
267 | } | 274 | } |
268 | else | 275 | else |
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs index 6bb758e..cf72b58 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs | |||
@@ -92,7 +92,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
92 | m_HomeURI = thisModuleConfig.GetString("HomeURI", m_HomeURI); | 92 | m_HomeURI = thisModuleConfig.GetString("HomeURI", m_HomeURI); |
93 | m_OutboundPermission = thisModuleConfig.GetBoolean("OutboundPermission", true); | 93 | m_OutboundPermission = thisModuleConfig.GetBoolean("OutboundPermission", true); |
94 | m_ThisGatekeeper = thisModuleConfig.GetString("Gatekeeper", string.Empty); | 94 | m_ThisGatekeeper = thisModuleConfig.GetString("Gatekeeper", string.Empty); |
95 | m_RestrictInventoryAccessAbroad = thisModuleConfig.GetBoolean("RestrictInventoryAccessAbroad", true); | 95 | m_RestrictInventoryAccessAbroad = thisModuleConfig.GetBoolean("RestrictInventoryAccessAbroad", false); |
96 | } | 96 | } |
97 | else | 97 | else |
98 | m_log.Warn("[HG INVENTORY ACCESS MODULE]: HGInventoryAccessModule configs not found. ProfileServerURI not set!"); | 98 | m_log.Warn("[HG INVENTORY ACCESS MODULE]: HGInventoryAccessModule configs not found. ProfileServerURI not set!"); |
@@ -263,13 +263,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
263 | //} | 263 | //} |
264 | 264 | ||
265 | // OK, we're done fetching. Pass it up to the default RezObject | 265 | // OK, we're done fetching. Pass it up to the default RezObject |
266 | SceneObjectGroup sog = base.RezObject(remoteClient, itemID, RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection, | 266 | return base.RezObject(remoteClient, itemID, RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection, |
267 | RezSelected, RemoveItem, fromTaskID, attachment); | 267 | RezSelected, RemoveItem, fromTaskID, attachment); |
268 | |||
269 | if (sog == null) | ||
270 | remoteClient.SendAgentAlertMessage("Unable to rez: problem accessing inventory or locating assets", false); | ||
271 | |||
272 | return sog; | ||
273 | 268 | ||
274 | } | 269 | } |
275 | 270 | ||
@@ -313,8 +308,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
313 | protected override InventoryItemBase GetItem(UUID agentID, UUID itemID) | 308 | protected override InventoryItemBase GetItem(UUID agentID, UUID itemID) |
314 | { | 309 | { |
315 | InventoryItemBase item = base.GetItem(agentID, itemID); | 310 | InventoryItemBase item = base.GetItem(agentID, itemID); |
316 | if (item == null) | ||
317 | return null; | ||
318 | 311 | ||
319 | string userAssetServer = string.Empty; | 312 | string userAssetServer = string.Empty; |
320 | if (IsForeignUser(agentID, out userAssetServer)) | 313 | if (IsForeignUser(agentID, out userAssetServer)) |
@@ -351,7 +344,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
351 | 344 | ||
352 | private void ProcessInventoryForArriving(IClientAPI client) | 345 | private void ProcessInventoryForArriving(IClientAPI client) |
353 | { | 346 | { |
354 | // No-op for now, but we may need to do something for freign users inventory | ||
355 | } | 347 | } |
356 | 348 | ||
357 | // | 349 | // |
@@ -398,7 +390,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
398 | 390 | ||
399 | private void ProcessInventoryForLeaving(IClientAPI client) | 391 | private void ProcessInventoryForLeaving(IClientAPI client) |
400 | { | 392 | { |
401 | // No-op for now | ||
402 | } | 393 | } |
403 | 394 | ||
404 | #endregion | 395 | #endregion |
diff --git a/OpenSim/Region/ScriptEngine/Shared/ScriptException.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGUuidGatherer.cs index f55ba7e..fcb544f 100644 --- a/OpenSim/Region/ScriptEngine/Shared/ScriptException.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGUuidGatherer.cs | |||
@@ -26,19 +26,32 @@ | |||
26 | */ | 26 | */ |
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using System.Runtime.Serialization; | 29 | using System.Collections.Generic; |
30 | 30 | ||
31 | namespace OpenSim.Region.ScriptEngine.Shared | 31 | using OpenSim.Framework; |
32 | using OpenSim.Region.Framework.Scenes; | ||
33 | using OpenSim.Services.Interfaces; | ||
34 | using OpenMetaverse; | ||
35 | |||
36 | namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | ||
32 | { | 37 | { |
33 | [Serializable] | 38 | public class HGUuidGatherer : UuidGatherer |
34 | public class ScriptException : Exception | ||
35 | { | 39 | { |
36 | public ScriptException() : base() {} | 40 | protected string m_assetServerURL; |
37 | 41 | protected HGAssetMapper m_assetMapper; | |
38 | public ScriptException(string message) : base(message) {} | ||
39 | 42 | ||
40 | public ScriptException(string message, Exception innerException) : base(message, innerException) {} | 43 | public HGUuidGatherer(HGAssetMapper assMap, IAssetService assetCache, string assetServerURL) : base(assetCache) |
44 | { | ||
45 | m_assetMapper = assMap; | ||
46 | m_assetServerURL = assetServerURL; | ||
47 | } | ||
41 | 48 | ||
42 | public ScriptException(SerializationInfo info, StreamingContext context) :base(info, context) {} | 49 | protected override AssetBase GetAsset(UUID uuid) |
50 | { | ||
51 | if (string.Empty == m_assetServerURL) | ||
52 | return m_assetCache.Get(uuid.ToString()); | ||
53 | else | ||
54 | return m_assetMapper.FetchAsset(m_assetServerURL, uuid); | ||
55 | } | ||
43 | } | 56 | } |
44 | } \ No newline at end of file | 57 | } |
diff --git a/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs b/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs index e411585..e135c21 100644 --- a/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs +++ b/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs | |||
@@ -95,14 +95,14 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring | |||
95 | { | 95 | { |
96 | foreach (IMonitor monitor in m_staticMonitors) | 96 | foreach (IMonitor monitor in m_staticMonitors) |
97 | { | 97 | { |
98 | MainConsole.Instance.OutputFormat( | 98 | m_log.InfoFormat( |
99 | "[MONITOR MODULE]: {0} reports {1} = {2}", | 99 | "[MONITOR MODULE]: {0} reports {1} = {2}", |
100 | m_scene.RegionInfo.RegionName, monitor.GetFriendlyName(), monitor.GetFriendlyValue()); | 100 | m_scene.RegionInfo.RegionName, monitor.GetFriendlyName(), monitor.GetFriendlyValue()); |
101 | } | 101 | } |
102 | 102 | ||
103 | foreach (KeyValuePair<string, float> tuple in m_scene.StatsReporter.GetExtraSimStats()) | 103 | foreach (KeyValuePair<string, float> tuple in m_scene.StatsReporter.GetExtraSimStats()) |
104 | { | 104 | { |
105 | MainConsole.Instance.OutputFormat( | 105 | m_log.InfoFormat( |
106 | "[MONITOR MODULE]: {0} reports {1} = {2}", | 106 | "[MONITOR MODULE]: {0} reports {1} = {2}", |
107 | m_scene.RegionInfo.RegionName, tuple.Key, tuple.Value); | 107 | m_scene.RegionInfo.RegionName, tuple.Key, tuple.Value); |
108 | } | 108 | } |
diff --git a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs index fd8d5e3..65e4c90 100755 --- a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs +++ b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs | |||
@@ -1,170 +1,161 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) Contributors, http://opensimulator.org/ | 2 | * Copyright (c) Contributors, http://opensimulator.org/ |
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | 3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. |
4 | * | 4 | * |
5 | * Redistribution and use in source and binary forms, with or without | 5 | * Redistribution and use in source and binary forms, with or without |
6 | * modification, are permitted provided that the following conditions are met: | 6 | * modification, are permitted provided that the following conditions are met: |
7 | * * Redistributions of source code must retain the above copyright | 7 | * * Redistributions of source code must retain the above copyright |
8 | * notice, this list of conditions and the following disclaimer. | 8 | * notice, this list of conditions and the following disclaimer. |
9 | * * Redistributions in binary form must reproduce the above copyright | 9 | * * Redistributions in binary form must reproduce the above copyright |
10 | * notice, this list of conditions and the following disclaimer in the | 10 | * notice, this list of conditions and the following disclaimer in the |
11 | * documentation and/or other materials provided with the distribution. | 11 | * documentation and/or other materials provided with the distribution. |
12 | * * Neither the name of the OpenSimulator Project nor the | 12 | * * Neither the name of the OpenSimulator Project nor the |
13 | * names of its contributors may be used to endorse or promote products | 13 | * names of its contributors may be used to endorse or promote products |
14 | * derived from this software without specific prior written permission. | 14 | * derived from this software without specific prior written permission. |
15 | * | 15 | * |
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | 16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY |
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | 19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY |
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 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 | 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 | 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 | 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. | 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using System.IO; | 29 | using System.IO; |
30 | using System.Text; | 30 | using System.Text; |
31 | using log4net; | 31 | using log4net; |
32 | 32 | ||
33 | namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging | 33 | namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging |
34 | { | 34 | { |
35 | /// <summary> | 35 | /// <summary> |
36 | /// Class for writing a high performance, high volume log file. | 36 | /// Class for writing a high performance, high volume log file. |
37 | /// Sometimes, to debug, one has a high volume logging to do and the regular | 37 | /// Sometimes, to debug, one has a high volume logging to do and the regular |
38 | /// log file output is not appropriate. | 38 | /// log file output is not appropriate. |
39 | /// Create a new instance with the parameters needed and | 39 | /// Create a new instance with the parameters needed and |
40 | /// call Write() to output a line. Call Close() when finished. | 40 | /// call Write() to output a line. Call Close() when finished. |
41 | /// If created with no parameters, it will not log anything. | 41 | /// If created with no parameters, it will not log anything. |
42 | /// </summary> | 42 | /// </summary> |
43 | public class LogWriter : IDisposable | 43 | public class LogWriter : IDisposable |
44 | { | 44 | { |
45 | public bool Enabled { get; private set; } | 45 | public bool Enabled { get; private set; } |
46 | 46 | ||
47 | private string m_logDirectory = "."; | 47 | private string m_logDirectory = "."; |
48 | private int m_logMaxFileTimeMin = 5; // 5 minutes | 48 | private int m_logMaxFileTimeMin = 5; // 5 minutes |
49 | public String LogFileHeader { get; set; } | 49 | public String LogFileHeader { get; set; } |
50 | 50 | ||
51 | private StreamWriter m_logFile = null; | 51 | private StreamWriter m_logFile = null; |
52 | private TimeSpan m_logFileLife; | 52 | private TimeSpan m_logFileLife; |
53 | private DateTime m_logFileEndTime; | 53 | private DateTime m_logFileEndTime; |
54 | private Object m_logFileWriteLock = new Object(); | 54 | private Object m_logFileWriteLock = new Object(); |
55 | 55 | ||
56 | // set externally when debugging. If let 'null', this does not write any error messages. | 56 | // set externally when debugging. If let 'null', this does not write any error messages. |
57 | public ILog ErrorLogger = null; | 57 | public ILog ErrorLogger = null; |
58 | private string LogHeader = "[LOG WRITER]"; | 58 | private string LogHeader = "[LOG WRITER]"; |
59 | 59 | ||
60 | /// <summary> | 60 | /// <summary> |
61 | /// Create a log writer that will not write anything. Good for when not enabled | 61 | /// Create a log writer that will not write anything. Good for when not enabled |
62 | /// but the write statements are still in the code. | 62 | /// but the write statements are still in the code. |
63 | /// </summary> | 63 | /// </summary> |
64 | public LogWriter() | 64 | public LogWriter() |
65 | { | 65 | { |
66 | Enabled = false; | 66 | Enabled = false; |
67 | m_logFile = null; | 67 | m_logFile = null; |
68 | } | 68 | } |
69 | 69 | ||
70 | /// <summary> | 70 | /// <summary> |
71 | /// Create a log writer instance. | 71 | /// Create a log writer instance. |
72 | /// </summary> | 72 | /// </summary> |
73 | /// <param name="dir">The directory to create the log file in. May be 'null' for default.</param> | 73 | /// <param name="dir">The directory to create the log file in. May be 'null' for default.</param> |
74 | /// <param name="headr">The characters that begin the log file name. May be 'null' for default.</param> | 74 | /// <param name="headr">The characters that begin the log file name. May be 'null' for default.</param> |
75 | /// <param name="maxFileTime">Maximum age of a log file in minutes. If zero, will set default.</param> | 75 | /// <param name="maxFileTime">Maximum age of a log file in minutes. If zero, will set default.</param> |
76 | public LogWriter(string dir, string headr, int maxFileTime) | 76 | public LogWriter(string dir, string headr, int maxFileTime) |
77 | { | 77 | { |
78 | m_logDirectory = dir == null ? "." : dir; | 78 | m_logDirectory = dir == null ? "." : dir; |
79 | 79 | ||
80 | LogFileHeader = headr == null ? "log-" : headr; | 80 | LogFileHeader = headr == null ? "log-" : headr; |
81 | 81 | ||
82 | m_logMaxFileTimeMin = maxFileTime; | 82 | m_logMaxFileTimeMin = maxFileTime; |
83 | if (m_logMaxFileTimeMin < 1) | 83 | if (m_logMaxFileTimeMin < 1) |
84 | m_logMaxFileTimeMin = 5; | 84 | m_logMaxFileTimeMin = 5; |
85 | 85 | ||
86 | m_logFileLife = new TimeSpan(0, m_logMaxFileTimeMin, 0); | 86 | m_logFileLife = new TimeSpan(0, m_logMaxFileTimeMin, 0); |
87 | m_logFileEndTime = DateTime.Now + m_logFileLife; | 87 | m_logFileEndTime = DateTime.Now + m_logFileLife; |
88 | 88 | ||
89 | Enabled = true; | 89 | Enabled = true; |
90 | } | 90 | } |
91 | 91 | ||
92 | public void Dispose() | 92 | public void Dispose() |
93 | { | 93 | { |
94 | this.Close(); | 94 | this.Close(); |
95 | } | 95 | } |
96 | 96 | ||
97 | public void Close() | 97 | public void Close() |
98 | { | 98 | { |
99 | Enabled = false; | 99 | Enabled = false; |
100 | if (m_logFile != null) | 100 | if (m_logFile != null) |
101 | { | 101 | { |
102 | m_logFile.Close(); | 102 | m_logFile.Close(); |
103 | m_logFile.Dispose(); | 103 | m_logFile.Dispose(); |
104 | m_logFile = null; | 104 | m_logFile = null; |
105 | } | 105 | } |
106 | } | 106 | } |
107 | 107 | ||
108 | public void Write(string line, params object[] args) | 108 | public void Write(string line, params object[] args) |
109 | { | 109 | { |
110 | if (!Enabled) return; | 110 | if (!Enabled) return; |
111 | Write(String.Format(line, args)); | 111 | Write(String.Format(line, args)); |
112 | } | 112 | } |
113 | 113 | ||
114 | public void Flush() | 114 | public void Write(string line) |
115 | { | 115 | { |
116 | if (!Enabled) return; | 116 | if (!Enabled) return; |
117 | if (m_logFile != null) | 117 | try |
118 | { | 118 | { |
119 | m_logFile.Flush(); | 119 | lock (m_logFileWriteLock) |
120 | } | 120 | { |
121 | } | 121 | DateTime now = DateTime.Now; |
122 | 122 | if (m_logFile == null || now > m_logFileEndTime) | |
123 | public void Write(string line) | 123 | { |
124 | { | 124 | if (m_logFile != null) |
125 | if (!Enabled) return; | 125 | { |
126 | try | 126 | m_logFile.Close(); |
127 | { | 127 | m_logFile.Dispose(); |
128 | lock (m_logFileWriteLock) | 128 | m_logFile = null; |
129 | { | 129 | } |
130 | DateTime now = DateTime.Now; | 130 | |
131 | if (m_logFile == null || now > m_logFileEndTime) | 131 | // First log file or time has expired, start writing to a new log file |
132 | { | 132 | m_logFileEndTime = now + m_logFileLife; |
133 | if (m_logFile != null) | 133 | string path = (m_logDirectory.Length > 0 ? m_logDirectory |
134 | { | 134 | + System.IO.Path.DirectorySeparatorChar.ToString() : "") |
135 | m_logFile.Close(); | 135 | + String.Format("{0}{1}.log", LogFileHeader, now.ToString("yyyyMMddHHmmss")); |
136 | m_logFile.Dispose(); | 136 | m_logFile = new StreamWriter(File.Open(path, FileMode.Append, FileAccess.Write)); |
137 | m_logFile = null; | 137 | } |
138 | } | 138 | if (m_logFile != null) |
139 | 139 | { | |
140 | // First log file or time has expired, start writing to a new log file | 140 | StringBuilder buff = new StringBuilder(line.Length + 25); |
141 | m_logFileEndTime = now + m_logFileLife; | 141 | buff.Append(now.ToString("yyyyMMddHHmmssfff")); |
142 | string path = (m_logDirectory.Length > 0 ? m_logDirectory | 142 | // buff.Append(now.ToString("yyyyMMddHHmmss")); |
143 | + System.IO.Path.DirectorySeparatorChar.ToString() : "") | 143 | buff.Append(","); |
144 | + String.Format("{0}{1}.log", LogFileHeader, now.ToString("yyyyMMddHHmmss")); | 144 | buff.Append(line); |
145 | m_logFile = new StreamWriter(File.Open(path, FileMode.Append, FileAccess.Write)); | 145 | buff.Append("\r\n"); |
146 | } | 146 | m_logFile.Write(buff.ToString()); |
147 | if (m_logFile != null) | 147 | } |
148 | { | 148 | } |
149 | StringBuilder buff = new StringBuilder(line.Length + 25); | 149 | } |
150 | buff.Append(now.ToString("yyyyMMddHHmmssfff")); | 150 | catch (Exception e) |
151 | // buff.Append(now.ToString("yyyyMMddHHmmss")); | 151 | { |
152 | buff.Append(","); | 152 | if (ErrorLogger != null) |
153 | buff.Append(line); | 153 | { |
154 | buff.Append("\r\n"); | 154 | ErrorLogger.ErrorFormat("{0}: FAILURE WRITING TO LOGFILE: {1}", LogHeader, e); |
155 | m_logFile.Write(buff.ToString()); | 155 | } |
156 | } | 156 | Enabled = false; |
157 | } | 157 | } |
158 | } | 158 | return; |
159 | catch (Exception e) | 159 | } |
160 | { | 160 | } |
161 | if (ErrorLogger != null) | 161 | } \ No newline at end of file |
162 | { | ||
163 | ErrorLogger.ErrorFormat("{0}: FAILURE WRITING TO LOGFILE: {1}", LogHeader, e); | ||
164 | } | ||
165 | Enabled = false; | ||
166 | } | ||
167 | return; | ||
168 | } | ||
169 | } | ||
170 | } | ||
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs index acefc97..4eecaa2 100644 --- a/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs +++ b/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs | |||
@@ -137,9 +137,6 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
137 | ud.FirstName = words[0]; | 137 | ud.FirstName = words[0]; |
138 | ud.LastName = "@" + words[1]; | 138 | ud.LastName = "@" + words[1]; |
139 | users.Add(ud); | 139 | users.Add(ud); |
140 | // WARNING! that uriStr is not quite right... it may be missing the / at the end, | ||
141 | // which will cause trouble (duplicate entries on some tables). We should | ||
142 | // get the UUI instead from the UAS. TO BE FIXED. | ||
143 | AddUser(userID, names[0], names[1], uriStr); | 140 | AddUser(userID, names[0], names[1], uriStr); |
144 | m_log.DebugFormat("[USER MANAGEMENT MODULE]: User {0}@{1} found", words[0], words[1]); | 141 | m_log.DebugFormat("[USER MANAGEMENT MODULE]: User {0}@{1} found", words[0], words[1]); |
145 | } | 142 | } |
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs index b4811da..f4ed67b 100644 --- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs +++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs | |||
@@ -31,7 +31,6 @@ using System.Reflection; | |||
31 | 31 | ||
32 | using OpenSim.Framework; | 32 | using OpenSim.Framework; |
33 | using OpenSim.Framework.Console; | 33 | using OpenSim.Framework.Console; |
34 | using OpenSim.Region.ClientStack.LindenUDP; | ||
35 | using OpenSim.Region.Framework; | 34 | using OpenSim.Region.Framework; |
36 | using OpenSim.Region.Framework.Interfaces; | 35 | using OpenSim.Region.Framework.Interfaces; |
37 | using OpenSim.Region.Framework.Scenes; | 36 | using OpenSim.Region.Framework.Scenes; |
@@ -430,7 +429,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
430 | 429 | ||
431 | public void AddUser(UUID uuid, string first, string last, string homeURL) | 430 | public void AddUser(UUID uuid, string first, string last, string homeURL) |
432 | { | 431 | { |
433 | //m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, first {1}, last {2}, url {3}", uuid, first, last, homeURL); | 432 | // m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, first {1}, last {2}, url {3}", uuid, first, last, homeURL); |
433 | |||
434 | AddUser(uuid, homeURL + ";" + first + " " + last); | 434 | AddUser(uuid, homeURL + ";" + first + " " + last); |
435 | } | 435 | } |
436 | 436 | ||
@@ -553,8 +553,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
553 | MainConsole.Instance.Output("-----------------------------------------------------------------------------"); | 553 | MainConsole.Instance.Output("-----------------------------------------------------------------------------"); |
554 | foreach (KeyValuePair<UUID, UserData> kvp in m_UserCache) | 554 | foreach (KeyValuePair<UUID, UserData> kvp in m_UserCache) |
555 | { | 555 | { |
556 | MainConsole.Instance.Output(String.Format("{0} {1} {2} ({3})", | 556 | MainConsole.Instance.Output(String.Format("{0} {1} {2}", |
557 | kvp.Key, kvp.Value.FirstName, kvp.Value.LastName, kvp.Value.HomeURL)); | 557 | kvp.Key, kvp.Value.FirstName, kvp.Value.LastName)); |
558 | } | 558 | } |
559 | 559 | ||
560 | return; | 560 | return; |
diff --git a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml index 6c73d91..424e0ab 100644 --- a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml +++ b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml | |||
@@ -15,7 +15,6 @@ | |||
15 | <RegionModule id="InventoryAccessModule" type="OpenSim.Region.CoreModules.Framework.InventoryAccess.BasicInventoryAccessModule" /> | 15 | <RegionModule id="InventoryAccessModule" type="OpenSim.Region.CoreModules.Framework.InventoryAccess.BasicInventoryAccessModule" /> |
16 | <RegionModule id="HGInventoryAccessModule" type="OpenSim.Region.CoreModules.Framework.InventoryAccess.HGInventoryAccessModule" /> | 16 | <RegionModule id="HGInventoryAccessModule" type="OpenSim.Region.CoreModules.Framework.InventoryAccess.HGInventoryAccessModule" /> |
17 | <RegionModule id="LandManagementModule" type="OpenSim.Region.CoreModules.World.Land.LandManagementModule" /> | 17 | <RegionModule id="LandManagementModule" type="OpenSim.Region.CoreModules.World.Land.LandManagementModule" /> |
18 | <RegionModule id="DwellModule" type="OpenSim.Region.CoreModules.World.Land.DwellModule" /> | ||
19 | <RegionModule id="PrimCountModule" type="OpenSim.Region.CoreModules.World.Land.PrimCountModule" /> | 18 | <RegionModule id="PrimCountModule" type="OpenSim.Region.CoreModules.World.Land.PrimCountModule" /> |
20 | <RegionModule id="ExportSerialisationModule" type="OpenSim.Region.CoreModules.World.Serialiser.SerialiserModule" /> | 19 | <RegionModule id="ExportSerialisationModule" type="OpenSim.Region.CoreModules.World.Serialiser.SerialiserModule" /> |
21 | <RegionModule id="ArchiverModule" type="OpenSim.Region.CoreModules.World.Archiver.ArchiverModule" /> | 20 | <RegionModule id="ArchiverModule" type="OpenSim.Region.CoreModules.World.Archiver.ArchiverModule" /> |
diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs deleted file mode 100644 index fce9490..0000000 --- a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs +++ /dev/null | |||
@@ -1,61 +0,0 @@ | |||
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 | using System.Drawing; | ||
30 | using OpenSim.Region.Framework.Interfaces; | ||
31 | |||
32 | namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture | ||
33 | { | ||
34 | public class DynamicTexture : IDynamicTexture | ||
35 | { | ||
36 | public string InputCommands { get; private set; } | ||
37 | public Uri InputUri { get; private set; } | ||
38 | public string InputParams { get; private set; } | ||
39 | public byte[] Data { get; private set; } | ||
40 | public Size Size { get; private set; } | ||
41 | public bool IsReuseable { get; private set; } | ||
42 | |||
43 | public DynamicTexture(string inputCommands, string inputParams, byte[] data, Size size, bool isReuseable) | ||
44 | { | ||
45 | InputCommands = inputCommands; | ||
46 | InputParams = inputParams; | ||
47 | Data = data; | ||
48 | Size = size; | ||
49 | IsReuseable = isReuseable; | ||
50 | } | ||
51 | |||
52 | public DynamicTexture(Uri inputUri, string inputParams, byte[] data, Size size, bool isReuseable) | ||
53 | { | ||
54 | InputUri = inputUri; | ||
55 | InputParams = inputParams; | ||
56 | Data = data; | ||
57 | Size = size; | ||
58 | IsReuseable = isReuseable; | ||
59 | } | ||
60 | } | ||
61 | } \ No newline at end of file | ||
diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs index 93a045e..18bd018 100644 --- a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs | |||
@@ -42,29 +42,13 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture | |||
42 | { | 42 | { |
43 | public class DynamicTextureModule : IRegionModule, IDynamicTextureManager | 43 | public class DynamicTextureModule : IRegionModule, IDynamicTextureManager |
44 | { | 44 | { |
45 | // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 45 | //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
46 | 46 | ||
47 | private const int ALL_SIDES = -1; | 47 | private const int ALL_SIDES = -1; |
48 | 48 | ||
49 | public const int DISP_EXPIRE = 1; | 49 | public const int DISP_EXPIRE = 1; |
50 | public const int DISP_TEMP = 2; | 50 | public const int DISP_TEMP = 2; |
51 | 51 | ||
52 | /// <summary> | ||
53 | /// If true then where possible dynamic textures are reused. | ||
54 | /// </summary> | ||
55 | public bool ReuseTextures { get; set; } | ||
56 | |||
57 | /// <summary> | ||
58 | /// If false, then textures which have a low data size are not reused when ReuseTextures = true. | ||
59 | /// </summary> | ||
60 | /// <remarks> | ||
61 | /// LL viewers 3.3.4 and before appear to not fully render textures pulled from the viewer cache if those | ||
62 | /// textures have a relatively high pixel surface but a small data size. Typically, this appears to happen | ||
63 | /// if the data size is smaller than the viewer's discard level 2 size estimate. So if this is setting is | ||
64 | /// false, textures smaller than the calculation in IsSizeReuseable are always regenerated rather than reused | ||
65 | /// to work around this problem.</remarks> | ||
66 | public bool ReuseLowDataTextures { get; set; } | ||
67 | |||
68 | private Dictionary<UUID, Scene> RegisteredScenes = new Dictionary<UUID, Scene>(); | 52 | private Dictionary<UUID, Scene> RegisteredScenes = new Dictionary<UUID, Scene>(); |
69 | 53 | ||
70 | private Dictionary<string, IDynamicTextureRender> RenderPlugins = | 54 | private Dictionary<string, IDynamicTextureRender> RenderPlugins = |
@@ -72,15 +56,6 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture | |||
72 | 56 | ||
73 | private Dictionary<UUID, DynamicTextureUpdater> Updaters = new Dictionary<UUID, DynamicTextureUpdater>(); | 57 | private Dictionary<UUID, DynamicTextureUpdater> Updaters = new Dictionary<UUID, DynamicTextureUpdater>(); |
74 | 58 | ||
75 | /// <summary> | ||
76 | /// Record dynamic textures that we can reuse for a given data and parameter combination rather than | ||
77 | /// regenerate. | ||
78 | /// </summary> | ||
79 | /// <remarks> | ||
80 | /// Key is string.Format("{0}{1}", data | ||
81 | /// </remarks> | ||
82 | private Cache m_reuseableDynamicTextures; | ||
83 | |||
84 | #region IDynamicTextureManager Members | 59 | #region IDynamicTextureManager Members |
85 | 60 | ||
86 | public void RegisterRender(string handleType, IDynamicTextureRender render) | 61 | public void RegisterRender(string handleType, IDynamicTextureRender render) |
@@ -94,17 +69,17 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture | |||
94 | /// <summary> | 69 | /// <summary> |
95 | /// Called by code which actually renders the dynamic texture to supply texture data. | 70 | /// Called by code which actually renders the dynamic texture to supply texture data. |
96 | /// </summary> | 71 | /// </summary> |
97 | /// <param name="updaterId"></param> | 72 | /// <param name="id"></param> |
98 | /// <param name="texture"></param> | 73 | /// <param name="data"></param> |
99 | public void ReturnData(UUID updaterId, IDynamicTexture texture) | 74 | public void ReturnData(UUID id, byte[] data) |
100 | { | 75 | { |
101 | DynamicTextureUpdater updater = null; | 76 | DynamicTextureUpdater updater = null; |
102 | 77 | ||
103 | lock (Updaters) | 78 | lock (Updaters) |
104 | { | 79 | { |
105 | if (Updaters.ContainsKey(updaterId)) | 80 | if (Updaters.ContainsKey(id)) |
106 | { | 81 | { |
107 | updater = Updaters[updaterId]; | 82 | updater = Updaters[id]; |
108 | } | 83 | } |
109 | } | 84 | } |
110 | 85 | ||
@@ -113,16 +88,7 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture | |||
113 | if (RegisteredScenes.ContainsKey(updater.SimUUID)) | 88 | if (RegisteredScenes.ContainsKey(updater.SimUUID)) |
114 | { | 89 | { |
115 | Scene scene = RegisteredScenes[updater.SimUUID]; | 90 | Scene scene = RegisteredScenes[updater.SimUUID]; |
116 | UUID newTextureID = updater.DataReceived(texture.Data, scene); | 91 | updater.DataReceived(data, scene); |
117 | |||
118 | if (ReuseTextures | ||
119 | && !updater.BlendWithOldTexture | ||
120 | && texture.IsReuseable | ||
121 | && (ReuseLowDataTextures || IsDataSizeReuseable(texture))) | ||
122 | { | ||
123 | m_reuseableDynamicTextures.Store( | ||
124 | GenerateReusableTextureKey(texture.InputCommands, texture.InputParams), newTextureID); | ||
125 | } | ||
126 | } | 92 | } |
127 | } | 93 | } |
128 | 94 | ||
@@ -138,27 +104,6 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture | |||
138 | } | 104 | } |
139 | } | 105 | } |
140 | 106 | ||
141 | /// <summary> | ||
142 | /// Determines whether the texture is reuseable based on its data size. | ||
143 | /// </summary> | ||
144 | /// <remarks> | ||
145 | /// This is a workaround for a viewer bug where very small data size textures relative to their pixel size | ||
146 | /// are not redisplayed properly when pulled from cache. The calculation here is based on the typical discard | ||
147 | /// level of 2, a 'rate' of 0.125 and 4 components (which makes for a factor of 0.5). | ||
148 | /// </remarks> | ||
149 | /// <returns></returns> | ||
150 | private bool IsDataSizeReuseable(IDynamicTexture texture) | ||
151 | { | ||
152 | // Console.WriteLine("{0} {1}", texture.Size.Width, texture.Size.Height); | ||
153 | int discardLevel2DataThreshold = (int)Math.Ceiling((texture.Size.Width >> 2) * (texture.Size.Height >> 2) * 0.5); | ||
154 | |||
155 | // m_log.DebugFormat( | ||
156 | // "[DYNAMIC TEXTURE MODULE]: Discard level 2 threshold {0}, texture data length {1}", | ||
157 | // discardLevel2DataThreshold, texture.Data.Length); | ||
158 | |||
159 | return discardLevel2DataThreshold < texture.Data.Length; | ||
160 | } | ||
161 | |||
162 | public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, | 107 | public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, |
163 | string extraParams, int updateTimer) | 108 | string extraParams, int updateTimer) |
164 | { | 109 | { |
@@ -222,61 +167,22 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture | |||
222 | public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, | 167 | public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, |
223 | string extraParams, int updateTimer, bool SetBlending, int disp, byte AlphaValue, int face) | 168 | string extraParams, int updateTimer, bool SetBlending, int disp, byte AlphaValue, int face) |
224 | { | 169 | { |
225 | if (!RenderPlugins.ContainsKey(contentType)) | 170 | if (RenderPlugins.ContainsKey(contentType)) |
226 | return UUID.Zero; | ||
227 | |||
228 | Scene scene; | ||
229 | RegisteredScenes.TryGetValue(simID, out scene); | ||
230 | |||
231 | if (scene == null) | ||
232 | return UUID.Zero; | ||
233 | |||
234 | SceneObjectPart part = scene.GetSceneObjectPart(primID); | ||
235 | |||
236 | if (part == null) | ||
237 | return UUID.Zero; | ||
238 | |||
239 | // If we want to reuse dynamic textures then we have to ignore any request from the caller to expire | ||
240 | // them. | ||
241 | if (ReuseTextures) | ||
242 | disp = disp & ~DISP_EXPIRE; | ||
243 | |||
244 | DynamicTextureUpdater updater = new DynamicTextureUpdater(); | ||
245 | updater.SimUUID = simID; | ||
246 | updater.PrimID = primID; | ||
247 | updater.ContentType = contentType; | ||
248 | updater.BodyData = data; | ||
249 | updater.UpdateTimer = updateTimer; | ||
250 | updater.UpdaterID = UUID.Random(); | ||
251 | updater.Params = extraParams; | ||
252 | updater.BlendWithOldTexture = SetBlending; | ||
253 | updater.FrontAlpha = AlphaValue; | ||
254 | updater.Face = face; | ||
255 | updater.Url = "Local image"; | ||
256 | updater.Disp = disp; | ||
257 | |||
258 | object objReusableTextureUUID = null; | ||
259 | |||
260 | if (ReuseTextures && !updater.BlendWithOldTexture) | ||
261 | { | 171 | { |
262 | string reuseableTextureKey = GenerateReusableTextureKey(data, extraParams); | 172 | DynamicTextureUpdater updater = new DynamicTextureUpdater(); |
263 | objReusableTextureUUID = m_reuseableDynamicTextures.Get(reuseableTextureKey); | 173 | updater.SimUUID = simID; |
264 | 174 | updater.PrimID = primID; | |
265 | if (objReusableTextureUUID != null) | 175 | updater.ContentType = contentType; |
266 | { | 176 | updater.BodyData = data; |
267 | // If something else has removed this temporary asset from the cache, detect and invalidate | 177 | updater.UpdateTimer = updateTimer; |
268 | // our cached uuid. | 178 | updater.UpdaterID = UUID.Random(); |
269 | if (scene.AssetService.GetMetadata(objReusableTextureUUID.ToString()) == null) | 179 | updater.Params = extraParams; |
270 | { | 180 | updater.BlendWithOldTexture = SetBlending; |
271 | m_reuseableDynamicTextures.Invalidate(reuseableTextureKey); | 181 | updater.FrontAlpha = AlphaValue; |
272 | objReusableTextureUUID = null; | 182 | updater.Face = face; |
273 | } | 183 | updater.Url = "Local image"; |
274 | } | 184 | updater.Disp = disp; |
275 | } | ||
276 | 185 | ||
277 | // We cannot reuse a dynamic texture if the data is going to be blended with something already there. | ||
278 | if (objReusableTextureUUID == null) | ||
279 | { | ||
280 | lock (Updaters) | 186 | lock (Updaters) |
281 | { | 187 | { |
282 | if (!Updaters.ContainsKey(updater.UpdaterID)) | 188 | if (!Updaters.ContainsKey(updater.UpdaterID)) |
@@ -285,29 +191,11 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture | |||
285 | } | 191 | } |
286 | } | 192 | } |
287 | 193 | ||
288 | // m_log.DebugFormat( | ||
289 | // "[DYNAMIC TEXTURE MODULE]: Requesting generation of new dynamic texture for {0} in {1}", | ||
290 | // part.Name, part.ParentGroup.Scene.Name); | ||
291 | |||
292 | RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams); | 194 | RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams); |
195 | return updater.UpdaterID; | ||
293 | } | 196 | } |
294 | else | 197 | |
295 | { | 198 | return UUID.Zero; |
296 | // m_log.DebugFormat( | ||
297 | // "[DYNAMIC TEXTURE MODULE]: Reusing cached texture {0} for {1} in {2}", | ||
298 | // objReusableTextureUUID, part.Name, part.ParentGroup.Scene.Name); | ||
299 | |||
300 | // No need to add to updaters as the texture is always the same. Not that this functionality | ||
301 | // apppears to be implemented anyway. | ||
302 | updater.UpdatePart(part, (UUID)objReusableTextureUUID); | ||
303 | } | ||
304 | |||
305 | return updater.UpdaterID; | ||
306 | } | ||
307 | |||
308 | private string GenerateReusableTextureKey(string data, string extraParams) | ||
309 | { | ||
310 | return string.Format("{0}{1}", data, extraParams); | ||
311 | } | 199 | } |
312 | 200 | ||
313 | public void GetDrawStringSize(string contentType, string text, string fontName, int fontSize, | 201 | public void GetDrawStringSize(string contentType, string text, string fontName, int fontSize, |
@@ -327,13 +215,6 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture | |||
327 | 215 | ||
328 | public void Initialise(Scene scene, IConfigSource config) | 216 | public void Initialise(Scene scene, IConfigSource config) |
329 | { | 217 | { |
330 | IConfig texturesConfig = config.Configs["Textures"]; | ||
331 | if (texturesConfig != null) | ||
332 | { | ||
333 | ReuseTextures = texturesConfig.GetBoolean("ReuseDynamicTextures", false); | ||
334 | ReuseLowDataTextures = texturesConfig.GetBoolean("ReuseDynamicLowDataTextures", false); | ||
335 | } | ||
336 | |||
337 | if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID)) | 218 | if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID)) |
338 | { | 219 | { |
339 | RegisteredScenes.Add(scene.RegionInfo.RegionID, scene); | 220 | RegisteredScenes.Add(scene.RegionInfo.RegionID, scene); |
@@ -343,11 +224,6 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture | |||
343 | 224 | ||
344 | public void PostInitialise() | 225 | public void PostInitialise() |
345 | { | 226 | { |
346 | if (ReuseTextures) | ||
347 | { | ||
348 | m_reuseableDynamicTextures = new Cache(CacheMedium.Memory, CacheStrategy.Conservative); | ||
349 | m_reuseableDynamicTextures.DefaultTTL = new TimeSpan(24, 0, 0); | ||
350 | } | ||
351 | } | 227 | } |
352 | 228 | ||
353 | public void Close() | 229 | public void Close() |
@@ -393,60 +269,9 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture | |||
393 | } | 269 | } |
394 | 270 | ||
395 | /// <summary> | 271 | /// <summary> |
396 | /// Update the given part with the new texture. | ||
397 | /// </summary> | ||
398 | /// <returns> | ||
399 | /// The old texture UUID. | ||
400 | /// </returns> | ||
401 | public UUID UpdatePart(SceneObjectPart part, UUID textureID) | ||
402 | { | ||
403 | UUID oldID; | ||
404 | |||
405 | lock (part) | ||
406 | { | ||
407 | // mostly keep the values from before | ||
408 | Primitive.TextureEntry tmptex = part.Shape.Textures; | ||
409 | |||
410 | // FIXME: Need to return the appropriate ID if only a single face is replaced. | ||
411 | oldID = tmptex.DefaultTexture.TextureID; | ||
412 | |||
413 | if (Face == ALL_SIDES) | ||
414 | { | ||
415 | oldID = tmptex.DefaultTexture.TextureID; | ||
416 | tmptex.DefaultTexture.TextureID = textureID; | ||
417 | } | ||
418 | else | ||
419 | { | ||
420 | try | ||
421 | { | ||
422 | Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face); | ||
423 | texface.TextureID = textureID; | ||
424 | tmptex.FaceTextures[Face] = texface; | ||
425 | } | ||
426 | catch (Exception) | ||
427 | { | ||
428 | tmptex.DefaultTexture.TextureID = textureID; | ||
429 | } | ||
430 | } | ||
431 | |||
432 | // I'm pretty sure we always want to force this to true | ||
433 | // I'm pretty sure noone whats to set fullbright true if it wasn't true before. | ||
434 | // tmptex.DefaultTexture.Fullbright = true; | ||
435 | |||
436 | part.UpdateTextureEntry(tmptex.GetBytes()); | ||
437 | } | ||
438 | |||
439 | return oldID; | ||
440 | } | ||
441 | |||
442 | /// <summary> | ||
443 | /// Called once new texture data has been received for this updater. | 272 | /// Called once new texture data has been received for this updater. |
444 | /// </summary> | 273 | /// </summary> |
445 | /// <param name="data"></param> | 274 | public void DataReceived(byte[] data, Scene scene) |
446 | /// <param name="scene"></param> | ||
447 | /// <param name="isReuseable">True if the data given is reuseable.</param> | ||
448 | /// <returns>The asset UUID given to the incoming data.</returns> | ||
449 | public UUID DataReceived(byte[] data, Scene scene) | ||
450 | { | 275 | { |
451 | SceneObjectPart part = scene.GetSceneObjectPart(PrimID); | 276 | SceneObjectPart part = scene.GetSceneObjectPart(PrimID); |
452 | 277 | ||
@@ -456,8 +281,7 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture | |||
456 | String.Format("DynamicTextureModule: Error preparing image using URL {0}", Url); | 281 | String.Format("DynamicTextureModule: Error preparing image using URL {0}", Url); |
457 | scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Say, | 282 | scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Say, |
458 | 0, part.ParentGroup.RootPart.AbsolutePosition, part.Name, part.UUID, false); | 283 | 0, part.ParentGroup.RootPart.AbsolutePosition, part.Name, part.UUID, false); |
459 | 284 | return; | |
460 | return UUID.Zero; | ||
461 | } | 285 | } |
462 | 286 | ||
463 | byte[] assetData = null; | 287 | byte[] assetData = null; |
@@ -495,29 +319,56 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture | |||
495 | IJ2KDecoder cacheLayerDecode = scene.RequestModuleInterface<IJ2KDecoder>(); | 319 | IJ2KDecoder cacheLayerDecode = scene.RequestModuleInterface<IJ2KDecoder>(); |
496 | if (cacheLayerDecode != null) | 320 | if (cacheLayerDecode != null) |
497 | { | 321 | { |
498 | if (!cacheLayerDecode.Decode(asset.FullID, asset.Data)) | 322 | cacheLayerDecode.Decode(asset.FullID, asset.Data); |
499 | m_log.WarnFormat( | 323 | cacheLayerDecode = null; |
500 | "[DYNAMIC TEXTURE MODULE]: Decoding of dynamically generated asset {0} for {1} in {2} failed", | ||
501 | asset.ID, part.Name, part.ParentGroup.Scene.Name); | ||
502 | } | 324 | } |
503 | 325 | ||
504 | UUID oldID = UpdatePart(part, asset.FullID); | 326 | UUID oldID = UUID.Zero; |
505 | 327 | ||
506 | if (oldID != UUID.Zero && ((Disp & DISP_EXPIRE) != 0)) | 328 | lock (part) |
507 | { | 329 | { |
508 | if (oldAsset == null) | 330 | // mostly keep the values from before |
509 | oldAsset = scene.AssetService.Get(oldID.ToString()); | 331 | Primitive.TextureEntry tmptex = part.Shape.Textures; |
332 | |||
333 | // remove the old asset from the cache | ||
334 | oldID = tmptex.DefaultTexture.TextureID; | ||
335 | |||
336 | if (Face == ALL_SIDES) | ||
337 | { | ||
338 | tmptex.DefaultTexture.TextureID = asset.FullID; | ||
339 | } | ||
340 | else | ||
341 | { | ||
342 | try | ||
343 | { | ||
344 | Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face); | ||
345 | texface.TextureID = asset.FullID; | ||
346 | tmptex.FaceTextures[Face] = texface; | ||
347 | } | ||
348 | catch (Exception) | ||
349 | { | ||
350 | tmptex.DefaultTexture.TextureID = asset.FullID; | ||
351 | } | ||
352 | } | ||
510 | 353 | ||
354 | // I'm pretty sure we always want to force this to true | ||
355 | // I'm pretty sure noone whats to set fullbright true if it wasn't true before. | ||
356 | // tmptex.DefaultTexture.Fullbright = true; | ||
357 | |||
358 | part.UpdateTextureEntry(tmptex.GetBytes()); | ||
359 | } | ||
360 | |||
361 | if (oldID != UUID.Zero && ((Disp & DISP_EXPIRE) != 0)) | ||
362 | { | ||
363 | if (oldAsset == null) oldAsset = scene.AssetService.Get(oldID.ToString()); | ||
511 | if (oldAsset != null) | 364 | if (oldAsset != null) |
512 | { | 365 | { |
513 | if (oldAsset.Temporary) | 366 | if (oldAsset.Temporary == true) |
514 | { | 367 | { |
515 | scene.AssetService.Delete(oldID.ToString()); | 368 | scene.AssetService.Delete(oldID.ToString()); |
516 | } | 369 | } |
517 | } | 370 | } |
518 | } | 371 | } |
519 | |||
520 | return asset.FullID; | ||
521 | } | 372 | } |
522 | 373 | ||
523 | private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha) | 374 | private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha) |
diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs index 0b9174f..56221aa 100644 --- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs | |||
@@ -58,7 +58,6 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
58 | public string body; | 58 | public string body; |
59 | public int responseCode; | 59 | public int responseCode; |
60 | public string responseBody; | 60 | public string responseBody; |
61 | public string responseType = "text/plain"; | ||
62 | //public ManualResetEvent ev; | 61 | //public ManualResetEvent ev; |
63 | public bool requestDone; | 62 | public bool requestDone; |
64 | public int startTime; | 63 | public int startTime; |
@@ -271,22 +270,6 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
271 | } | 270 | } |
272 | } | 271 | } |
273 | 272 | ||
274 | public void HttpContentType(UUID request, string type) | ||
275 | { | ||
276 | lock (m_UrlMap) | ||
277 | { | ||
278 | if (m_RequestMap.ContainsKey(request)) | ||
279 | { | ||
280 | UrlData urlData = m_RequestMap[request]; | ||
281 | urlData.requests[request].responseType = type; | ||
282 | } | ||
283 | else | ||
284 | { | ||
285 | m_log.Info("[HttpRequestHandler] There is no http-in request with id " + request.ToString()); | ||
286 | } | ||
287 | } | ||
288 | } | ||
289 | |||
290 | public void HttpResponse(UUID request, int status, string body) | 273 | public void HttpResponse(UUID request, int status, string body) |
291 | { | 274 | { |
292 | lock (m_RequestMap) | 275 | lock (m_RequestMap) |
diff --git a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs index 45e6527..6f83948 100644 --- a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs | |||
@@ -32,7 +32,6 @@ using System.Net; | |||
32 | using Nini.Config; | 32 | using Nini.Config; |
33 | using OpenMetaverse; | 33 | using OpenMetaverse; |
34 | using OpenMetaverse.Imaging; | 34 | using OpenMetaverse.Imaging; |
35 | using OpenSim.Region.CoreModules.Scripting.DynamicTexture; | ||
36 | using OpenSim.Region.Framework.Interfaces; | 35 | using OpenSim.Region.Framework.Interfaces; |
37 | using OpenSim.Region.Framework.Scenes; | 36 | using OpenSim.Region.Framework.Scenes; |
38 | using log4net; | 37 | using log4net; |
@@ -68,18 +67,12 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL | |||
68 | return true; | 67 | return true; |
69 | } | 68 | } |
70 | 69 | ||
71 | // public bool AlwaysIdenticalConversion(string bodyData, string extraParams) | 70 | public byte[] ConvertUrl(string url, string extraParams) |
72 | // { | ||
73 | // // We don't support conversion of body data. | ||
74 | // return false; | ||
75 | // } | ||
76 | |||
77 | public IDynamicTexture ConvertUrl(string url, string extraParams) | ||
78 | { | 71 | { |
79 | return null; | 72 | return null; |
80 | } | 73 | } |
81 | 74 | ||
82 | public IDynamicTexture ConvertData(string bodyData, string extraParams) | 75 | public byte[] ConvertStream(Stream data, string extraParams) |
83 | { | 76 | { |
84 | return null; | 77 | return null; |
85 | } | 78 | } |
@@ -172,11 +165,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL | |||
172 | 165 | ||
173 | private void HttpRequestReturn(IAsyncResult result) | 166 | private void HttpRequestReturn(IAsyncResult result) |
174 | { | 167 | { |
168 | |||
175 | RequestState state = (RequestState) result.AsyncState; | 169 | RequestState state = (RequestState) result.AsyncState; |
176 | WebRequest request = (WebRequest) state.Request; | 170 | WebRequest request = (WebRequest) state.Request; |
177 | Stream stream = null; | 171 | Stream stream = null; |
178 | byte[] imageJ2000 = new byte[0]; | 172 | byte[] imageJ2000 = new byte[0]; |
179 | Size newSize = new Size(0, 0); | ||
180 | 173 | ||
181 | try | 174 | try |
182 | { | 175 | { |
@@ -189,43 +182,37 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL | |||
189 | try | 182 | try |
190 | { | 183 | { |
191 | Bitmap image = new Bitmap(stream); | 184 | Bitmap image = new Bitmap(stream); |
185 | Size newsize; | ||
192 | 186 | ||
193 | // TODO: make this a bit less hard coded | 187 | // TODO: make this a bit less hard coded |
194 | if ((image.Height < 64) && (image.Width < 64)) | 188 | if ((image.Height < 64) && (image.Width < 64)) |
195 | { | 189 | { |
196 | newSize.Width = 32; | 190 | newsize = new Size(32, 32); |
197 | newSize.Height = 32; | ||
198 | } | 191 | } |
199 | else if ((image.Height < 128) && (image.Width < 128)) | 192 | else if ((image.Height < 128) && (image.Width < 128)) |
200 | { | 193 | { |
201 | newSize.Width = 64; | 194 | newsize = new Size(64, 64); |
202 | newSize.Height = 64; | ||
203 | } | 195 | } |
204 | else if ((image.Height < 256) && (image.Width < 256)) | 196 | else if ((image.Height < 256) && (image.Width < 256)) |
205 | { | 197 | { |
206 | newSize.Width = 128; | 198 | newsize = new Size(128, 128); |
207 | newSize.Height = 128; | ||
208 | } | 199 | } |
209 | else if ((image.Height < 512 && image.Width < 512)) | 200 | else if ((image.Height < 512 && image.Width < 512)) |
210 | { | 201 | { |
211 | newSize.Width = 256; | 202 | newsize = new Size(256, 256); |
212 | newSize.Height = 256; | ||
213 | } | 203 | } |
214 | else if ((image.Height < 1024 && image.Width < 1024)) | 204 | else if ((image.Height < 1024 && image.Width < 1024)) |
215 | { | 205 | { |
216 | newSize.Width = 512; | 206 | newsize = new Size(512, 512); |
217 | newSize.Height = 512; | ||
218 | } | 207 | } |
219 | else | 208 | else |
220 | { | 209 | { |
221 | newSize.Width = 1024; | 210 | newsize = new Size(1024, 1024); |
222 | newSize.Height = 1024; | ||
223 | } | 211 | } |
224 | 212 | ||
225 | using (Bitmap resize = new Bitmap(image, newSize)) | 213 | Bitmap resize = new Bitmap(image, newsize); |
226 | { | 214 | |
227 | imageJ2000 = OpenJPEG.EncodeFromImage(resize, true); | 215 | imageJ2000 = OpenJPEG.EncodeFromImage(resize, true); |
228 | } | ||
229 | } | 216 | } |
230 | catch (Exception) | 217 | catch (Exception) |
231 | { | 218 | { |
@@ -240,6 +227,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL | |||
240 | } | 227 | } |
241 | catch (WebException) | 228 | catch (WebException) |
242 | { | 229 | { |
230 | |||
243 | } | 231 | } |
244 | finally | 232 | finally |
245 | { | 233 | { |
@@ -248,14 +236,9 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL | |||
248 | stream.Close(); | 236 | stream.Close(); |
249 | } | 237 | } |
250 | } | 238 | } |
251 | 239 | m_log.DebugFormat("[LOADIMAGEURLMODULE] Returning {0} bytes of image data for request {1}", | |
252 | m_log.DebugFormat("[LOADIMAGEURLMODULE]: Returning {0} bytes of image data for request {1}", | ||
253 | imageJ2000.Length, state.RequestID); | 240 | imageJ2000.Length, state.RequestID); |
254 | 241 | m_textureManager.ReturnData(state.RequestID, imageJ2000); | |
255 | m_textureManager.ReturnData( | ||
256 | state.RequestID, | ||
257 | new OpenSim.Region.CoreModules.Scripting.DynamicTexture.DynamicTexture( | ||
258 | request.RequestUri, null, imageJ2000, newSize, false)); | ||
259 | } | 242 | } |
260 | 243 | ||
261 | #region Nested type: RequestState | 244 | #region Nested type: RequestState |
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs index 41baccc..9787c8c 100644 --- a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs +++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs | |||
@@ -45,292 +45,31 @@ using OpenSim.Tests.Common.Mock; | |||
45 | namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests | 45 | namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests |
46 | { | 46 | { |
47 | [TestFixture] | 47 | [TestFixture] |
48 | public class VectorRenderModuleTests : OpenSimTestCase | 48 | public class VectorRenderModuleTests |
49 | { | 49 | { |
50 | Scene m_scene; | ||
51 | DynamicTextureModule m_dtm; | ||
52 | VectorRenderModule m_vrm; | ||
53 | |||
54 | private void SetupScene(bool reuseTextures) | ||
55 | { | ||
56 | m_scene = new SceneHelpers().SetupScene(); | ||
57 | |||
58 | m_dtm = new DynamicTextureModule(); | ||
59 | m_dtm.ReuseTextures = reuseTextures; | ||
60 | // m_dtm.ReuseLowDataTextures = reuseTextures; | ||
61 | |||
62 | m_vrm = new VectorRenderModule(); | ||
63 | |||
64 | SceneHelpers.SetupSceneModules(m_scene, m_dtm, m_vrm); | ||
65 | } | ||
66 | |||
67 | [Test] | 50 | [Test] |
68 | public void TestDraw() | 51 | public void TestDraw() |
69 | { | 52 | { |
70 | TestHelpers.InMethod(); | 53 | TestHelpers.InMethod(); |
71 | 54 | ||
72 | SetupScene(false); | 55 | Scene scene = new SceneHelpers().SetupScene(); |
73 | SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); | 56 | DynamicTextureModule dtm = new DynamicTextureModule(); |
74 | UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; | 57 | VectorRenderModule vrm = new VectorRenderModule(); |
75 | 58 | SceneHelpers.SetupSceneModules(scene, dtm, vrm); | |
76 | m_dtm.AddDynamicTextureData( | ||
77 | m_scene.RegionInfo.RegionID, | ||
78 | so.UUID, | ||
79 | m_vrm.GetContentType(), | ||
80 | "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;", | ||
81 | "", | ||
82 | 0); | ||
83 | |||
84 | Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); | ||
85 | } | ||
86 | |||
87 | [Test] | ||
88 | public void TestRepeatSameDraw() | ||
89 | { | ||
90 | TestHelpers.InMethod(); | ||
91 | |||
92 | string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;"; | ||
93 | |||
94 | SetupScene(false); | ||
95 | SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); | ||
96 | |||
97 | m_dtm.AddDynamicTextureData( | ||
98 | m_scene.RegionInfo.RegionID, | ||
99 | so.UUID, | ||
100 | m_vrm.GetContentType(), | ||
101 | dtText, | ||
102 | "", | ||
103 | 0); | ||
104 | |||
105 | UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; | ||
106 | |||
107 | m_dtm.AddDynamicTextureData( | ||
108 | m_scene.RegionInfo.RegionID, | ||
109 | so.UUID, | ||
110 | m_vrm.GetContentType(), | ||
111 | dtText, | ||
112 | "", | ||
113 | 0); | ||
114 | |||
115 | Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); | ||
116 | } | ||
117 | |||
118 | [Test] | ||
119 | public void TestRepeatSameDrawDifferentExtraParams() | ||
120 | { | ||
121 | TestHelpers.InMethod(); | ||
122 | |||
123 | string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;"; | ||
124 | |||
125 | SetupScene(false); | ||
126 | SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); | ||
127 | |||
128 | m_dtm.AddDynamicTextureData( | ||
129 | m_scene.RegionInfo.RegionID, | ||
130 | so.UUID, | ||
131 | m_vrm.GetContentType(), | ||
132 | dtText, | ||
133 | "", | ||
134 | 0); | ||
135 | |||
136 | UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; | ||
137 | |||
138 | m_dtm.AddDynamicTextureData( | ||
139 | m_scene.RegionInfo.RegionID, | ||
140 | so.UUID, | ||
141 | m_vrm.GetContentType(), | ||
142 | dtText, | ||
143 | "alpha:250", | ||
144 | 0); | ||
145 | |||
146 | Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); | ||
147 | } | ||
148 | |||
149 | [Test] | ||
150 | public void TestRepeatSameDrawContainingImage() | ||
151 | { | ||
152 | TestHelpers.InMethod(); | ||
153 | |||
154 | string dtText | ||
155 | = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://localhost/shouldnotexist.png"; | ||
156 | |||
157 | SetupScene(false); | ||
158 | SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); | ||
159 | |||
160 | m_dtm.AddDynamicTextureData( | ||
161 | m_scene.RegionInfo.RegionID, | ||
162 | so.UUID, | ||
163 | m_vrm.GetContentType(), | ||
164 | dtText, | ||
165 | "", | ||
166 | 0); | ||
167 | |||
168 | UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; | ||
169 | |||
170 | m_dtm.AddDynamicTextureData( | ||
171 | m_scene.RegionInfo.RegionID, | ||
172 | so.UUID, | ||
173 | m_vrm.GetContentType(), | ||
174 | dtText, | ||
175 | "", | ||
176 | 0); | ||
177 | |||
178 | Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); | ||
179 | } | ||
180 | |||
181 | [Test] | ||
182 | public void TestDrawReusingTexture() | ||
183 | { | ||
184 | TestHelpers.InMethod(); | ||
185 | 59 | ||
186 | SetupScene(true); | 60 | SceneObjectGroup so = SceneHelpers.AddSceneObject(scene); |
187 | SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); | ||
188 | UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; | 61 | UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; |
189 | 62 | ||
190 | m_dtm.AddDynamicTextureData( | 63 | dtm.AddDynamicTextureData( |
191 | m_scene.RegionInfo.RegionID, | 64 | scene.RegionInfo.RegionID, |
192 | so.UUID, | 65 | so.UUID, |
193 | m_vrm.GetContentType(), | 66 | vrm.GetContentType(), |
194 | "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;", | 67 | "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;", |
195 | "", | 68 | "", |
196 | 0); | 69 | 0); |
197 | 70 | ||
198 | Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); | ||
199 | } | ||
200 | |||
201 | [Test] | ||
202 | public void TestRepeatSameDrawReusingTexture() | ||
203 | { | ||
204 | TestHelpers.InMethod(); | ||
205 | // TestHelpers.EnableLogging(); | ||
206 | |||
207 | string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;"; | ||
208 | |||
209 | SetupScene(true); | ||
210 | SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); | ||
211 | |||
212 | m_dtm.AddDynamicTextureData( | ||
213 | m_scene.RegionInfo.RegionID, | ||
214 | so.UUID, | ||
215 | m_vrm.GetContentType(), | ||
216 | dtText, | ||
217 | "", | ||
218 | 0); | ||
219 | |||
220 | UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; | ||
221 | |||
222 | m_dtm.AddDynamicTextureData( | ||
223 | m_scene.RegionInfo.RegionID, | ||
224 | so.UUID, | ||
225 | m_vrm.GetContentType(), | ||
226 | dtText, | ||
227 | "", | ||
228 | 0); | ||
229 | |||
230 | Assert.That(firstDynamicTextureID, Is.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); | ||
231 | } | ||
232 | |||
233 | /// <summary> | ||
234 | /// Test a low data dynamically generated texture such that it is treated as a low data texture that causes | ||
235 | /// problems for current viewers. | ||
236 | /// </summary> | ||
237 | /// <remarks> | ||
238 | /// As we do not set DynamicTextureModule.ReuseLowDataTextures = true in this test, it should not reuse the | ||
239 | /// texture | ||
240 | /// </remarks> | ||
241 | [Test] | ||
242 | public void TestRepeatSameDrawLowDataTexture() | ||
243 | { | ||
244 | TestHelpers.InMethod(); | ||
245 | // TestHelpers.EnableLogging(); | ||
246 | |||
247 | string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;"; | ||
248 | |||
249 | SetupScene(true); | ||
250 | SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); | ||
251 | |||
252 | m_dtm.AddDynamicTextureData( | ||
253 | m_scene.RegionInfo.RegionID, | ||
254 | so.UUID, | ||
255 | m_vrm.GetContentType(), | ||
256 | dtText, | ||
257 | "1024", | ||
258 | 0); | ||
259 | |||
260 | UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; | ||
261 | |||
262 | m_dtm.AddDynamicTextureData( | ||
263 | m_scene.RegionInfo.RegionID, | ||
264 | so.UUID, | ||
265 | m_vrm.GetContentType(), | ||
266 | dtText, | ||
267 | "1024", | ||
268 | 0); | ||
269 | |||
270 | Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); | ||
271 | } | ||
272 | |||
273 | [Test] | ||
274 | public void TestRepeatSameDrawDifferentExtraParamsReusingTexture() | ||
275 | { | ||
276 | TestHelpers.InMethod(); | ||
277 | |||
278 | string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;"; | ||
279 | |||
280 | SetupScene(true); | ||
281 | SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); | ||
282 | |||
283 | m_dtm.AddDynamicTextureData( | ||
284 | m_scene.RegionInfo.RegionID, | ||
285 | so.UUID, | ||
286 | m_vrm.GetContentType(), | ||
287 | dtText, | ||
288 | "", | ||
289 | 0); | ||
290 | |||
291 | UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; | ||
292 | |||
293 | m_dtm.AddDynamicTextureData( | ||
294 | m_scene.RegionInfo.RegionID, | ||
295 | so.UUID, | ||
296 | m_vrm.GetContentType(), | ||
297 | dtText, | ||
298 | "alpha:250", | ||
299 | 0); | ||
300 | |||
301 | Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); | ||
302 | } | ||
303 | |||
304 | [Test] | ||
305 | public void TestRepeatSameDrawContainingImageReusingTexture() | ||
306 | { | ||
307 | TestHelpers.InMethod(); | ||
308 | |||
309 | string dtText | ||
310 | = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://localhost/shouldnotexist.png"; | ||
311 | |||
312 | SetupScene(true); | ||
313 | SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); | ||
314 | |||
315 | m_dtm.AddDynamicTextureData( | ||
316 | m_scene.RegionInfo.RegionID, | ||
317 | so.UUID, | ||
318 | m_vrm.GetContentType(), | ||
319 | dtText, | ||
320 | "", | ||
321 | 0); | ||
322 | |||
323 | UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; | ||
324 | |||
325 | m_dtm.AddDynamicTextureData( | ||
326 | m_scene.RegionInfo.RegionID, | ||
327 | so.UUID, | ||
328 | m_vrm.GetContentType(), | ||
329 | dtText, | ||
330 | "", | ||
331 | 0); | ||
332 | 71 | ||
333 | Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); | 72 | Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); |
334 | } | 73 | } |
335 | } | 74 | } |
336 | } \ No newline at end of file | 75 | } \ No newline at end of file |
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs index 673c2d1..8b2f2f8 100644 --- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs | |||
@@ -30,12 +30,10 @@ using System.Drawing; | |||
30 | using System.Drawing.Imaging; | 30 | using System.Drawing.Imaging; |
31 | using System.Globalization; | 31 | using System.Globalization; |
32 | using System.IO; | 32 | using System.IO; |
33 | using System.Linq; | ||
34 | using System.Net; | 33 | using System.Net; |
35 | using Nini.Config; | 34 | using Nini.Config; |
36 | using OpenMetaverse; | 35 | using OpenMetaverse; |
37 | using OpenMetaverse.Imaging; | 36 | using OpenMetaverse.Imaging; |
38 | using OpenSim.Region.CoreModules.Scripting.DynamicTexture; | ||
39 | using OpenSim.Region.Framework.Interfaces; | 37 | using OpenSim.Region.Framework.Interfaces; |
40 | using OpenSim.Region.Framework.Scenes; | 38 | using OpenSim.Region.Framework.Scenes; |
41 | using log4net; | 39 | using log4net; |
@@ -47,13 +45,9 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender | |||
47 | { | 45 | { |
48 | public class VectorRenderModule : IRegionModule, IDynamicTextureRender | 46 | public class VectorRenderModule : IRegionModule, IDynamicTextureRender |
49 | { | 47 | { |
50 | // These fields exist for testing purposes, please do not remove. | ||
51 | // private static bool s_flipper; | ||
52 | // private static byte[] s_asset1Data; | ||
53 | // private static byte[] s_asset2Data; | ||
54 | |||
55 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 48 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
56 | 49 | ||
50 | private string m_name = "VectorRenderModule"; | ||
57 | private Scene m_scene; | 51 | private Scene m_scene; |
58 | private IDynamicTextureManager m_textureManager; | 52 | private IDynamicTextureManager m_textureManager; |
59 | private Graphics m_graph; | 53 | private Graphics m_graph; |
@@ -67,12 +61,12 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender | |||
67 | 61 | ||
68 | public string GetContentType() | 62 | public string GetContentType() |
69 | { | 63 | { |
70 | return "vector"; | 64 | return ("vector"); |
71 | } | 65 | } |
72 | 66 | ||
73 | public string GetName() | 67 | public string GetName() |
74 | { | 68 | { |
75 | return Name; | 69 | return m_name; |
76 | } | 70 | } |
77 | 71 | ||
78 | public bool SupportsAsynchronous() | 72 | public bool SupportsAsynchronous() |
@@ -80,20 +74,14 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender | |||
80 | return true; | 74 | return true; |
81 | } | 75 | } |
82 | 76 | ||
83 | // public bool AlwaysIdenticalConversion(string bodyData, string extraParams) | 77 | public byte[] ConvertUrl(string url, string extraParams) |
84 | // { | ||
85 | // string[] lines = GetLines(bodyData); | ||
86 | // return lines.Any((str, r) => str.StartsWith("Image")); | ||
87 | // } | ||
88 | |||
89 | public IDynamicTexture ConvertUrl(string url, string extraParams) | ||
90 | { | 78 | { |
91 | return null; | 79 | return null; |
92 | } | 80 | } |
93 | 81 | ||
94 | public IDynamicTexture ConvertData(string bodyData, string extraParams) | 82 | public byte[] ConvertStream(Stream data, string extraParams) |
95 | { | 83 | { |
96 | return Draw(bodyData, extraParams); | 84 | return null; |
97 | } | 85 | } |
98 | 86 | ||
99 | public bool AsyncConvertUrl(UUID id, string url, string extraParams) | 87 | public bool AsyncConvertUrl(UUID id, string url, string extraParams) |
@@ -103,28 +91,21 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender | |||
103 | 91 | ||
104 | public bool AsyncConvertData(UUID id, string bodyData, string extraParams) | 92 | public bool AsyncConvertData(UUID id, string bodyData, string extraParams) |
105 | { | 93 | { |
106 | // XXX: This isn't actually being done asynchronously! | 94 | Draw(bodyData, id, extraParams); |
107 | m_textureManager.ReturnData(id, ConvertData(bodyData, extraParams)); | ||
108 | |||
109 | return true; | 95 | return true; |
110 | } | 96 | } |
111 | 97 | ||
112 | public void GetDrawStringSize(string text, string fontName, int fontSize, | 98 | public void GetDrawStringSize(string text, string fontName, int fontSize, |
113 | out double xSize, out double ySize) | 99 | out double xSize, out double ySize) |
114 | { | 100 | { |
115 | lock (this) | 101 | using (Font myFont = new Font(fontName, fontSize)) |
116 | { | 102 | { |
117 | using (Font myFont = new Font(fontName, fontSize)) | 103 | SizeF stringSize = new SizeF(); |
104 | lock (m_graph) | ||
118 | { | 105 | { |
119 | SizeF stringSize = new SizeF(); | 106 | stringSize = m_graph.MeasureString(text, myFont); |
120 | 107 | xSize = stringSize.Width; | |
121 | // XXX: This lock may be unnecessary. | 108 | ySize = stringSize.Height; |
122 | lock (m_graph) | ||
123 | { | ||
124 | stringSize = m_graph.MeasureString(text, myFont); | ||
125 | xSize = stringSize.Width; | ||
126 | ySize = stringSize.Height; | ||
127 | } | ||
128 | } | 109 | } |
129 | } | 110 | } |
130 | } | 111 | } |
@@ -163,13 +144,6 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender | |||
163 | { | 144 | { |
164 | m_textureManager.RegisterRender(GetContentType(), this); | 145 | m_textureManager.RegisterRender(GetContentType(), this); |
165 | } | 146 | } |
166 | |||
167 | // This code exists for testing purposes, please do not remove. | ||
168 | // s_asset1Data = m_scene.AssetService.Get("00000000-0000-1111-9999-000000000001").Data; | ||
169 | // s_asset1Data = m_scene.AssetService.Get("9f4acf0d-1841-4e15-bdb8-3a12efc9dd8f").Data; | ||
170 | |||
171 | // Terrain dirt - smallest bin/assets file (6004 bytes) | ||
172 | // s_asset2Data = m_scene.AssetService.Get("b8d3965a-ad78-bf43-699b-bff8eca6c975").Data; | ||
173 | } | 147 | } |
174 | 148 | ||
175 | public void Close() | 149 | public void Close() |
@@ -178,7 +152,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender | |||
178 | 152 | ||
179 | public string Name | 153 | public string Name |
180 | { | 154 | { |
181 | get { return "VectorRenderModule"; } | 155 | get { return m_name; } |
182 | } | 156 | } |
183 | 157 | ||
184 | public bool IsSharedModule | 158 | public bool IsSharedModule |
@@ -188,7 +162,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender | |||
188 | 162 | ||
189 | #endregion | 163 | #endregion |
190 | 164 | ||
191 | private IDynamicTexture Draw(string data, string extraParams) | 165 | private void Draw(string data, UUID id, string extraParams) |
192 | { | 166 | { |
193 | // We need to cater for old scripts that didnt use extraParams neatly, they use either an integer size which represents both width and height, or setalpha | 167 | // We need to cater for old scripts that didnt use extraParams neatly, they use either an integer size which represents both width and height, or setalpha |
194 | // we will now support multiple comma seperated params in the form width:256,height:512,alpha:255 | 168 | // we will now support multiple comma seperated params in the form width:256,height:512,alpha:255 |
@@ -331,57 +305,40 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender | |||
331 | 305 | ||
332 | Bitmap bitmap = null; | 306 | Bitmap bitmap = null; |
333 | Graphics graph = null; | 307 | Graphics graph = null; |
334 | bool reuseable = false; | ||
335 | 308 | ||
336 | try | 309 | try |
337 | { | 310 | { |
338 | // XXX: In testing, it appears that if multiple threads dispose of separate GDI+ objects simultaneously, | 311 | if (alpha == 256) |
339 | // the native malloc heap can become corrupted, possibly due to a double free(). This may be due to | 312 | bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb); |
340 | // bugs in the underlying libcairo used by mono's libgdiplus.dll on Linux/OSX. These problems were | 313 | else |
341 | // seen with both libcario 1.10.2-6.1ubuntu3 and 1.8.10-2ubuntu1. They go away if disposal is perfomed | 314 | bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); |
342 | // under lock. | 315 | |
343 | lock (this) | 316 | graph = Graphics.FromImage(bitmap); |
344 | { | ||
345 | if (alpha == 256) | ||
346 | bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb); | ||
347 | else | ||
348 | bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); | ||
349 | 317 | ||
350 | graph = Graphics.FromImage(bitmap); | 318 | // this is really just to save people filling the |
351 | 319 | // background color in their scripts, only do when fully opaque | |
352 | // this is really just to save people filling the | 320 | if (alpha >= 255) |
353 | // background color in their scripts, only do when fully opaque | 321 | { |
354 | if (alpha >= 255) | 322 | using (SolidBrush bgFillBrush = new SolidBrush(bgColor)) |
355 | { | 323 | { |
356 | using (SolidBrush bgFillBrush = new SolidBrush(bgColor)) | 324 | graph.FillRectangle(bgFillBrush, 0, 0, width, height); |
357 | { | ||
358 | graph.FillRectangle(bgFillBrush, 0, 0, width, height); | ||
359 | } | ||
360 | } | 325 | } |
361 | 326 | } | |
362 | for (int w = 0; w < bitmap.Width; w++) | 327 | |
328 | for (int w = 0; w < bitmap.Width; w++) | ||
329 | { | ||
330 | if (alpha <= 255) | ||
363 | { | 331 | { |
364 | if (alpha <= 255) | 332 | for (int h = 0; h < bitmap.Height; h++) |
365 | { | 333 | { |
366 | for (int h = 0; h < bitmap.Height; h++) | 334 | bitmap.SetPixel(w, h, Color.FromArgb(alpha, bitmap.GetPixel(w, h))); |
367 | { | ||
368 | bitmap.SetPixel(w, h, Color.FromArgb(alpha, bitmap.GetPixel(w, h))); | ||
369 | } | ||
370 | } | 335 | } |
371 | } | 336 | } |
372 | |||
373 | GDIDraw(data, graph, altDataDelim, out reuseable); | ||
374 | } | 337 | } |
375 | 338 | ||
339 | GDIDraw(data, graph, altDataDelim); | ||
340 | |||
376 | byte[] imageJ2000 = new byte[0]; | 341 | byte[] imageJ2000 = new byte[0]; |
377 | |||
378 | // This code exists for testing purposes, please do not remove. | ||
379 | // if (s_flipper) | ||
380 | // imageJ2000 = s_asset1Data; | ||
381 | // else | ||
382 | // imageJ2000 = s_asset2Data; | ||
383 | // | ||
384 | // s_flipper = !s_flipper; | ||
385 | 342 | ||
386 | try | 343 | try |
387 | { | 344 | { |
@@ -394,24 +351,15 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender | |||
394 | e.Message, e.StackTrace); | 351 | e.Message, e.StackTrace); |
395 | } | 352 | } |
396 | 353 | ||
397 | return new OpenSim.Region.CoreModules.Scripting.DynamicTexture.DynamicTexture( | 354 | m_textureManager.ReturnData(id, imageJ2000); |
398 | data, extraParams, imageJ2000, new Size(width, height), reuseable); | ||
399 | } | 355 | } |
400 | finally | 356 | finally |
401 | { | 357 | { |
402 | // XXX: In testing, it appears that if multiple threads dispose of separate GDI+ objects simultaneously, | 358 | if (graph != null) |
403 | // the native malloc heap can become corrupted, possibly due to a double free(). This may be due to | 359 | graph.Dispose(); |
404 | // bugs in the underlying libcairo used by mono's libgdiplus.dll on Linux/OSX. These problems were | 360 | |
405 | // seen with both libcario 1.10.2-6.1ubuntu3 and 1.8.10-2ubuntu1. They go away if disposal is perfomed | 361 | if (bitmap != null) |
406 | // under lock. | 362 | bitmap.Dispose(); |
407 | lock (this) | ||
408 | { | ||
409 | if (graph != null) | ||
410 | graph.Dispose(); | ||
411 | |||
412 | if (bitmap != null) | ||
413 | bitmap.Dispose(); | ||
414 | } | ||
415 | } | 363 | } |
416 | } | 364 | } |
417 | 365 | ||
@@ -470,21 +418,8 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender | |||
470 | } | 418 | } |
471 | */ | 419 | */ |
472 | 420 | ||
473 | /// <summary> | 421 | private void GDIDraw(string data, Graphics graph, char dataDelim) |
474 | /// Split input data into discrete command lines. | ||
475 | /// </summary> | ||
476 | /// <returns></returns> | ||
477 | /// <param name='data'></param> | ||
478 | /// <param name='dataDelim'></param> | ||
479 | private string[] GetLines(string data, char dataDelim) | ||
480 | { | ||
481 | char[] lineDelimiter = { dataDelim }; | ||
482 | return data.Split(lineDelimiter); | ||
483 | } | ||
484 | |||
485 | private void GDIDraw(string data, Graphics graph, char dataDelim, out bool reuseable) | ||
486 | { | 422 | { |
487 | reuseable = true; | ||
488 | Point startPoint = new Point(0, 0); | 423 | Point startPoint = new Point(0, 0); |
489 | Point endPoint = new Point(0, 0); | 424 | Point endPoint = new Point(0, 0); |
490 | Pen drawPen = null; | 425 | Pen drawPen = null; |
@@ -499,9 +434,11 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender | |||
499 | myFont = new Font(fontName, fontSize); | 434 | myFont = new Font(fontName, fontSize); |
500 | myBrush = new SolidBrush(Color.Black); | 435 | myBrush = new SolidBrush(Color.Black); |
501 | 436 | ||
437 | char[] lineDelimiter = {dataDelim}; | ||
502 | char[] partsDelimiter = {','}; | 438 | char[] partsDelimiter = {','}; |
439 | string[] lines = data.Split(lineDelimiter); | ||
503 | 440 | ||
504 | foreach (string line in GetLines(data, dataDelim)) | 441 | foreach (string line in lines) |
505 | { | 442 | { |
506 | string nextLine = line.Trim(); | 443 | string nextLine = line.Trim(); |
507 | //replace with switch, or even better, do some proper parsing | 444 | //replace with switch, or even better, do some proper parsing |
@@ -532,10 +469,6 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender | |||
532 | } | 469 | } |
533 | else if (nextLine.StartsWith("Image")) | 470 | else if (nextLine.StartsWith("Image")) |
534 | { | 471 | { |
535 | // We cannot reuse any generated texture involving fetching an image via HTTP since that image | ||
536 | // can change. | ||
537 | reuseable = false; | ||
538 | |||
539 | float x = 0; | 472 | float x = 0; |
540 | float y = 0; | 473 | float y = 0; |
541 | GetParams(partsDelimiter, ref nextLine, 5, ref x, ref y); | 474 | GetParams(partsDelimiter, ref nextLine, 5, ref x, ref y); |
diff --git a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs index e167e31..07bb291 100644 --- a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs | |||
@@ -28,7 +28,6 @@ | |||
28 | using System; | 28 | using System; |
29 | using System.Collections; | 29 | using System.Collections; |
30 | using System.Collections.Generic; | 30 | using System.Collections.Generic; |
31 | using System.Text.RegularExpressions; | ||
32 | using Nini.Config; | 31 | using Nini.Config; |
33 | using OpenMetaverse; | 32 | using OpenMetaverse; |
34 | using OpenSim.Framework; | 33 | using OpenSim.Framework; |
@@ -173,42 +172,12 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
173 | /// <param name="hostID">UUID of the SceneObjectPart</param> | 172 | /// <param name="hostID">UUID of the SceneObjectPart</param> |
174 | /// <param name="channel">channel to listen on</param> | 173 | /// <param name="channel">channel to listen on</param> |
175 | /// <param name="name">name to filter on</param> | 174 | /// <param name="name">name to filter on</param> |
176 | /// <param name="id"> | 175 | /// <param name="id">key to filter on (user given, could be totally faked)</param> |
177 | /// key to filter on (user given, could be totally faked) | ||
178 | /// </param> | ||
179 | /// <param name="msg">msg to filter on</param> | ||
180 | /// <returns>number of the scripts handle</returns> | ||
181 | public int Listen(uint localID, UUID itemID, UUID hostID, int channel, | ||
182 | string name, UUID id, string msg) | ||
183 | { | ||
184 | return m_listenerManager.AddListener(localID, itemID, hostID, | ||
185 | channel, name, id, msg); | ||
186 | } | ||
187 | |||
188 | /// <summary> | ||
189 | /// Create a listen event callback with the specified filters. | ||
190 | /// The parameters localID,itemID are needed to uniquely identify | ||
191 | /// the script during 'peek' time. Parameter hostID is needed to | ||
192 | /// determine the position of the script. | ||
193 | /// </summary> | ||
194 | /// <param name="localID">localID of the script engine</param> | ||
195 | /// <param name="itemID">UUID of the script engine</param> | ||
196 | /// <param name="hostID">UUID of the SceneObjectPart</param> | ||
197 | /// <param name="channel">channel to listen on</param> | ||
198 | /// <param name="name">name to filter on</param> | ||
199 | /// <param name="id"> | ||
200 | /// key to filter on (user given, could be totally faked) | ||
201 | /// </param> | ||
202 | /// <param name="msg">msg to filter on</param> | 176 | /// <param name="msg">msg to filter on</param> |
203 | /// <param name="regexBitfield"> | ||
204 | /// Bitfield indicating which strings should be processed as regex. | ||
205 | /// </param> | ||
206 | /// <returns>number of the scripts handle</returns> | 177 | /// <returns>number of the scripts handle</returns> |
207 | public int Listen(uint localID, UUID itemID, UUID hostID, int channel, | 178 | public int Listen(uint localID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg) |
208 | string name, UUID id, string msg, int regexBitfield) | ||
209 | { | 179 | { |
210 | return m_listenerManager.AddListener(localID, itemID, hostID, | 180 | return m_listenerManager.AddListener(localID, itemID, hostID, channel, name, id, msg); |
211 | channel, name, id, msg, regexBitfield); | ||
212 | } | 181 | } |
213 | 182 | ||
214 | /// <summary> | 183 | /// <summary> |
@@ -357,7 +326,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
357 | if (channel == 0) | 326 | if (channel == 0) |
358 | { | 327 | { |
359 | // Channel 0 goes to viewer ONLY | 328 | // Channel 0 goes to viewer ONLY |
360 | m_scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Broadcast, 0, pos, name, id, target, false, false); | 329 | m_scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Broadcast, 0, pos, name, id, false, false, target); |
361 | return true; | 330 | return true; |
362 | } | 331 | } |
363 | 332 | ||
@@ -501,25 +470,15 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
501 | m_curlisteners = 0; | 470 | m_curlisteners = 0; |
502 | } | 471 | } |
503 | 472 | ||
504 | public int AddListener(uint localID, UUID itemID, UUID hostID, | 473 | public int AddListener(uint localID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg) |
505 | int channel, string name, UUID id, string msg) | ||
506 | { | ||
507 | return AddListener(localID, itemID, hostID, channel, name, id, | ||
508 | msg, 0); | ||
509 | } | ||
510 | |||
511 | public int AddListener(uint localID, UUID itemID, UUID hostID, | ||
512 | int channel, string name, UUID id, string msg, | ||
513 | int regexBitfield) | ||
514 | { | 474 | { |
515 | // do we already have a match on this particular filter event? | 475 | // do we already have a match on this particular filter event? |
516 | List<ListenerInfo> coll = GetListeners(itemID, channel, name, id, | 476 | List<ListenerInfo> coll = GetListeners(itemID, channel, name, id, msg); |
517 | msg); | ||
518 | 477 | ||
519 | if (coll.Count > 0) | 478 | if (coll.Count > 0) |
520 | { | 479 | { |
521 | // special case, called with same filter settings, return same | 480 | // special case, called with same filter settings, return same handle |
522 | // handle (2008-05-02, tested on 1.21.1 server, still holds) | 481 | // (2008-05-02, tested on 1.21.1 server, still holds) |
523 | return coll[0].GetHandle(); | 482 | return coll[0].GetHandle(); |
524 | } | 483 | } |
525 | 484 | ||
@@ -531,9 +490,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
531 | 490 | ||
532 | if (newHandle > 0) | 491 | if (newHandle > 0) |
533 | { | 492 | { |
534 | ListenerInfo li = new ListenerInfo(newHandle, localID, | 493 | ListenerInfo li = new ListenerInfo(newHandle, localID, itemID, hostID, channel, name, id, msg); |
535 | itemID, hostID, channel, name, id, msg, | ||
536 | regexBitfield); | ||
537 | 494 | ||
538 | List<ListenerInfo> listeners; | 495 | List<ListenerInfo> listeners; |
539 | if (!m_listeners.TryGetValue(channel,out listeners)) | 496 | if (!m_listeners.TryGetValue(channel,out listeners)) |
@@ -674,22 +631,6 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
674 | return -1; | 631 | return -1; |
675 | } | 632 | } |
676 | 633 | ||
677 | /// These are duplicated from ScriptBaseClass | ||
678 | /// http://opensimulator.org/mantis/view.php?id=6106#c21945 | ||
679 | #region Constants for the bitfield parameter of osListenRegex | ||
680 | |||
681 | /// <summary> | ||
682 | /// process name parameter as regex | ||
683 | /// </summary> | ||
684 | public const int OS_LISTEN_REGEX_NAME = 0x1; | ||
685 | |||
686 | /// <summary> | ||
687 | /// process message parameter as regex | ||
688 | /// </summary> | ||
689 | public const int OS_LISTEN_REGEX_MESSAGE = 0x2; | ||
690 | |||
691 | #endregion | ||
692 | |||
693 | // Theres probably a more clever and efficient way to | 634 | // Theres probably a more clever and efficient way to |
694 | // do this, maybe with regex. | 635 | // do this, maybe with regex. |
695 | // PM2008: Ha, one could even be smart and define a specialized Enumerator. | 636 | // PM2008: Ha, one could even be smart and define a specialized Enumerator. |
@@ -715,10 +656,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
715 | { | 656 | { |
716 | continue; | 657 | continue; |
717 | } | 658 | } |
718 | if (li.GetName().Length > 0 && ( | 659 | if (li.GetName().Length > 0 && !li.GetName().Equals(name)) |
719 | ((li.RegexBitfield & OS_LISTEN_REGEX_NAME) != OS_LISTEN_REGEX_NAME && !li.GetName().Equals(name)) || | ||
720 | ((li.RegexBitfield & OS_LISTEN_REGEX_NAME) == OS_LISTEN_REGEX_NAME && !Regex.IsMatch(name, li.GetName())) | ||
721 | )) | ||
722 | { | 660 | { |
723 | continue; | 661 | continue; |
724 | } | 662 | } |
@@ -726,10 +664,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
726 | { | 664 | { |
727 | continue; | 665 | continue; |
728 | } | 666 | } |
729 | if (li.GetMessage().Length > 0 && ( | 667 | if (li.GetMessage().Length > 0 && !li.GetMessage().Equals(msg)) |
730 | ((li.RegexBitfield & OS_LISTEN_REGEX_MESSAGE) != OS_LISTEN_REGEX_MESSAGE && !li.GetMessage().Equals(msg)) || | ||
731 | ((li.RegexBitfield & OS_LISTEN_REGEX_MESSAGE) == OS_LISTEN_REGEX_MESSAGE && !Regex.IsMatch(msg, li.GetMessage())) | ||
732 | )) | ||
733 | { | 668 | { |
734 | continue; | 669 | continue; |
735 | } | 670 | } |
@@ -762,13 +697,10 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
762 | { | 697 | { |
763 | int idx = 0; | 698 | int idx = 0; |
764 | Object[] item = new Object[6]; | 699 | Object[] item = new Object[6]; |
765 | int dataItemLength = 6; | ||
766 | 700 | ||
767 | while (idx < data.Length) | 701 | while (idx < data.Length) |
768 | { | 702 | { |
769 | dataItemLength = (idx + 7 == data.Length || (idx + 7 < data.Length && data[idx + 7] is bool)) ? 7 : 6; | 703 | Array.Copy(data, idx, item, 0, 6); |
770 | item = new Object[dataItemLength]; | ||
771 | Array.Copy(data, idx, item, 0, dataItemLength); | ||
772 | 704 | ||
773 | ListenerInfo info = | 705 | ListenerInfo info = |
774 | ListenerInfo.FromData(localID, itemID, hostID, item); | 706 | ListenerInfo.FromData(localID, itemID, hostID, item); |
@@ -780,12 +712,12 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
780 | m_listeners[(int)item[2]].Add(info); | 712 | m_listeners[(int)item[2]].Add(info); |
781 | } | 713 | } |
782 | 714 | ||
783 | idx+=dataItemLength; | 715 | idx+=6; |
784 | } | 716 | } |
785 | } | 717 | } |
786 | } | 718 | } |
787 | 719 | ||
788 | public class ListenerInfo : IWorldCommListenerInfo | 720 | public class ListenerInfo: IWorldCommListenerInfo |
789 | { | 721 | { |
790 | private bool m_active; // Listener is active or not | 722 | private bool m_active; // Listener is active or not |
791 | private int m_handle; // Assigned handle of this listener | 723 | private int m_handle; // Assigned handle of this listener |
@@ -799,29 +731,16 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
799 | 731 | ||
800 | public ListenerInfo(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name, UUID id, string message) | 732 | public ListenerInfo(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name, UUID id, string message) |
801 | { | 733 | { |
802 | Initialise(handle, localID, ItemID, hostID, channel, name, id, | 734 | Initialise(handle, localID, ItemID, hostID, channel, name, id, message); |
803 | message, 0); | ||
804 | } | ||
805 | |||
806 | public ListenerInfo(int handle, uint localID, UUID ItemID, | ||
807 | UUID hostID, int channel, string name, UUID id, | ||
808 | string message, int regexBitfield) | ||
809 | { | ||
810 | Initialise(handle, localID, ItemID, hostID, channel, name, id, | ||
811 | message, regexBitfield); | ||
812 | } | 735 | } |
813 | 736 | ||
814 | public ListenerInfo(ListenerInfo li, string name, UUID id, string message) | 737 | public ListenerInfo(ListenerInfo li, string name, UUID id, string message) |
815 | { | 738 | { |
816 | Initialise(li.m_handle, li.m_localID, li.m_itemID, li.m_hostID, li.m_channel, name, id, message, 0); | 739 | Initialise(li.m_handle, li.m_localID, li.m_itemID, li.m_hostID, li.m_channel, name, id, message); |
817 | } | ||
818 | |||
819 | public ListenerInfo(ListenerInfo li, string name, UUID id, string message, int regexBitfield) | ||
820 | { | ||
821 | Initialise(li.m_handle, li.m_localID, li.m_itemID, li.m_hostID, li.m_channel, name, id, message, regexBitfield); | ||
822 | } | 740 | } |
823 | 741 | ||
824 | private void Initialise(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name, UUID id, string message, int regexBitfield) | 742 | private void Initialise(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name, |
743 | UUID id, string message) | ||
825 | { | 744 | { |
826 | m_active = true; | 745 | m_active = true; |
827 | m_handle = handle; | 746 | m_handle = handle; |
@@ -832,12 +751,11 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
832 | m_name = name; | 751 | m_name = name; |
833 | m_id = id; | 752 | m_id = id; |
834 | m_message = message; | 753 | m_message = message; |
835 | RegexBitfield = regexBitfield; | ||
836 | } | 754 | } |
837 | 755 | ||
838 | public Object[] GetSerializationData() | 756 | public Object[] GetSerializationData() |
839 | { | 757 | { |
840 | Object[] data = new Object[7]; | 758 | Object[] data = new Object[6]; |
841 | 759 | ||
842 | data[0] = m_active; | 760 | data[0] = m_active; |
843 | data[1] = m_handle; | 761 | data[1] = m_handle; |
@@ -845,19 +763,16 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
845 | data[3] = m_name; | 763 | data[3] = m_name; |
846 | data[4] = m_id; | 764 | data[4] = m_id; |
847 | data[5] = m_message; | 765 | data[5] = m_message; |
848 | data[6] = RegexBitfield; | ||
849 | 766 | ||
850 | return data; | 767 | return data; |
851 | } | 768 | } |
852 | 769 | ||
853 | public static ListenerInfo FromData(uint localID, UUID ItemID, UUID hostID, Object[] data) | 770 | public static ListenerInfo FromData(uint localID, UUID ItemID, UUID hostID, Object[] data) |
854 | { | 771 | { |
855 | ListenerInfo linfo = new ListenerInfo((int)data[1], localID, ItemID, hostID, (int)data[2], (string)data[3], (UUID)data[4], (string)data[5]); | 772 | ListenerInfo linfo = new ListenerInfo((int)data[1], localID, |
856 | linfo.m_active = (bool)data[0]; | 773 | ItemID, hostID, (int)data[2], (string)data[3], |
857 | if (data.Length >= 7) | 774 | (UUID)data[4], (string)data[5]); |
858 | { | 775 | linfo.m_active=(bool)data[0]; |
859 | linfo.RegexBitfield = (int)data[6]; | ||
860 | } | ||
861 | 776 | ||
862 | return linfo; | 777 | return linfo; |
863 | } | 778 | } |
@@ -916,7 +831,5 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
916 | { | 831 | { |
917 | return m_id; | 832 | return m_id; |
918 | } | 833 | } |
919 | |||
920 | public int RegexBitfield { get; private set; } | ||
921 | } | 834 | } |
922 | } | 835 | } |
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs index 1e1c7d0..008465f 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs | |||
@@ -56,8 +56,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset | |||
56 | 56 | ||
57 | private bool m_Enabled = false; | 57 | private bool m_Enabled = false; |
58 | 58 | ||
59 | private AssetPermissions m_AssetPerms; | ||
60 | |||
61 | public Type ReplaceableInterface | 59 | public Type ReplaceableInterface |
62 | { | 60 | { |
63 | get { return null; } | 61 | get { return null; } |
@@ -130,9 +128,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset | |||
130 | if (m_LocalAssetServiceURI != string.Empty) | 128 | if (m_LocalAssetServiceURI != string.Empty) |
131 | m_LocalAssetServiceURI = m_LocalAssetServiceURI.Trim('/'); | 129 | m_LocalAssetServiceURI = m_LocalAssetServiceURI.Trim('/'); |
132 | 130 | ||
133 | IConfig hgConfig = source.Configs["HGAssetService"]; | ||
134 | m_AssetPerms = new AssetPermissions(hgConfig); // it's ok if arg is null | ||
135 | |||
136 | m_Enabled = true; | 131 | m_Enabled = true; |
137 | m_log.Info("[HG ASSET CONNECTOR]: HG asset broker enabled"); | 132 | m_log.Info("[HG ASSET CONNECTOR]: HG asset broker enabled"); |
138 | } | 133 | } |
@@ -211,11 +206,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset | |||
211 | asset = m_HGService.Get(id); | 206 | asset = m_HGService.Get(id); |
212 | if (asset != null) | 207 | if (asset != null) |
213 | { | 208 | { |
214 | // Now store it locally, if allowed | 209 | // Now store it locally |
215 | if (m_AssetPerms.AllowedImport(asset.Type)) | 210 | // For now, let me just do it for textures and scripts |
211 | if (((AssetType)asset.Type == AssetType.Texture) || | ||
212 | ((AssetType)asset.Type == AssetType.LSLBytecode) || | ||
213 | ((AssetType)asset.Type == AssetType.LSLText)) | ||
214 | { | ||
216 | m_GridService.Store(asset); | 215 | m_GridService.Store(asset); |
217 | else | 216 | } |
218 | return null; | ||
219 | } | 217 | } |
220 | } | 218 | } |
221 | else | 219 | else |
@@ -330,12 +328,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset | |||
330 | 328 | ||
331 | string id = string.Empty; | 329 | string id = string.Empty; |
332 | if (IsHG(asset.ID)) | 330 | if (IsHG(asset.ID)) |
333 | { | 331 | id = m_HGService.Store(asset); |
334 | if (m_AssetPerms.AllowedExport(asset.Type)) | ||
335 | id = m_HGService.Store(asset); | ||
336 | else | ||
337 | return String.Empty; | ||
338 | } | ||
339 | else | 332 | else |
340 | id = m_GridService.Store(asset); | 333 | id = m_GridService.Store(asset); |
341 | 334 | ||
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs index 449c1f1..c78915f 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs | |||
@@ -204,11 +204,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset | |||
204 | public byte[] GetData(string id) | 204 | public byte[] GetData(string id) |
205 | { | 205 | { |
206 | // m_log.DebugFormat("[LOCAL ASSET SERVICES CONNECTOR]: Requesting data for asset {0}", id); | 206 | // m_log.DebugFormat("[LOCAL ASSET SERVICES CONNECTOR]: Requesting data for asset {0}", id); |
207 | 207 | ||
208 | AssetBase asset = null; | 208 | AssetBase asset = m_Cache.Get(id); |
209 | |||
210 | if (m_Cache != null) | ||
211 | asset = m_Cache.Get(id); | ||
212 | 209 | ||
213 | if (asset != null) | 210 | if (asset != null) |
214 | return asset.Data; | 211 | return asset.Data; |
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs deleted file mode 100644 index 1982473..0000000 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs +++ /dev/null | |||
@@ -1,136 +0,0 @@ | |||
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 | using System.Collections.Generic; | ||
30 | using System.IO; | ||
31 | using System.Reflection; | ||
32 | using System.Threading; | ||
33 | using log4net.Config; | ||
34 | using Nini.Config; | ||
35 | using NUnit.Framework; | ||
36 | using OpenMetaverse; | ||
37 | using OpenSim.Framework; | ||
38 | using OpenSim.Region.Framework.Scenes; | ||
39 | using OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset; | ||
40 | using OpenSim.Tests.Common; | ||
41 | |||
42 | namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset.Tests | ||
43 | { | ||
44 | [TestFixture] | ||
45 | public class AssetConnectorsTests : OpenSimTestCase | ||
46 | { | ||
47 | [Test] | ||
48 | public void TestAddAsset() | ||
49 | { | ||
50 | TestHelpers.InMethod(); | ||
51 | // TestHelpers.EnableLogging(); | ||
52 | |||
53 | IConfigSource config = new IniConfigSource(); | ||
54 | config.AddConfig("Modules"); | ||
55 | config.Configs["Modules"].Set("AssetServices", "LocalAssetServicesConnector"); | ||
56 | config.AddConfig("AssetService"); | ||
57 | config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Services.AssetService.dll:AssetService"); | ||
58 | config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll"); | ||
59 | |||
60 | LocalAssetServicesConnector lasc = new LocalAssetServicesConnector(); | ||
61 | lasc.Initialise(config); | ||
62 | |||
63 | AssetBase a1 = AssetHelpers.CreateNotecardAsset(); | ||
64 | lasc.Store(a1); | ||
65 | |||
66 | AssetBase retreivedA1 = lasc.Get(a1.ID); | ||
67 | Assert.That(retreivedA1.ID, Is.EqualTo(a1.ID)); | ||
68 | Assert.That(retreivedA1.Metadata.ID, Is.EqualTo(a1.Metadata.ID)); | ||
69 | Assert.That(retreivedA1.Data.Length, Is.EqualTo(a1.Data.Length)); | ||
70 | |||
71 | AssetMetadata retrievedA1Metadata = lasc.GetMetadata(a1.ID); | ||
72 | Assert.That(retrievedA1Metadata.ID, Is.EqualTo(a1.ID)); | ||
73 | |||
74 | byte[] retrievedA1Data = lasc.GetData(a1.ID); | ||
75 | Assert.That(retrievedA1Data.Length, Is.EqualTo(a1.Data.Length)); | ||
76 | |||
77 | // TODO: Add cache and check that this does receive a copy of the asset | ||
78 | } | ||
79 | |||
80 | [Test] | ||
81 | public void TestAddTemporaryAsset() | ||
82 | { | ||
83 | TestHelpers.InMethod(); | ||
84 | // TestHelpers.EnableLogging(); | ||
85 | |||
86 | IConfigSource config = new IniConfigSource(); | ||
87 | config.AddConfig("Modules"); | ||
88 | config.Configs["Modules"].Set("AssetServices", "LocalAssetServicesConnector"); | ||
89 | config.AddConfig("AssetService"); | ||
90 | config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Services.AssetService.dll:AssetService"); | ||
91 | config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll"); | ||
92 | |||
93 | LocalAssetServicesConnector lasc = new LocalAssetServicesConnector(); | ||
94 | lasc.Initialise(config); | ||
95 | |||
96 | AssetBase a1 = AssetHelpers.CreateNotecardAsset(); | ||
97 | a1.Temporary = true; | ||
98 | |||
99 | lasc.Store(a1); | ||
100 | |||
101 | Assert.That(lasc.Get(a1.ID), Is.Null); | ||
102 | Assert.That(lasc.GetData(a1.ID), Is.Null); | ||
103 | Assert.That(lasc.GetMetadata(a1.ID), Is.Null); | ||
104 | |||
105 | // TODO: Add cache and check that this does receive a copy of the asset | ||
106 | } | ||
107 | |||
108 | [Test] | ||
109 | public void TestAddLocalAsset() | ||
110 | { | ||
111 | TestHelpers.InMethod(); | ||
112 | // TestHelpers.EnableLogging(); | ||
113 | |||
114 | IConfigSource config = new IniConfigSource(); | ||
115 | config.AddConfig("Modules"); | ||
116 | config.Configs["Modules"].Set("AssetServices", "LocalAssetServicesConnector"); | ||
117 | config.AddConfig("AssetService"); | ||
118 | config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Services.AssetService.dll:AssetService"); | ||
119 | config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll"); | ||
120 | |||
121 | LocalAssetServicesConnector lasc = new LocalAssetServicesConnector(); | ||
122 | lasc.Initialise(config); | ||
123 | |||
124 | AssetBase a1 = AssetHelpers.CreateNotecardAsset(); | ||
125 | a1.Local = true; | ||
126 | |||
127 | lasc.Store(a1); | ||
128 | |||
129 | Assert.That(lasc.Get(a1.ID), Is.Null); | ||
130 | Assert.That(lasc.GetData(a1.ID), Is.Null); | ||
131 | Assert.That(lasc.GetMetadata(a1.ID), Is.Null); | ||
132 | |||
133 | // TODO: Add cache and check that this does receive a copy of the asset | ||
134 | } | ||
135 | } | ||
136 | } \ No newline at end of file | ||
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs index 4338133..b286d17 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs | |||
@@ -43,15 +43,11 @@ using OpenSim.Tests.Common; | |||
43 | namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests | 43 | namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests |
44 | { | 44 | { |
45 | [TestFixture] | 45 | [TestFixture] |
46 | public class GridConnectorsTests : OpenSimTestCase | 46 | public class GridConnectorsTests |
47 | { | 47 | { |
48 | LocalGridServicesConnector m_LocalConnector; | 48 | LocalGridServicesConnector m_LocalConnector; |
49 | 49 | private void SetUp() | |
50 | [SetUp] | ||
51 | public override void SetUp() | ||
52 | { | 50 | { |
53 | base.SetUp(); | ||
54 | |||
55 | IConfigSource config = new IniConfigSource(); | 51 | IConfigSource config = new IniConfigSource(); |
56 | config.AddConfig("Modules"); | 52 | config.AddConfig("Modules"); |
57 | config.AddConfig("GridService"); | 53 | config.AddConfig("GridService"); |
@@ -75,6 +71,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests | |||
75 | TestHelpers.InMethod(); | 71 | TestHelpers.InMethod(); |
76 | // log4net.Config.XmlConfigurator.Configure(); | 72 | // log4net.Config.XmlConfigurator.Configure(); |
77 | 73 | ||
74 | SetUp(); | ||
75 | |||
78 | // Create 4 regions | 76 | // Create 4 regions |
79 | GridRegion r1 = new GridRegion(); | 77 | GridRegion r1 = new GridRegion(); |
80 | r1.RegionName = "Test Region 1"; | 78 | r1.RegionName = "Test Region 1"; |
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs index 221f815..b0edce7 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs | |||
@@ -65,13 +65,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser | |||
65 | 65 | ||
66 | public void OnMakeRootAgent(ScenePresence sp) | 66 | public void OnMakeRootAgent(ScenePresence sp) |
67 | { | 67 | { |
68 | // m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected root presence {0} in {1}", sp.UUID, sp.Scene.RegionInfo.RegionName); | ||
69 | |||
68 | if (sp.PresenceType != PresenceType.Npc) | 70 | if (sp.PresenceType != PresenceType.Npc) |
69 | { | ||
70 | string userid = sp.Scene.UserManagementModule.GetUserUUI(sp.UUID); | ||
71 | //m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected root presence {0} in {1}", userid, sp.Scene.RegionInfo.RegionName); | ||
72 | m_GridUserService.SetLastPosition( | 71 | m_GridUserService.SetLastPosition( |
73 | userid, UUID.Zero, sp.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat); | 72 | sp.UUID.ToString(), UUID.Zero, sp.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat); |
74 | } | ||
75 | } | 73 | } |
76 | 74 | ||
77 | public void OnNewClient(IClientAPI client) | 75 | public void OnNewClient(IClientAPI client) |
@@ -84,16 +82,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser | |||
84 | if (client.SceneAgent.IsChildAgent) | 82 | if (client.SceneAgent.IsChildAgent) |
85 | return; | 83 | return; |
86 | 84 | ||
87 | string userId = client.AgentId.ToString(); | 85 | // m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected client logout {0} in {1}", client.AgentId, client.Scene.RegionInfo.RegionName); |
88 | if (client.Scene is Scene) | ||
89 | { | ||
90 | Scene s = (Scene)client.Scene; | ||
91 | userId = s.UserManagementModule.GetUserUUI(client.AgentId); | ||
92 | } | ||
93 | //m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected client logout {0} in {1}", userId, client.Scene.RegionInfo.RegionName); | ||
94 | |||
95 | m_GridUserService.LoggedOut( | 86 | m_GridUserService.LoggedOut( |
96 | userId, client.SessionId, client.Scene.RegionInfo.RegionID, | 87 | client.AgentId.ToString(), client.SessionId, client.Scene.RegionInfo.RegionID, |
97 | client.SceneAgent.AbsolutePosition, client.SceneAgent.Lookat); | 88 | client.SceneAgent.AbsolutePosition, client.SceneAgent.Lookat); |
98 | } | 89 | } |
99 | } | 90 | } |
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs index 04acf67..badb552 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs | |||
@@ -44,9 +44,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser | |||
44 | { | 44 | { |
45 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 45 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
46 | 46 | ||
47 | private const int KEEPTIME = 30; // 30 secs | ||
48 | private ExpiringCache<string, GridUserInfo> m_Infos = new ExpiringCache<string, GridUserInfo>(); | ||
49 | |||
50 | #region ISharedRegionModule | 47 | #region ISharedRegionModule |
51 | 48 | ||
52 | private bool m_Enabled = false; | 49 | private bool m_Enabled = false; |
@@ -131,60 +128,23 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser | |||
131 | 128 | ||
132 | public bool LoggedOut(string userID, UUID sessionID, UUID region, Vector3 position, Vector3 lookat) | 129 | public bool LoggedOut(string userID, UUID sessionID, UUID region, Vector3 position, Vector3 lookat) |
133 | { | 130 | { |
134 | if (m_Infos.Contains(userID)) | ||
135 | m_Infos.Remove(userID); | ||
136 | |||
137 | return m_RemoteConnector.LoggedOut(userID, sessionID, region, position, lookat); | 131 | return m_RemoteConnector.LoggedOut(userID, sessionID, region, position, lookat); |
138 | } | 132 | } |
139 | 133 | ||
140 | 134 | ||
141 | public bool SetHome(string userID, UUID regionID, Vector3 position, Vector3 lookAt) | 135 | public bool SetHome(string userID, UUID regionID, Vector3 position, Vector3 lookAt) |
142 | { | 136 | { |
143 | if (m_RemoteConnector.SetHome(userID, regionID, position, lookAt)) | 137 | return m_RemoteConnector.SetHome(userID, regionID, position, lookAt); |
144 | { | ||
145 | // Update the cache too | ||
146 | GridUserInfo info = null; | ||
147 | if (m_Infos.TryGetValue(userID, out info)) | ||
148 | { | ||
149 | info.HomeRegionID = regionID; | ||
150 | info.HomePosition = position; | ||
151 | info.HomeLookAt = lookAt; | ||
152 | } | ||
153 | return true; | ||
154 | } | ||
155 | |||
156 | return false; | ||
157 | } | 138 | } |
158 | 139 | ||
159 | public bool SetLastPosition(string userID, UUID sessionID, UUID regionID, Vector3 position, Vector3 lookAt) | 140 | public bool SetLastPosition(string userID, UUID sessionID, UUID regionID, Vector3 position, Vector3 lookAt) |
160 | { | 141 | { |
161 | if (m_RemoteConnector.SetLastPosition(userID, sessionID, regionID, position, lookAt)) | 142 | return m_RemoteConnector.SetLastPosition(userID, sessionID, regionID, position, lookAt); |
162 | { | ||
163 | // Update the cache too | ||
164 | GridUserInfo info = null; | ||
165 | if (m_Infos.TryGetValue(userID, out info)) | ||
166 | { | ||
167 | info.LastRegionID = regionID; | ||
168 | info.LastPosition = position; | ||
169 | info.LastLookAt = lookAt; | ||
170 | } | ||
171 | return true; | ||
172 | } | ||
173 | |||
174 | return false; | ||
175 | } | 143 | } |
176 | 144 | ||
177 | public GridUserInfo GetGridUserInfo(string userID) | 145 | public GridUserInfo GetGridUserInfo(string userID) |
178 | { | 146 | { |
179 | GridUserInfo info = null; | 147 | return m_RemoteConnector.GetGridUserInfo(userID); |
180 | if (m_Infos.TryGetValue(userID, out info)) | ||
181 | return info; | ||
182 | |||
183 | info = m_RemoteConnector.GetGridUserInfo(userID); | ||
184 | |||
185 | m_Infos.AddOrUpdate(userID, info, KEEPTIME); | ||
186 | |||
187 | return info; | ||
188 | } | 148 | } |
189 | 149 | ||
190 | public GridUserInfo[] GetGridUserInfo(string[] userID) | 150 | public GridUserInfo[] GetGridUserInfo(string[] userID) |
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs index 8ed1833..6eb99ea 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs | |||
@@ -313,11 +313,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation | |||
313 | 313 | ||
314 | if (m_scenes.ContainsKey(destination.RegionID)) | 314 | if (m_scenes.ContainsKey(destination.RegionID)) |
315 | { | 315 | { |
316 | // m_log.DebugFormat( | 316 | Util.FireAndForget(delegate { m_scenes[destination.RegionID].IncomingCloseAgent(id); }); |
317 | // "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate", | ||
318 | // s.RegionInfo.RegionName, destination.RegionHandle); | ||
319 | |||
320 | Util.FireAndForget(delegate { m_scenes[destination.RegionID].IncomingCloseAgent(id, false); }); | ||
321 | return true; | 317 | return true; |
322 | } | 318 | } |
323 | //m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent"); | 319 | //m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent"); |
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index ade5e76..619550c 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs | |||
@@ -43,7 +43,6 @@ using OpenSim.Region.Framework.Interfaces; | |||
43 | using OpenSim.Region.Framework.Scenes; | 43 | using OpenSim.Region.Framework.Scenes; |
44 | using OpenSim.Region.Framework.Scenes.Serialization; | 44 | using OpenSim.Region.Framework.Scenes.Serialization; |
45 | using OpenSim.Services.Interfaces; | 45 | using OpenSim.Services.Interfaces; |
46 | using System.Threading; | ||
47 | 46 | ||
48 | namespace OpenSim.Region.CoreModules.World.Archiver | 47 | namespace OpenSim.Region.CoreModules.World.Archiver |
49 | { | 48 | { |
@@ -53,30 +52,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
53 | public class ArchiveReadRequest | 52 | public class ArchiveReadRequest |
54 | { | 53 | { |
55 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 54 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
56 | |||
57 | /// <summary> | ||
58 | /// Contains data used while dearchiving a single scene. | ||
59 | /// </summary> | ||
60 | private class DearchiveContext | ||
61 | { | ||
62 | public Scene Scene { get; set; } | ||
63 | |||
64 | public List<string> SerialisedSceneObjects { get; set; } | ||
65 | |||
66 | public List<string> SerialisedParcels { get; set; } | ||
67 | |||
68 | public List<SceneObjectGroup> SceneObjects { get; set; } | ||
69 | |||
70 | public DearchiveContext(Scene scene) | ||
71 | { | ||
72 | Scene = scene; | ||
73 | SerialisedSceneObjects = new List<string>(); | ||
74 | SerialisedParcels = new List<string>(); | ||
75 | SceneObjects = new List<SceneObjectGroup>(); | ||
76 | } | ||
77 | } | ||
78 | 55 | ||
79 | |||
80 | /// <summary> | 56 | /// <summary> |
81 | /// The maximum major version of OAR that we can read. Minor versions shouldn't need a max number since version | 57 | /// The maximum major version of OAR that we can read. Minor versions shouldn't need a max number since version |
82 | /// bumps here should be compatible. | 58 | /// bumps here should be compatible. |
@@ -86,10 +62,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
86 | /// <summary> | 62 | /// <summary> |
87 | /// Has the control file been loaded for this archive? | 63 | /// Has the control file been loaded for this archive? |
88 | /// </summary> | 64 | /// </summary> |
89 | public bool ControlFileLoaded { get; private set; } | 65 | public bool ControlFileLoaded { get; private set; } |
90 | 66 | ||
91 | protected string m_loadPath; | 67 | protected Scene m_scene; |
92 | protected Scene m_rootScene; | ||
93 | protected Stream m_loadStream; | 68 | protected Stream m_loadStream; |
94 | protected Guid m_requestId; | 69 | protected Guid m_requestId; |
95 | protected string m_errorMessage; | 70 | protected string m_errorMessage; |
@@ -116,27 +91,16 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
116 | { | 91 | { |
117 | if (m_UserMan == null) | 92 | if (m_UserMan == null) |
118 | { | 93 | { |
119 | m_UserMan = m_rootScene.RequestModuleInterface<IUserManagement>(); | 94 | m_UserMan = m_scene.RequestModuleInterface<IUserManagement>(); |
120 | } | 95 | } |
121 | return m_UserMan; | 96 | return m_UserMan; |
122 | } | 97 | } |
123 | } | 98 | } |
124 | 99 | ||
125 | /// <summary> | ||
126 | /// Used to cache lookups for valid groups. | ||
127 | /// </summary> | ||
128 | private IDictionary<UUID, bool> m_validGroupUuids = new Dictionary<UUID, bool>(); | ||
129 | |||
130 | private IGroupsModule m_groupsModule; | ||
131 | |||
132 | private IAssetService m_assetService = null; | ||
133 | |||
134 | |||
135 | public ArchiveReadRequest(Scene scene, string loadPath, bool merge, bool skipAssets, Guid requestId) | 100 | public ArchiveReadRequest(Scene scene, string loadPath, bool merge, bool skipAssets, Guid requestId) |
136 | { | 101 | { |
137 | m_rootScene = scene; | 102 | m_scene = scene; |
138 | 103 | ||
139 | m_loadPath = loadPath; | ||
140 | try | 104 | try |
141 | { | 105 | { |
142 | m_loadStream = new GZipStream(ArchiveHelpers.GetStream(loadPath), CompressionMode.Decompress); | 106 | m_loadStream = new GZipStream(ArchiveHelpers.GetStream(loadPath), CompressionMode.Decompress); |
@@ -156,15 +120,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
156 | 120 | ||
157 | // Zero can never be a valid user id | 121 | // Zero can never be a valid user id |
158 | m_validUserUuids[UUID.Zero] = false; | 122 | m_validUserUuids[UUID.Zero] = false; |
159 | |||
160 | m_groupsModule = m_rootScene.RequestModuleInterface<IGroupsModule>(); | ||
161 | m_assetService = m_rootScene.AssetService; | ||
162 | } | 123 | } |
163 | 124 | ||
164 | public ArchiveReadRequest(Scene scene, Stream loadStream, bool merge, bool skipAssets, Guid requestId) | 125 | public ArchiveReadRequest(Scene scene, Stream loadStream, bool merge, bool skipAssets, Guid requestId) |
165 | { | 126 | { |
166 | m_rootScene = scene; | 127 | m_scene = scene; |
167 | m_loadPath = null; | ||
168 | m_loadStream = loadStream; | 128 | m_loadStream = loadStream; |
169 | m_merge = merge; | 129 | m_merge = merge; |
170 | m_skipAssets = skipAssets; | 130 | m_skipAssets = skipAssets; |
@@ -172,9 +132,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
172 | 132 | ||
173 | // Zero can never be a valid user id | 133 | // Zero can never be a valid user id |
174 | m_validUserUuids[UUID.Zero] = false; | 134 | m_validUserUuids[UUID.Zero] = false; |
175 | |||
176 | m_groupsModule = m_rootScene.RequestModuleInterface<IGroupsModule>(); | ||
177 | m_assetService = m_rootScene.AssetService; | ||
178 | } | 135 | } |
179 | 136 | ||
180 | /// <summary> | 137 | /// <summary> |
@@ -182,25 +139,25 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
182 | /// </summary> | 139 | /// </summary> |
183 | public void DearchiveRegion() | 140 | public void DearchiveRegion() |
184 | { | 141 | { |
142 | // The same code can handle dearchiving 0.1 and 0.2 OpenSim Archive versions | ||
143 | DearchiveRegion0DotStar(); | ||
144 | } | ||
145 | |||
146 | private void DearchiveRegion0DotStar() | ||
147 | { | ||
185 | int successfulAssetRestores = 0; | 148 | int successfulAssetRestores = 0; |
186 | int failedAssetRestores = 0; | 149 | int failedAssetRestores = 0; |
150 | List<string> serialisedSceneObjects = new List<string>(); | ||
151 | List<string> serialisedParcels = new List<string>(); | ||
152 | string filePath = "NONE"; | ||
187 | 153 | ||
188 | DearchiveScenesInfo dearchivedScenes; | 154 | TarArchiveReader archive = new TarArchiveReader(m_loadStream); |
189 | |||
190 | // We dearchive all the scenes at once, because the files in the TAR archive might be mixed. | ||
191 | // Therefore, we have to keep track of the dearchive context of all the scenes. | ||
192 | Dictionary<UUID, DearchiveContext> sceneContexts = new Dictionary<UUID, DearchiveContext>(); | ||
193 | |||
194 | string fullPath = "NONE"; | ||
195 | TarArchiveReader archive = null; | ||
196 | byte[] data; | 155 | byte[] data; |
197 | TarArchiveReader.TarEntryType entryType; | 156 | TarArchiveReader.TarEntryType entryType; |
198 | 157 | ||
199 | try | 158 | try |
200 | { | 159 | { |
201 | FindAndLoadControlFile(out archive, out dearchivedScenes); | 160 | while ((data = archive.ReadEntry(out filePath, out entryType)) != null) |
202 | |||
203 | while ((data = archive.ReadEntry(out fullPath, out entryType)) != null) | ||
204 | { | 161 | { |
205 | //m_log.DebugFormat( | 162 | //m_log.DebugFormat( |
206 | // "[ARCHIVER]: Successfully read {0} ({1} bytes)", filePath, data.Length); | 163 | // "[ARCHIVER]: Successfully read {0} ({1} bytes)", filePath, data.Length); |
@@ -208,30 +165,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
208 | if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType) | 165 | if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType) |
209 | continue; | 166 | continue; |
210 | 167 | ||
211 | |||
212 | // Find the scene that this file belongs to | ||
213 | |||
214 | Scene scene; | ||
215 | string filePath; | ||
216 | if (!dearchivedScenes.GetRegionFromPath(fullPath, out scene, out filePath)) | ||
217 | continue; // this file belongs to a region that we're not loading | ||
218 | |||
219 | DearchiveContext sceneContext = null; | ||
220 | if (scene != null) | ||
221 | { | ||
222 | if (!sceneContexts.TryGetValue(scene.RegionInfo.RegionID, out sceneContext)) | ||
223 | { | ||
224 | sceneContext = new DearchiveContext(scene); | ||
225 | sceneContexts.Add(scene.RegionInfo.RegionID, sceneContext); | ||
226 | } | ||
227 | } | ||
228 | |||
229 | |||
230 | // Process the file | ||
231 | |||
232 | if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH)) | 168 | if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH)) |
233 | { | 169 | { |
234 | sceneContext.SerialisedSceneObjects.Add(Encoding.UTF8.GetString(data)); | 170 | serialisedSceneObjects.Add(Encoding.UTF8.GetString(data)); |
235 | } | 171 | } |
236 | else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH) && !m_skipAssets) | 172 | else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH) && !m_skipAssets) |
237 | { | 173 | { |
@@ -245,19 +181,19 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
245 | } | 181 | } |
246 | else if (!m_merge && filePath.StartsWith(ArchiveConstants.TERRAINS_PATH)) | 182 | else if (!m_merge && filePath.StartsWith(ArchiveConstants.TERRAINS_PATH)) |
247 | { | 183 | { |
248 | LoadTerrain(scene, filePath, data); | 184 | LoadTerrain(filePath, data); |
249 | } | 185 | } |
250 | else if (!m_merge && filePath.StartsWith(ArchiveConstants.SETTINGS_PATH)) | 186 | else if (!m_merge && filePath.StartsWith(ArchiveConstants.SETTINGS_PATH)) |
251 | { | 187 | { |
252 | LoadRegionSettings(scene, filePath, data, dearchivedScenes); | 188 | LoadRegionSettings(filePath, data); |
253 | } | 189 | } |
254 | else if (!m_merge && filePath.StartsWith(ArchiveConstants.LANDDATA_PATH)) | 190 | else if (!m_merge && filePath.StartsWith(ArchiveConstants.LANDDATA_PATH)) |
255 | { | 191 | { |
256 | sceneContext.SerialisedParcels.Add(Encoding.UTF8.GetString(data)); | 192 | serialisedParcels.Add(Encoding.UTF8.GetString(data)); |
257 | } | 193 | } |
258 | else if (filePath == ArchiveConstants.CONTROL_FILE_PATH) | 194 | else if (filePath == ArchiveConstants.CONTROL_FILE_PATH) |
259 | { | 195 | { |
260 | // Ignore, because we already read the control file | 196 | LoadControlFile(filePath, data); |
261 | } | 197 | } |
262 | } | 198 | } |
263 | 199 | ||
@@ -265,16 +201,15 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
265 | } | 201 | } |
266 | catch (Exception e) | 202 | catch (Exception e) |
267 | { | 203 | { |
268 | m_log.Error( | 204 | m_log.ErrorFormat( |
269 | String.Format("[ARCHIVER]: Aborting load with error in archive file {0} ", fullPath), e); | 205 | "[ARCHIVER]: Aborting load with error in archive file {0}. {1}", filePath, e); |
270 | m_errorMessage += e.ToString(); | 206 | m_errorMessage += e.ToString(); |
271 | m_rootScene.EventManager.TriggerOarFileLoaded(m_requestId, new List<UUID>(), m_errorMessage); | 207 | m_scene.EventManager.TriggerOarFileLoaded(m_requestId, m_errorMessage); |
272 | return; | 208 | return; |
273 | } | 209 | } |
274 | finally | 210 | finally |
275 | { | 211 | { |
276 | if (archive != null) | 212 | archive.Close(); |
277 | archive.Close(); | ||
278 | } | 213 | } |
279 | 214 | ||
280 | if (!m_skipAssets) | 215 | if (!m_skipAssets) |
@@ -288,143 +223,32 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
288 | } | 223 | } |
289 | } | 224 | } |
290 | 225 | ||
291 | foreach (DearchiveContext sceneContext in sceneContexts.Values) | 226 | if (!m_merge) |
292 | { | 227 | { |
293 | m_log.InfoFormat("[ARCHIVER]: Loading region {0}", sceneContext.Scene.RegionInfo.RegionName); | 228 | m_log.Info("[ARCHIVER]: Clearing all existing scene objects"); |
294 | 229 | m_scene.DeleteAllSceneObjects(); | |
295 | if (!m_merge) | ||
296 | { | ||
297 | m_log.Info("[ARCHIVER]: Clearing all existing scene objects"); | ||
298 | sceneContext.Scene.DeleteAllSceneObjects(); | ||
299 | } | ||
300 | |||
301 | try | ||
302 | { | ||
303 | LoadParcels(sceneContext.Scene, sceneContext.SerialisedParcels); | ||
304 | LoadObjects(sceneContext.Scene, sceneContext.SerialisedSceneObjects, sceneContext.SceneObjects); | ||
305 | |||
306 | // Inform any interested parties that the region has changed. We waited until now so that all | ||
307 | // of the region's objects will be loaded when we send this notification. | ||
308 | IEstateModule estateModule = sceneContext.Scene.RequestModuleInterface<IEstateModule>(); | ||
309 | if (estateModule != null) | ||
310 | estateModule.TriggerRegionInfoChange(); | ||
311 | } | ||
312 | catch (Exception e) | ||
313 | { | ||
314 | m_log.Error("[ARCHIVER]: Error loading parcels or objects ", e); | ||
315 | m_errorMessage += e.ToString(); | ||
316 | m_rootScene.EventManager.TriggerOarFileLoaded(m_requestId, new List<UUID>(), m_errorMessage); | ||
317 | return; | ||
318 | } | ||
319 | } | 230 | } |
320 | 231 | ||
321 | // Start the scripts. We delayed this because we want the OAR to finish loading ASAP, so | 232 | LoadParcels(serialisedParcels); |
322 | // that users can enter the scene. If we allow the scripts to start in the loop above | 233 | LoadObjects(serialisedSceneObjects); |
323 | // then they significantly increase the time until the OAR finishes loading. | ||
324 | Util.FireAndForget(delegate(object o) | ||
325 | { | ||
326 | Thread.Sleep(15000); | ||
327 | m_log.Info("[ARCHIVER]: Starting scripts in scene objects"); | ||
328 | |||
329 | foreach (DearchiveContext sceneContext in sceneContexts.Values) | ||
330 | { | ||
331 | foreach (SceneObjectGroup sceneObject in sceneContext.SceneObjects) | ||
332 | { | ||
333 | sceneObject.CreateScriptInstances(0, false, sceneContext.Scene.DefaultScriptEngine, 0); // StateSource.RegionStart | ||
334 | sceneObject.ResumeScripts(); | ||
335 | } | ||
336 | |||
337 | sceneContext.SceneObjects.Clear(); | ||
338 | } | ||
339 | }); | ||
340 | 234 | ||
341 | m_log.InfoFormat("[ARCHIVER]: Successfully loaded archive"); | 235 | m_log.InfoFormat("[ARCHIVER]: Successfully loaded archive"); |
342 | 236 | ||
343 | m_rootScene.EventManager.TriggerOarFileLoaded(m_requestId, dearchivedScenes.GetLoadedScenes(), m_errorMessage); | 237 | m_scene.EventManager.TriggerOarFileLoaded(m_requestId, m_errorMessage); |
344 | } | ||
345 | |||
346 | /// <summary> | ||
347 | /// Searches through the files in the archive for the control file, and reads it. | ||
348 | /// We must read the control file first, in order to know which regions are available. | ||
349 | /// </summary> | ||
350 | /// <remarks> | ||
351 | /// In most cases the control file *is* first, since that's how we create archives. However, | ||
352 | /// it's possible that someone rewrote the archive externally so we can't rely on this fact. | ||
353 | /// </remarks> | ||
354 | /// <param name="archive"></param> | ||
355 | /// <param name="dearchivedScenes"></param> | ||
356 | private void FindAndLoadControlFile(out TarArchiveReader archive, out DearchiveScenesInfo dearchivedScenes) | ||
357 | { | ||
358 | archive = new TarArchiveReader(m_loadStream); | ||
359 | dearchivedScenes = new DearchiveScenesInfo(); | ||
360 | |||
361 | string filePath; | ||
362 | byte[] data; | ||
363 | TarArchiveReader.TarEntryType entryType; | ||
364 | bool firstFile = true; | ||
365 | |||
366 | while ((data = archive.ReadEntry(out filePath, out entryType)) != null) | ||
367 | { | ||
368 | if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType) | ||
369 | continue; | ||
370 | |||
371 | if (filePath == ArchiveConstants.CONTROL_FILE_PATH) | ||
372 | { | ||
373 | LoadControlFile(filePath, data, dearchivedScenes); | ||
374 | |||
375 | // Find which scenes are available in the simulator | ||
376 | ArchiveScenesGroup simulatorScenes = new ArchiveScenesGroup(); | ||
377 | SceneManager.Instance.ForEachScene(delegate(Scene scene2) | ||
378 | { | ||
379 | simulatorScenes.AddScene(scene2); | ||
380 | }); | ||
381 | simulatorScenes.CalcSceneLocations(); | ||
382 | dearchivedScenes.SetSimulatorScenes(m_rootScene, simulatorScenes); | ||
383 | |||
384 | // If the control file wasn't the first file then reset the read pointer | ||
385 | if (!firstFile) | ||
386 | { | ||
387 | m_log.Warn("Control file wasn't the first file in the archive"); | ||
388 | if (m_loadStream.CanSeek) | ||
389 | { | ||
390 | m_loadStream.Seek(0, SeekOrigin.Begin); | ||
391 | } | ||
392 | else if (m_loadPath != null) | ||
393 | { | ||
394 | archive.Close(); | ||
395 | archive = null; | ||
396 | m_loadStream.Close(); | ||
397 | m_loadStream = null; | ||
398 | m_loadStream = new GZipStream(ArchiveHelpers.GetStream(m_loadPath), CompressionMode.Decompress); | ||
399 | archive = new TarArchiveReader(m_loadStream); | ||
400 | } | ||
401 | else | ||
402 | { | ||
403 | // There isn't currently a scenario where this happens, but it's best to add a check just in case | ||
404 | throw new Exception("Error reading archive: control file wasn't the first file, and the input stream doesn't allow seeking"); | ||
405 | } | ||
406 | } | ||
407 | |||
408 | return; | ||
409 | } | ||
410 | |||
411 | firstFile = false; | ||
412 | } | ||
413 | |||
414 | throw new Exception("Control file not found"); | ||
415 | } | 238 | } |
416 | 239 | ||
417 | /// <summary> | 240 | /// <summary> |
418 | /// Load serialized scene objects. | 241 | /// Load serialized scene objects. |
419 | /// </summary> | 242 | /// </summary> |
420 | protected void LoadObjects(Scene scene, List<string> serialisedSceneObjects, List<SceneObjectGroup> sceneObjects) | 243 | /// <param name="serialisedSceneObjects"></param> |
244 | protected void LoadObjects(List<string> serialisedSceneObjects) | ||
421 | { | 245 | { |
422 | // Reload serialized prims | 246 | // Reload serialized prims |
423 | m_log.InfoFormat("[ARCHIVER]: Loading {0} scene objects. Please wait.", serialisedSceneObjects.Count); | 247 | m_log.InfoFormat("[ARCHIVER]: Loading {0} scene objects. Please wait.", serialisedSceneObjects.Count); |
424 | 248 | ||
425 | UUID oldTelehubUUID = scene.RegionInfo.RegionSettings.TelehubObject; | 249 | UUID oldTelehubUUID = m_scene.RegionInfo.RegionSettings.TelehubObject; |
426 | 250 | ||
427 | IRegionSerialiserModule serialiser = scene.RequestModuleInterface<IRegionSerialiserModule>(); | 251 | IRegionSerialiserModule serialiser = m_scene.RequestModuleInterface<IRegionSerialiserModule>(); |
428 | int sceneObjectsLoadedCount = 0; | 252 | int sceneObjectsLoadedCount = 0; |
429 | 253 | ||
430 | foreach (string serialisedSceneObject in serialisedSceneObjects) | 254 | foreach (string serialisedSceneObject in serialisedSceneObjects) |
@@ -445,7 +269,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
445 | 269 | ||
446 | SceneObjectGroup sceneObject = serialiser.DeserializeGroupFromXml2(serialisedSceneObject); | 270 | SceneObjectGroup sceneObject = serialiser.DeserializeGroupFromXml2(serialisedSceneObject); |
447 | 271 | ||
448 | bool isTelehub = (sceneObject.UUID == oldTelehubUUID) && (oldTelehubUUID != UUID.Zero); | 272 | bool isTelehub = (sceneObject.UUID == oldTelehubUUID); |
449 | 273 | ||
450 | // For now, give all incoming scene objects new uuids. This will allow scenes to be cloned | 274 | // For now, give all incoming scene objects new uuids. This will allow scenes to be cloned |
451 | // on the same region server and multiple examples a single object archive to be imported | 275 | // on the same region server and multiple examples a single object archive to be imported |
@@ -455,8 +279,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
455 | if (isTelehub) | 279 | if (isTelehub) |
456 | { | 280 | { |
457 | // Change the Telehub Object to the new UUID | 281 | // Change the Telehub Object to the new UUID |
458 | scene.RegionInfo.RegionSettings.TelehubObject = sceneObject.UUID; | 282 | m_scene.RegionInfo.RegionSettings.TelehubObject = sceneObject.UUID; |
459 | scene.RegionInfo.RegionSettings.Save(); | 283 | m_scene.RegionInfo.RegionSettings.Save(); |
460 | oldTelehubUUID = UUID.Zero; | 284 | oldTelehubUUID = UUID.Zero; |
461 | } | 285 | } |
462 | 286 | ||
@@ -466,20 +290,17 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
466 | { | 290 | { |
467 | if (part.CreatorData == null || part.CreatorData == string.Empty) | 291 | if (part.CreatorData == null || part.CreatorData == string.Empty) |
468 | { | 292 | { |
469 | if (!ResolveUserUuid(scene, part.CreatorID)) | 293 | if (!ResolveUserUuid(part.CreatorID)) |
470 | part.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner; | 294 | part.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner; |
471 | } | 295 | } |
472 | if (UserManager != null) | 296 | if (UserManager != null) |
473 | UserManager.AddUser(part.CreatorID, part.CreatorData); | 297 | UserManager.AddUser(part.CreatorID, part.CreatorData); |
474 | 298 | ||
475 | if (!ResolveUserUuid(scene, part.OwnerID)) | 299 | if (!ResolveUserUuid(part.OwnerID)) |
476 | part.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner; | 300 | part.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; |
477 | |||
478 | if (!ResolveUserUuid(scene, part.LastOwnerID)) | ||
479 | part.LastOwnerID = scene.RegionInfo.EstateSettings.EstateOwner; | ||
480 | 301 | ||
481 | if (!ResolveGroupUuid(part.GroupID)) | 302 | if (!ResolveUserUuid(part.LastOwnerID)) |
482 | part.GroupID = UUID.Zero; | 303 | part.LastOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; |
483 | 304 | ||
484 | // And zap any troublesome sit target information | 305 | // And zap any troublesome sit target information |
485 | // part.SitTargetOrientation = new Quaternion(0, 0, 0, 1); | 306 | // part.SitTargetOrientation = new Quaternion(0, 0, 0, 1); |
@@ -490,14 +311,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
490 | // being no copy/no mod for everyone | 311 | // being no copy/no mod for everyone |
491 | lock (part.TaskInventory) | 312 | lock (part.TaskInventory) |
492 | { | 313 | { |
493 | if (!ResolveUserUuid(scene, part.CreatorID)) | 314 | if (!ResolveUserUuid(part.CreatorID)) |
494 | part.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner; | 315 | part.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner; |
495 | 316 | ||
496 | if (!ResolveUserUuid(scene, part.OwnerID)) | 317 | if (!ResolveUserUuid(part.OwnerID)) |
497 | part.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner; | 318 | part.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; |
498 | 319 | ||
499 | if (!ResolveUserUuid(scene, part.LastOwnerID)) | 320 | if (!ResolveUserUuid(part.LastOwnerID)) |
500 | part.LastOwnerID = scene.RegionInfo.EstateSettings.EstateOwner; | 321 | part.LastOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; |
501 | 322 | ||
502 | // And zap any troublesome sit target information | 323 | // And zap any troublesome sit target information |
503 | part.SitTargetOrientation = new Quaternion(0, 0, 0, 1); | 324 | part.SitTargetOrientation = new Quaternion(0, 0, 0, 1); |
@@ -510,31 +331,26 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
510 | TaskInventoryDictionary inv = part.TaskInventory; | 331 | TaskInventoryDictionary inv = part.TaskInventory; |
511 | foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv) | 332 | foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv) |
512 | { | 333 | { |
513 | if (!ResolveUserUuid(scene, kvp.Value.OwnerID)) | 334 | if (!ResolveUserUuid(kvp.Value.OwnerID)) |
514 | { | 335 | { |
515 | kvp.Value.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner; | 336 | kvp.Value.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; |
516 | } | 337 | } |
517 | |||
518 | if (kvp.Value.CreatorData == null || kvp.Value.CreatorData == string.Empty) | 338 | if (kvp.Value.CreatorData == null || kvp.Value.CreatorData == string.Empty) |
519 | { | 339 | { |
520 | if (!ResolveUserUuid(scene, kvp.Value.CreatorID)) | 340 | if (!ResolveUserUuid(kvp.Value.CreatorID)) |
521 | kvp.Value.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner; | 341 | kvp.Value.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner; |
522 | } | 342 | } |
523 | |||
524 | if (UserManager != null) | 343 | if (UserManager != null) |
525 | UserManager.AddUser(kvp.Value.CreatorID, kvp.Value.CreatorData); | 344 | UserManager.AddUser(kvp.Value.CreatorID, kvp.Value.CreatorData); |
526 | |||
527 | if (!ResolveGroupUuid(kvp.Value.GroupID)) | ||
528 | kvp.Value.GroupID = UUID.Zero; | ||
529 | } | 345 | } |
530 | part.TaskInventory.LockItemsForRead(false); | 346 | part.TaskInventory.LockItemsForRead(false); |
531 | } | 347 | } |
532 | } | 348 | } |
533 | 349 | ||
534 | if (scene.AddRestoredSceneObject(sceneObject, true, false)) | 350 | if (m_scene.AddRestoredSceneObject(sceneObject, true, false)) |
535 | { | 351 | { |
536 | sceneObjectsLoadedCount++; | 352 | sceneObjectsLoadedCount++; |
537 | sceneObject.CreateScriptInstances(0, false, scene.DefaultScriptEngine, 0); | 353 | sceneObject.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, 0); |
538 | sceneObject.ResumeScripts(); | 354 | sceneObject.ResumeScripts(); |
539 | } | 355 | } |
540 | } | 356 | } |
@@ -549,17 +365,16 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
549 | if (oldTelehubUUID != UUID.Zero) | 365 | if (oldTelehubUUID != UUID.Zero) |
550 | { | 366 | { |
551 | m_log.WarnFormat("Telehub object not found: {0}", oldTelehubUUID); | 367 | m_log.WarnFormat("Telehub object not found: {0}", oldTelehubUUID); |
552 | scene.RegionInfo.RegionSettings.TelehubObject = UUID.Zero; | 368 | m_scene.RegionInfo.RegionSettings.TelehubObject = UUID.Zero; |
553 | scene.RegionInfo.RegionSettings.ClearSpawnPoints(); | 369 | m_scene.RegionInfo.RegionSettings.ClearSpawnPoints(); |
554 | } | 370 | } |
555 | } | 371 | } |
556 | 372 | ||
557 | /// <summary> | 373 | /// <summary> |
558 | /// Load serialized parcels. | 374 | /// Load serialized parcels. |
559 | /// </summary> | 375 | /// </summary> |
560 | /// <param name="scene"></param> | ||
561 | /// <param name="serialisedParcels"></param> | 376 | /// <param name="serialisedParcels"></param> |
562 | protected void LoadParcels(Scene scene, List<string> serialisedParcels) | 377 | protected void LoadParcels(List<string> serialisedParcels) |
563 | { | 378 | { |
564 | // Reload serialized parcels | 379 | // Reload serialized parcels |
565 | m_log.InfoFormat("[ARCHIVER]: Loading {0} parcels. Please wait.", serialisedParcels.Count); | 380 | m_log.InfoFormat("[ARCHIVER]: Loading {0} parcels. Please wait.", serialisedParcels.Count); |
@@ -567,27 +382,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
567 | foreach (string serialisedParcel in serialisedParcels) | 382 | foreach (string serialisedParcel in serialisedParcels) |
568 | { | 383 | { |
569 | LandData parcel = LandDataSerializer.Deserialize(serialisedParcel); | 384 | LandData parcel = LandDataSerializer.Deserialize(serialisedParcel); |
385 | if (!ResolveUserUuid(parcel.OwnerID)) | ||
386 | parcel.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; | ||
570 | 387 | ||
571 | // Validate User and Group UUID's | ||
572 | |||
573 | if (!ResolveUserUuid(scene, parcel.OwnerID)) | ||
574 | parcel.OwnerID = m_rootScene.RegionInfo.EstateSettings.EstateOwner; | ||
575 | |||
576 | if (!ResolveGroupUuid(parcel.GroupID)) | ||
577 | { | ||
578 | parcel.GroupID = UUID.Zero; | ||
579 | parcel.IsGroupOwned = false; | ||
580 | } | ||
581 | |||
582 | List<LandAccessEntry> accessList = new List<LandAccessEntry>(); | ||
583 | foreach (LandAccessEntry entry in parcel.ParcelAccessList) | ||
584 | { | ||
585 | if (ResolveUserUuid(scene, entry.AgentID)) | ||
586 | accessList.Add(entry); | ||
587 | // else, drop this access rule | ||
588 | } | ||
589 | parcel.ParcelAccessList = accessList; | ||
590 | |||
591 | // m_log.DebugFormat( | 388 | // m_log.DebugFormat( |
592 | // "[ARCHIVER]: Adding parcel {0}, local id {1}, area {2}", | 389 | // "[ARCHIVER]: Adding parcel {0}, local id {1}, area {2}", |
593 | // parcel.Name, parcel.LocalID, parcel.Area); | 390 | // parcel.Name, parcel.LocalID, parcel.Area); |
@@ -598,24 +395,23 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
598 | if (!m_merge) | 395 | if (!m_merge) |
599 | { | 396 | { |
600 | bool setupDefaultParcel = (landData.Count == 0); | 397 | bool setupDefaultParcel = (landData.Count == 0); |
601 | scene.LandChannel.Clear(setupDefaultParcel); | 398 | m_scene.LandChannel.Clear(setupDefaultParcel); |
602 | } | 399 | } |
603 | 400 | ||
604 | scene.EventManager.TriggerIncomingLandDataFromStorage(landData); | 401 | m_scene.EventManager.TriggerIncomingLandDataFromStorage(landData); |
605 | m_log.InfoFormat("[ARCHIVER]: Restored {0} parcels.", landData.Count); | 402 | m_log.InfoFormat("[ARCHIVER]: Restored {0} parcels.", landData.Count); |
606 | } | 403 | } |
607 | 404 | ||
608 | /// <summary> | 405 | /// <summary> |
609 | /// Look up the given user id to check whether it's one that is valid for this grid. | 406 | /// Look up the given user id to check whether it's one that is valid for this grid. |
610 | /// </summary> | 407 | /// </summary> |
611 | /// <param name="scene"></param> | ||
612 | /// <param name="uuid"></param> | 408 | /// <param name="uuid"></param> |
613 | /// <returns></returns> | 409 | /// <returns></returns> |
614 | private bool ResolveUserUuid(Scene scene, UUID uuid) | 410 | private bool ResolveUserUuid(UUID uuid) |
615 | { | 411 | { |
616 | if (!m_validUserUuids.ContainsKey(uuid)) | 412 | if (!m_validUserUuids.ContainsKey(uuid)) |
617 | { | 413 | { |
618 | UserAccount account = scene.UserAccountService.GetUserAccount(scene.RegionInfo.ScopeID, uuid); | 414 | UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, uuid); |
619 | m_validUserUuids.Add(uuid, account != null); | 415 | m_validUserUuids.Add(uuid, account != null); |
620 | } | 416 | } |
621 | 417 | ||
@@ -623,30 +419,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
623 | } | 419 | } |
624 | 420 | ||
625 | /// <summary> | 421 | /// <summary> |
626 | /// Look up the given group id to check whether it's one that is valid for this grid. | ||
627 | /// </summary> | ||
628 | /// <param name="uuid"></param> | ||
629 | /// <returns></returns> | ||
630 | private bool ResolveGroupUuid(UUID uuid) | ||
631 | { | ||
632 | if (uuid == UUID.Zero) | ||
633 | return true; // this means the object has no group | ||
634 | |||
635 | if (!m_validGroupUuids.ContainsKey(uuid)) | ||
636 | { | ||
637 | bool exists; | ||
638 | |||
639 | if (m_groupsModule == null) | ||
640 | exists = false; | ||
641 | else | ||
642 | exists = (m_groupsModule.GetGroupRecord(uuid) != null); | ||
643 | |||
644 | m_validGroupUuids.Add(uuid, exists); | ||
645 | } | ||
646 | |||
647 | return m_validGroupUuids[uuid]; | ||
648 | } | ||
649 | |||
650 | /// Load an asset | 422 | /// Load an asset |
651 | /// </summary> | 423 | /// </summary> |
652 | /// <param name="assetFilename"></param> | 424 | /// <param name="assetFilename"></param> |
@@ -670,7 +442,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
670 | string extension = filename.Substring(i); | 442 | string extension = filename.Substring(i); |
671 | string uuid = filename.Remove(filename.Length - extension.Length); | 443 | string uuid = filename.Remove(filename.Length - extension.Length); |
672 | 444 | ||
673 | if (m_assetService.GetMetadata(uuid) != null) | 445 | if (m_scene.AssetService.GetMetadata(uuid) != null) |
674 | { | 446 | { |
675 | // m_log.DebugFormat("[ARCHIVER]: found existing asset {0}",uuid); | 447 | // m_log.DebugFormat("[ARCHIVER]: found existing asset {0}",uuid); |
676 | return true; | 448 | return true; |
@@ -690,7 +462,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
690 | 462 | ||
691 | // We're relying on the asset service to do the sensible thing and not store the asset if it already | 463 | // We're relying on the asset service to do the sensible thing and not store the asset if it already |
692 | // exists. | 464 | // exists. |
693 | m_assetService.Store(asset); | 465 | m_scene.AssetService.Store(asset); |
694 | 466 | ||
695 | /** | 467 | /** |
696 | * Create layers on decode for image assets. This is likely to significantly increase the time to load archives so | 468 | * Create layers on decode for image assets. This is likely to significantly increase the time to load archives so |
@@ -718,14 +490,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
718 | /// <summary> | 490 | /// <summary> |
719 | /// Load region settings data | 491 | /// Load region settings data |
720 | /// </summary> | 492 | /// </summary> |
721 | /// <param name="scene"></param> | ||
722 | /// <param name="settingsPath"></param> | 493 | /// <param name="settingsPath"></param> |
723 | /// <param name="data"></param> | 494 | /// <param name="data"></param> |
724 | /// <param name="dearchivedScenes"></param> | ||
725 | /// <returns> | 495 | /// <returns> |
726 | /// true if settings were loaded successfully, false otherwise | 496 | /// true if settings were loaded successfully, false otherwise |
727 | /// </returns> | 497 | /// </returns> |
728 | private bool LoadRegionSettings(Scene scene, string settingsPath, byte[] data, DearchiveScenesInfo dearchivedScenes) | 498 | private bool LoadRegionSettings(string settingsPath, byte[] data) |
729 | { | 499 | { |
730 | RegionSettings loadedRegionSettings; | 500 | RegionSettings loadedRegionSettings; |
731 | 501 | ||
@@ -741,7 +511,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
741 | return false; | 511 | return false; |
742 | } | 512 | } |
743 | 513 | ||
744 | RegionSettings currentRegionSettings = scene.RegionInfo.RegionSettings; | 514 | RegionSettings currentRegionSettings = m_scene.RegionInfo.RegionSettings; |
745 | 515 | ||
746 | currentRegionSettings.AgentLimit = loadedRegionSettings.AgentLimit; | 516 | currentRegionSettings.AgentLimit = loadedRegionSettings.AgentLimit; |
747 | currentRegionSettings.AllowDamage = loadedRegionSettings.AllowDamage; | 517 | currentRegionSettings.AllowDamage = loadedRegionSettings.AllowDamage; |
@@ -778,14 +548,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
778 | foreach (SpawnPoint sp in loadedRegionSettings.SpawnPoints()) | 548 | foreach (SpawnPoint sp in loadedRegionSettings.SpawnPoints()) |
779 | currentRegionSettings.AddSpawnPoint(sp); | 549 | currentRegionSettings.AddSpawnPoint(sp); |
780 | 550 | ||
781 | currentRegionSettings.LoadedCreationDateTime = dearchivedScenes.LoadedCreationDateTime; | ||
782 | currentRegionSettings.LoadedCreationID = dearchivedScenes.GetOriginalRegionID(scene.RegionInfo.RegionID).ToString(); | ||
783 | |||
784 | currentRegionSettings.Save(); | 551 | currentRegionSettings.Save(); |
785 | 552 | ||
786 | scene.TriggerEstateSunUpdate(); | 553 | m_scene.TriggerEstateSunUpdate(); |
787 | 554 | ||
788 | IEstateModule estateModule = scene.RequestModuleInterface<IEstateModule>(); | 555 | IEstateModule estateModule = m_scene.RequestModuleInterface<IEstateModule>(); |
556 | |||
789 | if (estateModule != null) | 557 | if (estateModule != null) |
790 | estateModule.sendRegionHandshakeToAll(); | 558 | estateModule.sendRegionHandshakeToAll(); |
791 | 559 | ||
@@ -795,15 +563,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
795 | /// <summary> | 563 | /// <summary> |
796 | /// Load terrain data | 564 | /// Load terrain data |
797 | /// </summary> | 565 | /// </summary> |
798 | /// <param name="scene"></param> | ||
799 | /// <param name="terrainPath"></param> | 566 | /// <param name="terrainPath"></param> |
800 | /// <param name="data"></param> | 567 | /// <param name="data"></param> |
801 | /// <returns> | 568 | /// <returns> |
802 | /// true if terrain was resolved successfully, false otherwise. | 569 | /// true if terrain was resolved successfully, false otherwise. |
803 | /// </returns> | 570 | /// </returns> |
804 | private bool LoadTerrain(Scene scene, string terrainPath, byte[] data) | 571 | private bool LoadTerrain(string terrainPath, byte[] data) |
805 | { | 572 | { |
806 | ITerrainModule terrainModule = scene.RequestModuleInterface<ITerrainModule>(); | 573 | ITerrainModule terrainModule = m_scene.RequestModuleInterface<ITerrainModule>(); |
807 | 574 | ||
808 | MemoryStream ms = new MemoryStream(data); | 575 | MemoryStream ms = new MemoryStream(data); |
809 | terrainModule.LoadFromStream(terrainPath, ms); | 576 | terrainModule.LoadFromStream(terrainPath, ms); |
@@ -819,18 +586,17 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
819 | /// </summary> | 586 | /// </summary> |
820 | /// <param name="path"></param> | 587 | /// <param name="path"></param> |
821 | /// <param name="data"></param> | 588 | /// <param name="data"></param> |
822 | /// <param name="dearchivedScenes"></param> | 589 | public void LoadControlFile(string path, byte[] data) |
823 | public DearchiveScenesInfo LoadControlFile(string path, byte[] data, DearchiveScenesInfo dearchivedScenes) | ||
824 | { | 590 | { |
825 | XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable()); | 591 | XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable()); |
826 | XmlParserContext context = new XmlParserContext(null, nsmgr, null, XmlSpace.None); | 592 | XmlParserContext context = new XmlParserContext(null, nsmgr, null, XmlSpace.None); |
827 | XmlTextReader xtr = new XmlTextReader(Encoding.ASCII.GetString(data), XmlNodeType.Document, context); | 593 | XmlTextReader xtr = new XmlTextReader(Encoding.ASCII.GetString(data), XmlNodeType.Document, context); |
828 | 594 | ||
829 | // Loaded metadata will be empty if no information exists in the archive | 595 | RegionSettings currentRegionSettings = m_scene.RegionInfo.RegionSettings; |
830 | dearchivedScenes.LoadedCreationDateTime = 0; | ||
831 | dearchivedScenes.DefaultOriginalID = ""; | ||
832 | 596 | ||
833 | bool multiRegion = false; | 597 | // Loaded metadata will empty if no information exists in the archive |
598 | currentRegionSettings.LoadedCreationDateTime = 0; | ||
599 | currentRegionSettings.LoadedCreationID = ""; | ||
834 | 600 | ||
835 | while (xtr.Read()) | 601 | while (xtr.Read()) |
836 | { | 602 | { |
@@ -856,44 +622,18 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
856 | { | 622 | { |
857 | int value; | 623 | int value; |
858 | if (Int32.TryParse(xtr.ReadElementContentAsString(), out value)) | 624 | if (Int32.TryParse(xtr.ReadElementContentAsString(), out value)) |
859 | dearchivedScenes.LoadedCreationDateTime = value; | 625 | currentRegionSettings.LoadedCreationDateTime = value; |
860 | } | 626 | } |
861 | else if (xtr.Name.ToString() == "row") | 627 | else if (xtr.Name.ToString() == "id") |
862 | { | ||
863 | multiRegion = true; | ||
864 | dearchivedScenes.StartRow(); | ||
865 | } | ||
866 | else if (xtr.Name.ToString() == "region") | ||
867 | { | ||
868 | dearchivedScenes.StartRegion(); | ||
869 | } | ||
870 | else if (xtr.Name.ToString() == "id") | ||
871 | { | ||
872 | string id = xtr.ReadElementContentAsString(); | ||
873 | dearchivedScenes.DefaultOriginalID = id; | ||
874 | if (multiRegion) | ||
875 | dearchivedScenes.SetRegionOriginalID(id); | ||
876 | } | ||
877 | else if (xtr.Name.ToString() == "dir") | ||
878 | { | 628 | { |
879 | dearchivedScenes.SetRegionDirectory(xtr.ReadElementContentAsString()); | 629 | currentRegionSettings.LoadedCreationID = xtr.ReadElementContentAsString(); |
880 | } | 630 | } |
881 | } | 631 | } |
882 | } | 632 | } |
883 | 633 | ||
884 | dearchivedScenes.MultiRegionFormat = multiRegion; | 634 | currentRegionSettings.Save(); |
885 | if (!multiRegion) | 635 | |
886 | { | ||
887 | // Add the single scene | ||
888 | dearchivedScenes.StartRow(); | ||
889 | dearchivedScenes.StartRegion(); | ||
890 | dearchivedScenes.SetRegionOriginalID(dearchivedScenes.DefaultOriginalID); | ||
891 | dearchivedScenes.SetRegionDirectory(""); | ||
892 | } | ||
893 | |||
894 | ControlFileLoaded = true; | 636 | ControlFileLoaded = true; |
895 | |||
896 | return dearchivedScenes; | ||
897 | } | 637 | } |
898 | } | 638 | } |
899 | } | 639 | } \ No newline at end of file |
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs deleted file mode 100644 index d8dace2..0000000 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs +++ /dev/null | |||
@@ -1,176 +0,0 @@ | |||
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 | using System.Collections.Generic; | ||
30 | using System.Linq; | ||
31 | using System.Text; | ||
32 | using OpenSim.Region.Framework.Scenes; | ||
33 | using OpenMetaverse; | ||
34 | using System.Drawing; | ||
35 | |||
36 | namespace OpenSim.Region.CoreModules.World.Archiver | ||
37 | { | ||
38 | /// <summary> | ||
39 | /// A group of regions arranged in a rectangle, possibly with holes. | ||
40 | /// </summary> | ||
41 | /// <remarks> | ||
42 | /// The regions usually (but not necessarily) belong to an archive file, in which case we | ||
43 | /// store additional information used to create the archive (e.g., each region's | ||
44 | /// directory within the archive). | ||
45 | /// </remarks> | ||
46 | public class ArchiveScenesGroup | ||
47 | { | ||
48 | /// <summary> | ||
49 | /// All the regions. The outer dictionary contains rows (key: Y coordinate). | ||
50 | /// The inner dictionaries contain each row's regions (key: X coordinate). | ||
51 | /// </summary> | ||
52 | public SortedDictionary<uint, SortedDictionary<uint, Scene>> Regions { get; set; } | ||
53 | |||
54 | /// <summary> | ||
55 | /// The subdirectory where each region is stored in the archive. | ||
56 | /// </summary> | ||
57 | protected Dictionary<UUID, string> m_regionDirs; | ||
58 | |||
59 | /// <summary> | ||
60 | /// The grid coordinates of the regions' bounding box. | ||
61 | /// </summary> | ||
62 | public Rectangle Rect { get; set; } | ||
63 | |||
64 | |||
65 | public ArchiveScenesGroup() | ||
66 | { | ||
67 | Regions = new SortedDictionary<uint, SortedDictionary<uint, Scene>>(); | ||
68 | m_regionDirs = new Dictionary<UUID, string>(); | ||
69 | Rect = new Rectangle(0, 0, 0, 0); | ||
70 | } | ||
71 | |||
72 | public void AddScene(Scene scene) | ||
73 | { | ||
74 | uint x = scene.RegionInfo.RegionLocX; | ||
75 | uint y = scene.RegionInfo.RegionLocY; | ||
76 | |||
77 | SortedDictionary<uint, Scene> row; | ||
78 | if (!Regions.TryGetValue(y, out row)) | ||
79 | { | ||
80 | row = new SortedDictionary<uint, Scene>(); | ||
81 | Regions[y] = row; | ||
82 | } | ||
83 | |||
84 | row[x] = scene; | ||
85 | } | ||
86 | |||
87 | /// <summary> | ||
88 | /// Called after all the scenes have been added. Performs calculations that require | ||
89 | /// knowledge of all the scenes. | ||
90 | /// </summary> | ||
91 | public void CalcSceneLocations() | ||
92 | { | ||
93 | if (Regions.Count == 0) | ||
94 | return; | ||
95 | |||
96 | // Find the bounding rectangle | ||
97 | |||
98 | uint firstY = Regions.First().Key; | ||
99 | uint lastY = Regions.Last().Key; | ||
100 | |||
101 | uint? firstX = null; | ||
102 | uint? lastX = null; | ||
103 | |||
104 | foreach (SortedDictionary<uint, Scene> row in Regions.Values) | ||
105 | { | ||
106 | uint curFirstX = row.First().Key; | ||
107 | uint curLastX = row.Last().Key; | ||
108 | |||
109 | firstX = (firstX == null) ? curFirstX : (firstX < curFirstX) ? firstX : curFirstX; | ||
110 | lastX = (lastX == null) ? curLastX : (lastX > curLastX) ? lastX : curLastX; | ||
111 | } | ||
112 | |||
113 | Rect = new Rectangle((int)firstX, (int)firstY, (int)(lastX - firstX + 1), (int)(lastY - firstY + 1)); | ||
114 | |||
115 | |||
116 | // Calculate the subdirectory in which each region will be stored in the archive | ||
117 | |||
118 | m_regionDirs.Clear(); | ||
119 | ForEachScene(delegate(Scene scene) | ||
120 | { | ||
121 | // We add the region's coordinates to ensure uniqueness even if multiple regions have the same name | ||
122 | string path = string.Format("{0}_{1}_{2}", | ||
123 | scene.RegionInfo.RegionLocX - Rect.X + 1, | ||
124 | scene.RegionInfo.RegionLocY - Rect.Y + 1, | ||
125 | scene.RegionInfo.RegionName.Replace(' ', '_')); | ||
126 | m_regionDirs[scene.RegionInfo.RegionID] = path; | ||
127 | }); | ||
128 | } | ||
129 | |||
130 | /// <summary> | ||
131 | /// Returns the subdirectory where the region is stored. | ||
132 | /// </summary> | ||
133 | /// <param name="regionID"></param> | ||
134 | /// <returns></returns> | ||
135 | public string GetRegionDir(UUID regionID) | ||
136 | { | ||
137 | return m_regionDirs[regionID]; | ||
138 | } | ||
139 | |||
140 | /// <summary> | ||
141 | /// Performs an action on all the scenes in this order: rows from South to North, | ||
142 | /// and within each row West to East. | ||
143 | /// </summary> | ||
144 | /// <param name="action"></param> | ||
145 | public void ForEachScene(Action<Scene> action) | ||
146 | { | ||
147 | foreach (SortedDictionary<uint, Scene> row in Regions.Values) | ||
148 | { | ||
149 | foreach (Scene scene in row.Values) | ||
150 | { | ||
151 | action(scene); | ||
152 | } | ||
153 | } | ||
154 | } | ||
155 | |||
156 | /// <summary> | ||
157 | /// Returns the scene at position 'location'. | ||
158 | /// </summary> | ||
159 | /// <param name="location">A location in the grid</param> | ||
160 | /// <param name="scene">The scene at this location</param> | ||
161 | /// <returns>Whether the scene was found</returns> | ||
162 | public bool TryGetScene(Point location, out Scene scene) | ||
163 | { | ||
164 | SortedDictionary<uint, Scene> row; | ||
165 | if (Regions.TryGetValue((uint)location.Y, out row)) | ||
166 | { | ||
167 | if (row.TryGetValue((uint)location.X, out scene)) | ||
168 | return true; | ||
169 | } | ||
170 | |||
171 | scene = null; | ||
172 | return false; | ||
173 | } | ||
174 | |||
175 | } | ||
176 | } | ||
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs deleted file mode 100644 index d751b1c..0000000 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs +++ /dev/null | |||
@@ -1,634 +0,0 @@ | |||
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 | using System.Collections.Generic; | ||
30 | using System.IO; | ||
31 | using System.IO.Compression; | ||
32 | using System.Reflection; | ||
33 | using System.Text.RegularExpressions; | ||
34 | using System.Threading; | ||
35 | using System.Xml; | ||
36 | using log4net; | ||
37 | using OpenMetaverse; | ||
38 | using OpenSim.Framework; | ||
39 | using OpenSim.Framework.Serialization; | ||
40 | using OpenSim.Region.CoreModules.World.Terrain; | ||
41 | using OpenSim.Region.Framework.Interfaces; | ||
42 | using OpenSim.Region.Framework.Scenes; | ||
43 | using Ionic.Zlib; | ||
44 | using GZipStream = Ionic.Zlib.GZipStream; | ||
45 | using CompressionMode = Ionic.Zlib.CompressionMode; | ||
46 | using OpenSim.Framework.Serialization.External; | ||
47 | |||
48 | namespace OpenSim.Region.CoreModules.World.Archiver | ||
49 | { | ||
50 | /// <summary> | ||
51 | /// Prepare to write out an archive. | ||
52 | /// </summary> | ||
53 | public class ArchiveWriteRequest | ||
54 | { | ||
55 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
56 | |||
57 | /// <summary> | ||
58 | /// The minimum major version of OAR that we can write. | ||
59 | /// </summary> | ||
60 | public static int MIN_MAJOR_VERSION = 0; | ||
61 | |||
62 | /// <summary> | ||
63 | /// The maximum major version of OAR that we can write. | ||
64 | /// </summary> | ||
65 | public static int MAX_MAJOR_VERSION = 1; | ||
66 | |||
67 | /// <summary> | ||
68 | /// Whether we're saving a multi-region archive. | ||
69 | /// </summary> | ||
70 | public bool MultiRegionFormat { get; set; } | ||
71 | |||
72 | /// <summary> | ||
73 | /// Determine whether this archive will save assets. Default is true. | ||
74 | /// </summary> | ||
75 | public bool SaveAssets { get; set; } | ||
76 | |||
77 | /// <summary> | ||
78 | /// Determines which objects will be included in the archive, according to their permissions. | ||
79 | /// Default is null, meaning no permission checks. | ||
80 | /// </summary> | ||
81 | public string CheckPermissions { get; set; } | ||
82 | |||
83 | protected Scene m_rootScene; | ||
84 | protected Stream m_saveStream; | ||
85 | protected TarArchiveWriter m_archiveWriter; | ||
86 | protected Guid m_requestId; | ||
87 | protected Dictionary<string, object> m_options; | ||
88 | |||
89 | /// <summary> | ||
90 | /// Constructor | ||
91 | /// </summary> | ||
92 | /// <param name="module">Calling module</param> | ||
93 | /// <param name="savePath">The path to which to save data.</param> | ||
94 | /// <param name="requestId">The id associated with this request</param> | ||
95 | /// <exception cref="System.IO.IOException"> | ||
96 | /// If there was a problem opening a stream for the file specified by the savePath | ||
97 | /// </exception> | ||
98 | public ArchiveWriteRequest(Scene scene, string savePath, Guid requestId) : this(scene, requestId) | ||
99 | { | ||
100 | try | ||
101 | { | ||
102 | m_saveStream = new GZipStream(new FileStream(savePath, FileMode.Create), CompressionMode.Compress, CompressionLevel.BestCompression); | ||
103 | } | ||
104 | catch (EntryPointNotFoundException e) | ||
105 | { | ||
106 | m_log.ErrorFormat( | ||
107 | "[ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream." | ||
108 | + "If you've manually installed Mono, have you appropriately updated zlib1g as well?"); | ||
109 | m_log.ErrorFormat("{0} {1}", e.Message, e.StackTrace); | ||
110 | } | ||
111 | } | ||
112 | |||
113 | /// <summary> | ||
114 | /// Constructor. | ||
115 | /// </summary> | ||
116 | /// <param name="scene">The root scene to archive</param> | ||
117 | /// <param name="saveStream">The stream to which to save data.</param> | ||
118 | /// <param name="requestId">The id associated with this request</param> | ||
119 | public ArchiveWriteRequest(Scene scene, Stream saveStream, Guid requestId) : this(scene, requestId) | ||
120 | { | ||
121 | m_saveStream = saveStream; | ||
122 | } | ||
123 | |||
124 | protected ArchiveWriteRequest(Scene scene, Guid requestId) | ||
125 | { | ||
126 | m_rootScene = scene; | ||
127 | m_requestId = requestId; | ||
128 | m_archiveWriter = null; | ||
129 | |||
130 | MultiRegionFormat = false; | ||
131 | SaveAssets = true; | ||
132 | CheckPermissions = null; | ||
133 | } | ||
134 | |||
135 | /// <summary> | ||
136 | /// Archive the region requested. | ||
137 | /// </summary> | ||
138 | /// <exception cref="System.IO.IOException">if there was an io problem with creating the file</exception> | ||
139 | public void ArchiveRegion(Dictionary<string, object> options) | ||
140 | { | ||
141 | m_options = options; | ||
142 | |||
143 | if (options.ContainsKey("all") && (bool)options["all"]) | ||
144 | MultiRegionFormat = true; | ||
145 | |||
146 | if (options.ContainsKey("noassets") && (bool)options["noassets"]) | ||
147 | SaveAssets = false; | ||
148 | |||
149 | Object temp; | ||
150 | if (options.TryGetValue("checkPermissions", out temp)) | ||
151 | CheckPermissions = (string)temp; | ||
152 | |||
153 | |||
154 | // Find the regions to archive | ||
155 | ArchiveScenesGroup scenesGroup = new ArchiveScenesGroup(); | ||
156 | if (MultiRegionFormat) | ||
157 | { | ||
158 | m_log.InfoFormat("[ARCHIVER]: Saving {0} regions", SceneManager.Instance.Scenes.Count); | ||
159 | SceneManager.Instance.ForEachScene(delegate(Scene scene) | ||
160 | { | ||
161 | scenesGroup.AddScene(scene); | ||
162 | }); | ||
163 | } | ||
164 | else | ||
165 | { | ||
166 | scenesGroup.AddScene(m_rootScene); | ||
167 | } | ||
168 | scenesGroup.CalcSceneLocations(); | ||
169 | |||
170 | |||
171 | m_archiveWriter = new TarArchiveWriter(m_saveStream); | ||
172 | |||
173 | try | ||
174 | { | ||
175 | // Write out control file. It should be first so that it will be found ASAP when loading the file. | ||
176 | m_archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, CreateControlFile(scenesGroup)); | ||
177 | m_log.InfoFormat("[ARCHIVER]: Added control file to archive."); | ||
178 | |||
179 | // Archive the regions | ||
180 | |||
181 | Dictionary<UUID, AssetType> assetUuids = new Dictionary<UUID, AssetType>(); | ||
182 | |||
183 | scenesGroup.ForEachScene(delegate(Scene scene) | ||
184 | { | ||
185 | string regionDir = MultiRegionFormat ? scenesGroup.GetRegionDir(scene.RegionInfo.RegionID) : ""; | ||
186 | ArchiveOneRegion(scene, regionDir, assetUuids); | ||
187 | }); | ||
188 | |||
189 | // Archive the assets | ||
190 | |||
191 | if (SaveAssets) | ||
192 | { | ||
193 | m_log.DebugFormat("[ARCHIVER]: Saving {0} assets", assetUuids.Count); | ||
194 | |||
195 | // Asynchronously request all the assets required to perform this archive operation | ||
196 | AssetsRequest ar | ||
197 | = new AssetsRequest( | ||
198 | new AssetsArchiver(m_archiveWriter), assetUuids, | ||
199 | m_rootScene.AssetService, m_rootScene.UserAccountService, | ||
200 | m_rootScene.RegionInfo.ScopeID, options, ReceivedAllAssets); | ||
201 | |||
202 | Util.FireAndForget(o => ar.Execute()); | ||
203 | |||
204 | // CloseArchive() will be called from ReceivedAllAssets() | ||
205 | } | ||
206 | else | ||
207 | { | ||
208 | m_log.DebugFormat("[ARCHIVER]: Not saving assets since --noassets was specified"); | ||
209 | CloseArchive(string.Empty); | ||
210 | } | ||
211 | } | ||
212 | catch (Exception e) | ||
213 | { | ||
214 | CloseArchive(e.Message); | ||
215 | throw; | ||
216 | } | ||
217 | } | ||
218 | |||
219 | |||
220 | private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary<UUID, AssetType> assetUuids) | ||
221 | { | ||
222 | m_log.InfoFormat("[ARCHIVER]: Writing region {0}", scene.RegionInfo.RegionName); | ||
223 | |||
224 | EntityBase[] entities = scene.GetEntities(); | ||
225 | List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>(); | ||
226 | |||
227 | int numObjectsSkippedPermissions = 0; | ||
228 | |||
229 | // Filter entities so that we only have scene objects. | ||
230 | // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods | ||
231 | // end up having to do this | ||
232 | IPermissionsModule permissionsModule = scene.RequestModuleInterface<IPermissionsModule>(); | ||
233 | foreach (EntityBase entity in entities) | ||
234 | { | ||
235 | if (entity is SceneObjectGroup) | ||
236 | { | ||
237 | SceneObjectGroup sceneObject = (SceneObjectGroup)entity; | ||
238 | |||
239 | if (!sceneObject.IsDeleted && !sceneObject.IsAttachment) | ||
240 | { | ||
241 | if (!CanUserArchiveObject(scene.RegionInfo.EstateSettings.EstateOwner, sceneObject, CheckPermissions, permissionsModule)) | ||
242 | { | ||
243 | // The user isn't allowed to copy/transfer this object, so it will not be included in the OAR. | ||
244 | ++numObjectsSkippedPermissions; | ||
245 | } | ||
246 | else | ||
247 | { | ||
248 | sceneObjects.Add(sceneObject); | ||
249 | } | ||
250 | } | ||
251 | } | ||
252 | } | ||
253 | |||
254 | if (SaveAssets) | ||
255 | { | ||
256 | UuidGatherer assetGatherer = new UuidGatherer(scene.AssetService); | ||
257 | int prevAssets = assetUuids.Count; | ||
258 | |||
259 | foreach (SceneObjectGroup sceneObject in sceneObjects) | ||
260 | { | ||
261 | assetGatherer.GatherAssetUuids(sceneObject, assetUuids); | ||
262 | } | ||
263 | |||
264 | m_log.DebugFormat( | ||
265 | "[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets", | ||
266 | sceneObjects.Count, assetUuids.Count - prevAssets); | ||
267 | } | ||
268 | |||
269 | if (numObjectsSkippedPermissions > 0) | ||
270 | { | ||
271 | m_log.DebugFormat( | ||
272 | "[ARCHIVER]: {0} scene objects skipped due to lack of permissions", | ||
273 | numObjectsSkippedPermissions); | ||
274 | } | ||
275 | |||
276 | // Make sure that we also request terrain texture assets | ||
277 | RegionSettings regionSettings = scene.RegionInfo.RegionSettings; | ||
278 | |||
279 | if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1) | ||
280 | assetUuids[regionSettings.TerrainTexture1] = AssetType.Texture; | ||
281 | |||
282 | if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2) | ||
283 | assetUuids[regionSettings.TerrainTexture2] = AssetType.Texture; | ||
284 | |||
285 | if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3) | ||
286 | assetUuids[regionSettings.TerrainTexture3] = AssetType.Texture; | ||
287 | |||
288 | if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4) | ||
289 | assetUuids[regionSettings.TerrainTexture4] = AssetType.Texture; | ||
290 | |||
291 | Save(scene, sceneObjects, regionDir); | ||
292 | } | ||
293 | |||
294 | /// <summary> | ||
295 | /// Checks whether the user has permission to export an object group to an OAR. | ||
296 | /// </summary> | ||
297 | /// <param name="user">The user</param> | ||
298 | /// <param name="objGroup">The object group</param> | ||
299 | /// <param name="checkPermissions">Which permissions to check: "C" = Copy, "T" = Transfer</param> | ||
300 | /// <param name="permissionsModule">The scene's permissions module</param> | ||
301 | /// <returns>Whether the user is allowed to export the object to an OAR</returns> | ||
302 | private bool CanUserArchiveObject(UUID user, SceneObjectGroup objGroup, string checkPermissions, IPermissionsModule permissionsModule) | ||
303 | { | ||
304 | if (checkPermissions == null) | ||
305 | return true; | ||
306 | |||
307 | if (permissionsModule == null) | ||
308 | return true; // this shouldn't happen | ||
309 | |||
310 | // Check whether the user is permitted to export all of the parts in the SOG. If any | ||
311 | // part can't be exported then the entire SOG can't be exported. | ||
312 | |||
313 | bool permitted = true; | ||
314 | //int primNumber = 1; | ||
315 | |||
316 | foreach (SceneObjectPart obj in objGroup.Parts) | ||
317 | { | ||
318 | uint perm; | ||
319 | PermissionClass permissionClass = permissionsModule.GetPermissionClass(user, obj); | ||
320 | switch (permissionClass) | ||
321 | { | ||
322 | case PermissionClass.Owner: | ||
323 | perm = obj.BaseMask; | ||
324 | break; | ||
325 | case PermissionClass.Group: | ||
326 | perm = obj.GroupMask | obj.EveryoneMask; | ||
327 | break; | ||
328 | case PermissionClass.Everyone: | ||
329 | default: | ||
330 | perm = obj.EveryoneMask; | ||
331 | break; | ||
332 | } | ||
333 | |||
334 | bool canCopy = (perm & (uint)PermissionMask.Copy) != 0; | ||
335 | bool canTransfer = (perm & (uint)PermissionMask.Transfer) != 0; | ||
336 | |||
337 | // Special case: if Everyone can copy the object then this implies it can also be | ||
338 | // Transferred. | ||
339 | // However, if the user is the Owner then we don't check EveryoneMask, because it seems that the mask | ||
340 | // always (incorrectly) includes the Copy bit set in this case. But that's a mistake: the viewer | ||
341 | // does NOT show that the object has Everyone-Copy permissions, and doesn't allow it to be copied. | ||
342 | if (permissionClass != PermissionClass.Owner) | ||
343 | canTransfer |= (obj.EveryoneMask & (uint)PermissionMask.Copy) != 0; | ||
344 | |||
345 | bool partPermitted = true; | ||
346 | if (checkPermissions.Contains("C") && !canCopy) | ||
347 | partPermitted = false; | ||
348 | if (checkPermissions.Contains("T") && !canTransfer) | ||
349 | partPermitted = false; | ||
350 | |||
351 | // If the user is the Creator of the object then it can always be included in the OAR | ||
352 | bool creator = (obj.CreatorID.Guid == user.Guid); | ||
353 | if (creator) | ||
354 | partPermitted = true; | ||
355 | |||
356 | //string name = (objGroup.PrimCount == 1) ? objGroup.Name : string.Format("{0} ({1}/{2})", obj.Name, primNumber, objGroup.PrimCount); | ||
357 | //m_log.DebugFormat("[ARCHIVER]: Object permissions: {0}: Base={1:X4}, Owner={2:X4}, Everyone={3:X4}, permissionClass={4}, checkPermissions={5}, canCopy={6}, canTransfer={7}, creator={8}, permitted={9}", | ||
358 | // name, obj.BaseMask, obj.OwnerMask, obj.EveryoneMask, | ||
359 | // permissionClass, checkPermissions, canCopy, canTransfer, creator, partPermitted); | ||
360 | |||
361 | if (!partPermitted) | ||
362 | { | ||
363 | permitted = false; | ||
364 | break; | ||
365 | } | ||
366 | |||
367 | //++primNumber; | ||
368 | } | ||
369 | |||
370 | return permitted; | ||
371 | } | ||
372 | |||
373 | /// <summary> | ||
374 | /// Create the control file. | ||
375 | /// </summary> | ||
376 | /// <returns></returns> | ||
377 | public string CreateControlFile(ArchiveScenesGroup scenesGroup) | ||
378 | { | ||
379 | int majorVersion; | ||
380 | int minorVersion; | ||
381 | |||
382 | if (MultiRegionFormat) | ||
383 | { | ||
384 | majorVersion = MAX_MAJOR_VERSION; | ||
385 | minorVersion = 0; | ||
386 | } | ||
387 | else | ||
388 | { | ||
389 | // To support older versions of OpenSim, we continue to create single-region OARs | ||
390 | // using the old file format. In the future this format will be discontinued. | ||
391 | majorVersion = 0; | ||
392 | minorVersion = 8; | ||
393 | } | ||
394 | // | ||
395 | // if (m_options.ContainsKey("version")) | ||
396 | // { | ||
397 | // string[] parts = m_options["version"].ToString().Split('.'); | ||
398 | // if (parts.Length >= 1) | ||
399 | // { | ||
400 | // majorVersion = Int32.Parse(parts[0]); | ||
401 | // | ||
402 | // if (parts.Length >= 2) | ||
403 | // minorVersion = Int32.Parse(parts[1]); | ||
404 | // } | ||
405 | // } | ||
406 | // | ||
407 | // if (majorVersion < MIN_MAJOR_VERSION || majorVersion > MAX_MAJOR_VERSION) | ||
408 | // { | ||
409 | // throw new Exception( | ||
410 | // string.Format( | ||
411 | // "OAR version number for save must be between {0} and {1}", | ||
412 | // MIN_MAJOR_VERSION, MAX_MAJOR_VERSION)); | ||
413 | // } | ||
414 | // else if (majorVersion == MAX_MAJOR_VERSION) | ||
415 | // { | ||
416 | // // Force 1.0 | ||
417 | // minorVersion = 0; | ||
418 | // } | ||
419 | // else if (majorVersion == MIN_MAJOR_VERSION) | ||
420 | // { | ||
421 | // // Force 0.4 | ||
422 | // minorVersion = 4; | ||
423 | // } | ||
424 | |||
425 | m_log.InfoFormat("[ARCHIVER]: Creating version {0}.{1} OAR", majorVersion, minorVersion); | ||
426 | if (majorVersion == 1) | ||
427 | { | ||
428 | m_log.WarnFormat("[ARCHIVER]: Please be aware that version 1.0 OARs are not compatible with OpenSim versions prior to 0.7.4. Do not use the --all option if you want to produce a compatible OAR"); | ||
429 | } | ||
430 | |||
431 | String s; | ||
432 | |||
433 | using (StringWriter sw = new StringWriter()) | ||
434 | { | ||
435 | using (XmlTextWriter xtw = new XmlTextWriter(sw)) | ||
436 | { | ||
437 | xtw.Formatting = Formatting.Indented; | ||
438 | xtw.WriteStartDocument(); | ||
439 | xtw.WriteStartElement("archive"); | ||
440 | xtw.WriteAttributeString("major_version", majorVersion.ToString()); | ||
441 | xtw.WriteAttributeString("minor_version", minorVersion.ToString()); | ||
442 | |||
443 | xtw.WriteStartElement("creation_info"); | ||
444 | DateTime now = DateTime.UtcNow; | ||
445 | TimeSpan t = now - new DateTime(1970, 1, 1); | ||
446 | xtw.WriteElementString("datetime", ((int)t.TotalSeconds).ToString()); | ||
447 | if (!MultiRegionFormat) | ||
448 | xtw.WriteElementString("id", m_rootScene.RegionInfo.RegionID.ToString()); | ||
449 | xtw.WriteEndElement(); | ||
450 | |||
451 | xtw.WriteElementString("assets_included", SaveAssets.ToString()); | ||
452 | |||
453 | if (MultiRegionFormat) | ||
454 | { | ||
455 | WriteRegionsManifest(scenesGroup, xtw); | ||
456 | } | ||
457 | else | ||
458 | { | ||
459 | xtw.WriteStartElement("region_info"); | ||
460 | WriteRegionInfo(m_rootScene, xtw); | ||
461 | xtw.WriteEndElement(); | ||
462 | } | ||
463 | |||
464 | xtw.WriteEndElement(); | ||
465 | |||
466 | xtw.Flush(); | ||
467 | } | ||
468 | |||
469 | s = sw.ToString(); | ||
470 | } | ||
471 | |||
472 | return s; | ||
473 | } | ||
474 | |||
475 | /// <summary> | ||
476 | /// Writes the list of regions included in a multi-region OAR. | ||
477 | /// </summary> | ||
478 | private static void WriteRegionsManifest(ArchiveScenesGroup scenesGroup, XmlTextWriter xtw) | ||
479 | { | ||
480 | xtw.WriteStartElement("regions"); | ||
481 | |||
482 | // Write the regions in order: rows from South to North, then regions from West to East. | ||
483 | // The list of regions can have "holes"; we write empty elements in their position. | ||
484 | |||
485 | for (uint y = (uint)scenesGroup.Rect.Top; y < scenesGroup.Rect.Bottom; ++y) | ||
486 | { | ||
487 | SortedDictionary<uint, Scene> row; | ||
488 | if (scenesGroup.Regions.TryGetValue(y, out row)) | ||
489 | { | ||
490 | xtw.WriteStartElement("row"); | ||
491 | |||
492 | for (uint x = (uint)scenesGroup.Rect.Left; x < scenesGroup.Rect.Right; ++x) | ||
493 | { | ||
494 | Scene scene; | ||
495 | if (row.TryGetValue(x, out scene)) | ||
496 | { | ||
497 | xtw.WriteStartElement("region"); | ||
498 | xtw.WriteElementString("id", scene.RegionInfo.RegionID.ToString()); | ||
499 | xtw.WriteElementString("dir", scenesGroup.GetRegionDir(scene.RegionInfo.RegionID)); | ||
500 | WriteRegionInfo(scene, xtw); | ||
501 | xtw.WriteEndElement(); | ||
502 | } | ||
503 | else | ||
504 | { | ||
505 | // Write a placeholder for a missing region | ||
506 | xtw.WriteElementString("region", ""); | ||
507 | } | ||
508 | } | ||
509 | |||
510 | xtw.WriteEndElement(); | ||
511 | } | ||
512 | else | ||
513 | { | ||
514 | // Write a placeholder for a missing row | ||
515 | xtw.WriteElementString("row", ""); | ||
516 | } | ||
517 | } | ||
518 | |||
519 | xtw.WriteEndElement(); // "regions" | ||
520 | } | ||
521 | |||
522 | protected static void WriteRegionInfo(Scene scene, XmlTextWriter xtw) | ||
523 | { | ||
524 | bool isMegaregion; | ||
525 | Vector2 size; | ||
526 | |||
527 | IRegionCombinerModule rcMod = scene.RequestModuleInterface<IRegionCombinerModule>(); | ||
528 | |||
529 | if (rcMod != null) | ||
530 | isMegaregion = rcMod.IsRootForMegaregion(scene.RegionInfo.RegionID); | ||
531 | else | ||
532 | isMegaregion = false; | ||
533 | |||
534 | if (isMegaregion) | ||
535 | size = rcMod.GetSizeOfMegaregion(scene.RegionInfo.RegionID); | ||
536 | else | ||
537 | size = new Vector2((float)Constants.RegionSize, (float)Constants.RegionSize); | ||
538 | |||
539 | xtw.WriteElementString("is_megaregion", isMegaregion.ToString()); | ||
540 | xtw.WriteElementString("size_in_meters", string.Format("{0},{1}", size.X, size.Y)); | ||
541 | } | ||
542 | |||
543 | |||
544 | protected void Save(Scene scene, List<SceneObjectGroup> sceneObjects, string regionDir) | ||
545 | { | ||
546 | if (regionDir != string.Empty) | ||
547 | regionDir = ArchiveConstants.REGIONS_PATH + regionDir + "/"; | ||
548 | |||
549 | m_log.InfoFormat("[ARCHIVER]: Adding region settings to archive."); | ||
550 | |||
551 | // Write out region settings | ||
552 | string settingsPath = String.Format("{0}{1}{2}.xml", | ||
553 | regionDir, ArchiveConstants.SETTINGS_PATH, scene.RegionInfo.RegionName); | ||
554 | m_archiveWriter.WriteFile(settingsPath, RegionSettingsSerializer.Serialize(scene.RegionInfo.RegionSettings)); | ||
555 | |||
556 | m_log.InfoFormat("[ARCHIVER]: Adding parcel settings to archive."); | ||
557 | |||
558 | // Write out land data (aka parcel) settings | ||
559 | List<ILandObject> landObjects = scene.LandChannel.AllParcels(); | ||
560 | foreach (ILandObject lo in landObjects) | ||
561 | { | ||
562 | LandData landData = lo.LandData; | ||
563 | string landDataPath = String.Format("{0}{1}{2}.xml", | ||
564 | regionDir, ArchiveConstants.LANDDATA_PATH, landData.GlobalID.ToString()); | ||
565 | m_archiveWriter.WriteFile(landDataPath, LandDataSerializer.Serialize(landData, m_options)); | ||
566 | } | ||
567 | |||
568 | m_log.InfoFormat("[ARCHIVER]: Adding terrain information to archive."); | ||
569 | |||
570 | // Write out terrain | ||
571 | string terrainPath = String.Format("{0}{1}{2}.r32", | ||
572 | regionDir, ArchiveConstants.TERRAINS_PATH, scene.RegionInfo.RegionName); | ||
573 | |||
574 | MemoryStream ms = new MemoryStream(); | ||
575 | scene.RequestModuleInterface<ITerrainModule>().SaveToStream(terrainPath, ms); | ||
576 | m_archiveWriter.WriteFile(terrainPath, ms.ToArray()); | ||
577 | ms.Close(); | ||
578 | |||
579 | m_log.InfoFormat("[ARCHIVER]: Adding scene objects to archive."); | ||
580 | |||
581 | // Write out scene object metadata | ||
582 | IRegionSerialiserModule serializer = scene.RequestModuleInterface<IRegionSerialiserModule>(); | ||
583 | foreach (SceneObjectGroup sceneObject in sceneObjects) | ||
584 | { | ||
585 | //m_log.DebugFormat("[ARCHIVER]: Saving {0} {1}, {2}", entity.Name, entity.UUID, entity.GetType()); | ||
586 | |||
587 | string serializedObject = serializer.SerializeGroupToXml2(sceneObject, m_options); | ||
588 | string objectPath = string.Format("{0}{1}", regionDir, ArchiveHelpers.CreateObjectPath(sceneObject)); | ||
589 | m_archiveWriter.WriteFile(objectPath, serializedObject); | ||
590 | } | ||
591 | } | ||
592 | |||
593 | protected void ReceivedAllAssets( | ||
594 | ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids) | ||
595 | { | ||
596 | foreach (UUID uuid in assetsNotFoundUuids) | ||
597 | { | ||
598 | m_log.DebugFormat("[ARCHIVER]: Could not find asset {0}", uuid); | ||
599 | } | ||
600 | |||
601 | // m_log.InfoFormat( | ||
602 | // "[ARCHIVER]: Received {0} of {1} assets requested", | ||
603 | // assetsFoundUuids.Count, assetsFoundUuids.Count + assetsNotFoundUuids.Count); | ||
604 | |||
605 | CloseArchive(String.Empty); | ||
606 | } | ||
607 | |||
608 | |||
609 | /// <summary> | ||
610 | /// Closes the archive and notifies that we're done. | ||
611 | /// </summary> | ||
612 | /// <param name="errorMessage">The error that occurred, or empty for success</param> | ||
613 | protected void CloseArchive(string errorMessage) | ||
614 | { | ||
615 | try | ||
616 | { | ||
617 | if (m_archiveWriter != null) | ||
618 | m_archiveWriter.Close(); | ||
619 | m_saveStream.Close(); | ||
620 | } | ||
621 | catch (Exception e) | ||
622 | { | ||
623 | m_log.Error(string.Format("[ARCHIVER]: Error closing archive: {0} ", e.Message), e); | ||
624 | if (errorMessage == string.Empty) | ||
625 | errorMessage = e.Message; | ||
626 | } | ||
627 | |||
628 | m_log.InfoFormat("[ARCHIVER]: Finished writing out OAR for {0}", m_rootScene.RegionInfo.RegionName); | ||
629 | |||
630 | m_rootScene.EventManager.TriggerOarFileSaved(m_requestId, errorMessage); | ||
631 | } | ||
632 | |||
633 | } | ||
634 | } | ||
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs new file mode 100644 index 0000000..0780d86 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs | |||
@@ -0,0 +1,153 @@ | |||
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 | using System.Collections.Generic; | ||
30 | using System.IO; | ||
31 | using System.Reflection; | ||
32 | using System.Xml; | ||
33 | using log4net; | ||
34 | using OpenMetaverse; | ||
35 | using OpenSim.Framework; | ||
36 | using OpenSim.Framework.Serialization; | ||
37 | using OpenSim.Framework.Serialization.External; | ||
38 | using OpenSim.Region.CoreModules.World.Terrain; | ||
39 | using OpenSim.Region.Framework.Interfaces; | ||
40 | using OpenSim.Region.Framework.Scenes; | ||
41 | |||
42 | namespace OpenSim.Region.CoreModules.World.Archiver | ||
43 | { | ||
44 | /// <summary> | ||
45 | /// Method called when all the necessary assets for an archive request have been received. | ||
46 | /// </summary> | ||
47 | public delegate void AssetsRequestCallback( | ||
48 | ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids); | ||
49 | |||
50 | /// <summary> | ||
51 | /// Execute the write of an archive once we have received all the necessary data | ||
52 | /// </summary> | ||
53 | public class ArchiveWriteRequestExecution | ||
54 | { | ||
55 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
56 | |||
57 | protected ITerrainModule m_terrainModule; | ||
58 | protected IRegionSerialiserModule m_serialiser; | ||
59 | protected List<SceneObjectGroup> m_sceneObjects; | ||
60 | protected Scene m_scene; | ||
61 | protected TarArchiveWriter m_archiveWriter; | ||
62 | protected Guid m_requestId; | ||
63 | protected Dictionary<string, object> m_options; | ||
64 | |||
65 | public ArchiveWriteRequestExecution( | ||
66 | List<SceneObjectGroup> sceneObjects, | ||
67 | ITerrainModule terrainModule, | ||
68 | IRegionSerialiserModule serialiser, | ||
69 | Scene scene, | ||
70 | TarArchiveWriter archiveWriter, | ||
71 | Guid requestId, | ||
72 | Dictionary<string, object> options) | ||
73 | { | ||
74 | m_sceneObjects = sceneObjects; | ||
75 | m_terrainModule = terrainModule; | ||
76 | m_serialiser = serialiser; | ||
77 | m_scene = scene; | ||
78 | m_archiveWriter = archiveWriter; | ||
79 | m_requestId = requestId; | ||
80 | m_options = options; | ||
81 | } | ||
82 | |||
83 | protected internal void ReceivedAllAssets( | ||
84 | ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids) | ||
85 | { | ||
86 | try | ||
87 | { | ||
88 | Save(assetsFoundUuids, assetsNotFoundUuids); | ||
89 | } | ||
90 | finally | ||
91 | { | ||
92 | m_archiveWriter.Close(); | ||
93 | } | ||
94 | |||
95 | m_log.InfoFormat("[ARCHIVER]: Finished writing out OAR for {0}", m_scene.RegionInfo.RegionName); | ||
96 | |||
97 | m_scene.EventManager.TriggerOarFileSaved(m_requestId, String.Empty); | ||
98 | } | ||
99 | |||
100 | protected internal void Save(ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids) | ||
101 | { | ||
102 | foreach (UUID uuid in assetsNotFoundUuids) | ||
103 | { | ||
104 | m_log.DebugFormat("[ARCHIVER]: Could not find asset {0}", uuid); | ||
105 | } | ||
106 | |||
107 | // m_log.InfoFormat( | ||
108 | // "[ARCHIVER]: Received {0} of {1} assets requested", | ||
109 | // assetsFoundUuids.Count, assetsFoundUuids.Count + assetsNotFoundUuids.Count); | ||
110 | |||
111 | m_log.InfoFormat("[ARCHIVER]: Adding region settings to archive."); | ||
112 | |||
113 | // Write out region settings | ||
114 | string settingsPath | ||
115 | = String.Format("{0}{1}.xml", ArchiveConstants.SETTINGS_PATH, m_scene.RegionInfo.RegionName); | ||
116 | m_archiveWriter.WriteFile(settingsPath, RegionSettingsSerializer.Serialize(m_scene.RegionInfo.RegionSettings)); | ||
117 | |||
118 | m_log.InfoFormat("[ARCHIVER]: Adding parcel settings to archive."); | ||
119 | |||
120 | // Write out land data (aka parcel) settings | ||
121 | List<ILandObject>landObjects = m_scene.LandChannel.AllParcels(); | ||
122 | foreach (ILandObject lo in landObjects) | ||
123 | { | ||
124 | LandData landData = lo.LandData; | ||
125 | string landDataPath = String.Format("{0}{1}.xml", ArchiveConstants.LANDDATA_PATH, | ||
126 | landData.GlobalID.ToString()); | ||
127 | m_archiveWriter.WriteFile(landDataPath, LandDataSerializer.Serialize(landData, m_options)); | ||
128 | } | ||
129 | |||
130 | m_log.InfoFormat("[ARCHIVER]: Adding terrain information to archive."); | ||
131 | |||
132 | // Write out terrain | ||
133 | string terrainPath | ||
134 | = String.Format("{0}{1}.r32", ArchiveConstants.TERRAINS_PATH, m_scene.RegionInfo.RegionName); | ||
135 | |||
136 | MemoryStream ms = new MemoryStream(); | ||
137 | m_terrainModule.SaveToStream(terrainPath, ms); | ||
138 | m_archiveWriter.WriteFile(terrainPath, ms.ToArray()); | ||
139 | ms.Close(); | ||
140 | |||
141 | m_log.InfoFormat("[ARCHIVER]: Adding scene objects to archive."); | ||
142 | |||
143 | // Write out scene object metadata | ||
144 | foreach (SceneObjectGroup sceneObject in m_sceneObjects) | ||
145 | { | ||
146 | //m_log.DebugFormat("[ARCHIVER]: Saving {0} {1}, {2}", entity.Name, entity.UUID, entity.GetType()); | ||
147 | |||
148 | string serializedObject = m_serialiser.SerializeGroupToXml2(sceneObject, m_options); | ||
149 | m_archiveWriter.WriteFile(ArchiveHelpers.CreateObjectPath(sceneObject), serializedObject); | ||
150 | } | ||
151 | } | ||
152 | } | ||
153 | } \ No newline at end of file | ||
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs new file mode 100644 index 0000000..4edaaca --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs | |||
@@ -0,0 +1,438 @@ | |||
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 | using System.Collections.Generic; | ||
30 | using System.IO; | ||
31 | using System.IO.Compression; | ||
32 | using System.Reflection; | ||
33 | using System.Text.RegularExpressions; | ||
34 | using System.Threading; | ||
35 | using System.Xml; | ||
36 | using log4net; | ||
37 | using OpenMetaverse; | ||
38 | using OpenSim.Framework; | ||
39 | using OpenSim.Framework.Serialization; | ||
40 | using OpenSim.Region.CoreModules.World.Terrain; | ||
41 | using OpenSim.Region.Framework.Interfaces; | ||
42 | using OpenSim.Region.Framework.Scenes; | ||
43 | using Ionic.Zlib; | ||
44 | using GZipStream = Ionic.Zlib.GZipStream; | ||
45 | using CompressionMode = Ionic.Zlib.CompressionMode; | ||
46 | |||
47 | namespace OpenSim.Region.CoreModules.World.Archiver | ||
48 | { | ||
49 | /// <summary> | ||
50 | /// Prepare to write out an archive. | ||
51 | /// </summary> | ||
52 | public class ArchiveWriteRequestPreparation | ||
53 | { | ||
54 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
55 | |||
56 | /// <summary> | ||
57 | /// The minimum major version of OAR that we can write. | ||
58 | /// </summary> | ||
59 | public static int MIN_MAJOR_VERSION = 0; | ||
60 | |||
61 | /// <summary> | ||
62 | /// The maximum major version of OAR that we can write. | ||
63 | /// </summary> | ||
64 | public static int MAX_MAJOR_VERSION = 0; | ||
65 | |||
66 | /// <summary> | ||
67 | /// Determine whether this archive will save assets. Default is true. | ||
68 | /// </summary> | ||
69 | public bool SaveAssets { get; set; } | ||
70 | |||
71 | protected ArchiverModule m_module; | ||
72 | protected Scene m_scene; | ||
73 | protected Stream m_saveStream; | ||
74 | protected Guid m_requestId; | ||
75 | |||
76 | /// <summary> | ||
77 | /// Constructor | ||
78 | /// </summary> | ||
79 | /// <param name="module">Calling module</param> | ||
80 | /// <param name="savePath">The path to which to save data.</param> | ||
81 | /// <param name="requestId">The id associated with this request</param> | ||
82 | /// <exception cref="System.IO.IOException"> | ||
83 | /// If there was a problem opening a stream for the file specified by the savePath | ||
84 | /// </exception> | ||
85 | public ArchiveWriteRequestPreparation(ArchiverModule module, string savePath, Guid requestId) : this(module, requestId) | ||
86 | { | ||
87 | try | ||
88 | { | ||
89 | m_saveStream = new GZipStream(new FileStream(savePath, FileMode.Create), CompressionMode.Compress, CompressionLevel.BestCompression); | ||
90 | } | ||
91 | catch (EntryPointNotFoundException e) | ||
92 | { | ||
93 | m_log.ErrorFormat( | ||
94 | "[ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream." | ||
95 | + "If you've manually installed Mono, have you appropriately updated zlib1g as well?"); | ||
96 | m_log.ErrorFormat("{0} {1}", e.Message, e.StackTrace); | ||
97 | } | ||
98 | } | ||
99 | |||
100 | /// <summary> | ||
101 | /// Constructor. | ||
102 | /// </summary> | ||
103 | /// <param name="module">Calling module</param> | ||
104 | /// <param name="saveStream">The stream to which to save data.</param> | ||
105 | /// <param name="requestId">The id associated with this request</param> | ||
106 | public ArchiveWriteRequestPreparation(ArchiverModule module, Stream saveStream, Guid requestId) : this(module, requestId) | ||
107 | { | ||
108 | m_saveStream = saveStream; | ||
109 | } | ||
110 | |||
111 | protected ArchiveWriteRequestPreparation(ArchiverModule module, Guid requestId) | ||
112 | { | ||
113 | m_module = module; | ||
114 | |||
115 | // FIXME: This is only here for regression test purposes since they do not supply a module. Need to fix | ||
116 | // this. | ||
117 | if (m_module != null) | ||
118 | m_scene = m_module.Scene; | ||
119 | |||
120 | m_requestId = requestId; | ||
121 | |||
122 | SaveAssets = true; | ||
123 | } | ||
124 | |||
125 | /// <summary> | ||
126 | /// Archive the region requested. | ||
127 | /// </summary> | ||
128 | /// <exception cref="System.IO.IOException">if there was an io problem with creating the file</exception> | ||
129 | public void ArchiveRegion(Dictionary<string, object> options) | ||
130 | { | ||
131 | if (options.ContainsKey("noassets") && (bool)options["noassets"]) | ||
132 | SaveAssets = false; | ||
133 | |||
134 | try | ||
135 | { | ||
136 | Dictionary<UUID, AssetType> assetUuids = new Dictionary<UUID, AssetType>(); | ||
137 | |||
138 | EntityBase[] entities = m_scene.GetEntities(); | ||
139 | List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>(); | ||
140 | |||
141 | string checkPermissions = null; | ||
142 | int numObjectsSkippedPermissions = 0; | ||
143 | Object temp; | ||
144 | if (options.TryGetValue("checkPermissions", out temp)) | ||
145 | checkPermissions = (string)temp; | ||
146 | |||
147 | // Filter entities so that we only have scene objects. | ||
148 | // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods | ||
149 | // end up having to do this | ||
150 | foreach (EntityBase entity in entities) | ||
151 | { | ||
152 | if (entity is SceneObjectGroup) | ||
153 | { | ||
154 | SceneObjectGroup sceneObject = (SceneObjectGroup)entity; | ||
155 | |||
156 | if (!sceneObject.IsDeleted && !sceneObject.IsAttachment) | ||
157 | { | ||
158 | if (!CanUserArchiveObject(m_scene.RegionInfo.EstateSettings.EstateOwner, sceneObject, checkPermissions)) | ||
159 | { | ||
160 | // The user isn't allowed to copy/transfer this object, so it will not be included in the OAR. | ||
161 | ++numObjectsSkippedPermissions; | ||
162 | } | ||
163 | else | ||
164 | { | ||
165 | sceneObjects.Add(sceneObject); | ||
166 | } | ||
167 | } | ||
168 | } | ||
169 | } | ||
170 | |||
171 | if (SaveAssets) | ||
172 | { | ||
173 | UuidGatherer assetGatherer = new UuidGatherer(m_scene.AssetService); | ||
174 | |||
175 | foreach (SceneObjectGroup sceneObject in sceneObjects) | ||
176 | { | ||
177 | assetGatherer.GatherAssetUuids(sceneObject, assetUuids); | ||
178 | } | ||
179 | |||
180 | m_log.DebugFormat( | ||
181 | "[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets", | ||
182 | sceneObjects.Count, assetUuids.Count); | ||
183 | } | ||
184 | else | ||
185 | { | ||
186 | m_log.DebugFormat("[ARCHIVER]: Not saving assets since --noassets was specified"); | ||
187 | } | ||
188 | |||
189 | if (numObjectsSkippedPermissions > 0) | ||
190 | { | ||
191 | m_log.DebugFormat( | ||
192 | "[ARCHIVER]: {0} scene objects skipped due to lack of permissions", | ||
193 | numObjectsSkippedPermissions); | ||
194 | } | ||
195 | |||
196 | // Make sure that we also request terrain texture assets | ||
197 | RegionSettings regionSettings = m_scene.RegionInfo.RegionSettings; | ||
198 | |||
199 | if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1) | ||
200 | assetUuids[regionSettings.TerrainTexture1] = AssetType.Texture; | ||
201 | |||
202 | if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2) | ||
203 | assetUuids[regionSettings.TerrainTexture2] = AssetType.Texture; | ||
204 | |||
205 | if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3) | ||
206 | assetUuids[regionSettings.TerrainTexture3] = AssetType.Texture; | ||
207 | |||
208 | if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4) | ||
209 | assetUuids[regionSettings.TerrainTexture4] = AssetType.Texture; | ||
210 | |||
211 | TarArchiveWriter archiveWriter = new TarArchiveWriter(m_saveStream); | ||
212 | |||
213 | // Asynchronously request all the assets required to perform this archive operation | ||
214 | ArchiveWriteRequestExecution awre | ||
215 | = new ArchiveWriteRequestExecution( | ||
216 | sceneObjects, | ||
217 | m_scene.RequestModuleInterface<ITerrainModule>(), | ||
218 | m_scene.RequestModuleInterface<IRegionSerialiserModule>(), | ||
219 | m_scene, | ||
220 | archiveWriter, | ||
221 | m_requestId, | ||
222 | options); | ||
223 | |||
224 | m_log.InfoFormat("[ARCHIVER]: Creating archive file. This may take some time."); | ||
225 | |||
226 | // Write out control file. This has to be done first so that subsequent loaders will see this file first | ||
227 | // XXX: I know this is a weak way of doing it since external non-OAR aware tar executables will not do this | ||
228 | archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, CreateControlFile(options)); | ||
229 | m_log.InfoFormat("[ARCHIVER]: Added control file to archive."); | ||
230 | |||
231 | if (SaveAssets) | ||
232 | { | ||
233 | AssetsRequest ar | ||
234 | = new AssetsRequest( | ||
235 | new AssetsArchiver(archiveWriter), assetUuids, | ||
236 | m_scene.AssetService, m_scene.UserAccountService, | ||
237 | m_scene.RegionInfo.ScopeID, options, awre.ReceivedAllAssets); | ||
238 | |||
239 | Util.FireAndForget(o => ar.Execute()); | ||
240 | } | ||
241 | else | ||
242 | { | ||
243 | awre.ReceivedAllAssets(new List<UUID>(), new List<UUID>()); | ||
244 | } | ||
245 | } | ||
246 | catch (Exception) | ||
247 | { | ||
248 | m_saveStream.Close(); | ||
249 | throw; | ||
250 | } | ||
251 | } | ||
252 | |||
253 | /// <summary> | ||
254 | /// Checks whether the user has permission to export an object group to an OAR. | ||
255 | /// </summary> | ||
256 | /// <param name="user">The user</param> | ||
257 | /// <param name="objGroup">The object group</param> | ||
258 | /// <param name="checkPermissions">Which permissions to check: "C" = Copy, "T" = Transfer</param> | ||
259 | /// <returns>Whether the user is allowed to export the object to an OAR</returns> | ||
260 | private bool CanUserArchiveObject(UUID user, SceneObjectGroup objGroup, string checkPermissions) | ||
261 | { | ||
262 | if (checkPermissions == null) | ||
263 | return true; | ||
264 | |||
265 | IPermissionsModule module = m_scene.RequestModuleInterface<IPermissionsModule>(); | ||
266 | if (module == null) | ||
267 | return true; // this shouldn't happen | ||
268 | |||
269 | // Check whether the user is permitted to export all of the parts in the SOG. If any | ||
270 | // part can't be exported then the entire SOG can't be exported. | ||
271 | |||
272 | bool permitted = true; | ||
273 | //int primNumber = 1; | ||
274 | |||
275 | foreach (SceneObjectPart obj in objGroup.Parts) | ||
276 | { | ||
277 | uint perm; | ||
278 | PermissionClass permissionClass = module.GetPermissionClass(user, obj); | ||
279 | switch (permissionClass) | ||
280 | { | ||
281 | case PermissionClass.Owner: | ||
282 | perm = obj.BaseMask; | ||
283 | break; | ||
284 | case PermissionClass.Group: | ||
285 | perm = obj.GroupMask | obj.EveryoneMask; | ||
286 | break; | ||
287 | case PermissionClass.Everyone: | ||
288 | default: | ||
289 | perm = obj.EveryoneMask; | ||
290 | break; | ||
291 | } | ||
292 | |||
293 | bool canCopy = (perm & (uint)PermissionMask.Copy) != 0; | ||
294 | bool canTransfer = (perm & (uint)PermissionMask.Transfer) != 0; | ||
295 | |||
296 | // Special case: if Everyone can copy the object then this implies it can also be | ||
297 | // Transferred. | ||
298 | // However, if the user is the Owner then we don't check EveryoneMask, because it seems that the mask | ||
299 | // always (incorrectly) includes the Copy bit set in this case. But that's a mistake: the viewer | ||
300 | // does NOT show that the object has Everyone-Copy permissions, and doesn't allow it to be copied. | ||
301 | if (permissionClass != PermissionClass.Owner) | ||
302 | canTransfer |= (obj.EveryoneMask & (uint)PermissionMask.Copy) != 0; | ||
303 | |||
304 | bool partPermitted = true; | ||
305 | if (checkPermissions.Contains("C") && !canCopy) | ||
306 | partPermitted = false; | ||
307 | if (checkPermissions.Contains("T") && !canTransfer) | ||
308 | partPermitted = false; | ||
309 | |||
310 | // If the user is the Creator of the object then it can always be included in the OAR | ||
311 | bool creator = (obj.CreatorID.Guid == user.Guid); | ||
312 | if (creator) | ||
313 | partPermitted = true; | ||
314 | |||
315 | //string name = (objGroup.PrimCount == 1) ? objGroup.Name : string.Format("{0} ({1}/{2})", obj.Name, primNumber, objGroup.PrimCount); | ||
316 | //m_log.DebugFormat("[ARCHIVER]: Object permissions: {0}: Base={1:X4}, Owner={2:X4}, Everyone={3:X4}, permissionClass={4}, checkPermissions={5}, canCopy={6}, canTransfer={7}, creator={8}, permitted={9}", | ||
317 | // name, obj.BaseMask, obj.OwnerMask, obj.EveryoneMask, | ||
318 | // permissionClass, checkPermissions, canCopy, canTransfer, creator, partPermitted); | ||
319 | |||
320 | if (!partPermitted) | ||
321 | { | ||
322 | permitted = false; | ||
323 | break; | ||
324 | } | ||
325 | |||
326 | //++primNumber; | ||
327 | } | ||
328 | |||
329 | return permitted; | ||
330 | } | ||
331 | |||
332 | /// <summary> | ||
333 | /// Create the control file for the most up to date archive | ||
334 | /// </summary> | ||
335 | /// <returns></returns> | ||
336 | public string CreateControlFile(Dictionary<string, object> options) | ||
337 | { | ||
338 | int majorVersion = MAX_MAJOR_VERSION, minorVersion = 8; | ||
339 | // | ||
340 | // if (options.ContainsKey("version")) | ||
341 | // { | ||
342 | // string[] parts = options["version"].ToString().Split('.'); | ||
343 | // if (parts.Length >= 1) | ||
344 | // { | ||
345 | // majorVersion = Int32.Parse(parts[0]); | ||
346 | // | ||
347 | // if (parts.Length >= 2) | ||
348 | // minorVersion = Int32.Parse(parts[1]); | ||
349 | // } | ||
350 | // } | ||
351 | // | ||
352 | // if (majorVersion < MIN_MAJOR_VERSION || majorVersion > MAX_MAJOR_VERSION) | ||
353 | // { | ||
354 | // throw new Exception( | ||
355 | // string.Format( | ||
356 | // "OAR version number for save must be between {0} and {1}", | ||
357 | // MIN_MAJOR_VERSION, MAX_MAJOR_VERSION)); | ||
358 | // } | ||
359 | // else if (majorVersion == MAX_MAJOR_VERSION) | ||
360 | // { | ||
361 | // // Force 1.0 | ||
362 | // minorVersion = 0; | ||
363 | // } | ||
364 | // else if (majorVersion == MIN_MAJOR_VERSION) | ||
365 | // { | ||
366 | // // Force 0.4 | ||
367 | // minorVersion = 4; | ||
368 | // } | ||
369 | |||
370 | m_log.InfoFormat("[ARCHIVER]: Creating version {0}.{1} OAR", majorVersion, minorVersion); | ||
371 | //if (majorVersion == 1) | ||
372 | //{ | ||
373 | // m_log.WarnFormat("[ARCHIVER]: Please be aware that version 1.0 OARs are not compatible with OpenSim 0.7.0.2 and earlier. Please use the --version=0 option if you want to produce a compatible OAR"); | ||
374 | //} | ||
375 | |||
376 | String s; | ||
377 | |||
378 | using (StringWriter sw = new StringWriter()) | ||
379 | { | ||
380 | using (XmlTextWriter xtw = new XmlTextWriter(sw)) | ||
381 | { | ||
382 | xtw.Formatting = Formatting.Indented; | ||
383 | xtw.WriteStartDocument(); | ||
384 | xtw.WriteStartElement("archive"); | ||
385 | xtw.WriteAttributeString("major_version", majorVersion.ToString()); | ||
386 | xtw.WriteAttributeString("minor_version", minorVersion.ToString()); | ||
387 | |||
388 | xtw.WriteStartElement("creation_info"); | ||
389 | DateTime now = DateTime.UtcNow; | ||
390 | TimeSpan t = now - new DateTime(1970, 1, 1); | ||
391 | xtw.WriteElementString("datetime", ((int)t.TotalSeconds).ToString()); | ||
392 | xtw.WriteElementString("id", UUID.Random().ToString()); | ||
393 | xtw.WriteEndElement(); | ||
394 | |||
395 | xtw.WriteStartElement("region_info"); | ||
396 | |||
397 | bool isMegaregion; | ||
398 | Vector2 size; | ||
399 | IRegionCombinerModule rcMod = null; | ||
400 | |||
401 | // FIXME: This is only here for regression test purposes since they do not supply a module. Need to fix | ||
402 | // this, possibly by doing control file creation somewhere else. | ||
403 | if (m_module != null) | ||
404 | rcMod = m_module.RegionCombinerModule; | ||
405 | |||
406 | if (rcMod != null) | ||
407 | isMegaregion = rcMod.IsRootForMegaregion(m_scene.RegionInfo.RegionID); | ||
408 | else | ||
409 | isMegaregion = false; | ||
410 | |||
411 | if (isMegaregion) | ||
412 | size = rcMod.GetSizeOfMegaregion(m_scene.RegionInfo.RegionID); | ||
413 | else | ||
414 | size = new Vector2((float)Constants.RegionSize, (float)Constants.RegionSize); | ||
415 | |||
416 | xtw.WriteElementString("is_megaregion", isMegaregion.ToString()); | ||
417 | xtw.WriteElementString("size_in_meters", string.Format("{0},{1}", size.X, size.Y)); | ||
418 | |||
419 | xtw.WriteEndElement(); | ||
420 | |||
421 | xtw.WriteElementString("assets_included", SaveAssets.ToString()); | ||
422 | |||
423 | xtw.WriteEndElement(); | ||
424 | |||
425 | xtw.Flush(); | ||
426 | } | ||
427 | |||
428 | s = sw.ToString(); | ||
429 | } | ||
430 | |||
431 | // if (m_scene != null) | ||
432 | // Console.WriteLine( | ||
433 | // "[ARCHIVE WRITE REQUEST PREPARATION]: Control file for {0} is: {1}", m_scene.RegionInfo.RegionName, s); | ||
434 | |||
435 | return s; | ||
436 | } | ||
437 | } | ||
438 | } | ||
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs index abf3713..bf3b124 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs | |||
@@ -32,8 +32,6 @@ using System.Reflection; | |||
32 | using log4net; | 32 | using log4net; |
33 | using NDesk.Options; | 33 | using NDesk.Options; |
34 | using Nini.Config; | 34 | using Nini.Config; |
35 | using OpenSim.Framework; | ||
36 | using OpenSim.Framework.Console; | ||
37 | using OpenSim.Region.Framework.Interfaces; | 35 | using OpenSim.Region.Framework.Interfaces; |
38 | using OpenSim.Region.Framework.Scenes; | 36 | using OpenSim.Region.Framework.Scenes; |
39 | 37 | ||
@@ -119,7 +117,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
119 | // | 117 | // |
120 | // foreach (string param in mainParams) | 118 | // foreach (string param in mainParams) |
121 | // m_log.DebugFormat("GOT PARAM [{0}]", param); | 119 | // m_log.DebugFormat("GOT PARAM [{0}]", param); |
122 | 120 | ||
123 | if (mainParams.Count > 2) | 121 | if (mainParams.Count > 2) |
124 | { | 122 | { |
125 | DearchiveRegion(mainParams[2], mergeOar, skipAssets, Guid.Empty); | 123 | DearchiveRegion(mainParams[2], mergeOar, skipAssets, Guid.Empty); |
@@ -148,22 +146,17 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
148 | ops.Add("noassets", delegate(string v) { options["noassets"] = v != null; }); | 146 | ops.Add("noassets", delegate(string v) { options["noassets"] = v != null; }); |
149 | ops.Add("publish", v => options["wipe-owners"] = v != null); | 147 | ops.Add("publish", v => options["wipe-owners"] = v != null); |
150 | ops.Add("perm=", delegate(string v) { options["checkPermissions"] = v; }); | 148 | ops.Add("perm=", delegate(string v) { options["checkPermissions"] = v; }); |
151 | ops.Add("all", delegate(string v) { options["all"] = v != null; }); | ||
152 | 149 | ||
153 | List<string> mainParams = ops.Parse(cmdparams); | 150 | List<string> mainParams = ops.Parse(cmdparams); |
154 | 151 | ||
155 | string path; | ||
156 | if (mainParams.Count > 2) | 152 | if (mainParams.Count > 2) |
157 | path = mainParams[2]; | 153 | { |
154 | ArchiveRegion(mainParams[2], options); | ||
155 | } | ||
158 | else | 156 | else |
159 | path = DEFAULT_OAR_BACKUP_FILENAME; | 157 | { |
160 | 158 | ArchiveRegion(DEFAULT_OAR_BACKUP_FILENAME, options); | |
161 | // Not doing this right now as this causes some problems with auto-backup systems. Maybe a force flag is | 159 | } |
162 | // needed | ||
163 | // if (!ConsoleUtil.CheckFileDoesNotExist(MainConsole.Instance, path)) | ||
164 | // return; | ||
165 | |||
166 | ArchiveRegion(path, options); | ||
167 | } | 160 | } |
168 | 161 | ||
169 | public void ArchiveRegion(string savePath, Dictionary<string, object> options) | 162 | public void ArchiveRegion(string savePath, Dictionary<string, object> options) |
@@ -176,7 +169,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
176 | m_log.InfoFormat( | 169 | m_log.InfoFormat( |
177 | "[ARCHIVER]: Writing archive for region {0} to {1}", Scene.RegionInfo.RegionName, savePath); | 170 | "[ARCHIVER]: Writing archive for region {0} to {1}", Scene.RegionInfo.RegionName, savePath); |
178 | 171 | ||
179 | new ArchiveWriteRequest(Scene, savePath, requestId).ArchiveRegion(options); | 172 | new ArchiveWriteRequestPreparation(this, savePath, requestId).ArchiveRegion(options); |
180 | } | 173 | } |
181 | 174 | ||
182 | public void ArchiveRegion(Stream saveStream) | 175 | public void ArchiveRegion(Stream saveStream) |
@@ -191,7 +184,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
191 | 184 | ||
192 | public void ArchiveRegion(Stream saveStream, Guid requestId, Dictionary<string, object> options) | 185 | public void ArchiveRegion(Stream saveStream, Guid requestId, Dictionary<string, object> options) |
193 | { | 186 | { |
194 | new ArchiveWriteRequest(Scene, saveStream, requestId).ArchiveRegion(options); | 187 | new ArchiveWriteRequestPreparation(this, saveStream, requestId).ArchiveRegion(options); |
195 | } | 188 | } |
196 | 189 | ||
197 | public void DearchiveRegion(string loadPath) | 190 | public void DearchiveRegion(string loadPath) |
diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs index e2f8833..89e9593 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs | |||
@@ -46,12 +46,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
46 | { | 46 | { |
47 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 47 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
48 | 48 | ||
49 | /// <summary> | ||
50 | /// Method called when all the necessary assets for an archive request have been received. | ||
51 | /// </summary> | ||
52 | public delegate void AssetsRequestCallback( | ||
53 | ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids); | ||
54 | |||
55 | enum RequestState | 49 | enum RequestState |
56 | { | 50 | { |
57 | Initial, | 51 | Initial, |
@@ -129,10 +123,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
129 | m_options = options; | 123 | m_options = options; |
130 | m_repliesRequired = uuids.Count; | 124 | m_repliesRequired = uuids.Count; |
131 | 125 | ||
132 | // FIXME: This is a really poor way of handling the timeout since it will always leave the original requesting thread | ||
133 | // hanging. Need to restructure so an original request thread waits for a ManualResetEvent on asset received | ||
134 | // so we can properly abort that thread. Or request all assets synchronously, though that would be a more | ||
135 | // radical change | ||
136 | m_requestCallbackTimer = new System.Timers.Timer(TIMEOUT); | 126 | m_requestCallbackTimer = new System.Timers.Timer(TIMEOUT); |
137 | m_requestCallbackTimer.AutoReset = false; | 127 | m_requestCallbackTimer.AutoReset = false; |
138 | m_requestCallbackTimer.Elapsed += new ElapsedEventHandler(OnRequestCallbackTimeout); | 128 | m_requestCallbackTimer.Elapsed += new ElapsedEventHandler(OnRequestCallbackTimeout); |
diff --git a/OpenSim/Region/CoreModules/World/Archiver/DearchiveScenesGroup.cs b/OpenSim/Region/CoreModules/World/Archiver/DearchiveScenesGroup.cs deleted file mode 100644 index 3dcc020..0000000 --- a/OpenSim/Region/CoreModules/World/Archiver/DearchiveScenesGroup.cs +++ /dev/null | |||
@@ -1,232 +0,0 @@ | |||
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 | using System.Collections.Generic; | ||
30 | using System.Linq; | ||
31 | using System.Text; | ||
32 | using OpenSim.Region.Framework.Scenes; | ||
33 | using OpenMetaverse; | ||
34 | using System.Drawing; | ||
35 | using log4net; | ||
36 | using System.Reflection; | ||
37 | using OpenSim.Framework.Serialization; | ||
38 | |||
39 | namespace OpenSim.Region.CoreModules.World.Archiver | ||
40 | { | ||
41 | /// <summary> | ||
42 | /// The regions included in an OAR file. | ||
43 | /// </summary> | ||
44 | public class DearchiveScenesInfo | ||
45 | { | ||
46 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
47 | |||
48 | /// <summary> | ||
49 | /// One region in the archive. | ||
50 | /// </summary> | ||
51 | public class RegionInfo | ||
52 | { | ||
53 | /// <summary> | ||
54 | /// The subdirectory in which the region is stored. | ||
55 | /// </summary> | ||
56 | public string Directory { get; set; } | ||
57 | |||
58 | /// <summary> | ||
59 | /// The region's coordinates (relative to the South-West corner of the block). | ||
60 | /// </summary> | ||
61 | public Point Location { get; set; } | ||
62 | |||
63 | /// <summary> | ||
64 | /// The UUID of the original scene from which this archived region was saved. | ||
65 | /// </summary> | ||
66 | public string OriginalID { get; set; } | ||
67 | |||
68 | /// <summary> | ||
69 | /// The scene in the current simulator into which this region is loaded. | ||
70 | /// If null then the region doesn't have a corresponding scene, and it won't be loaded. | ||
71 | /// </summary> | ||
72 | public Scene Scene { get; set; } | ||
73 | } | ||
74 | |||
75 | /// <summary> | ||
76 | /// Whether this archive uses the multi-region format. | ||
77 | /// </summary> | ||
78 | public Boolean MultiRegionFormat { get; set; } | ||
79 | |||
80 | /// <summary> | ||
81 | /// Maps (Region directory -> region) | ||
82 | /// </summary> | ||
83 | protected Dictionary<string, RegionInfo> m_directory2region = new Dictionary<string, RegionInfo>(); | ||
84 | |||
85 | /// <summary> | ||
86 | /// Maps (UUID of the scene in the simulator where the region will be loaded -> region) | ||
87 | /// </summary> | ||
88 | protected Dictionary<UUID, RegionInfo> m_newId2region = new Dictionary<UUID, RegionInfo>(); | ||
89 | |||
90 | public int LoadedCreationDateTime { get; set; } | ||
91 | public string DefaultOriginalID { get; set; } | ||
92 | |||
93 | // These variables are used while reading the archive control file | ||
94 | protected int? m_curY = null; | ||
95 | protected int? m_curX = null; | ||
96 | protected RegionInfo m_curRegion; | ||
97 | |||
98 | |||
99 | public DearchiveScenesInfo() | ||
100 | { | ||
101 | MultiRegionFormat = false; | ||
102 | } | ||
103 | |||
104 | |||
105 | // The following methods are used while reading the archive control file | ||
106 | |||
107 | public void StartRow() | ||
108 | { | ||
109 | m_curY = (m_curY == null) ? 0 : m_curY + 1; | ||
110 | m_curX = null; | ||
111 | } | ||
112 | |||
113 | public void StartRegion() | ||
114 | { | ||
115 | m_curX = (m_curX == null) ? 0 : m_curX + 1; | ||
116 | // Note: this doesn't mean we have a real region in this location; this could just be a "hole" | ||
117 | } | ||
118 | |||
119 | public void SetRegionOriginalID(string id) | ||
120 | { | ||
121 | m_curRegion = new RegionInfo(); | ||
122 | m_curRegion.Location = new Point((int)m_curX, (int)m_curY); | ||
123 | m_curRegion.OriginalID = id; | ||
124 | // 'curRegion' will be saved in 'm_directory2region' when SetRegionDir() is called | ||
125 | } | ||
126 | |||
127 | public void SetRegionDirectory(string directory) | ||
128 | { | ||
129 | m_curRegion.Directory = directory; | ||
130 | m_directory2region[directory] = m_curRegion; | ||
131 | } | ||
132 | |||
133 | |||
134 | /// <summary> | ||
135 | /// Sets all the scenes present in the simulator. | ||
136 | /// </summary> | ||
137 | /// <remarks> | ||
138 | /// This method matches regions in the archive to scenes in the simulator according to | ||
139 | /// their relative position. We only load regions if there's an existing Scene in the | ||
140 | /// grid location where the region should be loaded. | ||
141 | /// </remarks> | ||
142 | /// <param name="rootScene">The scene where the Load OAR operation was run</param> | ||
143 | /// <param name="simulatorScenes">All the scenes in the simulator</param> | ||
144 | public void SetSimulatorScenes(Scene rootScene, ArchiveScenesGroup simulatorScenes) | ||
145 | { | ||
146 | foreach (RegionInfo archivedRegion in m_directory2region.Values) | ||
147 | { | ||
148 | Point location = new Point((int)rootScene.RegionInfo.RegionLocX, (int)rootScene.RegionInfo.RegionLocY); | ||
149 | location.Offset(archivedRegion.Location); | ||
150 | |||
151 | Scene scene; | ||
152 | if (simulatorScenes.TryGetScene(location, out scene)) | ||
153 | { | ||
154 | archivedRegion.Scene = scene; | ||
155 | m_newId2region[scene.RegionInfo.RegionID] = archivedRegion; | ||
156 | } | ||
157 | else | ||
158 | { | ||
159 | m_log.WarnFormat("[ARCHIVER]: Not loading archived region {0} because there's no existing region at location {1},{2}", | ||
160 | archivedRegion.Directory, location.X, location.Y); | ||
161 | } | ||
162 | } | ||
163 | } | ||
164 | |||
165 | /// <summary> | ||
166 | /// Returns the archived region according to the path of a file in the archive. | ||
167 | /// Also, converts the full path into a path that is relative to the region's directory. | ||
168 | /// </summary> | ||
169 | /// <param name="fullPath">The path of a file in the archive</param> | ||
170 | /// <param name="scene">The corresponding Scene, or null if none</param> | ||
171 | /// <param name="relativePath">The path relative to the region's directory. (Or the original | ||
172 | /// path, if this file doesn't belong to a region.)</param> | ||
173 | /// <returns>True: use this file; False: skip it</returns> | ||
174 | public bool GetRegionFromPath(string fullPath, out Scene scene, out string relativePath) | ||
175 | { | ||
176 | scene = null; | ||
177 | relativePath = fullPath; | ||
178 | |||
179 | if (!MultiRegionFormat) | ||
180 | { | ||
181 | if (m_newId2region.Count > 0) | ||
182 | scene = m_newId2region.First().Value.Scene; | ||
183 | return true; | ||
184 | } | ||
185 | |||
186 | if (!fullPath.StartsWith(ArchiveConstants.REGIONS_PATH)) | ||
187 | return true; // this file doesn't belong to a region | ||
188 | |||
189 | string[] parts = fullPath.Split(new Char[] { '/' }, 3); | ||
190 | if (parts.Length != 3) | ||
191 | return false; | ||
192 | string regionDirectory = parts[1]; | ||
193 | relativePath = parts[2]; | ||
194 | |||
195 | RegionInfo region; | ||
196 | if (m_directory2region.TryGetValue(regionDirectory, out region)) | ||
197 | { | ||
198 | scene = region.Scene; | ||
199 | return (scene != null); | ||
200 | } | ||
201 | else | ||
202 | { | ||
203 | return false; | ||
204 | } | ||
205 | } | ||
206 | |||
207 | /// <summary> | ||
208 | /// Returns the original UUID of a region (from the simulator where the OAR was saved), | ||
209 | /// given the UUID of the scene it was loaded into in the current simulator. | ||
210 | /// </summary> | ||
211 | /// <param name="newID"></param> | ||
212 | /// <returns></returns> | ||
213 | public string GetOriginalRegionID(UUID newID) | ||
214 | { | ||
215 | RegionInfo region; | ||
216 | if (m_newId2region.TryGetValue(newID, out region)) | ||
217 | return region.OriginalID; | ||
218 | else | ||
219 | return DefaultOriginalID; | ||
220 | } | ||
221 | |||
222 | /// <summary> | ||
223 | /// Returns the scenes that have been (or will be) loaded. | ||
224 | /// </summary> | ||
225 | /// <returns></returns> | ||
226 | public List<UUID> GetLoadedScenes() | ||
227 | { | ||
228 | return m_newId2region.Keys.ToList(); | ||
229 | } | ||
230 | |||
231 | } | ||
232 | } | ||
diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs index 82f49b0..5deaf52 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs | |||
@@ -47,41 +47,32 @@ using ArchiveConstants = OpenSim.Framework.Serialization.ArchiveConstants; | |||
47 | using TarArchiveReader = OpenSim.Framework.Serialization.TarArchiveReader; | 47 | using TarArchiveReader = OpenSim.Framework.Serialization.TarArchiveReader; |
48 | using TarArchiveWriter = OpenSim.Framework.Serialization.TarArchiveWriter; | 48 | using TarArchiveWriter = OpenSim.Framework.Serialization.TarArchiveWriter; |
49 | using RegionSettings = OpenSim.Framework.RegionSettings; | 49 | using RegionSettings = OpenSim.Framework.RegionSettings; |
50 | using OpenSim.Region.Framework.Interfaces; | ||
51 | 50 | ||
52 | namespace OpenSim.Region.CoreModules.World.Archiver.Tests | 51 | namespace OpenSim.Region.CoreModules.World.Archiver.Tests |
53 | { | 52 | { |
54 | [TestFixture] | 53 | [TestFixture] |
55 | public class ArchiverTests : OpenSimTestCase | 54 | public class ArchiverTests |
56 | { | 55 | { |
57 | private Guid m_lastRequestId; | 56 | private Guid m_lastRequestId; |
58 | private string m_lastErrorMessage; | 57 | private string m_lastErrorMessage; |
59 | 58 | ||
60 | protected SceneHelpers m_sceneHelpers; | ||
61 | protected TestScene m_scene; | 59 | protected TestScene m_scene; |
62 | protected ArchiverModule m_archiverModule; | 60 | protected ArchiverModule m_archiverModule; |
63 | protected SerialiserModule m_serialiserModule; | ||
64 | 61 | ||
65 | protected TaskInventoryItem m_soundItem; | 62 | protected TaskInventoryItem m_soundItem; |
66 | 63 | ||
67 | [SetUp] | 64 | [SetUp] |
68 | public override void SetUp() | 65 | public void SetUp() |
69 | { | 66 | { |
70 | base.SetUp(); | ||
71 | |||
72 | // FIXME: Do something about this - relying on statics in unit tests causes trouble sooner or later | ||
73 | new SceneManager(); | ||
74 | |||
75 | m_archiverModule = new ArchiverModule(); | 67 | m_archiverModule = new ArchiverModule(); |
76 | m_serialiserModule = new SerialiserModule(); | 68 | SerialiserModule serialiserModule = new SerialiserModule(); |
77 | TerrainModule terrainModule = new TerrainModule(); | 69 | TerrainModule terrainModule = new TerrainModule(); |
78 | 70 | ||
79 | m_sceneHelpers = new SceneHelpers(); | 71 | m_scene = new SceneHelpers().SetupScene(); |
80 | m_scene = m_sceneHelpers.SetupScene(); | 72 | SceneHelpers.SetupSceneModules(m_scene, m_archiverModule, serialiserModule, terrainModule); |
81 | SceneHelpers.SetupSceneModules(m_scene, m_archiverModule, m_serialiserModule, terrainModule); | ||
82 | } | 73 | } |
83 | 74 | ||
84 | private void LoadCompleted(Guid requestId, List<UUID> loadedScenes, string errorMessage) | 75 | private void LoadCompleted(Guid requestId, string errorMessage) |
85 | { | 76 | { |
86 | lock (this) | 77 | lock (this) |
87 | { | 78 | { |
@@ -137,10 +128,26 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests | |||
137 | TestHelpers.InMethod(); | 128 | TestHelpers.InMethod(); |
138 | // log4net.Config.XmlConfigurator.Configure(); | 129 | // log4net.Config.XmlConfigurator.Configure(); |
139 | 130 | ||
140 | SceneObjectGroup sog1; | 131 | SceneObjectPart part1 = CreateSceneObjectPart1(); |
141 | SceneObjectGroup sog2; | 132 | SceneObjectGroup sog1 = new SceneObjectGroup(part1); |
142 | UUID ncAssetUuid; | 133 | m_scene.AddNewSceneObject(sog1, false); |
143 | CreateTestObjects(m_scene, out sog1, out sog2, out ncAssetUuid); | 134 | |
135 | SceneObjectPart part2 = CreateSceneObjectPart2(); | ||
136 | |||
137 | AssetNotecard nc = new AssetNotecard(); | ||
138 | nc.BodyText = "Hello World!"; | ||
139 | nc.Encode(); | ||
140 | UUID ncAssetUuid = new UUID("00000000-0000-0000-1000-000000000000"); | ||
141 | UUID ncItemUuid = new UUID("00000000-0000-0000-1100-000000000000"); | ||
142 | AssetBase ncAsset | ||
143 | = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero); | ||
144 | m_scene.AssetService.Store(ncAsset); | ||
145 | SceneObjectGroup sog2 = new SceneObjectGroup(part2); | ||
146 | TaskInventoryItem ncItem | ||
147 | = new TaskInventoryItem { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid }; | ||
148 | part2.Inventory.AddInventoryItem(ncItem, true); | ||
149 | |||
150 | m_scene.AddNewSceneObject(sog2, false); | ||
144 | 151 | ||
145 | MemoryStream archiveWriteStream = new MemoryStream(); | 152 | MemoryStream archiveWriteStream = new MemoryStream(); |
146 | m_scene.EventManager.OnOarFileSaved += SaveCompleted; | 153 | m_scene.EventManager.OnOarFileSaved += SaveCompleted; |
@@ -179,7 +186,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests | |||
179 | Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); | 186 | Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); |
180 | 187 | ||
181 | ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty); | 188 | ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty); |
182 | arr.LoadControlFile(filePath, data, new DearchiveScenesInfo()); | 189 | arr.LoadControlFile(filePath, data); |
183 | 190 | ||
184 | Assert.That(arr.ControlFileLoaded, Is.True); | 191 | Assert.That(arr.ControlFileLoaded, Is.True); |
185 | 192 | ||
@@ -204,30 +211,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests | |||
204 | // TODO: Test presence of more files and contents of files. | 211 | // TODO: Test presence of more files and contents of files. |
205 | } | 212 | } |
206 | 213 | ||
207 | private void CreateTestObjects(Scene scene, out SceneObjectGroup sog1, out SceneObjectGroup sog2, out UUID ncAssetUuid) | ||
208 | { | ||
209 | SceneObjectPart part1 = CreateSceneObjectPart1(); | ||
210 | sog1 = new SceneObjectGroup(part1); | ||
211 | scene.AddNewSceneObject(sog1, false); | ||
212 | |||
213 | AssetNotecard nc = new AssetNotecard(); | ||
214 | nc.BodyText = "Hello World!"; | ||
215 | nc.Encode(); | ||
216 | ncAssetUuid = UUID.Random(); | ||
217 | UUID ncItemUuid = UUID.Random(); | ||
218 | AssetBase ncAsset | ||
219 | = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero); | ||
220 | m_scene.AssetService.Store(ncAsset); | ||
221 | |||
222 | TaskInventoryItem ncItem | ||
223 | = new TaskInventoryItem { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid }; | ||
224 | SceneObjectPart part2 = CreateSceneObjectPart2(); | ||
225 | sog2 = new SceneObjectGroup(part2); | ||
226 | part2.Inventory.AddInventoryItem(ncItem, true); | ||
227 | |||
228 | scene.AddNewSceneObject(sog2, false); | ||
229 | } | ||
230 | |||
231 | /// <summary> | 214 | /// <summary> |
232 | /// Test saving an OpenSim Region Archive with the no assets option | 215 | /// Test saving an OpenSim Region Archive with the no assets option |
233 | /// </summary> | 216 | /// </summary> |
@@ -287,7 +270,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests | |||
287 | Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); | 270 | Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); |
288 | 271 | ||
289 | ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty); | 272 | ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty); |
290 | arr.LoadControlFile(filePath, data, new DearchiveScenesInfo()); | 273 | arr.LoadControlFile(filePath, data); |
291 | 274 | ||
292 | Assert.That(arr.ControlFileLoaded, Is.True); | 275 | Assert.That(arr.ControlFileLoaded, Is.True); |
293 | 276 | ||
@@ -324,7 +307,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests | |||
324 | 307 | ||
325 | tar.WriteFile( | 308 | tar.WriteFile( |
326 | ArchiveConstants.CONTROL_FILE_PATH, | 309 | ArchiveConstants.CONTROL_FILE_PATH, |
327 | new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup())); | 310 | new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary<string, Object>())); |
328 | 311 | ||
329 | SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, ownerId, "obj1-", 0x11); | 312 | SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, ownerId, "obj1-", 0x11); |
330 | SceneObjectPart sop2 | 313 | SceneObjectPart sop2 |
@@ -379,10 +362,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests | |||
379 | // Also check that direct entries which will also have a file entry containing that directory doesn't | 362 | // Also check that direct entries which will also have a file entry containing that directory doesn't |
380 | // upset load | 363 | // upset load |
381 | tar.WriteDir(ArchiveConstants.TERRAINS_PATH); | 364 | tar.WriteDir(ArchiveConstants.TERRAINS_PATH); |
382 | 365 | ||
383 | tar.WriteFile( | 366 | tar.WriteFile( |
384 | ArchiveConstants.CONTROL_FILE_PATH, | 367 | ArchiveConstants.CONTROL_FILE_PATH, |
385 | new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup())); | 368 | new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary<string, Object>())); |
369 | |||
386 | SceneObjectPart part1 = CreateSceneObjectPart1(); | 370 | SceneObjectPart part1 = CreateSceneObjectPart1(); |
387 | 371 | ||
388 | part1.SitTargetOrientation = new Quaternion(0.2f, 0.3f, 0.4f, 0.5f); | 372 | part1.SitTargetOrientation = new Quaternion(0.2f, 0.3f, 0.4f, 0.5f); |
@@ -405,12 +389,31 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests | |||
405 | Assert.That(soundDataResourceName, Is.Not.Null); | 389 | Assert.That(soundDataResourceName, Is.Not.Null); |
406 | 390 | ||
407 | byte[] soundData; | 391 | byte[] soundData; |
408 | UUID soundUuid; | 392 | Console.WriteLine("Loading " + soundDataResourceName); |
409 | CreateSoundAsset(tar, assembly, soundDataResourceName, out soundData, out soundUuid); | 393 | using (Stream resource = assembly.GetManifestResourceStream(soundDataResourceName)) |
410 | 394 | { | |
411 | TaskInventoryItem item1 | 395 | using (BinaryReader br = new BinaryReader(resource)) |
412 | = new TaskInventoryItem { AssetID = soundUuid, ItemID = soundItemUuid, Name = soundItemName }; | 396 | { |
413 | part1.Inventory.AddInventoryItem(item1, true); | 397 | // FIXME: Use the inspector instead |
398 | soundData = br.ReadBytes(99999999); | ||
399 | UUID soundUuid = UUID.Parse("00000000-0000-0000-0000-000000000001"); | ||
400 | string soundAssetFileName | ||
401 | = ArchiveConstants.ASSETS_PATH + soundUuid | ||
402 | + ArchiveConstants.ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.SoundWAV]; | ||
403 | tar.WriteFile(soundAssetFileName, soundData); | ||
404 | |||
405 | /* | ||
406 | AssetBase soundAsset = AssetHelpers.CreateAsset(soundUuid, soundData); | ||
407 | scene.AssetService.Store(soundAsset); | ||
408 | asset1FileName = ArchiveConstants.ASSETS_PATH + soundUuid + ".wav"; | ||
409 | */ | ||
410 | |||
411 | TaskInventoryItem item1 | ||
412 | = new TaskInventoryItem { AssetID = soundUuid, ItemID = soundItemUuid, Name = soundItemName }; | ||
413 | part1.Inventory.AddInventoryItem(item1, true); | ||
414 | } | ||
415 | } | ||
416 | |||
414 | m_scene.AddNewSceneObject(object1, false); | 417 | m_scene.AddNewSceneObject(object1, false); |
415 | 418 | ||
416 | string object1FileName = string.Format( | 419 | string object1FileName = string.Format( |
@@ -432,34 +435,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests | |||
432 | 435 | ||
433 | Assert.That(m_lastErrorMessage, Is.Null); | 436 | Assert.That(m_lastErrorMessage, Is.Null); |
434 | 437 | ||
435 | TestLoadedRegion(part1, soundItemName, soundData); | ||
436 | } | ||
437 | |||
438 | private static void CreateSoundAsset(TarArchiveWriter tar, Assembly assembly, string soundDataResourceName, out byte[] soundData, out UUID soundUuid) | ||
439 | { | ||
440 | using (Stream resource = assembly.GetManifestResourceStream(soundDataResourceName)) | ||
441 | { | ||
442 | using (BinaryReader br = new BinaryReader(resource)) | ||
443 | { | ||
444 | // FIXME: Use the inspector instead | ||
445 | soundData = br.ReadBytes(99999999); | ||
446 | soundUuid = UUID.Parse("00000000-0000-0000-0000-000000000001"); | ||
447 | string soundAssetFileName | ||
448 | = ArchiveConstants.ASSETS_PATH + soundUuid | ||
449 | + ArchiveConstants.ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.SoundWAV]; | ||
450 | tar.WriteFile(soundAssetFileName, soundData); | ||
451 | |||
452 | /* | ||
453 | AssetBase soundAsset = AssetHelpers.CreateAsset(soundUuid, soundData); | ||
454 | scene.AssetService.Store(soundAsset); | ||
455 | asset1FileName = ArchiveConstants.ASSETS_PATH + soundUuid + ".wav"; | ||
456 | */ | ||
457 | } | ||
458 | } | ||
459 | } | ||
460 | |||
461 | private void TestLoadedRegion(SceneObjectPart part1, string soundItemName, byte[] soundData) | ||
462 | { | ||
463 | SceneObjectPart object1PartLoaded = m_scene.GetSceneObjectPart(part1.Name); | 438 | SceneObjectPart object1PartLoaded = m_scene.GetSceneObjectPart(part1.Name); |
464 | 439 | ||
465 | Assert.That(object1PartLoaded, Is.Not.Null, "object1 was not loaded"); | 440 | Assert.That(object1PartLoaded, Is.Not.Null, "object1 was not loaded"); |
@@ -479,6 +454,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests | |||
479 | Assert.That(loadedSoundAsset.Data, Is.EqualTo(soundData), "saved and loaded sound data do not match"); | 454 | Assert.That(loadedSoundAsset.Data, Is.EqualTo(soundData), "saved and loaded sound data do not match"); |
480 | 455 | ||
481 | Assert.Greater(m_scene.LandChannel.AllParcels().Count, 0, "incorrect number of parcels"); | 456 | Assert.Greater(m_scene.LandChannel.AllParcels().Count, 0, "incorrect number of parcels"); |
457 | |||
458 | // Temporary | ||
459 | Console.WriteLine("Successfully completed {0}", MethodBase.GetCurrentMethod()); | ||
482 | } | 460 | } |
483 | 461 | ||
484 | /// <summary> | 462 | /// <summary> |
@@ -538,8 +516,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests | |||
538 | SerialiserModule serialiserModule = new SerialiserModule(); | 516 | SerialiserModule serialiserModule = new SerialiserModule(); |
539 | TerrainModule terrainModule = new TerrainModule(); | 517 | TerrainModule terrainModule = new TerrainModule(); |
540 | 518 | ||
541 | m_sceneHelpers = new SceneHelpers(); | 519 | TestScene scene2 = new SceneHelpers().SetupScene(); |
542 | TestScene scene2 = m_sceneHelpers.SetupScene(); | ||
543 | SceneHelpers.SetupSceneModules(scene2, archiverModule, serialiserModule, terrainModule); | 520 | SceneHelpers.SetupSceneModules(scene2, archiverModule, serialiserModule, terrainModule); |
544 | 521 | ||
545 | // Make sure there's a valid owner for the owner we saved (this should have been wiped if the code is | 522 | // Make sure there's a valid owner for the owner we saved (this should have been wiped if the code is |
@@ -577,7 +554,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests | |||
577 | tar.WriteDir(ArchiveConstants.TERRAINS_PATH); | 554 | tar.WriteDir(ArchiveConstants.TERRAINS_PATH); |
578 | tar.WriteFile( | 555 | tar.WriteFile( |
579 | ArchiveConstants.CONTROL_FILE_PATH, | 556 | ArchiveConstants.CONTROL_FILE_PATH, |
580 | new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup())); | 557 | new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary<string, Object>())); |
581 | 558 | ||
582 | RegionSettings rs = new RegionSettings(); | 559 | RegionSettings rs = new RegionSettings(); |
583 | rs.AgentLimit = 17; | 560 | rs.AgentLimit = 17; |
@@ -687,7 +664,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests | |||
687 | SerialiserModule serialiserModule = new SerialiserModule(); | 664 | SerialiserModule serialiserModule = new SerialiserModule(); |
688 | TerrainModule terrainModule = new TerrainModule(); | 665 | TerrainModule terrainModule = new TerrainModule(); |
689 | 666 | ||
690 | Scene scene = m_sceneHelpers.SetupScene(); | 667 | Scene scene = new SceneHelpers().SetupScene(); |
691 | SceneHelpers.SetupSceneModules(scene, archiverModule, serialiserModule, terrainModule); | 668 | SceneHelpers.SetupSceneModules(scene, archiverModule, serialiserModule, terrainModule); |
692 | 669 | ||
693 | m_scene.AddNewSceneObject(new SceneObjectGroup(part2), false); | 670 | m_scene.AddNewSceneObject(new SceneObjectGroup(part2), false); |
@@ -723,258 +700,5 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests | |||
723 | Assert.That(object2PartMerged.GroupPosition, Is.EqualTo(part2.GroupPosition), "object2 group position not equal after merge"); | 700 | Assert.That(object2PartMerged.GroupPosition, Is.EqualTo(part2.GroupPosition), "object2 group position not equal after merge"); |
724 | } | 701 | } |
725 | } | 702 | } |
726 | |||
727 | /// <summary> | ||
728 | /// Test saving a multi-region OAR. | ||
729 | /// </summary> | ||
730 | [Test] | ||
731 | public void TestSaveMultiRegionOar() | ||
732 | { | ||
733 | TestHelpers.InMethod(); | ||
734 | |||
735 | // Create test regions | ||
736 | |||
737 | int WIDTH = 2; | ||
738 | int HEIGHT = 2; | ||
739 | |||
740 | List<Scene> scenes = new List<Scene>(); | ||
741 | |||
742 | // Maps (Directory in OAR file -> scene) | ||
743 | Dictionary<string, Scene> regionPaths = new Dictionary<string, Scene>(); | ||
744 | |||
745 | // Maps (Scene -> expected object paths) | ||
746 | Dictionary<UUID, List<string>> expectedPaths = new Dictionary<UUID, List<string>>(); | ||
747 | |||
748 | // List of expected assets | ||
749 | List<UUID> expectedAssets = new List<UUID>(); | ||
750 | |||
751 | for (uint y = 0; y < HEIGHT; y++) | ||
752 | { | ||
753 | for (uint x = 0; x < WIDTH; x++) | ||
754 | { | ||
755 | Scene scene; | ||
756 | if (x == 0 && y == 0) | ||
757 | { | ||
758 | scene = m_scene; // this scene was already created in SetUp() | ||
759 | } | ||
760 | else | ||
761 | { | ||
762 | scene = m_sceneHelpers.SetupScene(string.Format("Unit test region {0}", (y * WIDTH) + x + 1), UUID.Random(), 1000 + x, 1000 + y); | ||
763 | SceneHelpers.SetupSceneModules(scene, new ArchiverModule(), m_serialiserModule, new TerrainModule()); | ||
764 | } | ||
765 | scenes.Add(scene); | ||
766 | |||
767 | string dir = String.Format("{0}_{1}_{2}", x + 1, y + 1, scene.RegionInfo.RegionName.Replace(" ", "_")); | ||
768 | regionPaths[dir] = scene; | ||
769 | |||
770 | SceneObjectGroup sog1; | ||
771 | SceneObjectGroup sog2; | ||
772 | UUID ncAssetUuid; | ||
773 | |||
774 | CreateTestObjects(scene, out sog1, out sog2, out ncAssetUuid); | ||
775 | |||
776 | expectedPaths[scene.RegionInfo.RegionID] = new List<string>(); | ||
777 | expectedPaths[scene.RegionInfo.RegionID].Add(ArchiveHelpers.CreateObjectPath(sog1)); | ||
778 | expectedPaths[scene.RegionInfo.RegionID].Add(ArchiveHelpers.CreateObjectPath(sog2)); | ||
779 | |||
780 | expectedAssets.Add(ncAssetUuid); | ||
781 | } | ||
782 | } | ||
783 | |||
784 | |||
785 | // Save OAR | ||
786 | |||
787 | MemoryStream archiveWriteStream = new MemoryStream(); | ||
788 | m_scene.EventManager.OnOarFileSaved += SaveCompleted; | ||
789 | |||
790 | Guid requestId = new Guid("00000000-0000-0000-0000-808080808080"); | ||
791 | |||
792 | Dictionary<string, Object> options = new Dictionary<string, Object>(); | ||
793 | options.Add("all", true); | ||
794 | |||
795 | lock (this) | ||
796 | { | ||
797 | m_archiverModule.ArchiveRegion(archiveWriteStream, requestId, options); | ||
798 | Monitor.Wait(this, 60000); | ||
799 | } | ||
800 | |||
801 | |||
802 | // Check that the OAR contains the expected data | ||
803 | |||
804 | Assert.That(m_lastRequestId, Is.EqualTo(requestId)); | ||
805 | |||
806 | byte[] archive = archiveWriteStream.ToArray(); | ||
807 | MemoryStream archiveReadStream = new MemoryStream(archive); | ||
808 | TarArchiveReader tar = new TarArchiveReader(archiveReadStream); | ||
809 | |||
810 | Dictionary<UUID, List<string>> foundPaths = new Dictionary<UUID, List<string>>(); | ||
811 | List<UUID> foundAssets = new List<UUID>(); | ||
812 | |||
813 | foreach (Scene scene in scenes) | ||
814 | { | ||
815 | foundPaths[scene.RegionInfo.RegionID] = new List<string>(); | ||
816 | } | ||
817 | |||
818 | string filePath; | ||
819 | TarArchiveReader.TarEntryType tarEntryType; | ||
820 | |||
821 | byte[] data = tar.ReadEntry(out filePath, out tarEntryType); | ||
822 | Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); | ||
823 | |||
824 | ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty); | ||
825 | arr.LoadControlFile(filePath, data, new DearchiveScenesInfo()); | ||
826 | |||
827 | Assert.That(arr.ControlFileLoaded, Is.True); | ||
828 | |||
829 | while (tar.ReadEntry(out filePath, out tarEntryType) != null) | ||
830 | { | ||
831 | if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) | ||
832 | { | ||
833 | // Assets are shared, so this file doesn't belong to any specific region. | ||
834 | string fileName = filePath.Remove(0, ArchiveConstants.ASSETS_PATH.Length); | ||
835 | if (fileName.EndsWith("_notecard.txt")) | ||
836 | foundAssets.Add(UUID.Parse(fileName.Substring(0, fileName.Length - "_notecard.txt".Length))); | ||
837 | } | ||
838 | else | ||
839 | { | ||
840 | // This file belongs to one of the regions. Find out which one. | ||
841 | Assert.IsTrue(filePath.StartsWith(ArchiveConstants.REGIONS_PATH)); | ||
842 | string[] parts = filePath.Split(new Char[] { '/' }, 3); | ||
843 | Assert.AreEqual(3, parts.Length); | ||
844 | string regionDirectory = parts[1]; | ||
845 | string relativePath = parts[2]; | ||
846 | Scene scene = regionPaths[regionDirectory]; | ||
847 | |||
848 | if (relativePath.StartsWith(ArchiveConstants.OBJECTS_PATH)) | ||
849 | { | ||
850 | foundPaths[scene.RegionInfo.RegionID].Add(relativePath); | ||
851 | } | ||
852 | } | ||
853 | } | ||
854 | |||
855 | Assert.AreEqual(scenes.Count, foundPaths.Count); | ||
856 | foreach (Scene scene in scenes) | ||
857 | { | ||
858 | Assert.That(foundPaths[scene.RegionInfo.RegionID], Is.EquivalentTo(expectedPaths[scene.RegionInfo.RegionID])); | ||
859 | } | ||
860 | |||
861 | Assert.That(foundAssets, Is.EquivalentTo(expectedAssets)); | ||
862 | } | ||
863 | |||
864 | /// <summary> | ||
865 | /// Test loading a multi-region OAR. | ||
866 | /// </summary> | ||
867 | [Test] | ||
868 | public void TestLoadMultiRegionOar() | ||
869 | { | ||
870 | TestHelpers.InMethod(); | ||
871 | |||
872 | // Create an ArchiveScenesGroup with the regions in the OAR. This is needed to generate the control file. | ||
873 | |||
874 | int WIDTH = 2; | ||
875 | int HEIGHT = 2; | ||
876 | |||
877 | for (uint y = 0; y < HEIGHT; y++) | ||
878 | { | ||
879 | for (uint x = 0; x < WIDTH; x++) | ||
880 | { | ||
881 | Scene scene; | ||
882 | if (x == 0 && y == 0) | ||
883 | { | ||
884 | scene = m_scene; // this scene was already created in SetUp() | ||
885 | } | ||
886 | else | ||
887 | { | ||
888 | scene = m_sceneHelpers.SetupScene(string.Format("Unit test region {0}", (y * WIDTH) + x + 1), UUID.Random(), 1000 + x, 1000 + y); | ||
889 | SceneHelpers.SetupSceneModules(scene, new ArchiverModule(), m_serialiserModule, new TerrainModule()); | ||
890 | } | ||
891 | } | ||
892 | } | ||
893 | |||
894 | ArchiveScenesGroup scenesGroup = new ArchiveScenesGroup(); | ||
895 | SceneManager.Instance.ForEachScene(delegate(Scene scene) | ||
896 | { | ||
897 | scenesGroup.AddScene(scene); | ||
898 | }); | ||
899 | scenesGroup.CalcSceneLocations(); | ||
900 | |||
901 | // Generate the OAR file | ||
902 | |||
903 | MemoryStream archiveWriteStream = new MemoryStream(); | ||
904 | TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream); | ||
905 | |||
906 | ArchiveWriteRequest writeRequest = new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty); | ||
907 | writeRequest.MultiRegionFormat = true; | ||
908 | tar.WriteFile( | ||
909 | ArchiveConstants.CONTROL_FILE_PATH, writeRequest.CreateControlFile(scenesGroup)); | ||
910 | |||
911 | SceneObjectPart part1 = CreateSceneObjectPart1(); | ||
912 | part1.SitTargetOrientation = new Quaternion(0.2f, 0.3f, 0.4f, 0.5f); | ||
913 | part1.SitTargetPosition = new Vector3(1, 2, 3); | ||
914 | |||
915 | SceneObjectGroup object1 = new SceneObjectGroup(part1); | ||
916 | |||
917 | // Let's put some inventory items into our object | ||
918 | string soundItemName = "sound-item1"; | ||
919 | UUID soundItemUuid = UUID.Parse("00000000-0000-0000-0000-000000000002"); | ||
920 | Type type = GetType(); | ||
921 | Assembly assembly = type.Assembly; | ||
922 | string soundDataResourceName = null; | ||
923 | string[] names = assembly.GetManifestResourceNames(); | ||
924 | foreach (string name in names) | ||
925 | { | ||
926 | if (name.EndsWith(".Resources.test-sound.wav")) | ||
927 | soundDataResourceName = name; | ||
928 | } | ||
929 | Assert.That(soundDataResourceName, Is.Not.Null); | ||
930 | |||
931 | byte[] soundData; | ||
932 | UUID soundUuid; | ||
933 | CreateSoundAsset(tar, assembly, soundDataResourceName, out soundData, out soundUuid); | ||
934 | |||
935 | TaskInventoryItem item1 | ||
936 | = new TaskInventoryItem { AssetID = soundUuid, ItemID = soundItemUuid, Name = soundItemName }; | ||
937 | part1.Inventory.AddInventoryItem(item1, true); | ||
938 | m_scene.AddNewSceneObject(object1, false); | ||
939 | |||
940 | string object1FileName = string.Format( | ||
941 | "{0}_{1:000}-{2:000}-{3:000}__{4}.xml", | ||
942 | part1.Name, | ||
943 | Math.Round(part1.GroupPosition.X), Math.Round(part1.GroupPosition.Y), Math.Round(part1.GroupPosition.Z), | ||
944 | part1.UUID); | ||
945 | string path = "regions/1_1_Unit_test_region/" + ArchiveConstants.OBJECTS_PATH + object1FileName; | ||
946 | tar.WriteFile(path, SceneObjectSerializer.ToXml2Format(object1)); | ||
947 | |||
948 | tar.Close(); | ||
949 | |||
950 | |||
951 | // Delete the current objects, to test that they're loaded from the OAR and didn't | ||
952 | // just remain in the scene. | ||
953 | SceneManager.Instance.ForEachScene(delegate(Scene scene) | ||
954 | { | ||
955 | scene.DeleteAllSceneObjects(); | ||
956 | }); | ||
957 | |||
958 | // Create a "hole", to test that that the corresponding region isn't loaded from the OAR | ||
959 | SceneManager.Instance.CloseScene(SceneManager.Instance.Scenes[1]); | ||
960 | |||
961 | |||
962 | // Check thay the OAR file contains the expected data | ||
963 | |||
964 | MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); | ||
965 | |||
966 | lock (this) | ||
967 | { | ||
968 | m_scene.EventManager.OnOarFileLoaded += LoadCompleted; | ||
969 | m_archiverModule.DearchiveRegion(archiveReadStream); | ||
970 | } | ||
971 | |||
972 | Assert.That(m_lastErrorMessage, Is.Null); | ||
973 | |||
974 | Assert.AreEqual(3, SceneManager.Instance.Scenes.Count); | ||
975 | |||
976 | TestLoadedRegion(part1, soundItemName, soundData); | ||
977 | } | ||
978 | |||
979 | } | 703 | } |
980 | } | 704 | } |
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs index 5fd1bce..fdef9d8 100644 --- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs | |||
@@ -40,7 +40,6 @@ 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; | ||
44 | 43 | ||
45 | namespace OpenSim.Region.CoreModules.World.Estate | 44 | namespace OpenSim.Region.CoreModules.World.Estate |
46 | { | 45 | { |
diff --git a/OpenSim/Region/CoreModules/World/Land/DwellModule.cs b/OpenSim/Region/CoreModules/World/Land/DwellModule.cs deleted file mode 100644 index d1f05a7..0000000 --- a/OpenSim/Region/CoreModules/World/Land/DwellModule.cs +++ /dev/null | |||
@@ -1,110 +0,0 @@ | |||
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 | using System.Collections; | ||
30 | using System.Collections.Generic; | ||
31 | using System.Diagnostics; | ||
32 | using System.Reflection; | ||
33 | using System.Text; | ||
34 | using log4net; | ||
35 | using Nini.Config; | ||
36 | using OpenMetaverse; | ||
37 | using OpenMetaverse.StructuredData; | ||
38 | using OpenMetaverse.Messages.Linden; | ||
39 | using OpenSim.Framework; | ||
40 | using OpenSim.Framework.Capabilities; | ||
41 | using OpenSim.Framework.Console; | ||
42 | using OpenSim.Framework.Servers; | ||
43 | using OpenSim.Framework.Servers.HttpServer; | ||
44 | using OpenSim.Region.CoreModules.Framework.InterfaceCommander; | ||
45 | using OpenSim.Region.Framework.Interfaces; | ||
46 | using OpenSim.Region.Framework.Scenes; | ||
47 | using OpenSim.Region.Physics.Manager; | ||
48 | using OpenSim.Services.Interfaces; | ||
49 | using Caps = OpenSim.Framework.Capabilities.Caps; | ||
50 | using GridRegion = OpenSim.Services.Interfaces.GridRegion; | ||
51 | |||
52 | namespace OpenSim.Region.CoreModules.World.Land | ||
53 | { | ||
54 | public class DwellModule : IDwellModule, INonSharedRegionModule | ||
55 | { | ||
56 | private Scene m_scene; | ||
57 | |||
58 | public Type ReplaceableInterface | ||
59 | { | ||
60 | get { return typeof(IDwellModule); } | ||
61 | } | ||
62 | |||
63 | public string Name | ||
64 | { | ||
65 | get { return "DwellModule"; } | ||
66 | } | ||
67 | |||
68 | public void Initialise(IConfigSource source) | ||
69 | { | ||
70 | } | ||
71 | |||
72 | public void AddRegion(Scene scene) | ||
73 | { | ||
74 | m_scene = scene; | ||
75 | |||
76 | m_scene.EventManager.OnNewClient += OnNewClient; | ||
77 | } | ||
78 | |||
79 | public void RegionLoaded(Scene scene) | ||
80 | { | ||
81 | } | ||
82 | |||
83 | public void RemoveRegion(Scene scene) | ||
84 | { | ||
85 | } | ||
86 | |||
87 | public void Close() | ||
88 | { | ||
89 | } | ||
90 | |||
91 | public void OnNewClient(IClientAPI client) | ||
92 | { | ||
93 | client.OnParcelDwellRequest += ClientOnParcelDwellRequest; | ||
94 | } | ||
95 | |||
96 | private void ClientOnParcelDwellRequest(int localID, IClientAPI client) | ||
97 | { | ||
98 | ILandObject parcel = m_scene.LandChannel.GetLandObject(localID); | ||
99 | if (parcel == null) | ||
100 | return; | ||
101 | |||
102 | client.SendParcelDwellReply(localID, parcel.LandData.GlobalID, parcel.LandData.Dwell); | ||
103 | } | ||
104 | |||
105 | public int GetDwell(UUID parcelID) | ||
106 | { | ||
107 | return 0; | ||
108 | } | ||
109 | } | ||
110 | } | ||
diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index b5e2bc3..aae6603 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs | |||
@@ -927,7 +927,6 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
927 | ILandObject newLand = startLandObject.Copy(); | 927 | ILandObject newLand = startLandObject.Copy(); |
928 | newLand.LandData.Name = newLand.LandData.Name; | 928 | newLand.LandData.Name = newLand.LandData.Name; |
929 | newLand.LandData.GlobalID = UUID.Random(); | 929 | newLand.LandData.GlobalID = UUID.Random(); |
930 | newLand.LandData.Dwell = 0; | ||
931 | 930 | ||
932 | newLand.SetLandBitmap(newLand.GetSquareLandBitmap(start_x, start_y, end_x, end_y)); | 931 | newLand.SetLandBitmap(newLand.GetSquareLandBitmap(start_x, start_y, end_x, end_y)); |
933 | 932 | ||
diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index d5b2adb..4f06737 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs | |||
@@ -33,7 +33,6 @@ 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; | ||
37 | 36 | ||
38 | namespace OpenSim.Region.CoreModules.World.Land | 37 | namespace OpenSim.Region.CoreModules.World.Land |
39 | { | 38 | { |
diff --git a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs index cbb3abe..102b4d7 100644 --- a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs | |||
@@ -69,7 +69,7 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
69 | /// without recounting the whole sim. | 69 | /// without recounting the whole sim. |
70 | /// | 70 | /// |
71 | /// We start out tainted so that the first get call resets the various prim counts. | 71 | /// We start out tainted so that the first get call resets the various prim counts. |
72 | /// </value> | 72 | /// <value> |
73 | private bool m_Tainted = true; | 73 | private bool m_Tainted = true; |
74 | 74 | ||
75 | private Object m_TaintLock = new Object(); | 75 | private Object m_TaintLock = new Object(); |
diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs index ab8f143..09f6758 100644 --- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs +++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs | |||
@@ -27,12 +27,9 @@ | |||
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.IO; | ||
31 | using System.Linq; | ||
32 | using System.Reflection; | 30 | using System.Reflection; |
33 | using System.Text; | 31 | using System.Text; |
34 | using System.Text.RegularExpressions; | 32 | using System.Text.RegularExpressions; |
35 | using System.Xml; | ||
36 | using log4net; | 33 | using log4net; |
37 | using Mono.Addins; | 34 | using Mono.Addins; |
38 | using NDesk.Options; | 35 | using NDesk.Options; |
@@ -43,7 +40,6 @@ using OpenSim.Framework.Console; | |||
43 | using OpenSim.Framework.Monitoring; | 40 | using OpenSim.Framework.Monitoring; |
44 | using OpenSim.Region.Framework.Interfaces; | 41 | using OpenSim.Region.Framework.Interfaces; |
45 | using OpenSim.Region.Framework.Scenes; | 42 | using OpenSim.Region.Framework.Scenes; |
46 | using OpenSim.Region.Framework.Scenes.Serialization; | ||
47 | 43 | ||
48 | namespace OpenSim.Region.CoreModules.World.Objects.Commands | 44 | namespace OpenSim.Region.CoreModules.World.Objects.Commands |
49 | { | 45 | { |
@@ -87,85 +83,52 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands | |||
87 | m_console.Commands.AddCommand( | 83 | m_console.Commands.AddCommand( |
88 | "Objects", false, "delete object owner", | 84 | "Objects", false, "delete object owner", |
89 | "delete object owner <UUID>", | 85 | "delete object owner <UUID>", |
90 | "Delete scene objects by owner", | 86 | "Delete a scene object by owner", HandleDeleteObject); |
91 | "Command will ask for confirmation before proceeding.", | ||
92 | HandleDeleteObject); | ||
93 | 87 | ||
94 | m_console.Commands.AddCommand( | 88 | m_console.Commands.AddCommand( |
95 | "Objects", false, "delete object creator", | 89 | "Objects", false, "delete object creator", |
96 | "delete object creator <UUID>", | 90 | "delete object creator <UUID>", |
97 | "Delete scene objects by creator", | 91 | "Delete a scene object by creator", HandleDeleteObject); |
98 | "Command will ask for confirmation before proceeding.", | ||
99 | HandleDeleteObject); | ||
100 | 92 | ||
101 | m_console.Commands.AddCommand( | 93 | m_console.Commands.AddCommand( |
102 | "Objects", false, "delete object id", | 94 | "Objects", false, "delete object uuid", |
103 | "delete object id <UUID-or-localID>", | 95 | "delete object uuid <UUID>", |
104 | "Delete a scene object by uuid or localID", | 96 | "Delete a scene object by uuid", HandleDeleteObject); |
105 | HandleDeleteObject); | ||
106 | 97 | ||
107 | m_console.Commands.AddCommand( | 98 | m_console.Commands.AddCommand( |
108 | "Objects", false, "delete object name", | 99 | "Objects", false, "delete object name", |
109 | "delete object name [--regex] <name>", | 100 | "delete object name [--regex] <name>", |
110 | "Delete a scene object by name.", | 101 | "Delete a scene object by name.", |
111 | "Command will ask for confirmation before proceeding.\n" | 102 | "If --regex is specified then the name is treatead as a regular expression", |
112 | + "If --regex is specified then the name is treatead as a regular expression", | ||
113 | HandleDeleteObject); | 103 | HandleDeleteObject); |
114 | 104 | ||
115 | m_console.Commands.AddCommand( | 105 | m_console.Commands.AddCommand( |
116 | "Objects", false, "delete object outside", | 106 | "Objects", false, "delete object outside", |
117 | "delete object outside", | 107 | "delete object outside", |
118 | "Delete all scene objects outside region boundaries", | 108 | "Delete all scene objects outside region boundaries", HandleDeleteObject); |
119 | "Command will ask for confirmation before proceeding.", | ||
120 | HandleDeleteObject); | ||
121 | 109 | ||
122 | m_console.Commands.AddCommand( | 110 | m_console.Commands.AddCommand( |
123 | "Objects", | 111 | "Objects", |
124 | false, | 112 | false, |
125 | "delete object pos", | 113 | "show object uuid", |
126 | "delete object pos <start-coord> to <end-coord>", | 114 | "show object uuid <UUID>", |
127 | "Delete scene objects within the given area.", | 115 | "Show details of a scene object with the given UUID", HandleShowObjectByUuid); |
128 | ConsoleUtil.CoordHelp, | ||
129 | HandleDeleteObject); | ||
130 | |||
131 | m_console.Commands.AddCommand( | ||
132 | "Objects", | ||
133 | false, | ||
134 | "show object id", | ||
135 | "show object id [--full] <UUID-or-localID>", | ||
136 | "Show details of a scene object with the given UUID or localID", | ||
137 | "The --full option will print out information on all the parts of the object.\n" | ||
138 | + "For yet more detailed part information, use the \"show part\" commands.", | ||
139 | HandleShowObjectById); | ||
140 | 116 | ||
141 | m_console.Commands.AddCommand( | 117 | m_console.Commands.AddCommand( |
142 | "Objects", | 118 | "Objects", |
143 | false, | 119 | false, |
144 | "show object name", | 120 | "show object name", |
145 | "show object name [--full] [--regex] <name>", | 121 | "show object name [--regex] <name>", |
146 | "Show details of scene objects with the given name.", | 122 | "Show details of scene objects with the given name.", |
147 | "The --full option will print out information on all the parts of the object.\n" | 123 | "If --regex is specified then the name is treatead as a regular expression", |
148 | + "For yet more detailed part information, use the \"show part\" commands.\n" | ||
149 | + "If --regex is specified then the name is treatead as a regular expression.", | ||
150 | HandleShowObjectByName); | 124 | HandleShowObjectByName); |
151 | 125 | ||
152 | m_console.Commands.AddCommand( | 126 | m_console.Commands.AddCommand( |
153 | "Objects", | 127 | "Objects", |
154 | false, | 128 | false, |
155 | "show object pos", | 129 | "show part uuid", |
156 | "show object pos [--full] <start-coord> to <end-coord>", | 130 | "show part uuid <UUID>", |
157 | "Show details of scene objects within the given area.", | 131 | "Show details of a scene object parts with the given UUID", HandleShowPartByUuid); |
158 | "The --full option will print out information on all the parts of the object.\n" | ||
159 | + "For yet more detailed part information, use the \"show part\" commands.\n" | ||
160 | + ConsoleUtil.CoordHelp, | ||
161 | HandleShowObjectByPos); | ||
162 | |||
163 | m_console.Commands.AddCommand( | ||
164 | "Objects", | ||
165 | false, | ||
166 | "show part id", | ||
167 | "show part id <UUID-or-localID>", | ||
168 | "Show details of a scene object part with the given UUID or localID", HandleShowPartById); | ||
169 | 132 | ||
170 | m_console.Commands.AddCommand( | 133 | m_console.Commands.AddCommand( |
171 | "Objects", | 134 | "Objects", |
@@ -173,28 +136,8 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands | |||
173 | "show part name", | 136 | "show part name", |
174 | "show part name [--regex] <name>", | 137 | "show part name [--regex] <name>", |
175 | "Show details of scene object parts with the given name.", | 138 | "Show details of scene object parts with the given name.", |
176 | "If --regex is specified then the name is treated as a regular expression", | 139 | "If --regex is specified then the name is treatead as a regular expression", |
177 | HandleShowPartByName); | 140 | HandleShowPartByName); |
178 | |||
179 | m_console.Commands.AddCommand( | ||
180 | "Objects", | ||
181 | false, | ||
182 | "show part pos", | ||
183 | "show part pos <start-coord> to <end-coord>", | ||
184 | "Show details of scene object parts within the given area.", | ||
185 | ConsoleUtil.CoordHelp, | ||
186 | HandleShowPartByPos); | ||
187 | |||
188 | m_console.Commands.AddCommand( | ||
189 | "Objects", | ||
190 | false, | ||
191 | "dump object id", | ||
192 | "dump object id <UUID-or-localID>", | ||
193 | "Dump the formatted serialization of the given object to the file <UUID>.xml", | ||
194 | "e.g. dump object uuid c1ed6809-cc24-4061-a4c2-93082a2d1f1d will dump serialization to c1ed6809-cc24-4061-a4c2-93082a2d1f1d.xml\n" | ||
195 | + "To locate the UUID or localID in the first place, you need to use the other show object commands.\n" | ||
196 | + "If a local ID is given then the filename used is still that for the UUID", | ||
197 | HandleDumpObjectById); | ||
198 | } | 141 | } |
199 | 142 | ||
200 | public void RemoveRegion(Scene scene) | 143 | public void RemoveRegion(Scene scene) |
@@ -207,75 +150,25 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands | |||
207 | // m_log.DebugFormat("[OBJECTS COMMANDS MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName); | 150 | // m_log.DebugFormat("[OBJECTS COMMANDS MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName); |
208 | } | 151 | } |
209 | 152 | ||
210 | /// <summary> | 153 | private void HandleShowObjectByUuid(string module, string[] cmd) |
211 | /// Outputs the sogs to console. | ||
212 | /// </summary> | ||
213 | /// <param name='searchPredicate'></param> | ||
214 | /// <param name='showFull'>If true then output all part details. If false then output summary.</param> | ||
215 | private void OutputSogsToConsole(Predicate<SceneObjectGroup> searchPredicate, bool showFull) | ||
216 | { | ||
217 | List<SceneObjectGroup> sceneObjects = m_scene.GetSceneObjectGroups().FindAll(searchPredicate); | ||
218 | |||
219 | StringBuilder sb = new StringBuilder(); | ||
220 | |||
221 | foreach (SceneObjectGroup so in sceneObjects) | ||
222 | { | ||
223 | AddSceneObjectReport(sb, so, showFull); | ||
224 | sb.Append("\n"); | ||
225 | } | ||
226 | |||
227 | sb.AppendFormat("{0} object(s) found in {1}\n", sceneObjects.Count, m_scene.Name); | ||
228 | |||
229 | m_console.OutputFormat(sb.ToString()); | ||
230 | } | ||
231 | |||
232 | private void OutputSopsToConsole(Predicate<SceneObjectPart> searchPredicate, bool showFull) | ||
233 | { | ||
234 | List<SceneObjectGroup> sceneObjects = m_scene.GetSceneObjectGroups(); | ||
235 | List<SceneObjectPart> parts = new List<SceneObjectPart>(); | ||
236 | |||
237 | sceneObjects.ForEach(so => parts.AddRange(Array.FindAll<SceneObjectPart>(so.Parts, searchPredicate))); | ||
238 | |||
239 | StringBuilder sb = new StringBuilder(); | ||
240 | |||
241 | foreach (SceneObjectPart part in parts) | ||
242 | { | ||
243 | AddScenePartReport(sb, part, showFull); | ||
244 | sb.Append("\n"); | ||
245 | } | ||
246 | |||
247 | sb.AppendFormat("{0} parts found in {1}\n", parts.Count, m_scene.Name); | ||
248 | |||
249 | m_console.OutputFormat(sb.ToString()); | ||
250 | } | ||
251 | |||
252 | private void HandleShowObjectById(string module, string[] cmdparams) | ||
253 | { | 154 | { |
254 | if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) | 155 | if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) |
255 | return; | 156 | return; |
256 | 157 | ||
257 | bool showFull = false; | 158 | if (cmd.Length < 4) |
258 | OptionSet options = new OptionSet().Add("full", v => showFull = v != null ); | ||
259 | |||
260 | List<string> mainParams = options.Parse(cmdparams); | ||
261 | |||
262 | if (mainParams.Count < 4) | ||
263 | { | 159 | { |
264 | m_console.OutputFormat("Usage: show object uuid <uuid>"); | 160 | m_console.OutputFormat("Usage: show object uuid <uuid>"); |
265 | return; | 161 | return; |
266 | } | 162 | } |
267 | 163 | ||
268 | UUID uuid; | 164 | UUID objectUuid; |
269 | uint localId; | 165 | if (!UUID.TryParse(cmd[3], out objectUuid)) |
270 | if (!ConsoleUtil.TryParseConsoleId(m_console, mainParams[3], out uuid, out localId)) | 166 | { |
167 | m_console.OutputFormat("{0} is not a valid uuid", cmd[3]); | ||
271 | return; | 168 | return; |
169 | } | ||
272 | 170 | ||
273 | SceneObjectGroup so; | 171 | SceneObjectGroup so = m_scene.GetSceneObjectGroup(objectUuid); |
274 | |||
275 | if (localId != ConsoleUtil.LocalIdNotFound) | ||
276 | so = m_scene.GetSceneObjectGroup(localId); | ||
277 | else | ||
278 | so = m_scene.GetSceneObjectGroup(uuid); | ||
279 | 172 | ||
280 | if (so == null) | 173 | if (so == null) |
281 | { | 174 | { |
@@ -284,7 +177,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands | |||
284 | } | 177 | } |
285 | 178 | ||
286 | StringBuilder sb = new StringBuilder(); | 179 | StringBuilder sb = new StringBuilder(); |
287 | AddSceneObjectReport(sb, so, showFull); | 180 | AddSceneObjectReport(sb, so); |
288 | 181 | ||
289 | m_console.OutputFormat(sb.ToString()); | 182 | m_console.OutputFormat(sb.ToString()); |
290 | } | 183 | } |
@@ -294,91 +187,70 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands | |||
294 | if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) | 187 | if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) |
295 | return; | 188 | return; |
296 | 189 | ||
297 | bool showFull = false; | ||
298 | bool useRegex = false; | 190 | bool useRegex = false; |
299 | OptionSet options = new OptionSet(); | 191 | OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null ); |
300 | options.Add("full", v => showFull = v != null ); | ||
301 | options.Add("regex", v => useRegex = v != null ); | ||
302 | 192 | ||
303 | List<string> mainParams = options.Parse(cmdparams); | 193 | List<string> mainParams = options.Parse(cmdparams); |
304 | 194 | ||
305 | if (mainParams.Count < 4) | 195 | if (mainParams.Count < 4) |
306 | { | 196 | { |
307 | m_console.OutputFormat("Usage: show object name [--full] [--regex] <name>"); | 197 | m_console.OutputFormat("Usage: show object name [--regex] <name>"); |
308 | return; | 198 | return; |
309 | } | 199 | } |
310 | 200 | ||
311 | string name = mainParams[3]; | 201 | string name = mainParams[3]; |
312 | 202 | ||
313 | Predicate<SceneObjectGroup> searchPredicate; | 203 | List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>(); |
204 | Action<SceneObjectGroup> searchAction; | ||
314 | 205 | ||
315 | if (useRegex) | 206 | if (useRegex) |
316 | { | 207 | { |
317 | Regex nameRegex = new Regex(name); | 208 | Regex nameRegex = new Regex(name); |
318 | searchPredicate = so => nameRegex.IsMatch(so.Name); | 209 | searchAction = so => { if (nameRegex.IsMatch(so.Name)) { sceneObjects.Add(so); }}; |
319 | } | 210 | } |
320 | else | 211 | else |
321 | { | 212 | { |
322 | searchPredicate = so => so.Name == name; | 213 | searchAction = so => { if (so.Name == name) { sceneObjects.Add(so); }}; |
323 | } | 214 | } |
324 | 215 | ||
325 | OutputSogsToConsole(searchPredicate, showFull); | 216 | m_scene.ForEachSOG(searchAction); |
326 | } | ||
327 | |||
328 | private void HandleShowObjectByPos(string module, string[] cmdparams) | ||
329 | { | ||
330 | if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) | ||
331 | return; | ||
332 | |||
333 | bool showFull = false; | ||
334 | OptionSet options = new OptionSet().Add("full", v => showFull = v != null ); | ||
335 | |||
336 | List<string> mainParams = options.Parse(cmdparams); | ||
337 | 217 | ||
338 | if (mainParams.Count < 5) | 218 | if (sceneObjects.Count == 0) |
339 | { | 219 | { |
340 | m_console.OutputFormat("Usage: show object pos [--full] <start-coord> to <end-coord>"); | 220 | m_console.OutputFormat("No objects with name {0} found in {1}", name, m_scene.RegionInfo.RegionName); |
341 | return; | 221 | return; |
342 | } | 222 | } |
343 | 223 | ||
344 | Vector3 startVector, endVector; | 224 | StringBuilder sb = new StringBuilder(); |
345 | |||
346 | if (!TryParseVectorRange(cmdparams.Skip(3).Take(3), out startVector, out endVector)) | ||
347 | return; | ||
348 | 225 | ||
349 | Predicate<SceneObjectGroup> searchPredicate | 226 | foreach (SceneObjectGroup so in sceneObjects) |
350 | = so => Util.IsInsideBox(so.AbsolutePosition, startVector, endVector); | 227 | { |
228 | AddSceneObjectReport(sb, so); | ||
229 | sb.Append("\n"); | ||
230 | } | ||
351 | 231 | ||
352 | OutputSogsToConsole(searchPredicate, showFull); | 232 | m_console.OutputFormat(sb.ToString()); |
353 | } | 233 | } |
354 | 234 | ||
355 | private void HandleShowPartById(string module, string[] cmdparams) | 235 | private void HandleShowPartByUuid(string module, string[] cmd) |
356 | { | 236 | { |
357 | if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) | 237 | if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) |
358 | return; | 238 | return; |
359 | 239 | ||
360 | // bool showFull = false; | 240 | if (cmd.Length < 4) |
361 | OptionSet options = new OptionSet(); | ||
362 | // options.Add("full", v => showFull = v != null ); | ||
363 | |||
364 | List<string> mainParams = options.Parse(cmdparams); | ||
365 | |||
366 | if (mainParams.Count < 4) | ||
367 | { | 241 | { |
368 | m_console.OutputFormat("Usage: show part id [--full] <UUID-or-localID>"); | 242 | m_console.OutputFormat("Usage: show part uuid <uuid>"); |
369 | return; | 243 | return; |
370 | } | 244 | } |
371 | 245 | ||
372 | UUID objectUuid; | 246 | UUID objectUuid; |
373 | uint localId; | 247 | if (!UUID.TryParse(cmd[3], out objectUuid)) |
374 | if (!ConsoleUtil.TryParseConsoleId(m_console, mainParams[3], out objectUuid, out localId)) | 248 | { |
249 | m_console.OutputFormat("{0} is not a valid uuid", cmd[3]); | ||
375 | return; | 250 | return; |
251 | } | ||
376 | 252 | ||
377 | SceneObjectPart sop; | 253 | SceneObjectPart sop = m_scene.GetSceneObjectPart(objectUuid); |
378 | if (localId == ConsoleUtil.LocalIdNotFound) | ||
379 | sop = m_scene.GetSceneObjectPart(objectUuid); | ||
380 | else | ||
381 | sop = m_scene.GetSceneObjectPart(localId); | ||
382 | 254 | ||
383 | if (sop == null) | 255 | if (sop == null) |
384 | { | 256 | { |
@@ -387,239 +259,84 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands | |||
387 | } | 259 | } |
388 | 260 | ||
389 | StringBuilder sb = new StringBuilder(); | 261 | StringBuilder sb = new StringBuilder(); |
390 | AddScenePartReport(sb, sop, true); | 262 | AddScenePartReport(sb, sop); |
391 | 263 | ||
392 | m_console.OutputFormat(sb.ToString()); | 264 | m_console.OutputFormat(sb.ToString()); |
393 | } | 265 | } |
394 | 266 | ||
395 | private void HandleShowPartByPos(string module, string[] cmdparams) | ||
396 | { | ||
397 | if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) | ||
398 | return; | ||
399 | |||
400 | // bool showFull = false; | ||
401 | OptionSet options = new OptionSet(); | ||
402 | // options.Add("full", v => showFull = v != null ); | ||
403 | |||
404 | List<string> mainParams = options.Parse(cmdparams); | ||
405 | |||
406 | if (mainParams.Count < 5) | ||
407 | { | ||
408 | m_console.OutputFormat("Usage: show part pos [--full] <start-coord> to <end-coord>"); | ||
409 | return; | ||
410 | } | ||
411 | |||
412 | string rawConsoleStartVector = mainParams[3]; | ||
413 | Vector3 startVector; | ||
414 | |||
415 | if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector)) | ||
416 | { | ||
417 | m_console.OutputFormat("Error: Start vector {0} does not have a valid format", rawConsoleStartVector); | ||
418 | return; | ||
419 | } | ||
420 | |||
421 | string rawConsoleEndVector = mainParams[5]; | ||
422 | Vector3 endVector; | ||
423 | |||
424 | if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector)) | ||
425 | { | ||
426 | m_console.OutputFormat("Error: End vector {0} does not have a valid format", rawConsoleEndVector); | ||
427 | return; | ||
428 | } | ||
429 | |||
430 | OutputSopsToConsole(sop => Util.IsInsideBox(sop.AbsolutePosition, startVector, endVector), true); | ||
431 | } | ||
432 | |||
433 | private void HandleShowPartByName(string module, string[] cmdparams) | 267 | private void HandleShowPartByName(string module, string[] cmdparams) |
434 | { | 268 | { |
435 | if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) | 269 | if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) |
436 | return; | 270 | return; |
437 | 271 | ||
438 | // bool showFull = false; | ||
439 | bool useRegex = false; | 272 | bool useRegex = false; |
440 | OptionSet options = new OptionSet(); | 273 | OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null ); |
441 | // options.Add("full", v => showFull = v != null ); | ||
442 | options.Add("regex", v => useRegex = v != null ); | ||
443 | 274 | ||
444 | List<string> mainParams = options.Parse(cmdparams); | 275 | List<string> mainParams = options.Parse(cmdparams); |
445 | 276 | ||
446 | if (mainParams.Count < 4) | 277 | if (mainParams.Count < 4) |
447 | { | 278 | { |
448 | m_console.OutputFormat("Usage: show part name [--full] [--regex] <name>"); | 279 | m_console.OutputFormat("Usage: show part name [--regex] <name>"); |
449 | return; | 280 | return; |
450 | } | 281 | } |
451 | 282 | ||
452 | string name = mainParams[3]; | 283 | string name = mainParams[3]; |
453 | 284 | ||
454 | Predicate<SceneObjectPart> searchPredicate; | 285 | List<SceneObjectPart> parts = new List<SceneObjectPart>(); |
286 | |||
287 | Action<SceneObjectGroup> searchAction; | ||
455 | 288 | ||
456 | if (useRegex) | 289 | if (useRegex) |
457 | { | 290 | { |
458 | Regex nameRegex = new Regex(name); | 291 | Regex nameRegex = new Regex(name); |
459 | searchPredicate = sop => nameRegex.IsMatch(sop.Name); | 292 | searchAction = so => so.ForEachPart(sop => { if (nameRegex.IsMatch(sop.Name)) { parts.Add(sop); } }); |
460 | } | 293 | } |
461 | else | 294 | else |
462 | { | 295 | { |
463 | searchPredicate = sop => sop.Name == name; | 296 | searchAction = so => so.ForEachPart(sop => { if (sop.Name == name) { parts.Add(sop); } }); |
464 | } | 297 | } |
465 | 298 | ||
466 | OutputSopsToConsole(searchPredicate, true); | 299 | m_scene.ForEachSOG(searchAction); |
467 | } | ||
468 | |||
469 | private void HandleDumpObjectById(string module, string[] cmdparams) | ||
470 | { | ||
471 | if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) | ||
472 | return; | ||
473 | 300 | ||
474 | if (cmdparams.Length < 4) | 301 | if (parts.Count == 0) |
475 | { | 302 | { |
476 | m_console.OutputFormat("Usage: dump object id <UUID-or-localID>"); | 303 | m_console.OutputFormat("No parts with name {0} found in {1}", name, m_scene.RegionInfo.RegionName); |
477 | return; | 304 | return; |
478 | } | 305 | } |
479 | 306 | ||
480 | UUID objectUuid; | 307 | StringBuilder sb = new StringBuilder(); |
481 | uint localId; | ||
482 | if (!ConsoleUtil.TryParseConsoleId(m_console, cmdparams[3], out objectUuid, out localId)) | ||
483 | return; | ||
484 | |||
485 | SceneObjectGroup so; | ||
486 | if (localId == ConsoleUtil.LocalIdNotFound) | ||
487 | so = m_scene.GetSceneObjectGroup(objectUuid); | ||
488 | else | ||
489 | so = m_scene.GetSceneObjectGroup(localId); | ||
490 | 308 | ||
491 | if (so == null) | 309 | foreach (SceneObjectPart part in parts) |
492 | { | 310 | { |
493 | // m_console.OutputFormat("No part found with uuid {0}", objectUuid); | 311 | AddScenePartReport(sb, part); |
494 | return; | 312 | sb.Append("\n"); |
495 | } | 313 | } |
496 | 314 | ||
497 | // In case we found it via local ID. | 315 | m_console.OutputFormat(sb.ToString()); |
498 | objectUuid = so.UUID; | ||
499 | |||
500 | string fileName = string.Format("{0}.xml", objectUuid); | ||
501 | |||
502 | if (!ConsoleUtil.CheckFileDoesNotExist(m_console, fileName)) | ||
503 | return; | ||
504 | |||
505 | using (XmlTextWriter xtw = new XmlTextWriter(fileName, Encoding.UTF8)) | ||
506 | { | ||
507 | xtw.Formatting = Formatting.Indented; | ||
508 | SceneObjectSerializer.ToOriginalXmlFormat(so, xtw, true); | ||
509 | } | ||
510 | |||
511 | m_console.OutputFormat("Object dumped to file {0}", fileName); | ||
512 | } | 316 | } |
513 | 317 | ||
514 | /// <summary> | 318 | private StringBuilder AddSceneObjectReport(StringBuilder sb, SceneObjectGroup so) |
515 | /// Append a scene object report to an input StringBuilder | ||
516 | /// </summary> | ||
517 | /// <returns></returns> | ||
518 | /// <param name='sb'></param> | ||
519 | /// <param name='so'</param> | ||
520 | /// <param name='showFull'> | ||
521 | /// If true then information on all parts of an object is appended. | ||
522 | /// If false then only summary information about an object is appended. | ||
523 | /// </param> | ||
524 | private StringBuilder AddSceneObjectReport(StringBuilder sb, SceneObjectGroup so, bool showFull) | ||
525 | { | 319 | { |
526 | if (showFull) | 320 | sb.AppendFormat("Name: {0}\n", so.Name); |
527 | { | 321 | sb.AppendFormat("Description: {0}\n", so.Description); |
528 | foreach (SceneObjectPart sop in so.Parts) | 322 | sb.AppendFormat("Location: {0} @ {1}\n", so.AbsolutePosition, so.Scene.RegionInfo.RegionName); |
529 | { | 323 | sb.AppendFormat("Parts: {0}\n", so.PrimCount); |
530 | AddScenePartReport(sb, sop, false); | 324 | sb.AppendFormat("Flags: {0}\n", so.RootPart.Flags); |
531 | sb.Append("\n"); | ||
532 | } | ||
533 | } | ||
534 | else | ||
535 | { | ||
536 | AddSummarySceneObjectReport(sb, so); | ||
537 | } | ||
538 | 325 | ||
539 | return sb; | 326 | return sb; |
540 | } | 327 | } |
541 | 328 | ||
542 | private StringBuilder AddSummarySceneObjectReport(StringBuilder sb, SceneObjectGroup so) | 329 | private StringBuilder AddScenePartReport(StringBuilder sb, SceneObjectPart sop) |
543 | { | ||
544 | ConsoleDisplayList cdl = new ConsoleDisplayList(); | ||
545 | cdl.AddRow("Name", so.Name); | ||
546 | cdl.AddRow("Descrition", so.Description); | ||
547 | cdl.AddRow("Local ID", so.LocalId); | ||
548 | cdl.AddRow("UUID", so.UUID); | ||
549 | cdl.AddRow("Location", string.Format("{0} @ {1}", so.AbsolutePosition, so.Scene.Name)); | ||
550 | cdl.AddRow("Parts", so.PrimCount); | ||
551 | cdl.AddRow("Flags", so.RootPart.Flags); | ||
552 | |||
553 | return sb.Append(cdl.ToString()); | ||
554 | } | ||
555 | |||
556 | /// <summary> | ||
557 | /// Append a scene object part report to an input StringBuilder | ||
558 | /// </summary> | ||
559 | /// <returns></returns> | ||
560 | /// <param name='sb'></param> | ||
561 | /// <param name='sop'</param> | ||
562 | /// <param name='showFull'> | ||
563 | /// If true then information on each inventory item will be shown. | ||
564 | /// If false then only summary inventory information is shown. | ||
565 | /// </param> | ||
566 | private StringBuilder AddScenePartReport(StringBuilder sb, SceneObjectPart sop, bool showFull) | ||
567 | { | ||
568 | ConsoleDisplayList cdl = new ConsoleDisplayList(); | ||
569 | cdl.AddRow("Name", sop.Name); | ||
570 | cdl.AddRow("Description", sop.Description); | ||
571 | cdl.AddRow("Local ID", sop.LocalId); | ||
572 | cdl.AddRow("UUID", sop.UUID); | ||
573 | cdl.AddRow("Location", string.Format("{0} @ {1}", sop.AbsolutePosition, sop.ParentGroup.Scene.Name)); | ||
574 | cdl.AddRow( | ||
575 | "Parent", | ||
576 | sop.IsRoot ? "Is Root" : string.Format("{0} {1}", sop.ParentGroup.Name, sop.ParentGroup.UUID)); | ||
577 | cdl.AddRow("Link number", sop.LinkNum); | ||
578 | cdl.AddRow("Flags", sop.Flags); | ||
579 | |||
580 | object itemsOutput; | ||
581 | if (showFull) | ||
582 | { | ||
583 | StringBuilder itemsSb = new StringBuilder("\n"); | ||
584 | itemsOutput = AddScenePartItemsReport(itemsSb, sop.Inventory).ToString(); | ||
585 | } | ||
586 | else | ||
587 | { | ||
588 | itemsOutput = sop.Inventory.Count; | ||
589 | } | ||
590 | |||
591 | |||
592 | cdl.AddRow("Items", itemsOutput); | ||
593 | |||
594 | return sb.Append(cdl.ToString()); | ||
595 | } | ||
596 | |||
597 | private StringBuilder AddScenePartItemsReport(StringBuilder sb, IEntityInventory inv) | ||
598 | { | 330 | { |
599 | ConsoleDisplayTable cdt = new ConsoleDisplayTable(); | 331 | sb.AppendFormat("Name: {0}\n", sop.Name); |
600 | cdt.Indent = 2; | 332 | sb.AppendFormat("Description: {0}\n", sop.Description); |
601 | 333 | sb.AppendFormat("Location: {0} @ {1}\n", sop.AbsolutePosition, sop.ParentGroup.Scene.RegionInfo.RegionName); | |
602 | cdt.AddColumn("Name", 50); | 334 | sb.AppendFormat("Parent: {0}", |
603 | cdt.AddColumn("Type", 12); | 335 | sop.IsRoot ? "Is Root\n" : string.Format("{0} {1}\n", sop.ParentGroup.Name, sop.ParentGroup.UUID)); |
604 | cdt.AddColumn("Running", 7); | 336 | sb.AppendFormat("Link number: {0}\n", sop.LinkNum); |
605 | cdt.AddColumn("Item UUID", 36); | 337 | sb.AppendFormat("Flags: {0}\n", sop.Flags); |
606 | cdt.AddColumn("Asset UUID", 36); | ||
607 | |||
608 | foreach (TaskInventoryItem item in inv.GetInventoryItems()) | ||
609 | { | ||
610 | bool foundScriptInstance, scriptRunning; | ||
611 | foundScriptInstance | ||
612 | = SceneObjectPartInventory.TryGetScriptInstanceRunning(m_scene, item, out scriptRunning); | ||
613 | |||
614 | cdt.AddRow( | ||
615 | item.Name, | ||
616 | ((InventoryType)item.InvType).ToString(), | ||
617 | foundScriptInstance ? scriptRunning.ToString() : "n/a", | ||
618 | item.ItemID.ToString(), | ||
619 | item.AssetID.ToString()); | ||
620 | } | ||
621 | 338 | ||
622 | return sb.Append(cdt.ToString()); | 339 | return sb; |
623 | } | 340 | } |
624 | 341 | ||
625 | private void HandleDeleteObject(string module, string[] cmd) | 342 | private void HandleDeleteObject(string module, string[] cmd) |
@@ -681,24 +398,19 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands | |||
681 | 398 | ||
682 | break; | 399 | break; |
683 | 400 | ||
684 | case "id": | 401 | case "uuid": |
685 | UUID uuid; | 402 | if (!UUID.TryParse(o, out match)) |
686 | uint localId; | ||
687 | if (!ConsoleUtil.TryParseConsoleId(m_console, o, out uuid, out localId)) | ||
688 | return; | 403 | return; |
689 | 404 | ||
690 | requireConfirmation = false; | 405 | requireConfirmation = false; |
691 | deletes = new List<SceneObjectGroup>(); | 406 | deletes = new List<SceneObjectGroup>(); |
692 | 407 | ||
693 | SceneObjectGroup so; | 408 | m_scene.ForEachSOG(delegate (SceneObjectGroup g) |
694 | if (localId == ConsoleUtil.LocalIdNotFound) | 409 | { |
695 | so = m_scene.GetSceneObjectGroup(uuid); | 410 | if (g.UUID == match && !g.IsAttachment) |
696 | else | 411 | deletes.Add(g); |
697 | so = m_scene.GetSceneObjectGroup(localId); | 412 | }); |
698 | 413 | ||
699 | if (!so.IsAttachment) | ||
700 | deletes.Add(so); | ||
701 | |||
702 | // if (deletes.Count == 0) | 414 | // if (deletes.Count == 0) |
703 | // m_console.OutputFormat("No objects were found with uuid {0}", match); | 415 | // m_console.OutputFormat("No objects were found with uuid {0}", match); |
704 | 416 | ||
@@ -738,10 +450,6 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands | |||
738 | 450 | ||
739 | break; | 451 | break; |
740 | 452 | ||
741 | case "pos": | ||
742 | deletes = GetDeleteCandidatesByPos(module, cmd); | ||
743 | break; | ||
744 | |||
745 | default: | 453 | default: |
746 | m_console.OutputFormat("Unrecognized mode {0}", mode); | 454 | m_console.OutputFormat("Unrecognized mode {0}", mode); |
747 | return; | 455 | return; |
@@ -756,7 +464,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands | |||
756 | string.Format( | 464 | string.Format( |
757 | "Are you sure that you want to delete {0} objects from {1}", | 465 | "Are you sure that you want to delete {0} objects from {1}", |
758 | deletes.Count, m_scene.RegionInfo.RegionName), | 466 | deletes.Count, m_scene.RegionInfo.RegionName), |
759 | "y/N"); | 467 | "n"); |
760 | 468 | ||
761 | if (response.ToLower() != "y") | 469 | if (response.ToLower() != "y") |
762 | { | 470 | { |
@@ -778,6 +486,9 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands | |||
778 | 486 | ||
779 | private List<SceneObjectGroup> GetDeleteCandidatesByName(string module, string[] cmdparams) | 487 | private List<SceneObjectGroup> GetDeleteCandidatesByName(string module, string[] cmdparams) |
780 | { | 488 | { |
489 | if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) | ||
490 | return null; | ||
491 | |||
781 | bool useRegex = false; | 492 | bool useRegex = false; |
782 | OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null ); | 493 | OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null ); |
783 | 494 | ||
@@ -811,52 +522,5 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands | |||
811 | 522 | ||
812 | return sceneObjects; | 523 | return sceneObjects; |
813 | } | 524 | } |
814 | |||
815 | /// <summary> | ||
816 | /// Get scene object delete candidates by position | ||
817 | /// </summary> | ||
818 | /// <param name='module'></param> | ||
819 | /// <param name='cmdparams'></param> | ||
820 | /// <returns>null if parsing failed on one of the arguments, otherwise a list of objects to delete. If there | ||
821 | /// are no objects to delete then the list will be empty./returns> | ||
822 | private List<SceneObjectGroup> GetDeleteCandidatesByPos(string module, string[] cmdparams) | ||
823 | { | ||
824 | if (cmdparams.Length < 5) | ||
825 | { | ||
826 | m_console.OutputFormat("Usage: delete object pos <start-coord> to <end-coord>"); | ||
827 | return null; | ||
828 | } | ||
829 | |||
830 | Vector3 startVector, endVector; | ||
831 | |||
832 | if (!TryParseVectorRange(cmdparams.Skip(3).Take(3), out startVector, out endVector)) | ||
833 | return null; | ||
834 | |||
835 | return m_scene.GetSceneObjectGroups().FindAll( | ||
836 | so => !so.IsAttachment && Util.IsInsideBox(so.AbsolutePosition, startVector, endVector)); | ||
837 | } | ||
838 | |||
839 | private bool TryParseVectorRange(IEnumerable<string> rawComponents, out Vector3 startVector, out Vector3 endVector) | ||
840 | { | ||
841 | string rawConsoleStartVector = rawComponents.Take(1).Single(); | ||
842 | |||
843 | if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector)) | ||
844 | { | ||
845 | m_console.OutputFormat("Error: Start vector {0} does not have a valid format", rawConsoleStartVector); | ||
846 | endVector = Vector3.Zero; | ||
847 | |||
848 | return false; | ||
849 | } | ||
850 | |||
851 | string rawConsoleEndVector = rawComponents.Skip(1).Take(1).Single(); | ||
852 | |||
853 | if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector)) | ||
854 | { | ||
855 | m_console.OutputFormat("Error: End vector {0} does not have a valid format", rawConsoleEndVector); | ||
856 | return false; | ||
857 | } | ||
858 | |||
859 | return true; | ||
860 | } | ||
861 | } | 525 | } |
862 | } \ No newline at end of file | 526 | } \ No newline at end of file |
diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs index 513a8f5..14c1a39 100644 --- a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs +++ b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs | |||
@@ -1,4 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) Contributors, http://opensimulator.org/ | 2 | * Copyright (c) Contributors, http://opensimulator.org/ |
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | 3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. |
4 | * | 4 | * |
@@ -24,110 +24,56 @@ | |||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | 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. | 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ | 26 | */ |
27 | using System; | ||
28 | using System.IO; | ||
29 | using System.Collections.Generic; | ||
30 | using System.Reflection; | ||
31 | 27 | ||
28 | using System; | ||
32 | using Nini.Config; | 29 | using Nini.Config; |
33 | using OpenMetaverse; | 30 | using OpenMetaverse; |
34 | using log4net; | ||
35 | using Mono.Addins; | ||
36 | |||
37 | using OpenSim.Framework; | 31 | using OpenSim.Framework; |
38 | using OpenSim.Region.Framework.Interfaces; | 32 | using OpenSim.Region.Framework.Interfaces; |
39 | using OpenSim.Region.Framework.Scenes; | 33 | using OpenSim.Region.Framework.Scenes; |
34 | using System.Reflection; | ||
35 | using log4net; | ||
40 | 36 | ||
41 | namespace OpenSim.Region.CoreModules.World.Sound | 37 | namespace OpenSim.Region.CoreModules.World.Sound |
42 | { | 38 | { |
43 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SoundModule")] | 39 | public class SoundModule : IRegionModule, ISoundModule |
44 | public class SoundModule : INonSharedRegionModule, ISoundModule | ||
45 | { | 40 | { |
46 | private static readonly ILog m_log = LogManager.GetLogger( | 41 | // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
47 | MethodBase.GetCurrentMethod().DeclaringType); | 42 | |
48 | 43 | protected Scene m_scene; | |
49 | private Scene m_scene; | 44 | |
50 | 45 | public void Initialise(Scene scene, IConfigSource source) | |
51 | public bool Enabled { get; private set; } | ||
52 | |||
53 | public float MaxDistance { get; private set; } | ||
54 | |||
55 | #region INonSharedRegionModule | ||
56 | |||
57 | public void Initialise(IConfigSource configSource) | ||
58 | { | ||
59 | IConfig config = configSource.Configs["Sounds"]; | ||
60 | |||
61 | if (config == null) | ||
62 | { | ||
63 | Enabled = true; | ||
64 | MaxDistance = 100.0f; | ||
65 | } | ||
66 | else | ||
67 | { | ||
68 | Enabled = config.GetString("Module", "OpenSim.Region.CoreModules.dll:SoundModule") == | ||
69 | Path.GetFileName(Assembly.GetExecutingAssembly().Location) | ||
70 | + ":" + MethodBase.GetCurrentMethod().DeclaringType.Name; | ||
71 | MaxDistance = config.GetFloat("MaxDistance", 100.0f); | ||
72 | } | ||
73 | } | ||
74 | |||
75 | public void AddRegion(Scene scene) { } | ||
76 | |||
77 | public void RemoveRegion(Scene scene) | ||
78 | { | 46 | { |
79 | m_scene.EventManager.OnClientLogin -= OnNewClient; | ||
80 | } | ||
81 | |||
82 | public void RegionLoaded(Scene scene) | ||
83 | { | ||
84 | if (!Enabled) | ||
85 | return; | ||
86 | |||
87 | m_scene = scene; | 47 | m_scene = scene; |
88 | m_scene.EventManager.OnClientLogin += OnNewClient; | 48 | |
89 | 49 | m_scene.EventManager.OnNewClient += OnNewClient; | |
50 | |||
90 | m_scene.RegisterModuleInterface<ISoundModule>(this); | 51 | m_scene.RegisterModuleInterface<ISoundModule>(this); |
91 | } | 52 | } |
92 | 53 | ||
93 | public void Close() { } | 54 | public void PostInitialise() {} |
94 | 55 | public void Close() {} | |
95 | public Type ReplaceableInterface | ||
96 | { | ||
97 | get { return typeof(ISoundModule); } | ||
98 | } | ||
99 | |||
100 | public string Name { get { return "Sound Module"; } } | 56 | public string Name { get { return "Sound Module"; } } |
101 | 57 | public bool IsSharedModule { get { return false; } } | |
102 | #endregion | 58 | |
103 | |||
104 | #region Event Handlers | ||
105 | |||
106 | private void OnNewClient(IClientAPI client) | 59 | private void OnNewClient(IClientAPI client) |
107 | { | 60 | { |
108 | client.OnSoundTrigger += TriggerSound; | 61 | client.OnSoundTrigger += TriggerSound; |
109 | } | 62 | } |
110 | 63 | ||
111 | #endregion | ||
112 | |||
113 | #region ISoundModule | ||
114 | |||
115 | public virtual void PlayAttachedSound( | 64 | public virtual void PlayAttachedSound( |
116 | UUID soundID, UUID ownerID, UUID objectID, double gain, Vector3 position, byte flags, float radius) | 65 | UUID soundID, UUID ownerID, UUID objectID, double gain, Vector3 position, byte flags, float radius) |
117 | { | 66 | { |
118 | SceneObjectPart part; | 67 | SceneObjectPart part = m_scene.GetSceneObjectPart(objectID); |
119 | if (!m_scene.TryGetSceneObjectPart(objectID, out part)) | 68 | if (part == null) |
120 | return; | 69 | return; |
121 | 70 | ||
122 | SceneObjectGroup grp = part.ParentGroup; | 71 | SceneObjectGroup grp = part.ParentGroup; |
123 | 72 | ||
124 | if (radius == 0) | ||
125 | radius = MaxDistance; | ||
126 | |||
127 | m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) | 73 | m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) |
128 | { | 74 | { |
129 | double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); | 75 | double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); |
130 | if (dis > MaxDistance) // Max audio distance | 76 | if (dis > 100.0) // Max audio distance |
131 | return; | 77 | return; |
132 | 78 | ||
133 | if (grp.IsAttachment) | 79 | if (grp.IsAttachment) |
@@ -140,21 +86,23 @@ namespace OpenSim.Region.CoreModules.World.Sound | |||
140 | } | 86 | } |
141 | 87 | ||
142 | // Scale by distance | 88 | // Scale by distance |
143 | double thisSpGain = gain * ((radius - dis) / radius); | 89 | if (radius == 0) |
90 | gain = (float)((double)gain * ((100.0 - dis) / 100.0)); | ||
91 | else | ||
92 | gain = (float)((double)gain * ((radius - dis) / radius)); | ||
144 | 93 | ||
145 | sp.ControllingClient.SendPlayAttachedSound(soundID, objectID, | 94 | sp.ControllingClient.SendPlayAttachedSound(soundID, objectID, ownerID, (float)gain, flags); |
146 | ownerID, (float)thisSpGain, flags); | ||
147 | }); | 95 | }); |
148 | } | 96 | } |
149 | 97 | ||
150 | public virtual void TriggerSound( | 98 | public virtual void TriggerSound( |
151 | UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius) | 99 | UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius) |
152 | { | 100 | { |
153 | SceneObjectPart part; | 101 | SceneObjectPart part = m_scene.GetSceneObjectPart(objectID); |
154 | if (!m_scene.TryGetSceneObjectPart(objectID, out part)) | 102 | if (part == null) |
155 | { | 103 | { |
156 | ScenePresence sp; | 104 | ScenePresence sp; |
157 | if (!m_scene.TryGetScenePresence(ownerID, out sp)) | 105 | if (!m_scene.TryGetScenePresence(objectID, out sp)) |
158 | return; | 106 | return; |
159 | } | 107 | } |
160 | else | 108 | else |
@@ -168,207 +116,24 @@ namespace OpenSim.Region.CoreModules.World.Sound | |||
168 | } | 116 | } |
169 | } | 117 | } |
170 | 118 | ||
171 | if (radius == 0) | ||
172 | radius = MaxDistance; | ||
173 | |||
174 | m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) | 119 | m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) |
175 | { | 120 | { |
176 | double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); | 121 | double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); |
177 | 122 | ||
178 | if (dis > MaxDistance) // Max audio distance | 123 | if (dis > 100.0) // Max audio distance |
179 | return; | 124 | return; |
180 | 125 | ||
181 | // Scale by distance | 126 | float thisSpGain; |
182 | double thisSpGain = gain * ((radius - dis) / radius); | ||
183 | |||
184 | sp.ControllingClient.SendTriggeredSound(soundId, ownerID, | ||
185 | objectID, parentID, handle, position, | ||
186 | (float)thisSpGain); | ||
187 | }); | ||
188 | } | ||
189 | |||
190 | public virtual void StopSound(UUID objectID) | ||
191 | { | ||
192 | SceneObjectPart m_host; | ||
193 | if (!m_scene.TryGetSceneObjectPart(objectID, out m_host)) | ||
194 | return; | ||
195 | |||
196 | StopSound(m_host); | ||
197 | } | ||
198 | |||
199 | private static void StopSound(SceneObjectPart m_host) | ||
200 | { | ||
201 | m_host.AdjustSoundGain(0); | ||
202 | // Xantor 20080528: Clear prim data of sound instead | ||
203 | if (m_host.ParentGroup.LoopSoundSlavePrims.Contains(m_host)) | ||
204 | { | ||
205 | if (m_host.ParentGroup.LoopSoundMasterPrim == m_host) | ||
206 | { | ||
207 | foreach (SceneObjectPart part in m_host.ParentGroup.LoopSoundSlavePrims) | ||
208 | { | ||
209 | part.Sound = UUID.Zero; | ||
210 | part.SoundFlags = 1 << 5; | ||
211 | part.SoundRadius = 0; | ||
212 | part.ScheduleFullUpdate(); | ||
213 | part.SendFullUpdateToAllClients(); | ||
214 | } | ||
215 | m_host.ParentGroup.LoopSoundMasterPrim = null; | ||
216 | m_host.ParentGroup.LoopSoundSlavePrims.Clear(); | ||
217 | } | ||
218 | else | ||
219 | { | ||
220 | m_host.Sound = UUID.Zero; | ||
221 | m_host.SoundFlags = 1 << 5; | ||
222 | m_host.SoundRadius = 0; | ||
223 | m_host.ScheduleFullUpdate(); | ||
224 | m_host.SendFullUpdateToAllClients(); | ||
225 | } | ||
226 | } | ||
227 | else | ||
228 | { | ||
229 | m_host.Sound = UUID.Zero; | ||
230 | m_host.SoundFlags = 1 << 5; | ||
231 | m_host.SoundRadius = 0; | ||
232 | m_host.ScheduleFullUpdate(); | ||
233 | m_host.SendFullUpdateToAllClients(); | ||
234 | } | ||
235 | } | ||
236 | |||
237 | public virtual void PreloadSound(UUID objectID, UUID soundID, float radius) | ||
238 | { | ||
239 | SceneObjectPart part; | ||
240 | if (soundID == UUID.Zero | ||
241 | || !m_scene.TryGetSceneObjectPart(objectID, out part)) | ||
242 | { | ||
243 | return; | ||
244 | } | ||
245 | |||
246 | if (radius == 0) | ||
247 | radius = MaxDistance; | ||
248 | |||
249 | m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) | ||
250 | { | ||
251 | if (!(Util.GetDistanceTo(sp.AbsolutePosition, part.AbsolutePosition) >= MaxDistance)) | ||
252 | sp.ControllingClient.SendPreLoadSound(objectID, objectID, soundID); | ||
253 | }); | ||
254 | } | ||
255 | |||
256 | // Xantor 20080528 we should do this differently. | ||
257 | // 1) apply the sound to the object | ||
258 | // 2) schedule full update | ||
259 | // just sending the sound out once doesn't work so well when other avatars come in view later on | ||
260 | // or when the prim gets moved, changed, sat on, whatever | ||
261 | // see large number of mantises (mantes?) | ||
262 | // 20080530 Updated to remove code duplication | ||
263 | // 20080530 Stop sound if there is one, otherwise volume only changes don't work | ||
264 | public void LoopSound(UUID objectID, UUID soundID, | ||
265 | double volume, double radius, bool isMaster) | ||
266 | { | ||
267 | SceneObjectPart m_host; | ||
268 | if (!m_scene.TryGetSceneObjectPart(objectID, out m_host)) | ||
269 | return; | ||
270 | |||
271 | if (isMaster) | ||
272 | m_host.ParentGroup.LoopSoundMasterPrim = m_host; | ||
273 | |||
274 | if (m_host.Sound != UUID.Zero) | ||
275 | StopSound(m_host); | ||
276 | |||
277 | m_host.Sound = soundID; | ||
278 | m_host.SoundGain = volume; | ||
279 | m_host.SoundFlags = 1; // looping | ||
280 | m_host.SoundRadius = radius; | ||
281 | |||
282 | m_host.ScheduleFullUpdate(); | ||
283 | m_host.SendFullUpdateToAllClients(); | ||
284 | } | ||
285 | |||
286 | public void SendSound(UUID objectID, UUID soundID, double volume, | ||
287 | bool triggered, byte flags, float radius, bool useMaster, | ||
288 | bool isMaster) | ||
289 | { | ||
290 | if (soundID == UUID.Zero) | ||
291 | return; | ||
292 | |||
293 | SceneObjectPart part; | ||
294 | if (!m_scene.TryGetSceneObjectPart(objectID, out part)) | ||
295 | return; | ||
296 | |||
297 | volume = Util.Clip((float)volume, 0, 1); | ||
298 | |||
299 | UUID parentID = part.ParentGroup.UUID; | ||
300 | |||
301 | Vector3 position = part.AbsolutePosition; // region local | ||
302 | ulong regionHandle = m_scene.RegionInfo.RegionHandle; | ||
303 | |||
304 | if (useMaster) | ||
305 | { | ||
306 | if (isMaster) | ||
307 | { | ||
308 | if (triggered) | ||
309 | TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius); | ||
310 | else | ||
311 | PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius); | ||
312 | part.ParentGroup.PlaySoundMasterPrim = part; | ||
313 | if (triggered) | ||
314 | TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius); | ||
315 | else | ||
316 | PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius); | ||
317 | foreach (SceneObjectPart prim in part.ParentGroup.PlaySoundSlavePrims) | ||
318 | { | ||
319 | position = prim.AbsolutePosition; // region local | ||
320 | if (triggered) | ||
321 | TriggerSound(soundID, part.OwnerID, prim.UUID, parentID, volume, position, regionHandle, radius); | ||
322 | else | ||
323 | PlayAttachedSound(soundID, part.OwnerID, prim.UUID, volume, position, flags, radius); | ||
324 | } | ||
325 | part.ParentGroup.PlaySoundSlavePrims.Clear(); | ||
326 | part.ParentGroup.PlaySoundMasterPrim = null; | ||
327 | } | ||
328 | else | ||
329 | { | ||
330 | part.ParentGroup.PlaySoundSlavePrims.Add(part); | ||
331 | } | ||
332 | } | ||
333 | else | ||
334 | { | ||
335 | if (triggered) | ||
336 | TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius); | ||
337 | else | ||
338 | PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius); | ||
339 | } | ||
340 | } | ||
341 | |||
342 | public void TriggerSoundLimited(UUID objectID, UUID sound, | ||
343 | double volume, Vector3 min, Vector3 max) | ||
344 | { | ||
345 | if (sound == UUID.Zero) | ||
346 | return; | ||
347 | |||
348 | SceneObjectPart part; | ||
349 | if (!m_scene.TryGetSceneObjectPart(objectID, out part)) | ||
350 | return; | ||
351 | |||
352 | m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) | ||
353 | { | ||
354 | double dis = Util.GetDistanceTo(sp.AbsolutePosition, | ||
355 | part.AbsolutePosition); | ||
356 | |||
357 | if (dis > MaxDistance) // Max audio distance | ||
358 | return; | ||
359 | else if (!Util.IsInsideBox(sp.AbsolutePosition, min, max)) | ||
360 | return; | ||
361 | 127 | ||
362 | // Scale by distance | 128 | // Scale by distance |
363 | double thisSpGain = volume * ((MaxDistance - dis) / MaxDistance); | 129 | if (radius == 0) |
130 | thisSpGain = (float)((double)gain * ((100.0 - dis) / 100.0)); | ||
131 | else | ||
132 | thisSpGain = (float)((double)gain * ((radius - dis) / radius)); | ||
364 | 133 | ||
365 | sp.ControllingClient.SendTriggeredSound(sound, part.OwnerID, | 134 | sp.ControllingClient.SendTriggeredSound( |
366 | part.UUID, part.ParentGroup.UUID, | 135 | soundId, ownerID, objectID, parentID, handle, position, thisSpGain); |
367 | m_scene.RegionInfo.RegionHandle, | ||
368 | part.AbsolutePosition, (float)thisSpGain); | ||
369 | }); | 136 | }); |
370 | } | 137 | } |
371 | |||
372 | #endregion | ||
373 | } | 138 | } |
374 | } | 139 | } |
diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs index d99567c..402b9fb 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs | |||
@@ -414,7 +414,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
414 | private void LoadPlugins() | 414 | private void LoadPlugins() |
415 | { | 415 | { |
416 | m_plugineffects = new Dictionary<string, ITerrainEffect>(); | 416 | m_plugineffects = new Dictionary<string, ITerrainEffect>(); |
417 | LoadPlugins(Assembly.GetCallingAssembly()); | ||
418 | string plugineffectsPath = "Terrain"; | 417 | string plugineffectsPath = "Terrain"; |
419 | 418 | ||
420 | // Load the files in the Terrain/ dir | 419 | // Load the files in the Terrain/ dir |
@@ -428,39 +427,34 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
428 | try | 427 | try |
429 | { | 428 | { |
430 | Assembly library = Assembly.LoadFrom(file); | 429 | Assembly library = Assembly.LoadFrom(file); |
431 | LoadPlugins(library); | 430 | foreach (Type pluginType in library.GetTypes()) |
432 | } | 431 | { |
433 | catch (BadImageFormatException) | 432 | try |
434 | { | 433 | { |
435 | } | 434 | if (pluginType.IsAbstract || pluginType.IsNotPublic) |
436 | } | 435 | continue; |
437 | } | ||
438 | |||
439 | private void LoadPlugins(Assembly library) | ||
440 | { | ||
441 | foreach (Type pluginType in library.GetTypes()) | ||
442 | { | ||
443 | try | ||
444 | { | ||
445 | if (pluginType.IsAbstract || pluginType.IsNotPublic) | ||
446 | continue; | ||
447 | 436 | ||
448 | string typeName = pluginType.Name; | 437 | string typeName = pluginType.Name; |
449 | 438 | ||
450 | if (pluginType.GetInterface("ITerrainEffect", false) != null) | 439 | if (pluginType.GetInterface("ITerrainEffect", false) != null) |
451 | { | 440 | { |
452 | ITerrainEffect terEffect = (ITerrainEffect)Activator.CreateInstance(library.GetType(pluginType.ToString())); | 441 | ITerrainEffect terEffect = (ITerrainEffect) Activator.CreateInstance(library.GetType(pluginType.ToString())); |
453 | 442 | ||
454 | InstallPlugin(typeName, terEffect); | 443 | InstallPlugin(typeName, terEffect); |
455 | } | 444 | } |
456 | else if (pluginType.GetInterface("ITerrainLoader", false) != null) | 445 | else if (pluginType.GetInterface("ITerrainLoader", false) != null) |
457 | { | 446 | { |
458 | ITerrainLoader terLoader = (ITerrainLoader)Activator.CreateInstance(library.GetType(pluginType.ToString())); | 447 | ITerrainLoader terLoader = (ITerrainLoader) Activator.CreateInstance(library.GetType(pluginType.ToString())); |
459 | m_loaders[terLoader.FileExtension] = terLoader; | 448 | m_loaders[terLoader.FileExtension] = terLoader; |
460 | m_log.Info("L ... " + typeName); | 449 | m_log.Info("L ... " + typeName); |
450 | } | ||
451 | } | ||
452 | catch (AmbiguousMatchException) | ||
453 | { | ||
454 | } | ||
461 | } | 455 | } |
462 | } | 456 | } |
463 | catch (AmbiguousMatchException) | 457 | catch (BadImageFormatException) |
464 | { | 458 | { |
465 | } | 459 | } |
466 | } | 460 | } |
@@ -1184,8 +1178,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
1184 | 1178 | ||
1185 | private void InterfaceRunPluginEffect(Object[] args) | 1179 | private void InterfaceRunPluginEffect(Object[] args) |
1186 | { | 1180 | { |
1187 | string firstArg = (string)args[0]; | 1181 | if ((string) args[0] == "list") |
1188 | if (firstArg == "list") | ||
1189 | { | 1182 | { |
1190 | m_log.Info("List of loaded plugins"); | 1183 | m_log.Info("List of loaded plugins"); |
1191 | foreach (KeyValuePair<string, ITerrainEffect> kvp in m_plugineffects) | 1184 | foreach (KeyValuePair<string, ITerrainEffect> kvp in m_plugineffects) |
@@ -1194,14 +1187,14 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
1194 | } | 1187 | } |
1195 | return; | 1188 | return; |
1196 | } | 1189 | } |
1197 | if (firstArg == "reload") | 1190 | if ((string) args[0] == "reload") |
1198 | { | 1191 | { |
1199 | LoadPlugins(); | 1192 | LoadPlugins(); |
1200 | return; | 1193 | return; |
1201 | } | 1194 | } |
1202 | if (m_plugineffects.ContainsKey(firstArg)) | 1195 | if (m_plugineffects.ContainsKey((string) args[0])) |
1203 | { | 1196 | { |
1204 | m_plugineffects[firstArg].RunEffect(m_channel); | 1197 | m_plugineffects[(string) args[0]].RunEffect(m_channel); |
1205 | CheckForTerrainUpdates(); | 1198 | CheckForTerrainUpdates(); |
1206 | } | 1199 | } |
1207 | else | 1200 | else |
diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs index 33f6c3f..3c48d07 100644 --- a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs +++ b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs | |||
@@ -222,13 +222,6 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
222 | bitmap = ImageUtils.ResizeImage(origBitmap, viewport.Width, viewport.Height); | 222 | bitmap = ImageUtils.ResizeImage(origBitmap, viewport.Width, viewport.Height); |
223 | } | 223 | } |
224 | 224 | ||
225 | // XXX: It shouldn't really be necesary to force a GC here as one should occur anyway pretty shortly | ||
226 | // afterwards. It's generally regarded as a bad idea to manually GC. If Warp3D is using lots of memory | ||
227 | // then this may be some issue with the Warp3D code itself, though it's also quite possible that generating | ||
228 | // this map tile simply takes a lot of memory. | ||
229 | GC.Collect(); | ||
230 | m_log.Debug("[WARP 3D IMAGE MODULE]: GC.Collect()"); | ||
231 | |||
232 | return bitmap; | 225 | return bitmap; |
233 | } | 226 | } |
234 | 227 | ||
diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs index d781eae..90a13a7 100644 --- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs | |||
@@ -114,15 +114,6 @@ namespace OpenSim.Region.Framework.Interfaces | |||
114 | void DetachSingleAttachmentToGround(IScenePresence sp, uint objectLocalID); | 114 | void DetachSingleAttachmentToGround(IScenePresence sp, uint objectLocalID); |
115 | 115 | ||
116 | /// <summary> | 116 | /// <summary> |
117 | /// Detach the given item to the ground at the specified coordinates & rotation | ||
118 | /// </summary> | ||
119 | /// <param name="sp"></param> | ||
120 | /// <param name="objectLocalID"></param> | ||
121 | /// <param name="absolutePos"></param> | ||
122 | /// <param name="absoluteRot"></param> | ||
123 | void DetachSingleAttachmentToGround(IScenePresence sp, uint objectLocalID, Vector3 absolutePos, Quaternion absoluteRot); | ||
124 | |||
125 | /// <summary> | ||
126 | /// Detach the given attachment so that it remains in the user's inventory. | 117 | /// Detach the given attachment so that it remains in the user's inventory. |
127 | /// </summary> | 118 | /// </summary> |
128 | /// <param name="sp">/param> | 119 | /// <param name="sp">/param> |
diff --git a/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs b/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs index 6df5cc2..8954513 100644 --- a/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs +++ b/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs | |||
@@ -25,8 +25,6 @@ | |||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | using System; | ||
29 | using System.Drawing; | ||
30 | using System.IO; | 28 | using System.IO; |
31 | using OpenMetaverse; | 29 | using OpenMetaverse; |
32 | 30 | ||
@@ -35,14 +33,7 @@ namespace OpenSim.Region.Framework.Interfaces | |||
35 | public interface IDynamicTextureManager | 33 | public interface IDynamicTextureManager |
36 | { | 34 | { |
37 | void RegisterRender(string handleType, IDynamicTextureRender render); | 35 | void RegisterRender(string handleType, IDynamicTextureRender render); |
38 | 36 | void ReturnData(UUID id, byte[] data); | |
39 | /// <summary> | ||
40 | /// Used by IDynamicTextureRender implementations to return renders | ||
41 | /// </summary> | ||
42 | /// <param name='id'></param> | ||
43 | /// <param name='data'></param> | ||
44 | /// <param name='isReuseable'></param> | ||
45 | void ReturnData(UUID id, IDynamicTexture texture); | ||
46 | 37 | ||
47 | UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams, | 38 | UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams, |
48 | int updateTimer); | 39 | int updateTimer); |
@@ -122,65 +113,11 @@ namespace OpenSim.Region.Framework.Interfaces | |||
122 | string GetName(); | 113 | string GetName(); |
123 | string GetContentType(); | 114 | string GetContentType(); |
124 | bool SupportsAsynchronous(); | 115 | bool SupportsAsynchronous(); |
125 | 116 | byte[] ConvertUrl(string url, string extraParams); | |
126 | // /// <summary> | 117 | byte[] ConvertStream(Stream data, string extraParams); |
127 | // /// Return true if converting the input body and extra params data will always result in the same byte[] array | ||
128 | // /// </summary> | ||
129 | // /// <remarks> | ||
130 | // /// This method allows the caller to use a previously generated asset if it has one. | ||
131 | // /// </remarks> | ||
132 | // /// <returns></returns> | ||
133 | // /// <param name='bodyData'></param> | ||
134 | // /// <param name='extraParams'></param> | ||
135 | // bool AlwaysIdenticalConversion(string bodyData, string extraParams); | ||
136 | |||
137 | IDynamicTexture ConvertUrl(string url, string extraParams); | ||
138 | IDynamicTexture ConvertData(string bodyData, string extraParams); | ||
139 | |||
140 | bool AsyncConvertUrl(UUID id, string url, string extraParams); | 118 | bool AsyncConvertUrl(UUID id, string url, string extraParams); |
141 | bool AsyncConvertData(UUID id, string bodyData, string extraParams); | 119 | bool AsyncConvertData(UUID id, string bodyData, string extraParams); |
142 | |||
143 | void GetDrawStringSize(string text, string fontName, int fontSize, | 120 | void GetDrawStringSize(string text, string fontName, int fontSize, |
144 | out double xSize, out double ySize); | 121 | out double xSize, out double ySize); |
145 | } | 122 | } |
146 | |||
147 | public interface IDynamicTexture | ||
148 | { | ||
149 | /// <summary> | ||
150 | /// Input commands used to generate this data. | ||
151 | /// </summary> | ||
152 | /// <remarks> | ||
153 | /// Null if input commands were not used. | ||
154 | /// </remarks> | ||
155 | string InputCommands { get; } | ||
156 | |||
157 | /// <summary> | ||
158 | /// Uri used to generate this data. | ||
159 | /// </summary> | ||
160 | /// <remarks> | ||
161 | /// Null if a uri was not used. | ||
162 | /// </remarks> | ||
163 | Uri InputUri { get; } | ||
164 | |||
165 | /// <summary> | ||
166 | /// Extra input params used to generate this data. | ||
167 | /// </summary> | ||
168 | string InputParams { get; } | ||
169 | |||
170 | /// <summary> | ||
171 | /// Texture data. | ||
172 | /// </summary> | ||
173 | byte[] Data { get; } | ||
174 | |||
175 | /// <summary> | ||
176 | /// Size of texture. | ||
177 | /// </summary> | ||
178 | Size Size { get; } | ||
179 | |||
180 | /// <summary> | ||
181 | /// Signal whether the texture is reuseable (i.e. whether the same input data will always generate the same | ||
182 | /// texture). | ||
183 | /// </summary> | ||
184 | bool IsReuseable { get; } | ||
185 | } | ||
186 | } | 123 | } |
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs index 8028d87..4274cbe 100644 --- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs +++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs | |||
@@ -152,19 +152,6 @@ namespace OpenSim.Region.Framework.Interfaces | |||
152 | void StopScriptInstance(UUID itemId); | 152 | void StopScriptInstance(UUID itemId); |
153 | 153 | ||
154 | /// <summary> | 154 | /// <summary> |
155 | /// Try to get the script running status. | ||
156 | /// </summary> | ||
157 | /// <returns> | ||
158 | /// Returns true if a script for the item was found in one of the simulator's script engines. In this case, | ||
159 | /// the running parameter will reflect the running status. | ||
160 | /// Returns false if the item could not be found, if the item is not a script or if a script instance for the | ||
161 | /// item was not found in any of the script engines. In this case, running status is irrelevant. | ||
162 | /// </returns> | ||
163 | /// <param name='itemId'></param> | ||
164 | /// <param name='running'></param> | ||
165 | bool TryGetScriptInstanceRunning(UUID itemId, out bool running); | ||
166 | |||
167 | /// <summary> | ||
168 | /// Add an item to this entity's inventory. If an item with the same name already exists, then an alternative | 155 | /// Add an item to this entity's inventory. If an item with the same name already exists, then an alternative |
169 | /// name is chosen. | 156 | /// name is chosen. |
170 | /// </summary> | 157 | /// </summary> |
@@ -283,25 +270,17 @@ namespace OpenSim.Region.Framework.Interfaces | |||
283 | void ApplyGodPermissions(uint perms); | 270 | void ApplyGodPermissions(uint perms); |
284 | 271 | ||
285 | /// <summary> | 272 | /// <summary> |
286 | /// Number of items in this inventory. | ||
287 | /// </summary> | ||
288 | int Count { get; } | ||
289 | |||
290 | /// <summary> | ||
291 | /// Returns true if this inventory contains any scripts | 273 | /// Returns true if this inventory contains any scripts |
292 | /// </summary></returns> | 274 | /// </summary></returns> |
293 | bool ContainsScripts(); | 275 | bool ContainsScripts(); |
294 | 276 | ||
295 | /// <summary> | 277 | /// <summary> |
296 | /// Number of scripts in this inventory. | 278 | /// Returns the count of scripts contained |
297 | /// </summary> | 279 | /// </summary></returns> |
298 | /// <remarks> | ||
299 | /// Includes both running and non running scripts. | ||
300 | /// </remarks> | ||
301 | int ScriptCount(); | 280 | int ScriptCount(); |
302 | 281 | ||
303 | /// <summary> | 282 | /// <summary> |
304 | /// Number of running scripts in this inventory. | 283 | /// Returns the count of running scripts contained |
305 | /// </summary></returns> | 284 | /// </summary></returns> |
306 | int RunningScriptCount(); | 285 | int RunningScriptCount(); |
307 | 286 | ||
diff --git a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs index 292efa4..ca2ad94 100644 --- a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs | |||
@@ -46,10 +46,6 @@ namespace OpenSim.Region.Framework.Interfaces | |||
46 | /// </summary> | 46 | /// </summary> |
47 | void sendRegionHandshakeToAll(); | 47 | void sendRegionHandshakeToAll(); |
48 | void TriggerEstateInfoChange(); | 48 | void TriggerEstateInfoChange(); |
49 | |||
50 | /// <summary> | ||
51 | /// Fires the OnRegionInfoChange event. | ||
52 | /// </summary> | ||
53 | void TriggerRegionInfoChange(); | 49 | void TriggerRegionInfoChange(); |
54 | 50 | ||
55 | void setEstateTerrainBaseTexture(int level, UUID texture); | 51 | void setEstateTerrainBaseTexture(int level, UUID texture); |
diff --git a/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs b/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs index da39e95..baac6e8 100644 --- a/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs | |||
@@ -35,7 +35,7 @@ namespace OpenSim.Region.Framework.Interfaces | |||
35 | 35 | ||
36 | public interface IJsonStoreModule | 36 | public interface IJsonStoreModule |
37 | { | 37 | { |
38 | bool CreateStore(string value, ref UUID result); | 38 | bool CreateStore(string value, out UUID result); |
39 | bool DestroyStore(UUID storeID); | 39 | bool DestroyStore(UUID storeID); |
40 | bool TestPath(UUID storeID, string path, bool useJson); | 40 | bool TestPath(UUID storeID, string path, bool useJson); |
41 | bool SetValue(UUID storeID, string path, string value, bool useJson); | 41 | bool SetValue(UUID storeID, string path, string value, bool useJson); |
diff --git a/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs b/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs index 70ff954..a76ffde 100644 --- a/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs +++ b/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs | |||
@@ -47,46 +47,9 @@ namespace OpenSim.Region.Framework.Interfaces | |||
47 | /// </summary> | 47 | /// </summary> |
48 | event ScriptCommand OnScriptCommand; | 48 | event ScriptCommand OnScriptCommand; |
49 | 49 | ||
50 | /// <summary> | ||
51 | /// Register an instance method as a script call by method name | ||
52 | /// </summary> | ||
53 | /// <param name="target"></param> | ||
54 | /// <param name="method"></param> | ||
55 | void RegisterScriptInvocation(object target, string method); | 50 | void RegisterScriptInvocation(object target, string method); |
56 | |||
57 | /// <summary> | ||
58 | /// Register a static or instance method as a script call by method info | ||
59 | /// </summary> | ||
60 | /// <param name="target">If target is a Type object, will assume method is static.</param> | ||
61 | /// <param name="method"></param> | ||
62 | void RegisterScriptInvocation(object target, MethodInfo method); | 51 | void RegisterScriptInvocation(object target, MethodInfo method); |
63 | |||
64 | /// <summary> | ||
65 | /// Register one or more instance methods as script calls by method name | ||
66 | /// </summary> | ||
67 | /// <param name="target"></param> | ||
68 | /// <param name="methods"></param> | ||
69 | void RegisterScriptInvocation(object target, string[] methods); | 52 | void RegisterScriptInvocation(object target, string[] methods); |
70 | |||
71 | /// <summary> | ||
72 | /// Register one or more static methods as script calls by method name | ||
73 | /// </summary> | ||
74 | /// <param name="target"></param> | ||
75 | /// <param name="methods"></param> | ||
76 | void RegisterScriptInvocation(Type target, string[] methods); | ||
77 | |||
78 | /// <summary> | ||
79 | /// Automatically register script invocations by checking for methods | ||
80 | /// with <see cref="ScriptInvocationAttribute"/>. Should only check | ||
81 | /// public methods. | ||
82 | /// </summary> | ||
83 | /// <param name="target"></param> | ||
84 | void RegisterScriptInvocations(IRegionModuleBase target); | ||
85 | |||
86 | /// <summary> | ||
87 | /// Returns an array of all registered script calls | ||
88 | /// </summary> | ||
89 | /// <returns></returns> | ||
90 | Delegate[] GetScriptInvocationList(); | 53 | Delegate[] GetScriptInvocationList(); |
91 | 54 | ||
92 | Delegate LookupScriptInvocation(string fname); | 55 | Delegate LookupScriptInvocation(string fname); |
@@ -105,44 +68,12 @@ namespace OpenSim.Region.Framework.Interfaces | |||
105 | /// <param name="key"></param> | 68 | /// <param name="key"></param> |
106 | void DispatchReply(UUID scriptId, int code, string text, string key); | 69 | void DispatchReply(UUID scriptId, int code, string text, string key); |
107 | 70 | ||
108 | /// <summary> | 71 | /// For constants |
109 | /// Operation to for a region module to register a constant to be used | ||
110 | /// by the script engine | ||
111 | /// </summary> | ||
112 | /// <param name="cname"> | ||
113 | /// The name of the constant. LSL convention is for constant names to | ||
114 | /// be uppercase. | ||
115 | /// </param> | ||
116 | /// <param name="value"> | ||
117 | /// The value of the constant. Should be of a type that can be | ||
118 | /// converted to one of <see cref="OpenSim.Region.ScriptEngine.Shared.LSL_Types"/> | ||
119 | /// </param> | ||
120 | void RegisterConstant(string cname, object value); | 72 | void RegisterConstant(string cname, object value); |
121 | |||
122 | /// <summary> | ||
123 | /// Automatically register all constants on a region module by | ||
124 | /// checking for fields with <see cref="ScriptConstantAttribute"/>. | ||
125 | /// </summary> | ||
126 | /// <param name="target"></param> | ||
127 | void RegisterConstants(IRegionModuleBase target); | ||
128 | |||
129 | /// <summary> | ||
130 | /// Operation to check for a registered constant | ||
131 | /// </summary> | ||
132 | /// <param name="cname">Name of constant</param> | ||
133 | /// <returns>Value of constant or null if none found.</returns> | ||
134 | object LookupModConstant(string cname); | 73 | object LookupModConstant(string cname); |
135 | Dictionary<string, object> GetConstants(); | 74 | Dictionary<string, object> GetConstants(); |
136 | 75 | ||
137 | // For use ONLY by the script API | 76 | // For use ONLY by the script API |
138 | void RaiseEvent(UUID script, string id, string module, string command, string key); | 77 | void RaiseEvent(UUID script, string id, string module, string command, string key); |
139 | } | 78 | } |
140 | |||
141 | [AttributeUsage(AttributeTargets.Method)] | ||
142 | public class ScriptInvocationAttribute : Attribute | ||
143 | { } | ||
144 | |||
145 | [AttributeUsage(AttributeTargets.Field)] | ||
146 | public class ScriptConstantAttribute : Attribute | ||
147 | { } | ||
148 | } | 79 | } |
diff --git a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs index 68af492..6117a80 100644 --- a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs +++ b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs | |||
@@ -32,96 +32,9 @@ namespace OpenSim.Region.Framework.Interfaces | |||
32 | { | 32 | { |
33 | public interface ISoundModule | 33 | public interface ISoundModule |
34 | { | 34 | { |
35 | /// <summary> | 35 | void PlayAttachedSound(UUID soundID, UUID ownerID, UUID objectID, double gain, Vector3 position, byte flags, float radius); |
36 | /// Maximum distance between a sound source and a recipient. | 36 | |
37 | /// </summary> | ||
38 | float MaxDistance { get; } | ||
39 | |||
40 | /// <summary> | ||
41 | /// Play a sound from an object. | ||
42 | /// </summary> | ||
43 | /// <param name="soundID">Sound asset ID</param> | ||
44 | /// <param name="ownerID">Sound source owner</param> | ||
45 | /// <param name="objectID">Sound source ID</param> | ||
46 | /// <param name="gain">Sound volume</param> | ||
47 | /// <param name="position">Sound source position</param> | ||
48 | /// <param name="flags">Sound flags</param> | ||
49 | /// <param name="radius"> | ||
50 | /// Radius used to affect gain over distance. | ||
51 | /// </param> | ||
52 | void PlayAttachedSound(UUID soundID, UUID ownerID, UUID objectID, | ||
53 | double gain, Vector3 position, byte flags, float radius); | ||
54 | |||
55 | /// <summary> | ||
56 | /// Trigger a sound in the scene. | ||
57 | /// </summary> | ||
58 | /// <param name="soundId">Sound asset ID</param> | ||
59 | /// <param name="ownerID">Sound source owner</param> | ||
60 | /// <param name="objectID">Sound source ID</param> | ||
61 | /// <param name="parentID">Sound source parent.</param> | ||
62 | /// <param name="gain">Sound volume</param> | ||
63 | /// <param name="position">Sound source position</param> | ||
64 | /// <param name="handle"></param> | ||
65 | /// <param name="radius"> | ||
66 | /// Radius used to affect gain over distance. | ||
67 | /// </param> | ||
68 | void TriggerSound( | 37 | void TriggerSound( |
69 | UUID soundId, UUID ownerID, UUID objectID, UUID parentID, | 38 | UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius); |
70 | double gain, Vector3 position, UInt64 handle, float radius); | ||
71 | |||
72 | /// <summary> | ||
73 | /// Stop sounds eminating from an object. | ||
74 | /// </summary> | ||
75 | /// <param name="objectID">Sound source ID</param> | ||
76 | void StopSound(UUID objectID); | ||
77 | |||
78 | /// <summary> | ||
79 | /// Preload sound to viewers within range. | ||
80 | /// </summary> | ||
81 | /// <param name="objectID">Sound source ID</param> | ||
82 | /// <param name="soundID">Sound asset ID</param> | ||
83 | /// <param name="radius"> | ||
84 | /// Radius used to determine which viewers should preload the sound. | ||
85 | /// </param> | ||
86 | void PreloadSound(UUID objectID, UUID soundID, float radius); | ||
87 | |||
88 | /// <summary> | ||
89 | /// Loop specified sound at specified volume with specified radius, | ||
90 | /// optionally declaring object as new sync master. | ||
91 | /// </summary> | ||
92 | /// <param name="objectID">Sound source ID</param> | ||
93 | /// <param name="soundID">Sound asset ID</param> | ||
94 | /// <param name="gain">Sound volume</param> | ||
95 | /// <param name="radius">Sound radius</param> | ||
96 | /// <param name="isMaster">Set object to sync master if true</param> | ||
97 | void LoopSound(UUID objectID, UUID soundID, double gain, | ||
98 | double radius, bool isMaster); | ||
99 | |||
100 | /// <summary> | ||
101 | /// Trigger or play an attached sound in this part's inventory. | ||
102 | /// </summary> | ||
103 | /// <param name="objectID">Sound source ID</param> | ||
104 | /// <param name="sound">Sound asset ID</param> | ||
105 | /// <param name="volume">Sound volume</param> | ||
106 | /// <param name="triggered">Triggered or not.</param> | ||
107 | /// <param name="flags"></param> | ||
108 | /// <param name="radius">Sound radius</param> | ||
109 | /// <param name="useMaster">Play using sound master</param> | ||
110 | /// <param name="isMaster">Play as sound master</param> | ||
111 | void SendSound(UUID objectID, UUID sound, double volume, | ||
112 | bool triggered, byte flags, float radius, bool useMaster, | ||
113 | bool isMaster); | ||
114 | |||
115 | /// <summary> | ||
116 | /// Trigger a sound to be played to all agents within an axis-aligned | ||
117 | /// bounding box. | ||
118 | /// </summary> | ||
119 | /// <param name="objectID">Sound source ID</param> | ||
120 | /// <param name="sound">Sound asset ID</param> | ||
121 | /// <param name="volume">Sound volume</param> | ||
122 | /// <param name="min">AABB bottom south-west corner</param> | ||
123 | /// <param name="max">AABB top north-east corner</param> | ||
124 | void TriggerSoundLimited(UUID objectID, UUID sound, double volume, | ||
125 | Vector3 min, Vector3 max); | ||
126 | } | 39 | } |
127 | } \ No newline at end of file | 40 | } \ No newline at end of file |
diff --git a/OpenSim/Region/Framework/Interfaces/IUrlModule.cs b/OpenSim/Region/Framework/Interfaces/IUrlModule.cs index 79e9f9d..457444c 100644 --- a/OpenSim/Region/Framework/Interfaces/IUrlModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IUrlModule.cs | |||
@@ -39,8 +39,6 @@ namespace OpenSim.Region.Framework.Interfaces | |||
39 | UUID RequestSecureURL(IScriptModule engine, SceneObjectPart host, UUID itemID); | 39 | UUID RequestSecureURL(IScriptModule engine, SceneObjectPart host, UUID itemID); |
40 | void ReleaseURL(string url); | 40 | void ReleaseURL(string url); |
41 | void HttpResponse(UUID request, int status, string body); | 41 | void HttpResponse(UUID request, int status, string body); |
42 | void HttpContentType(UUID request, string type); | ||
43 | |||
44 | string GetHttpHeader(UUID request, string header); | 42 | string GetHttpHeader(UUID request, string header); |
45 | int GetFreeUrls(); | 43 | int GetFreeUrls(); |
46 | 44 | ||
diff --git a/OpenSim/Region/Framework/Interfaces/IUserManagement.cs b/OpenSim/Region/Framework/Interfaces/IUserManagement.cs index f8088c3..24cd069 100644 --- a/OpenSim/Region/Framework/Interfaces/IUserManagement.cs +++ b/OpenSim/Region/Framework/Interfaces/IUserManagement.cs | |||
@@ -1,31 +1,4 @@ | |||
1 | /* | 1 | using System; |
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 | using System.Collections.Generic; | 2 | using System.Collections.Generic; |
30 | 3 | ||
31 | using OpenMetaverse; | 4 | using OpenMetaverse; |
diff --git a/OpenSim/Region/Framework/Interfaces/IWorldComm.cs b/OpenSim/Region/Framework/Interfaces/IWorldComm.cs index 20e0199..e8e375e 100644 --- a/OpenSim/Region/Framework/Interfaces/IWorldComm.cs +++ b/OpenSim/Region/Framework/Interfaces/IWorldComm.cs | |||
@@ -45,13 +45,6 @@ namespace OpenSim.Region.Framework.Interfaces | |||
45 | void Deactivate(); | 45 | void Deactivate(); |
46 | void Activate(); | 46 | void Activate(); |
47 | UUID GetID(); | 47 | UUID GetID(); |
48 | |||
49 | /// <summary> | ||
50 | /// Bitfield indicating which strings should be processed as regex. | ||
51 | /// 1 corresponds to IWorldCommListenerInfo::GetName() | ||
52 | /// 2 corresponds to IWorldCommListenerInfo::GetMessage() | ||
53 | /// </summary> | ||
54 | int RegexBitfield { get; } | ||
55 | } | 48 | } |
56 | 49 | ||
57 | public interface IWorldComm | 50 | public interface IWorldComm |
@@ -67,7 +60,7 @@ namespace OpenSim.Region.Framework.Interfaces | |||
67 | /// the script during 'peek' time. Parameter hostID is needed to | 60 | /// the script during 'peek' time. Parameter hostID is needed to |
68 | /// determine the position of the script. | 61 | /// determine the position of the script. |
69 | /// </summary> | 62 | /// </summary> |
70 | /// <param name="LocalID">localID of the script engine</param> | 63 | /// <param name="localID">localID of the script engine</param> |
71 | /// <param name="itemID">UUID of the script engine</param> | 64 | /// <param name="itemID">UUID of the script engine</param> |
72 | /// <param name="hostID">UUID of the SceneObjectPart</param> | 65 | /// <param name="hostID">UUID of the SceneObjectPart</param> |
73 | /// <param name="channel">channel to listen on</param> | 66 | /// <param name="channel">channel to listen on</param> |
@@ -77,23 +70,6 @@ namespace OpenSim.Region.Framework.Interfaces | |||
77 | /// <returns>number of the scripts handle</returns> | 70 | /// <returns>number of the scripts handle</returns> |
78 | int Listen(uint LocalID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg); | 71 | int Listen(uint LocalID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg); |
79 | 72 | ||
80 | /// <summary> | ||
81 | /// Create a listen event callback with the specified filters. | ||
82 | /// The parameters localID,itemID are needed to uniquely identify | ||
83 | /// the script during 'peek' time. Parameter hostID is needed to | ||
84 | /// determine the position of the script. | ||
85 | /// </summary> | ||
86 | /// <param name="LocalID">localID of the script engine</param> | ||
87 | /// <param name="itemID">UUID of the script engine</param> | ||
88 | /// <param name="hostID">UUID of the SceneObjectPart</param> | ||
89 | /// <param name="channel">channel to listen on</param> | ||
90 | /// <param name="name">name to filter on</param> | ||
91 | /// <param name="id">key to filter on (user given, could be totally faked)</param> | ||
92 | /// <param name="msg">msg to filter on</param> | ||
93 | /// <param name="regexBitfield">Bitfield indicating which strings should be processed as regex.</param> | ||
94 | /// <returns>number of the scripts handle</returns> | ||
95 | int Listen(uint LocalID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg, int regexBitfield); | ||
96 | |||
97 | /// <summary> | 73 | /// <summary> |
98 | /// This method scans over the objects which registered an interest in listen callbacks. | 74 | /// This method scans over the objects which registered an interest in listen callbacks. |
99 | /// For everyone it finds, it checks if it fits the given filter. If it does, then | 75 | /// For everyone it finds, it checks if it fits the given filter. If it does, then |
diff --git a/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs b/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs index 65ae445..ad421ee 100644 --- a/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs +++ b/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs | |||
@@ -41,7 +41,6 @@ namespace OpenSim.Region.Framework.Scenes.Animation | |||
41 | { | 41 | { |
42 | // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 42 | // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
43 | 43 | ||
44 | private OpenSim.Framework.Animation m_implicitDefaultAnimation = new OpenSim.Framework.Animation(); | ||
45 | private OpenSim.Framework.Animation m_defaultAnimation = new OpenSim.Framework.Animation(); | 44 | private OpenSim.Framework.Animation m_defaultAnimation = new OpenSim.Framework.Animation(); |
46 | private List<OpenSim.Framework.Animation> m_animations = new List<OpenSim.Framework.Animation>(); | 45 | private List<OpenSim.Framework.Animation> m_animations = new List<OpenSim.Framework.Animation>(); |
47 | 46 | ||
@@ -50,11 +49,6 @@ namespace OpenSim.Region.Framework.Scenes.Animation | |||
50 | get { return m_defaultAnimation; } | 49 | get { return m_defaultAnimation; } |
51 | } | 50 | } |
52 | 51 | ||
53 | public OpenSim.Framework.Animation ImplicitDefaultAnimation | ||
54 | { | ||
55 | get { return m_implicitDefaultAnimation; } | ||
56 | } | ||
57 | |||
58 | public AnimationSet() | 52 | public AnimationSet() |
59 | { | 53 | { |
60 | ResetDefaultAnimation(); | 54 | ResetDefaultAnimation(); |
@@ -125,18 +119,11 @@ namespace OpenSim.Region.Framework.Scenes.Animation | |||
125 | if (m_defaultAnimation.AnimID != animID) | 119 | if (m_defaultAnimation.AnimID != animID) |
126 | { | 120 | { |
127 | m_defaultAnimation = new OpenSim.Framework.Animation(animID, sequenceNum, objectID); | 121 | m_defaultAnimation = new OpenSim.Framework.Animation(animID, sequenceNum, objectID); |
128 | m_implicitDefaultAnimation = m_defaultAnimation; | ||
129 | return true; | 122 | return true; |
130 | } | 123 | } |
131 | return false; | 124 | return false; |
132 | } | 125 | } |
133 | 126 | ||
134 | // Called from serialization only | ||
135 | public void SetImplicitDefaultAnimation(UUID animID, int sequenceNum, UUID objectID) | ||
136 | { | ||
137 | m_implicitDefaultAnimation = new OpenSim.Framework.Animation(animID, sequenceNum, objectID); | ||
138 | } | ||
139 | |||
140 | protected bool ResetDefaultAnimation() | 127 | protected bool ResetDefaultAnimation() |
141 | { | 128 | { |
142 | return TrySetDefaultAnimation("STAND", 1, UUID.Zero); | 129 | return TrySetDefaultAnimation("STAND", 1, UUID.Zero); |
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 5b1c9f4..4a19c3b 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs | |||
@@ -47,75 +47,30 @@ namespace OpenSim.Region.Framework.Scenes | |||
47 | 47 | ||
48 | public delegate void OnFrameDelegate(); | 48 | public delegate void OnFrameDelegate(); |
49 | 49 | ||
50 | /// <summary> | ||
51 | /// Triggered on each sim frame. | ||
52 | /// </summary> | ||
53 | /// <remarks> | ||
54 | /// This gets triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.Update"/> | ||
55 | /// Core uses it for things like Sun, Wind & Clouds | ||
56 | /// The MRM module also uses it. | ||
57 | /// </remarks> | ||
58 | public event OnFrameDelegate OnFrame; | 50 | public event OnFrameDelegate OnFrame; |
59 | 51 | ||
60 | public delegate void ClientMovement(ScenePresence client); | 52 | public delegate void ClientMovement(ScenePresence client); |
61 | 53 | ||
62 | /// <summary> | ||
63 | /// Trigerred when an agent moves. | ||
64 | /// </summary> | ||
65 | /// <remarks> | ||
66 | /// This gets triggered in <see cref="OpenSim.Region.Framework.Scenes.ScenePresence.HandleAgentUpdate"/> | ||
67 | /// prior to <see cref="OpenSim.Region.Framework.Scenes.ScenePresence.TriggerScenePresenceUpdated"/> | ||
68 | /// </remarks> | ||
69 | public event ClientMovement OnClientMovement; | 54 | public event ClientMovement OnClientMovement; |
70 | 55 | ||
71 | public delegate void OnTerrainTaintedDelegate(); | 56 | public delegate void OnTerrainTaintedDelegate(); |
72 | 57 | ||
73 | /// <summary> | ||
74 | /// Triggered if the terrain has been edited | ||
75 | /// </summary> | ||
76 | /// <remarks> | ||
77 | /// This gets triggered in <see cref="OpenSim.Region.CoreModules.World.Terrain.CheckForTerrainUpdates"/> | ||
78 | /// after it determines that an update has been made. | ||
79 | /// </remarks> | ||
80 | public event OnTerrainTaintedDelegate OnTerrainTainted; | 58 | public event OnTerrainTaintedDelegate OnTerrainTainted; |
81 | 59 | ||
82 | public delegate void OnTerrainTickDelegate(); | 60 | public delegate void OnTerrainTickDelegate(); |
83 | 61 | ||
84 | /// <summary> | ||
85 | /// Triggered if the terrain has been edited | ||
86 | /// </summary> | ||
87 | /// <remarks> | ||
88 | /// This gets triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.UpdateTerrain"/> | ||
89 | /// but is used by core solely to update the physics engine. | ||
90 | /// </remarks> | ||
91 | public event OnTerrainTickDelegate OnTerrainTick; | ||
92 | |||
93 | public delegate void OnTerrainUpdateDelegate(); | 62 | public delegate void OnTerrainUpdateDelegate(); |
94 | 63 | ||
64 | public event OnTerrainTickDelegate OnTerrainTick; | ||
65 | |||
95 | public event OnTerrainUpdateDelegate OnTerrainUpdate; | 66 | public event OnTerrainUpdateDelegate OnTerrainUpdate; |
96 | 67 | ||
97 | public delegate void OnBackupDelegate(ISimulationDataService datastore, bool forceBackup); | 68 | public delegate void OnBackupDelegate(ISimulationDataService datastore, bool forceBackup); |
98 | 69 | ||
99 | /// <summary> | ||
100 | /// Triggered when a region is backed up/persisted to storage | ||
101 | /// </summary> | ||
102 | /// <remarks> | ||
103 | /// This gets triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.Backup"/> | ||
104 | /// and is fired before the persistence occurs. | ||
105 | /// </remarks> | ||
106 | public event OnBackupDelegate OnBackup; | 70 | public event OnBackupDelegate OnBackup; |
107 | 71 | ||
108 | public delegate void OnClientConnectCoreDelegate(IClientCore client); | 72 | public delegate void OnClientConnectCoreDelegate(IClientCore client); |
109 | 73 | ||
110 | /// <summary> | ||
111 | /// Triggered when a new client connects to the scene. | ||
112 | /// </summary> | ||
113 | /// <remarks> | ||
114 | /// This gets triggered in <see cref="TriggerOnNewClient"/>, | ||
115 | /// which checks if an instance of <see cref="OpenSim.Framework.IClientAPI"/> | ||
116 | /// also implements <see cref="OpenSim.Framework.Client.IClientCore"/> and as such, | ||
117 | /// is not triggered by <see cref="OpenSim.Region.OptionalModules.World.NPC">NPCs</see>. | ||
118 | /// </remarks> | ||
119 | public event OnClientConnectCoreDelegate OnClientConnect; | 74 | public event OnClientConnectCoreDelegate OnClientConnect; |
120 | 75 | ||
121 | public delegate void OnNewClientDelegate(IClientAPI client); | 76 | public delegate void OnNewClientDelegate(IClientAPI client); |
@@ -125,96 +80,33 @@ namespace OpenSim.Region.Framework.Scenes | |||
125 | /// </summary> | 80 | /// </summary> |
126 | /// <remarks> | 81 | /// <remarks> |
127 | /// This is triggered for both child and root agent client connections. | 82 | /// This is triggered for both child and root agent client connections. |
128 | /// | ||
129 | /// Triggered before OnClientLogin. | 83 | /// 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. | ||
133 | /// </remarks> | 84 | /// </remarks> |
134 | public event OnNewClientDelegate OnNewClient; | 85 | public event OnNewClientDelegate OnNewClient; |
135 | 86 | ||
136 | /// <summary> | 87 | /// <summary> |
137 | /// Fired if the client entering this sim is doing so as a new login | 88 | /// Fired if the client entering this sim is doing so as a new login |
138 | /// </summary> | 89 | /// </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> | ||
143 | public event Action<IClientAPI> OnClientLogin; | 90 | public event Action<IClientAPI> OnClientLogin; |
144 | 91 | ||
145 | public delegate void OnNewPresenceDelegate(ScenePresence presence); | 92 | public delegate void OnNewPresenceDelegate(ScenePresence presence); |
146 | 93 | ||
147 | /// <summary> | ||
148 | /// Triggered when a new presence is added to the scene | ||
149 | /// </summary> | ||
150 | /// <remarks> | ||
151 | /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewClient"/> which is used by both | ||
152 | /// <see cref="OpenSim.Framework.PresenceType.User">users</see> and <see cref="OpenSim.Framework.PresenceType.Npc">NPCs</see> | ||
153 | /// </remarks> | ||
154 | public event OnNewPresenceDelegate OnNewPresence; | 94 | public event OnNewPresenceDelegate OnNewPresence; |
155 | 95 | ||
156 | public delegate void OnRemovePresenceDelegate(UUID agentId); | 96 | public delegate void OnRemovePresenceDelegate(UUID agentId); |
157 | 97 | ||
158 | /// <summary> | ||
159 | /// Triggered when a presence is removed from the scene | ||
160 | /// </summary> | ||
161 | /// <remarks> | ||
162 | /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewClient"/> which is used by both | ||
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. | ||
167 | /// </remarks> | ||
168 | public event OnRemovePresenceDelegate OnRemovePresence; | 98 | public event OnRemovePresenceDelegate OnRemovePresence; |
169 | 99 | ||
170 | public delegate void OnParcelPrimCountUpdateDelegate(); | 100 | public delegate void OnParcelPrimCountUpdateDelegate(); |
171 | 101 | ||
172 | /// <summary> | ||
173 | /// Triggered whenever the prim count may have been altered, or prior | ||
174 | /// to an action that requires the current prim count to be accurate. | ||
175 | /// </summary> | ||
176 | /// <remarks> | ||
177 | /// Triggered by <see cref="TriggerParcelPrimCountUpdate"/> in | ||
178 | /// <see cref="OpenSim.OpenSimBase.CreateRegion"/>, | ||
179 | /// <see cref="OpenSim.Region.CoreModules.World.Land.LandManagementModule.EventManagerOnRequestParcelPrimCountUpdate"/>, | ||
180 | /// <see cref="OpenSim.Region.CoreModules.World.Land.LandManagementModule.ClientOnParcelObjectOwnerRequest"/>, | ||
181 | /// <see cref="OpenSim.Region.CoreModules.World.Land.LandObject.GetPrimsFree"/>, | ||
182 | /// <see cref="OpenSim.Region.CoreModules.World.Land.LandObject.UpdateLandSold"/>, | ||
183 | /// <see cref="OpenSim.Region.CoreModules.World.Land.LandObject.DeedToGroup"/>, | ||
184 | /// <see cref="OpenSim.Region.CoreModules.World.Land.LandObject.SendLandUpdateToClient"/> | ||
185 | /// </remarks> | ||
186 | public event OnParcelPrimCountUpdateDelegate OnParcelPrimCountUpdate; | 102 | public event OnParcelPrimCountUpdateDelegate OnParcelPrimCountUpdate; |
187 | 103 | ||
188 | public delegate void OnParcelPrimCountAddDelegate(SceneObjectGroup obj); | 104 | public delegate void OnParcelPrimCountAddDelegate(SceneObjectGroup obj); |
189 | 105 | ||
190 | /// <summary> | ||
191 | /// Triggered in response to <see cref="OnParcelPrimCountUpdate"/> for | ||
192 | /// objects that actually contribute to parcel prim count. | ||
193 | /// </summary> | ||
194 | /// <remarks> | ||
195 | /// Triggered by <see cref="TriggerParcelPrimCountAdd"/> in | ||
196 | /// <see cref="OpenSim.Region.CoreModules.World.Land.LandManagementModule.EventManagerOnParcelPrimCountUpdate"/> | ||
197 | /// </remarks> | ||
198 | public event OnParcelPrimCountAddDelegate OnParcelPrimCountAdd; | 106 | public event OnParcelPrimCountAddDelegate OnParcelPrimCountAdd; |
199 | 107 | ||
200 | public delegate void OnPluginConsoleDelegate(string[] args); | 108 | public delegate void OnPluginConsoleDelegate(string[] args); |
201 | 109 | ||
202 | /// <summary> | ||
203 | /// Triggered after <see cref="OpenSim.IApplicationPlugin.PostInitialise"/> | ||
204 | /// has been called for all <see cref="OpenSim.IApplicationPlugin"/> | ||
205 | /// loaded via <see cref="OpenSim.OpenSimBase.LoadPlugins"/>. | ||
206 | /// Handlers for this event are typically used to parse the arguments | ||
207 | /// from <see cref="OnPluginConsoleDelegate"/> in order to process or | ||
208 | /// filter the arguments and pass them onto <see cref="OpenSim.Region.CoreModules.Framework.InterfaceCommander.Commander.ProcessConsoleCommand"/> | ||
209 | /// </summary> | ||
210 | /// <remarks> | ||
211 | /// Triggered by <see cref="TriggerOnPluginConsole"/> in | ||
212 | /// <see cref="Scene.SendCommandToPlugins"/> via | ||
213 | /// <see cref="SceneManager.SendCommandToPluginModules"/> via | ||
214 | /// <see cref="OpenSim.OpenSimBase.HandleCommanderCommand"/> via | ||
215 | /// <see cref="OpenSim.OpenSimBase.AddPluginCommands"/> via | ||
216 | /// <see cref="OpenSim.OpenSimBase.StartupSpecific"/> | ||
217 | /// </remarks> | ||
218 | public event OnPluginConsoleDelegate OnPluginConsole; | 110 | public event OnPluginConsoleDelegate OnPluginConsole; |
219 | 111 | ||
220 | /// <summary> | 112 | /// <summary> |
@@ -229,28 +121,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
229 | 121 | ||
230 | public delegate void OnSetRootAgentSceneDelegate(UUID agentID, Scene scene); | 122 | public delegate void OnSetRootAgentSceneDelegate(UUID agentID, Scene scene); |
231 | 123 | ||
232 | /// <summary> | ||
233 | /// Triggered before the grunt work for adding a root agent to a | ||
234 | /// scene has been performed (resuming attachment scripts, physics, | ||
235 | /// animations etc.) | ||
236 | /// </summary> | ||
237 | /// <remarks> | ||
238 | /// Triggered before <see cref="OnMakeRootAgent"/> | ||
239 | /// by <see cref="TriggerSetRootAgentScene"/> | ||
240 | /// in <see cref="ScenePresence.MakeRootAgent"/> | ||
241 | /// via <see cref="Scene.AgentCrossing"/> | ||
242 | /// and <see cref="ScenePresence.CompleteMovement"/> | ||
243 | /// </remarks> | ||
244 | public event OnSetRootAgentSceneDelegate OnSetRootAgentScene; | 124 | public event OnSetRootAgentSceneDelegate OnSetRootAgentScene; |
245 | 125 | ||
246 | /// <summary> | ||
247 | /// Triggered after parcel properties have been updated. | ||
248 | /// </summary> | ||
249 | /// <remarks> | ||
250 | /// Triggered by <see cref="TriggerOnParcelPropertiesUpdateRequest"/> in | ||
251 | /// <see cref="OpenSim.Region.CoreModules.World.Land.LandManagementModule.ClientOnParcelPropertiesUpdateRequest"/>, | ||
252 | /// <see cref="OpenSim.Region.CoreModules.World.Land.LandManagementModule.ProcessPropertiesUpdate"/> | ||
253 | /// </remarks> | ||
254 | public event ParcelPropertiesUpdateRequest OnParcelPropertiesUpdateRequest; | 126 | public event ParcelPropertiesUpdateRequest OnParcelPropertiesUpdateRequest; |
255 | 127 | ||
256 | /// <summary> | 128 | /// <summary> |
@@ -265,45 +137,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
265 | /// <summary> | 137 | /// <summary> |
266 | /// Fired when an object is touched/grabbed. | 138 | /// Fired when an object is touched/grabbed. |
267 | /// </summary> | 139 | /// </summary> |
268 | /// <remarks> | ||
269 | /// The originalID is the local ID of the part that was actually touched. The localID itself is always that of | 140 | /// The originalID is the local ID of the part that was actually touched. The localID itself is always that of |
270 | /// the root part. | 141 | /// the root part. |
271 | /// Triggerd in response to <see cref="OpenSim.Framework.IClientAPI.OnGrabObject"/> | ||
272 | /// via <see cref="TriggerObjectGrab"/> | ||
273 | /// in <see cref="Scene.ProcessObjectGrab"/> | ||
274 | /// </remarks> | ||
275 | public event ObjectGrabDelegate OnObjectGrab; | 142 | public event ObjectGrabDelegate OnObjectGrab; |
276 | public delegate void ObjectGrabDelegate(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs); | 143 | public delegate void ObjectGrabDelegate(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs); |
277 | 144 | ||
278 | /// <summary> | ||
279 | /// Triggered when an object is being touched/grabbed continuously. | ||
280 | /// </summary> | ||
281 | /// <remarks> | ||
282 | /// Triggered in response to <see cref="OpenSim.Framework.IClientAPI.OnGrabUpdate"/> | ||
283 | /// via <see cref="TriggerObjectGrabbing"/> | ||
284 | /// in <see cref="Scene.ProcessObjectGrabUpdate"/> | ||
285 | /// </remarks> | ||
286 | public event ObjectGrabDelegate OnObjectGrabbing; | 145 | public event ObjectGrabDelegate OnObjectGrabbing; |
287 | |||
288 | /// <summary> | ||
289 | /// Triggered when an object stops being touched/grabbed. | ||
290 | /// </summary> | ||
291 | /// <remarks> | ||
292 | /// Triggered in response to <see cref="OpenSim.Framework.IClientAPI.OnDeGrabObject"/> | ||
293 | /// via <see cref="TriggerObjectDeGrab"/> | ||
294 | /// in <see cref="Scene.ProcessObjectDeGrab"/> | ||
295 | /// </remarks> | ||
296 | public event ObjectDeGrabDelegate OnObjectDeGrab; | 146 | public event ObjectDeGrabDelegate OnObjectDeGrab; |
297 | |||
298 | /// <summary> | ||
299 | /// Triggered when a script resets. | ||
300 | /// </summary> | ||
301 | /// <remarks> | ||
302 | /// Triggered by <see cref="TriggerScriptReset"/> | ||
303 | /// in <see cref="Scene.ProcessScriptReset"/> | ||
304 | /// via <see cref="OpenSim.Framework.IClientAPI.OnScriptReset"/> | ||
305 | /// via <see cref="OpenSim.Region.ClientStack.LindenUDP.LLClientView.HandleScriptReset"/> | ||
306 | /// </remarks> | ||
307 | public event ScriptResetDelegate OnScriptReset; | 147 | public event ScriptResetDelegate OnScriptReset; |
308 | 148 | ||
309 | public event OnPermissionErrorDelegate OnPermissionError; | 149 | public event OnPermissionErrorDelegate OnPermissionError; |
@@ -313,105 +153,29 @@ namespace OpenSim.Region.Framework.Scenes | |||
313 | /// </summary> | 153 | /// </summary> |
314 | /// <remarks> | 154 | /// <remarks> |
315 | /// Occurs after OnNewScript. | 155 | /// Occurs after OnNewScript. |
316 | /// Triggered by <see cref="TriggerRezScript"/> | ||
317 | /// in <see cref="SceneObjectPartInventory.CreateScriptInstance"/> | ||
318 | /// </remarks> | 156 | /// </remarks> |
319 | public event NewRezScript OnRezScript; | 157 | public event NewRezScript OnRezScript; |
320 | public delegate void NewRezScript(uint localID, UUID itemID, string script, int startParam, bool postOnRez, string engine, int stateSource); | 158 | public delegate void NewRezScript(uint localID, UUID itemID, string script, int startParam, bool postOnRez, string engine, int stateSource); |
321 | 159 | ||
322 | public delegate void RemoveScript(uint localID, UUID itemID); | 160 | public delegate void RemoveScript(uint localID, UUID itemID); |
323 | |||
324 | /// <summary> | ||
325 | /// Triggered when a script is removed from an object. | ||
326 | /// </summary> | ||
327 | /// <remarks> | ||
328 | /// Triggered by <see cref="TriggerRemoveScript"/> | ||
329 | /// in <see cref="Scene.RemoveTaskInventory"/>, | ||
330 | /// <see cref="Scene.CreateAgentInventoryItemFromTask"/>, | ||
331 | /// <see cref="SceneObjectPartInventory.RemoveScriptInstance"/>, | ||
332 | /// <see cref="SceneObjectPartInventory.RemoveInventoryItem"/> | ||
333 | /// </remarks> | ||
334 | public event RemoveScript OnRemoveScript; | 161 | public event RemoveScript OnRemoveScript; |
335 | 162 | ||
336 | public delegate void StartScript(uint localID, UUID itemID); | 163 | public delegate void StartScript(uint localID, UUID itemID); |
337 | |||
338 | /// <summary> | ||
339 | /// Triggered when a script starts. | ||
340 | /// </summary> | ||
341 | /// <remarks> | ||
342 | /// Triggered by <see cref="TriggerStartScript"/> | ||
343 | /// in <see cref="Scene.SetScriptRunning"/> | ||
344 | /// via <see cref="OpenSim.Framework.IClientAPI.OnSetScriptRunning"/>, | ||
345 | /// via <see cref="OpenSim.Region.ClientStack.LindenUDP.HandleSetScriptRunning"/> | ||
346 | /// </remarks> | ||
347 | public event StartScript OnStartScript; | 164 | public event StartScript OnStartScript; |
348 | 165 | ||
349 | public delegate void StopScript(uint localID, UUID itemID); | 166 | public delegate void StopScript(uint localID, UUID itemID); |
350 | |||
351 | /// <summary> | ||
352 | /// Triggered when a script stops. | ||
353 | /// </summary> | ||
354 | /// <remarks> | ||
355 | /// Triggered by <see cref="TriggerStopScript"/>, | ||
356 | /// in <see cref="SceneObjectPartInventory.CreateScriptInstance"/>, | ||
357 | /// <see cref="SceneObjectPartInventory.StopScriptInstance"/>, | ||
358 | /// <see cref="Scene.SetScriptRunning"/> | ||
359 | /// </remarks> | ||
360 | public event StopScript OnStopScript; | 167 | public event StopScript OnStopScript; |
361 | 168 | ||
362 | public delegate bool SceneGroupMoved(UUID groupID, Vector3 delta); | 169 | public delegate bool SceneGroupMoved(UUID groupID, Vector3 delta); |
363 | |||
364 | /// <summary> | ||
365 | /// Triggered when an object is moved. | ||
366 | /// </summary> | ||
367 | /// <remarks> | ||
368 | /// Triggered by <see cref="TriggerGroupMove"/> | ||
369 | /// in <see cref="SceneObjectGroup.UpdateGroupPosition"/>, | ||
370 | /// <see cref="SceneObjectGroup.GrabMovement"/> | ||
371 | /// </remarks> | ||
372 | public event SceneGroupMoved OnSceneGroupMove; | 170 | public event SceneGroupMoved OnSceneGroupMove; |
373 | 171 | ||
374 | public delegate void SceneGroupGrabed(UUID groupID, Vector3 offset, UUID userID); | 172 | public delegate void SceneGroupGrabed(UUID groupID, Vector3 offset, UUID userID); |
375 | |||
376 | /// <summary> | ||
377 | /// Triggered when an object is grabbed. | ||
378 | /// </summary> | ||
379 | /// <remarks> | ||
380 | /// Triggered by <see cref="TriggerGroupGrab"/> | ||
381 | /// in <see cref="SceneObjectGroup.OnGrabGroup"/> | ||
382 | /// via <see cref="SceneObjectGroup.ObjectGrabHandler"/> | ||
383 | /// via <see cref="Scene.ProcessObjectGrab"/> | ||
384 | /// via <see cref="OpenSim.Framework.IClientAPI.OnGrabObject"/> | ||
385 | /// via <see cref="OpenSim.Region.ClientStack.LindenUDP.LLClientView.HandleObjectGrab"/> | ||
386 | /// </remarks> | ||
387 | public event SceneGroupGrabed OnSceneGroupGrab; | 173 | public event SceneGroupGrabed OnSceneGroupGrab; |
388 | 174 | ||
389 | public delegate bool SceneGroupSpinStarted(UUID groupID); | 175 | public delegate bool SceneGroupSpinStarted(UUID groupID); |
390 | |||
391 | /// <summary> | ||
392 | /// Triggered when an object starts to spin. | ||
393 | /// </summary> | ||
394 | /// <remarks> | ||
395 | /// Triggered by <see cref="TriggerGroupSpinStart"/> | ||
396 | /// in <see cref="SceneObjectGroup.SpinStart"/> | ||
397 | /// via <see cref="SceneGraph.SpinStart"/> | ||
398 | /// via <see cref="OpenSim.Framework.IClientAPI.OnSpinStart"/> | ||
399 | /// via <see cref="OpenSim.Region.ClientStack.LindenUDP.LLClientView.HandleObjectSpinStart"/> | ||
400 | /// </remarks> | ||
401 | public event SceneGroupSpinStarted OnSceneGroupSpinStart; | 176 | public event SceneGroupSpinStarted OnSceneGroupSpinStart; |
402 | 177 | ||
403 | public delegate bool SceneGroupSpun(UUID groupID, Quaternion rotation); | 178 | public delegate bool SceneGroupSpun(UUID groupID, Quaternion rotation); |
404 | |||
405 | /// <summary> | ||
406 | /// Triggered when an object is being spun. | ||
407 | /// </summary> | ||
408 | /// <remarks> | ||
409 | /// Triggered by <see cref="TriggerGroupSpin"/> | ||
410 | /// in <see cref="SceneObjectGroup.SpinMovement"/> | ||
411 | /// via <see cref="SceneGraph.SpinObject"/> | ||
412 | /// via <see cref="OpenSim.Framework.IClientAPI.OnSpinUpdate"/> | ||
413 | /// via <see cref="OpenSim.Region.ClientStack.LindenUDP.LLClientView.HandleObjectSpinUpdate"/> | ||
414 | /// </remarks> | ||
415 | public event SceneGroupSpun OnSceneGroupSpin; | 179 | public event SceneGroupSpun OnSceneGroupSpin; |
416 | 180 | ||
417 | public delegate void LandObjectAdded(ILandObject newParcel); | 181 | public delegate void LandObjectAdded(ILandObject newParcel); |
@@ -440,9 +204,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
440 | /// </summary> | 204 | /// </summary> |
441 | /// <remarks> | 205 | /// <remarks> |
442 | /// At the point of firing, the scene still contains the client's scene presence. | 206 | /// 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. | ||
446 | /// </remarks> | 207 | /// </remarks> |
447 | public event ClientClosed OnClientClosed; | 208 | public event ClientClosed OnClientClosed; |
448 | 209 | ||
@@ -453,9 +214,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
453 | /// </summary> | 214 | /// </summary> |
454 | /// <remarks> | 215 | /// <remarks> |
455 | /// Occurs before OnRezScript | 216 | /// Occurs before OnRezScript |
456 | /// Triggered by <see cref="TriggerNewScript"/> | ||
457 | /// in <see cref="Scene.RezScriptFromAgentInventory"/>, | ||
458 | /// <see cref="Scene.RezNewScript"/> | ||
459 | /// </remarks> | 217 | /// </remarks> |
460 | public event NewScript OnNewScript; | 218 | public event NewScript OnNewScript; |
461 | 219 | ||
@@ -490,12 +248,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
490 | /// </summary> | 248 | /// </summary> |
491 | /// <remarks> | 249 | /// <remarks> |
492 | /// Triggered after the scene receives a client's upload of an updated script and has stored it in an asset. | 250 | /// Triggered after the scene receives a client's upload of an updated script and has stored it in an asset. |
493 | /// Triggered by <see cref="TriggerUpdateScript"/> | ||
494 | /// in <see cref="Scene.CapsUpdateTaskInventoryScriptAsset"/> | ||
495 | /// via <see cref="Scene.CapsUpdateTaskInventoryScriptAsset"/> | ||
496 | /// via <see cref="OpenSim.Region.ClientStack.Linden.BunchOfCaps.TaskScriptUpdated"/> | ||
497 | /// via <see cref="OpenSim.Region.ClientStack.Linden.TaskInventoryScriptUpdater.OnUpLoad"/> | ||
498 | /// via <see cref="OpenSim.Region.ClientStack.Linden.TaskInventoryScriptUpdater.uploaderCaps"/> | ||
499 | /// </remarks> | 251 | /// </remarks> |
500 | public event UpdateScript OnUpdateScript; | 252 | public event UpdateScript OnUpdateScript; |
501 | 253 | ||
@@ -521,203 +273,48 @@ namespace OpenSim.Region.Framework.Scenes | |||
521 | } | 273 | } |
522 | 274 | ||
523 | /// <summary> | 275 | /// <summary> |
524 | /// Triggered when some scene object properties change. | ||
525 | /// </summary> | ||
526 | /// <remarks> | ||
527 | /// ScriptChangedEvent is fired when a scene object property that a script might be interested | 276 | /// ScriptChangedEvent is fired when a scene object property that a script might be interested |
528 | /// in (such as color, scale or inventory) changes. Only enough information sent is for the LSL changed event. | 277 | /// in (such as color, scale or inventory) changes. Only enough information sent is for the LSL changed event. |
529 | /// This is not an indication that the script has changed (see OnUpdateScript for that). | 278 | /// This is not an indication that the script has changed (see OnUpdateScript for that). |
530 | /// This event is sent to a script to tell it that some property changed on | 279 | /// This event is sent to a script to tell it that some property changed on |
531 | /// the object the script is in. See http://lslwiki.net/lslwiki/wakka.php?wakka=changed . | 280 | /// the object the script is in. See http://lslwiki.net/lslwiki/wakka.php?wakka=changed . |
532 | /// Triggered by <see cref="TriggerOnScriptChangedEvent"/> | 281 | /// </summary> |
533 | /// in <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.EntityTransferModule.TeleportAgentWithinRegion"/>, | ||
534 | /// <see cref="SceneObjectPart.TriggerScriptChangedEvent"/> | ||
535 | /// </remarks> | ||
536 | public event ScriptChangedEvent OnScriptChangedEvent; | 282 | public event ScriptChangedEvent OnScriptChangedEvent; |
537 | public delegate void ScriptChangedEvent(uint localID, uint change); | 283 | public delegate void ScriptChangedEvent(uint localID, uint change); |
538 | 284 | ||
539 | public delegate void ScriptControlEvent(UUID item, UUID avatarID, uint held, uint changed); | 285 | public delegate void ScriptControlEvent(UUID item, UUID avatarID, uint held, uint changed); |
540 | |||
541 | /// <summary> | ||
542 | /// Triggered when a script receives control input from an agent. | ||
543 | /// </summary> | ||
544 | /// <remarks> | ||
545 | /// Triggered by <see cref="TriggerControlEvent"/> | ||
546 | /// in <see cref="ScenePresence.SendControlsToScripts"/> | ||
547 | /// via <see cref="ScenePresence.HandleAgentUpdate"/> | ||
548 | /// via <see cref="OpenSim.Framework.IClientAPI.OnAgentUpdate"/> | ||
549 | /// via <see cref="OpenSim.Region.ClientStack.LindenUDP.LLClientView.HandleAgentUpdate"/> | ||
550 | /// </remarks> | ||
551 | public event ScriptControlEvent OnScriptControlEvent; | 286 | public event ScriptControlEvent OnScriptControlEvent; |
552 | 287 | ||
553 | public delegate void ScriptAtTargetEvent(uint localID, uint handle, Vector3 targetpos, Vector3 atpos); | 288 | public delegate void ScriptAtTargetEvent(uint localID, uint handle, Vector3 targetpos, Vector3 atpos); |
554 | |||
555 | /// <summary> | ||
556 | /// Triggered when an object has arrived within a tolerance distance | ||
557 | /// of a motion target. | ||
558 | /// </summary> | ||
559 | /// <remarks> | ||
560 | /// Triggered by <see cref="TriggerAtTargetEvent"/> | ||
561 | /// in <see cref="SceneObjectGroup.checkAtTargets"/> | ||
562 | /// via <see cref="SceneObjectGroup.ScheduleGroupForFullUpdate"/>, | ||
563 | /// <see cref="Scene.CheckAtTargets"/> via <see cref="Scene.Update"/> | ||
564 | /// </remarks> | ||
565 | public event ScriptAtTargetEvent OnScriptAtTargetEvent; | 289 | public event ScriptAtTargetEvent OnScriptAtTargetEvent; |
566 | 290 | ||
567 | public delegate void ScriptNotAtTargetEvent(uint localID); | 291 | public delegate void ScriptNotAtTargetEvent(uint localID); |
568 | |||
569 | /// <summary> | ||
570 | /// Triggered when an object has a motion target but has not arrived | ||
571 | /// within a tolerance distance. | ||
572 | /// </summary> | ||
573 | /// <remarks> | ||
574 | /// Triggered by <see cref="TriggerNotAtTargetEvent"/> | ||
575 | /// in <see cref="SceneObjectGroup.checkAtTargets"/> | ||
576 | /// via <see cref="SceneObjectGroup.ScheduleGroupForFullUpdate"/>, | ||
577 | /// <see cref="Scene.CheckAtTargets"/> via <see cref="Scene.Update"/> | ||
578 | /// </remarks> | ||
579 | public event ScriptNotAtTargetEvent OnScriptNotAtTargetEvent; | 292 | public event ScriptNotAtTargetEvent OnScriptNotAtTargetEvent; |
580 | 293 | ||
581 | public delegate void ScriptAtRotTargetEvent(uint localID, uint handle, Quaternion targetrot, Quaternion atrot); | 294 | public delegate void ScriptAtRotTargetEvent(uint localID, uint handle, Quaternion targetrot, Quaternion atrot); |
582 | |||
583 | /// <summary> | ||
584 | /// Triggered when an object has arrived within a tolerance rotation | ||
585 | /// of a rotation target. | ||
586 | /// </summary> | ||
587 | /// <remarks> | ||
588 | /// Triggered by <see cref="TriggerAtRotTargetEvent"/> | ||
589 | /// in <see cref="SceneObjectGroup.checkAtTargets"/> | ||
590 | /// via <see cref="SceneObjectGroup.ScheduleGroupForFullUpdate"/>, | ||
591 | /// <see cref="Scene.CheckAtTargets"/> via <see cref="Scene.Update"/> | ||
592 | /// </remarks> | ||
593 | public event ScriptAtRotTargetEvent OnScriptAtRotTargetEvent; | 295 | public event ScriptAtRotTargetEvent OnScriptAtRotTargetEvent; |
594 | 296 | ||
595 | public delegate void ScriptNotAtRotTargetEvent(uint localID); | 297 | public delegate void ScriptNotAtRotTargetEvent(uint localID); |
596 | |||
597 | /// <summary> | ||
598 | /// Triggered when an object has a rotation target but has not arrived | ||
599 | /// within a tolerance rotation. | ||
600 | /// </summary> | ||
601 | /// <remarks> | ||
602 | /// Triggered by <see cref="TriggerNotAtRotTargetEvent"/> | ||
603 | /// in <see cref="SceneObjectGroup.checkAtTargets"/> | ||
604 | /// via <see cref="SceneObjectGroup.ScheduleGroupForFullUpdate"/>, | ||
605 | /// <see cref="Scene.CheckAtTargets"/> via <see cref="Scene.Update"/> | ||
606 | /// </remarks> | ||
607 | public event ScriptNotAtRotTargetEvent OnScriptNotAtRotTargetEvent; | 298 | public event ScriptNotAtRotTargetEvent OnScriptNotAtRotTargetEvent; |
608 | 299 | ||
609 | public delegate void ScriptColliding(uint localID, ColliderArgs colliders); | 300 | public delegate void ScriptColliding(uint localID, ColliderArgs colliders); |
610 | |||
611 | /// <summary> | ||
612 | /// Triggered when a physical collision has started between a prim | ||
613 | /// and something other than the region terrain. | ||
614 | /// </summary> | ||
615 | /// <remarks> | ||
616 | /// Triggered by <see cref="TriggerScriptCollidingStart"/> | ||
617 | /// in <see cref="SceneObjectPart.SendCollisionEvent"/> | ||
618 | /// via <see cref="SceneObjectPart.PhysicsCollision"/> | ||
619 | /// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.OnCollisionUpdate"/> | ||
620 | /// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.SendCollisionUpdate"/> | ||
621 | /// </remarks> | ||
622 | public event ScriptColliding OnScriptColliderStart; | 301 | public event ScriptColliding OnScriptColliderStart; |
623 | |||
624 | /// <summary> | ||
625 | /// Triggered when something that previously collided with a prim has | ||
626 | /// not stopped colliding with it. | ||
627 | /// </summary> | ||
628 | /// <remarks> | ||
629 | /// <seealso cref="OnScriptColliderStart"/> | ||
630 | /// Triggered by <see cref="TriggerScriptColliding"/> | ||
631 | /// in <see cref="SceneObjectPart.SendCollisionEvent"/> | ||
632 | /// via <see cref="SceneObjectPart.PhysicsCollision"/> | ||
633 | /// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.OnCollisionUpdate"/> | ||
634 | /// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.SendCollisionUpdate"/> | ||
635 | /// </remarks> | ||
636 | public event ScriptColliding OnScriptColliding; | 302 | public event ScriptColliding OnScriptColliding; |
637 | |||
638 | /// <summary> | ||
639 | /// Triggered when something that previously collided with a prim has | ||
640 | /// stopped colliding with it. | ||
641 | /// </summary> | ||
642 | /// <remarks> | ||
643 | /// Triggered by <see cref="TriggerScriptCollidingEnd"/> | ||
644 | /// in <see cref="SceneObjectPart.SendCollisionEvent"/> | ||
645 | /// via <see cref="SceneObjectPart.PhysicsCollision"/> | ||
646 | /// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.OnCollisionUpdate"/> | ||
647 | /// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.SendCollisionUpdate"/> | ||
648 | /// </remarks> | ||
649 | public event ScriptColliding OnScriptCollidingEnd; | 303 | public event ScriptColliding OnScriptCollidingEnd; |
650 | |||
651 | /// <summary> | ||
652 | /// Triggered when a physical collision has started between an object | ||
653 | /// and the region terrain. | ||
654 | /// </summary> | ||
655 | /// <remarks> | ||
656 | /// Triggered by <see cref="TriggerScriptLandCollidingStart"/> | ||
657 | /// in <see cref="SceneObjectPart.SendLandCollisionEvent"/> | ||
658 | /// via <see cref="SceneObjectPart.PhysicsCollision"/> | ||
659 | /// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.OnCollisionUpdate"/> | ||
660 | /// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.SendCollisionUpdate"/> | ||
661 | /// </remarks> | ||
662 | public event ScriptColliding OnScriptLandColliderStart; | 304 | public event ScriptColliding OnScriptLandColliderStart; |
663 | |||
664 | /// <summary> | ||
665 | /// Triggered when an object that previously collided with the region | ||
666 | /// terrain has not yet stopped colliding with it. | ||
667 | /// </summary> | ||
668 | /// <remarks> | ||
669 | /// Triggered by <see cref="TriggerScriptLandColliding"/> | ||
670 | /// in <see cref="SceneObjectPart.SendLandCollisionEvent"/> | ||
671 | /// via <see cref="SceneObjectPart.PhysicsCollision"/> | ||
672 | /// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.OnCollisionUpdate"/> | ||
673 | /// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.SendCollisionUpdate"/> | ||
674 | /// </remarks> | ||
675 | public event ScriptColliding OnScriptLandColliding; | 305 | public event ScriptColliding OnScriptLandColliding; |
676 | |||
677 | /// <summary> | ||
678 | /// Triggered when an object that previously collided with the region | ||
679 | /// terrain has stopped colliding with it. | ||
680 | /// </summary> | ||
681 | /// <remarks> | ||
682 | /// Triggered by <see cref="TriggerScriptLandCollidingEnd"/> | ||
683 | /// in <see cref="SceneObjectPart.SendLandCollisionEvent"/> | ||
684 | /// via <see cref="SceneObjectPart.PhysicsCollision"/> | ||
685 | /// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.OnCollisionUpdate"/> | ||
686 | /// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.SendCollisionUpdate"/> | ||
687 | /// </remarks> | ||
688 | public event ScriptColliding OnScriptLandColliderEnd; | 306 | public event ScriptColliding OnScriptLandColliderEnd; |
689 | 307 | ||
690 | public delegate void OnMakeChildAgentDelegate(ScenePresence presence); | 308 | public delegate void OnMakeChildAgentDelegate(ScenePresence presence); |
691 | |||
692 | /// <summary> | ||
693 | /// Triggered when an agent has been made a child agent of a scene. | ||
694 | /// </summary> | ||
695 | /// <remarks> | ||
696 | /// Triggered by <see cref="TriggerOnMakeChildAgent"/> | ||
697 | /// in <see cref="ScenePresence.MakeChildAgent"/> | ||
698 | /// via <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.EntityTransferModule.CrossAgentToNewRegionAsync"/>, | ||
699 | /// <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.EntityTransferModule.DoTeleport"/>, | ||
700 | /// <see cref="OpenSim.Region.CoreModules.InterGrid.KillAUser.ShutdownNoLogout"/> | ||
701 | /// </remarks> | ||
702 | public event OnMakeChildAgentDelegate OnMakeChildAgent; | 309 | public event OnMakeChildAgentDelegate OnMakeChildAgent; |
703 | 310 | ||
704 | public delegate void OnSaveNewWindlightProfileDelegate(); | 311 | public delegate void OnSaveNewWindlightProfileDelegate(); |
705 | public delegate void OnSendNewWindlightProfileTargetedDelegate(RegionLightShareData wl, UUID user); | 312 | public delegate void OnSendNewWindlightProfileTargetedDelegate(RegionLightShareData wl, UUID user); |
706 | 313 | ||
707 | /// <summary> | 314 | /// <summary> |
708 | /// Triggered after the grunt work for adding a root agent to a | ||
709 | /// scene has been performed (resuming attachment scripts, physics, | ||
710 | /// animations etc.) | ||
711 | /// </summary> | ||
712 | /// <remarks> | ||
713 | /// This event is on the critical path for transferring an avatar from one region to another. Try and do | 315 | /// This event is on the critical path for transferring an avatar from one region to another. Try and do |
714 | /// as little work on this event as possible, or do work asynchronously. | 316 | /// as little work on this event as possible, or do work asynchronously. |
715 | /// Triggered after <see cref="OnSetRootAgentScene"/> | 317 | /// </summary> |
716 | /// by <see cref="TriggerOnMakeRootAgent"/> | ||
717 | /// in <see cref="ScenePresence.MakeRootAgent"/> | ||
718 | /// via <see cref="Scene.AgentCrossing"/> | ||
719 | /// and <see cref="ScenePresence.CompleteMovement"/> | ||
720 | /// </remarks> | ||
721 | public event Action<ScenePresence> OnMakeRootAgent; | 318 | public event Action<ScenePresence> OnMakeRootAgent; |
722 | 319 | ||
723 | public event OnSendNewWindlightProfileTargetedDelegate OnSendNewWindlightProfileTargeted; | 320 | public event OnSendNewWindlightProfileTargetedDelegate OnSendNewWindlightProfileTargeted; |
@@ -743,17 +340,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
743 | public event AvatarKillData OnAvatarKilled; | 340 | public event AvatarKillData OnAvatarKilled; |
744 | public delegate void AvatarKillData(uint KillerLocalID, ScenePresence avatar); | 341 | public delegate void AvatarKillData(uint KillerLocalID, ScenePresence avatar); |
745 | 342 | ||
746 | /* | 343 | // public delegate void ScriptTimerEvent(uint localID, double timerinterval); |
747 | public delegate void ScriptTimerEvent(uint localID, double timerinterval); | 344 | |
748 | /// <summary> | 345 | // public event ScriptTimerEvent OnScriptTimerEvent; |
749 | /// Used to be triggered when the LSL timer event fires. | ||
750 | /// </summary> | ||
751 | /// <remarks> | ||
752 | /// Triggered by <see cref="TriggerTimerEvent"/> | ||
753 | /// via <see cref="SceneObjectPart.handleTimerAccounting"/> | ||
754 | /// </remarks> | ||
755 | public event ScriptTimerEvent OnScriptTimerEvent; | ||
756 | */ | ||
757 | 346 | ||
758 | public delegate void EstateToolsSunUpdate(ulong regionHandle, bool FixedTime, bool EstateSun, float LindenHour); | 347 | public delegate void EstateToolsSunUpdate(ulong regionHandle, bool FixedTime, bool EstateSun, float LindenHour); |
759 | public delegate void GetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID); | 348 | public delegate void GetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID); |
@@ -763,27 +352,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
763 | /// <summary> | 352 | /// <summary> |
764 | /// Triggered when an object is added to the scene. | 353 | /// Triggered when an object is added to the scene. |
765 | /// </summary> | 354 | /// </summary> |
766 | /// <remarks> | ||
767 | /// Triggered by <see cref="TriggerObjectAddedToScene"/> | ||
768 | /// in <see cref="Scene.AddNewSceneObject"/>, | ||
769 | /// <see cref="Scene.DuplicateObject"/>, | ||
770 | /// <see cref="Scene.doObjectDuplicateOnRay"/> | ||
771 | /// </remarks> | ||
772 | public event Action<SceneObjectGroup> OnObjectAddedToScene; | 355 | public event Action<SceneObjectGroup> OnObjectAddedToScene; |
773 | 356 | ||
774 | /// <summary> | 357 | /// <summary> |
775 | /// Delegate for <see cref="OnObjectBeingRemovedFromScene"/> | ||
776 | /// </summary> | ||
777 | /// <param name="obj">The object being removed from the scene</param> | ||
778 | public delegate void ObjectBeingRemovedFromScene(SceneObjectGroup obj); | ||
779 | |||
780 | /// <summary> | ||
781 | /// Triggered when an object is removed from the scene. | 358 | /// Triggered when an object is removed from the scene. |
782 | /// </summary> | 359 | /// </summary> |
783 | /// <remarks> | 360 | public delegate void ObjectBeingRemovedFromScene(SceneObjectGroup obj); |
784 | /// Triggered by <see cref="TriggerObjectBeingRemovedFromScene"/> | ||
785 | /// in <see cref="Scene.DeleteSceneObject"/> | ||
786 | /// </remarks> | ||
787 | public event ObjectBeingRemovedFromScene OnObjectBeingRemovedFromScene; | 361 | public event ObjectBeingRemovedFromScene OnObjectBeingRemovedFromScene; |
788 | 362 | ||
789 | public delegate void NoticeNoLandDataFromStorage(); | 363 | public delegate void NoticeNoLandDataFromStorage(); |
@@ -799,20 +373,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
799 | public event RequestParcelPrimCountUpdate OnRequestParcelPrimCountUpdate; | 373 | public event RequestParcelPrimCountUpdate OnRequestParcelPrimCountUpdate; |
800 | 374 | ||
801 | public delegate void ParcelPrimCountTainted(); | 375 | public delegate void ParcelPrimCountTainted(); |
802 | |||
803 | /// <summary> | ||
804 | /// Triggered when the parcel prim count has been altered. | ||
805 | /// </summary> | ||
806 | /// <remarks> | ||
807 | /// Triggered by <see cref="TriggerParcelPrimCountTainted"/> in | ||
808 | /// <see cref="OpenSim.Region.CoreModules.Avatar.Attachments.AttachmentsModule.DetachSingleAttachmentToGround"/>, | ||
809 | /// <see cref="OpenSim.Region.CoreModules.Avatar.Attachments.AttachmentsModule.AttachToAgent"/>, | ||
810 | /// <see cref="Scene.DeleteSceneObject"/>, | ||
811 | /// <see cref="Scene.SelectPrim"/>, | ||
812 | /// <see cref="Scene.DeselectPrim"/>, | ||
813 | /// <see cref="SceneObjectGroup.UpdatePrimFlags"/>, | ||
814 | /// <see cref="SceneObjectGroup.AbsolutePosition"/> | ||
815 | /// </remarks> | ||
816 | public event ParcelPrimCountTainted OnParcelPrimCountTainted; | 376 | public event ParcelPrimCountTainted OnParcelPrimCountTainted; |
817 | public event GetScriptRunning OnGetScriptRunning; | 377 | public event GetScriptRunning OnGetScriptRunning; |
818 | 378 | ||
@@ -876,7 +436,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
876 | /// the scripts may not have started yet | 436 | /// the scripts may not have started yet |
877 | /// Message is non empty string if there were problems loading the oar file | 437 | /// Message is non empty string if there were problems loading the oar file |
878 | /// </summary> | 438 | /// </summary> |
879 | public delegate void OarFileLoaded(Guid guid, List<UUID> loadedScenes, string message); | 439 | public delegate void OarFileLoaded(Guid guid, string message); |
880 | public event OarFileLoaded OnOarFileLoaded; | 440 | public event OarFileLoaded OnOarFileLoaded; |
881 | 441 | ||
882 | /// <summary> | 442 | /// <summary> |
@@ -929,13 +489,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
929 | /// <param name="copy"></param> | 489 | /// <param name="copy"></param> |
930 | /// <param name="original"></param> | 490 | /// <param name="original"></param> |
931 | /// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param> | 491 | /// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param> |
932 | /// <remarks> | ||
933 | /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.SceneObjectPart.Copy"/> | ||
934 | /// </remarks> | ||
935 | public event SceneObjectPartCopyDelegate OnSceneObjectPartCopy; | 492 | public event SceneObjectPartCopyDelegate OnSceneObjectPartCopy; |
936 | public delegate void SceneObjectPartCopyDelegate(SceneObjectPart copy, SceneObjectPart original, bool userExposed); | 493 | public delegate void SceneObjectPartCopyDelegate(SceneObjectPart copy, SceneObjectPart original, bool userExposed); |
937 | 494 | ||
938 | public delegate void SceneObjectPartUpdated(SceneObjectPart sop, bool full); | 495 | public delegate void SceneObjectPartUpdated(SceneObjectPart sop); |
939 | public event SceneObjectPartUpdated OnSceneObjectPartUpdated; | 496 | public event SceneObjectPartUpdated OnSceneObjectPartUpdated; |
940 | 497 | ||
941 | public delegate void ScenePresenceUpdated(ScenePresence sp); | 498 | public delegate void ScenePresenceUpdated(ScenePresence sp); |
@@ -973,28 +530,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
973 | public event PrimsLoaded OnPrimsLoaded; | 530 | public event PrimsLoaded OnPrimsLoaded; |
974 | 531 | ||
975 | public delegate void TeleportStart(IClientAPI client, GridRegion destination, GridRegion finalDestination, uint teleportFlags, bool gridLogout); | 532 | public delegate void TeleportStart(IClientAPI client, GridRegion destination, GridRegion finalDestination, uint teleportFlags, bool gridLogout); |
976 | |||
977 | /// <summary> | ||
978 | /// Triggered when a teleport starts | ||
979 | /// </summary> | ||
980 | /// <remarks> | ||
981 | /// Triggered by <see cref="TriggerTeleportStart"/> | ||
982 | /// in <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.EntityTransferModule.CreateAgent"/> | ||
983 | /// and <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.HGEntityTransferModule.CreateAgent"/> | ||
984 | /// via <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.EntityTransferModule.DoTeleport"/> | ||
985 | /// </remarks> | ||
986 | public event TeleportStart OnTeleportStart; | 533 | public event TeleportStart OnTeleportStart; |
987 | 534 | ||
988 | public delegate void TeleportFail(IClientAPI client, bool gridLogout); | 535 | public delegate void TeleportFail(IClientAPI client, bool gridLogout); |
989 | |||
990 | /// <summary> | ||
991 | /// Trigered when a teleport fails. | ||
992 | /// </summary> | ||
993 | /// <remarks> | ||
994 | /// Triggered by <see cref="TriggerTeleportFail"/> | ||
995 | /// in <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.EntityTransferModule.Fail"/> | ||
996 | /// via <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.EntityTransferModule.DoTeleport"/> | ||
997 | /// </remarks> | ||
998 | public event TeleportFail OnTeleportFail; | 536 | public event TeleportFail OnTeleportFail; |
999 | 537 | ||
1000 | public class MoneyTransferArgs : EventArgs | 538 | public class MoneyTransferArgs : EventArgs |
@@ -1002,9 +540,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1002 | public UUID sender; | 540 | public UUID sender; |
1003 | public UUID receiver; | 541 | public UUID receiver; |
1004 | 542 | ||
1005 | /// <summary> | 543 | // Always false. The SL protocol sucks. |
1006 | /// Always false. The SL protocol sucks. | ||
1007 | /// </summary> | ||
1008 | public bool authenticated = false; | 544 | public bool authenticated = false; |
1009 | 545 | ||
1010 | public int amount; | 546 | public int amount; |
@@ -1061,29 +597,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
1061 | 597 | ||
1062 | public delegate void LandBuy(Object sender, LandBuyArgs e); | 598 | public delegate void LandBuy(Object sender, LandBuyArgs e); |
1063 | 599 | ||
1064 | /// <summary> | ||
1065 | /// Triggered when an attempt to transfer grid currency occurs | ||
1066 | /// </summary> | ||
1067 | /// <remarks> | ||
1068 | /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.ProcessMoneyTransferRequest"/> | ||
1069 | /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.SubscribeToClientGridEvents"/> | ||
1070 | /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.SubscribeToClientEvents"/> | ||
1071 | /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewClient"/> | ||
1072 | /// </remarks> | ||
1073 | public event MoneyTransferEvent OnMoneyTransfer; | 600 | public event MoneyTransferEvent OnMoneyTransfer; |
1074 | |||
1075 | /// <summary> | ||
1076 | /// Triggered after after <see cref="OnValidateLandBuy"/> | ||
1077 | /// </summary> | ||
1078 | public event LandBuy OnLandBuy; | 601 | public event LandBuy OnLandBuy; |
1079 | |||
1080 | /// <summary> | ||
1081 | /// Triggered to allow or prevent a real estate transaction | ||
1082 | /// </summary> | ||
1083 | /// <remarks> | ||
1084 | /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.ProcessParcelBuy"/> | ||
1085 | /// <seealso cref="OpenSim.Region.OptionalModules.World.MoneyModule.SampleMoneyModule.ValidateLandBuy"/> | ||
1086 | /// </remarks> | ||
1087 | public event LandBuy OnValidateLandBuy; | 602 | public event LandBuy OnValidateLandBuy; |
1088 | 603 | ||
1089 | public void TriggerOnAttach(uint localID, UUID itemID, UUID avatarID) | 604 | public void TriggerOnAttach(uint localID, UUID itemID, UUID avatarID) |
@@ -2520,11 +2035,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2520 | } | 2035 | } |
2521 | } | 2036 | } |
2522 | 2037 | ||
2523 | /// <summary> | 2038 | // this lets us keep track of nasty script events like timer, etc. |
2524 | /// this lets us keep track of nasty script events like timer, etc. | ||
2525 | /// </summary> | ||
2526 | /// <param name="objLocalID"></param> | ||
2527 | /// <param name="Interval"></param> | ||
2528 | public void TriggerTimerEvent(uint objLocalID, double Interval) | 2039 | public void TriggerTimerEvent(uint objLocalID, double Interval) |
2529 | { | 2040 | { |
2530 | throw new NotImplementedException("TriggerTimerEvent was thought to be not used anymore and the registration for the event from scene object part has been commented out due to a memory leak"); | 2041 | throw new NotImplementedException("TriggerTimerEvent was thought to be not used anymore and the registration for the event from scene object part has been commented out due to a memory leak"); |
@@ -2586,7 +2097,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2586 | return 6; | 2097 | return 6; |
2587 | } | 2098 | } |
2588 | 2099 | ||
2589 | public void TriggerOarFileLoaded(Guid requestId, List<UUID> loadedScenes, string message) | 2100 | public void TriggerOarFileLoaded(Guid requestId, string message) |
2590 | { | 2101 | { |
2591 | OarFileLoaded handlerOarFileLoaded = OnOarFileLoaded; | 2102 | OarFileLoaded handlerOarFileLoaded = OnOarFileLoaded; |
2592 | if (handlerOarFileLoaded != null) | 2103 | if (handlerOarFileLoaded != null) |
@@ -2595,7 +2106,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2595 | { | 2106 | { |
2596 | try | 2107 | try |
2597 | { | 2108 | { |
2598 | d(requestId, loadedScenes, message); | 2109 | d(requestId, message); |
2599 | } | 2110 | } |
2600 | catch (Exception e) | 2111 | catch (Exception e) |
2601 | { | 2112 | { |
@@ -2880,7 +2391,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2880 | } | 2391 | } |
2881 | } | 2392 | } |
2882 | 2393 | ||
2883 | public void TriggerSceneObjectPartUpdated(SceneObjectPart sop, bool full) | 2394 | public void TriggerSceneObjectPartUpdated(SceneObjectPart sop) |
2884 | { | 2395 | { |
2885 | SceneObjectPartUpdated handler = OnSceneObjectPartUpdated; | 2396 | SceneObjectPartUpdated handler = OnSceneObjectPartUpdated; |
2886 | if (handler != null) | 2397 | if (handler != null) |
@@ -2889,7 +2400,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2889 | { | 2400 | { |
2890 | try | 2401 | try |
2891 | { | 2402 | { |
2892 | d(sop, full); | 2403 | d(sop); |
2893 | } | 2404 | } |
2894 | catch (Exception e) | 2405 | catch (Exception e) |
2895 | { | 2406 | { |
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 6208a57..906c1ee 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | |||
@@ -93,7 +93,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
93 | /// </summary> | 93 | /// </summary> |
94 | public void StartScripts() | 94 | public void StartScripts() |
95 | { | 95 | { |
96 | // m_log.InfoFormat("[SCENE]: Starting scripts in {0}, please wait.", RegionInfo.RegionName); | 96 | m_log.InfoFormat("[SCENE]: Starting scripts in {0}, please wait.", RegionInfo.RegionName); |
97 | 97 | ||
98 | IScriptModule[] engines = RequestModuleInterfaces<IScriptModule>(); | 98 | IScriptModule[] engines = RequestModuleInterfaces<IScriptModule>(); |
99 | 99 | ||
@@ -1469,7 +1469,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1469 | return newFolderID; | 1469 | return newFolderID; |
1470 | } | 1470 | } |
1471 | 1471 | ||
1472 | public void SendInventoryUpdate(IClientAPI client, InventoryFolderBase folder, bool fetchFolders, bool fetchItems) | 1472 | private void SendInventoryUpdate(IClientAPI client, InventoryFolderBase folder, bool fetchFolders, bool fetchItems) |
1473 | { | 1473 | { |
1474 | if (folder == null) | 1474 | if (folder == null) |
1475 | return; | 1475 | return; |
@@ -1997,9 +1997,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
1997 | // If child prims have invalid perms, fix them | 1997 | // If child prims have invalid perms, fix them |
1998 | grp.AdjustChildPrimPermissions(); | 1998 | grp.AdjustChildPrimPermissions(); |
1999 | 1999 | ||
2000 | // If child prims have invalid perms, fix them | ||
2001 | grp.AdjustChildPrimPermissions(); | ||
2002 | |||
2003 | if (remoteClient == null) | 2000 | if (remoteClient == null) |
2004 | { | 2001 | { |
2005 | // Autoreturn has a null client. Nothing else does. So | 2002 | // Autoreturn has a null client. Nothing else does. So |
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs index ce6415a..e970543 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs | |||
@@ -38,20 +38,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
38 | { | 38 | { |
39 | public partial class Scene | 39 | public partial class Scene |
40 | { | 40 | { |
41 | /// <summary> | ||
42 | /// Send chat to listeners. | ||
43 | /// </summary> | ||
44 | /// <param name='message'></param> | ||
45 | /// <param name='type'>/param> | ||
46 | /// <param name='channel'></param> | ||
47 | /// <param name='fromPos'></param> | ||
48 | /// <param name='fromName'></param> | ||
49 | /// <param name='fromID'></param> | ||
50 | /// <param name='targetID'></param> | ||
51 | /// <param name='fromAgent'></param> | ||
52 | /// <param name='broadcast'></param> | ||
53 | public void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName, | 41 | public void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName, |
54 | UUID fromID, UUID targetID, bool fromAgent, bool broadcast) | 42 | UUID fromID, bool fromAgent, bool broadcast, UUID destination) |
55 | { | 43 | { |
56 | OSChatMessage args = new OSChatMessage(); | 44 | OSChatMessage args = new OSChatMessage(); |
57 | 45 | ||
@@ -61,7 +49,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
61 | args.Position = fromPos; | 49 | args.Position = fromPos; |
62 | args.SenderUUID = fromID; | 50 | args.SenderUUID = fromID; |
63 | args.Scene = this; | 51 | args.Scene = this; |
64 | args.Destination = targetID; | 52 | args.Destination = destination; |
65 | 53 | ||
66 | if (fromAgent) | 54 | if (fromAgent) |
67 | { | 55 | { |
@@ -78,10 +66,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
78 | args.From = fromName; | 66 | args.From = fromName; |
79 | //args. | 67 | //args. |
80 | 68 | ||
81 | // m_log.DebugFormat( | ||
82 | // "[SCENE]: Sending message {0} on channel {1}, type {2} from {3}, broadcast {4}", | ||
83 | // args.Message.Replace("\n", "\\n"), args.Channel, args.Type, fromName, broadcast); | ||
84 | |||
85 | if (broadcast) | 69 | if (broadcast) |
86 | EventManager.TriggerOnChatBroadcast(this, args); | 70 | EventManager.TriggerOnChatBroadcast(this, args); |
87 | else | 71 | else |
@@ -91,7 +75,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
91 | protected void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName, | 75 | protected void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName, |
92 | UUID fromID, bool fromAgent, bool broadcast) | 76 | UUID fromID, bool fromAgent, bool broadcast) |
93 | { | 77 | { |
94 | SimChat(message, type, channel, fromPos, fromName, fromID, UUID.Zero, fromAgent, broadcast); | 78 | SimChat(message, type, channel, fromPos, fromName, fromID, fromAgent, broadcast, UUID.Zero); |
95 | } | 79 | } |
96 | 80 | ||
97 | /// <summary> | 81 | /// <summary> |
@@ -559,7 +543,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
559 | if (!InventoryService.AddFolder(folder)) | 543 | if (!InventoryService.AddFolder(folder)) |
560 | { | 544 | { |
561 | m_log.WarnFormat( | 545 | m_log.WarnFormat( |
562 | "[AGENT INVENTORY]: Failed to create folder for user {0} {1}", | 546 | "[AGENT INVENTORY]: Failed to move create folder for user {0} {1}", |
563 | remoteClient.Name, remoteClient.AgentId); | 547 | remoteClient.Name, remoteClient.AgentId); |
564 | } | 548 | } |
565 | } | 549 | } |
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 2543333..649d545 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs | |||
@@ -80,11 +80,6 @@ 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> | ||
88 | /// Statistical information for this scene. | 83 | /// Statistical information for this scene. |
89 | /// </summary> | 84 | /// </summary> |
90 | public SimStatsReporter StatsReporter { get; private set; } | 85 | public SimStatsReporter StatsReporter { get; private set; } |
@@ -108,31 +103,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
108 | /// </summary> | 103 | /// </summary> |
109 | public bool CollidablePrims { get; private set; } | 104 | public bool CollidablePrims { get; private set; } |
110 | 105 | ||
111 | /// <summary> | ||
112 | /// Minimum value of the size of a non-physical prim in each axis | ||
113 | /// </summary> | ||
114 | public float m_minNonphys = 0.001f; | ||
115 | |||
116 | /// <summary> | ||
117 | /// Maximum value of the size of a non-physical prim in each axis | ||
118 | /// </summary> | ||
119 | public float m_maxNonphys = 256; | 106 | public float m_maxNonphys = 256; |
120 | |||
121 | /// <summary> | ||
122 | /// Minimum value of the size of a physical prim in each axis | ||
123 | /// </summary> | ||
124 | public float m_minPhys = 0.01f; | ||
125 | |||
126 | /// <summary> | ||
127 | /// Maximum value of the size of a physical prim in each axis | ||
128 | /// </summary> | ||
129 | public float m_maxPhys = 10; | 107 | public float m_maxPhys = 10; |
130 | |||
131 | /// <summary> | ||
132 | /// Max prims an object will hold | ||
133 | /// </summary> | ||
134 | public int m_linksetCapacity = 0; | ||
135 | |||
136 | public bool m_clampPrimSize; | 108 | public bool m_clampPrimSize; |
137 | public bool m_trustBinaries; | 109 | public bool m_trustBinaries; |
138 | public bool m_allowScriptCrossings; | 110 | public bool m_allowScriptCrossings; |
@@ -313,31 +285,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
313 | } | 285 | } |
314 | private volatile bool m_shuttingDown; | 286 | private volatile bool m_shuttingDown; |
315 | 287 | ||
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 | |||
341 | // private int m_lastUpdate; | 288 | // private int m_lastUpdate; |
342 | private bool m_firstHeartbeat = true; | 289 | private bool m_firstHeartbeat = true; |
343 | 290 | ||
@@ -799,24 +746,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
799 | PhysicalPrims = startupConfig.GetBoolean("physical_prim", true); | 746 | PhysicalPrims = startupConfig.GetBoolean("physical_prim", true); |
800 | CollidablePrims = startupConfig.GetBoolean("collidable_prim", true); | 747 | CollidablePrims = startupConfig.GetBoolean("collidable_prim", true); |
801 | 748 | ||
802 | m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys); | 749 | m_maxNonphys = startupConfig.GetFloat("NonphysicalPrimMax", m_maxNonphys); |
803 | if (RegionInfo.NonphysPrimMin > 0) | ||
804 | { | ||
805 | m_minNonphys = RegionInfo.NonphysPrimMin; | ||
806 | } | ||
807 | |||
808 | m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys); | ||
809 | if (RegionInfo.NonphysPrimMax > 0) | 750 | if (RegionInfo.NonphysPrimMax > 0) |
810 | { | 751 | { |
811 | m_maxNonphys = RegionInfo.NonphysPrimMax; | 752 | m_maxNonphys = RegionInfo.NonphysPrimMax; |
812 | } | 753 | } |
813 | 754 | ||
814 | m_minPhys = startupConfig.GetFloat("PhysicalPrimMin", m_minPhys); | ||
815 | if (RegionInfo.PhysPrimMin > 0) | ||
816 | { | ||
817 | m_minPhys = RegionInfo.PhysPrimMin; | ||
818 | } | ||
819 | |||
820 | m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys); | 755 | m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys); |
821 | 756 | ||
822 | if (RegionInfo.PhysPrimMax > 0) | 757 | if (RegionInfo.PhysPrimMax > 0) |
@@ -824,12 +759,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
824 | m_maxPhys = RegionInfo.PhysPrimMax; | 759 | m_maxPhys = RegionInfo.PhysPrimMax; |
825 | } | 760 | } |
826 | 761 | ||
827 | m_linksetCapacity = startupConfig.GetInt("LinksetPrims", m_linksetCapacity); | ||
828 | if (RegionInfo.LinksetCapacity > 0) | ||
829 | { | ||
830 | m_linksetCapacity = RegionInfo.LinksetCapacity; | ||
831 | } | ||
832 | |||
833 | SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest"); | 762 | SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest"); |
834 | TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false); | 763 | TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false); |
835 | 764 | ||
@@ -855,6 +784,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
855 | m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); | 784 | m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); |
856 | m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine); | 785 | m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine); |
857 | 786 | ||
787 | IConfig packetConfig = m_config.Configs["PacketPool"]; | ||
788 | if (packetConfig != null) | ||
789 | { | ||
790 | PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true); | ||
791 | PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true); | ||
792 | } | ||
793 | |||
858 | m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); | 794 | m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); |
859 | m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion); | 795 | m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion); |
860 | CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false); | 796 | CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false); |
@@ -918,8 +854,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
918 | } | 854 | } |
919 | 855 | ||
920 | // FIXME: Ultimately this should be in a module. | 856 | // FIXME: Ultimately this should be in a module. |
921 | SendPeriodicAppearanceUpdates = true; | ||
922 | |||
923 | IConfig appearanceConfig = m_config.Configs["Appearance"]; | 857 | IConfig appearanceConfig = m_config.Configs["Appearance"]; |
924 | if (appearanceConfig != null) | 858 | if (appearanceConfig != null) |
925 | { | 859 | { |
@@ -1217,14 +1151,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
1217 | 1151 | ||
1218 | public void SetSceneCoreDebug(Dictionary<string, string> options) | 1152 | public void SetSceneCoreDebug(Dictionary<string, string> options) |
1219 | { | 1153 | { |
1220 | if (options.ContainsKey("active")) | ||
1221 | { | ||
1222 | bool active; | ||
1223 | |||
1224 | if (bool.TryParse(options["active"], out active)) | ||
1225 | Active = active; | ||
1226 | } | ||
1227 | |||
1228 | if (options.ContainsKey("scripting")) | 1154 | if (options.ContainsKey("scripting")) |
1229 | { | 1155 | { |
1230 | bool enableScripts = true; | 1156 | bool enableScripts = true; |
@@ -1300,12 +1226,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
1300 | // This is the method that shuts down the scene. | 1226 | // This is the method that shuts down the scene. |
1301 | public override void Close() | 1227 | public override void Close() |
1302 | { | 1228 | { |
1303 | if (m_shuttingDown) | ||
1304 | { | ||
1305 | m_log.WarnFormat("[SCENE]: Ignoring close request because already closing {0}", Name); | ||
1306 | return; | ||
1307 | } | ||
1308 | |||
1309 | m_log.InfoFormat("[SCENE]: Closing down the single simulator: {0}", RegionInfo.RegionName); | 1229 | m_log.InfoFormat("[SCENE]: Closing down the single simulator: {0}", RegionInfo.RegionName); |
1310 | 1230 | ||
1311 | StatsReporter.Close(); | 1231 | StatsReporter.Close(); |
@@ -1352,14 +1272,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
1352 | m_log.Debug("[SCENE]: Graph close"); | 1272 | m_log.Debug("[SCENE]: Graph close"); |
1353 | m_sceneGraph.Close(); | 1273 | m_sceneGraph.Close(); |
1354 | 1274 | ||
1355 | if (!GridService.DeregisterRegion(RegionInfo.RegionID)) | ||
1356 | m_log.WarnFormat("[SCENE]: Deregister from grid failed for region {0}", Name); | ||
1357 | |||
1358 | base.Close(); | ||
1359 | |||
1360 | // XEngine currently listens to the EventManager.OnShutdown event to trigger script stop and persistence. | ||
1361 | // Therefore. we must dispose of the PhysicsScene after this to prevent a window where script code can | ||
1362 | // attempt to reference a null or disposed physics scene. | ||
1363 | if (PhysicsScene != null) | 1275 | if (PhysicsScene != null) |
1364 | { | 1276 | { |
1365 | m_log.Debug("[SCENE]: Dispose Physics"); | 1277 | m_log.Debug("[SCENE]: Dispose Physics"); |
@@ -1369,6 +1281,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
1369 | phys.Dispose(); | 1281 | phys.Dispose(); |
1370 | phys = null; | 1282 | phys = null; |
1371 | } | 1283 | } |
1284 | |||
1285 | if (!GridService.DeregisterRegion(RegionInfo.RegionID)) | ||
1286 | m_log.WarnFormat("[SCENE]: Deregister from grid failed for region {0}", Name); | ||
1287 | |||
1288 | // call the base class Close method. | ||
1289 | m_log.Debug("[SCENE]: Base close"); | ||
1290 | base.Close(); | ||
1372 | } | 1291 | } |
1373 | 1292 | ||
1374 | /// <summary> | 1293 | /// <summary> |
@@ -1376,8 +1295,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
1376 | /// </summary> | 1295 | /// </summary> |
1377 | public void Start() | 1296 | public void Start() |
1378 | { | 1297 | { |
1379 | m_active = true; | ||
1380 | |||
1381 | // m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName); | 1298 | // m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName); |
1382 | 1299 | ||
1383 | //m_heartbeatTimer.Enabled = true; | 1300 | //m_heartbeatTimer.Enabled = true; |
@@ -1437,7 +1354,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1437 | #region Update Methods | 1354 | #region Update Methods |
1438 | 1355 | ||
1439 | /// <summary> | 1356 | /// <summary> |
1440 | /// Activate the various loops necessary to continually update the scene. | 1357 | /// Performs per-frame updates regularly |
1441 | /// </summary> | 1358 | /// </summary> |
1442 | private void Heartbeat() | 1359 | private void Heartbeat() |
1443 | { | 1360 | { |
@@ -1494,7 +1411,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1494 | List<Vector3> coarseLocations; | 1411 | List<Vector3> coarseLocations; |
1495 | List<UUID> avatarUUIDs; | 1412 | List<UUID> avatarUUIDs; |
1496 | 1413 | ||
1497 | while (!m_shuttingDown && ((endRun == null && Active) || MaintenanceRun < endRun)) | 1414 | while (!m_shuttingDown && (endRun == null || MaintenanceRun < endRun)) |
1498 | { | 1415 | { |
1499 | runtc = Util.EnvironmentTickCount(); | 1416 | runtc = Util.EnvironmentTickCount(); |
1500 | ++MaintenanceRun; | 1417 | ++MaintenanceRun; |
@@ -1556,7 +1473,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1556 | int sleepMS; | 1473 | int sleepMS; |
1557 | int framestart; | 1474 | int framestart; |
1558 | 1475 | ||
1559 | while (!m_shuttingDown && ((endFrame == null && Active) || Frame < endFrame)) | 1476 | while (!m_shuttingDown && (endFrame == null || Frame < endFrame)) |
1560 | { | 1477 | { |
1561 | framestart = Util.EnvironmentTickCount(); | 1478 | framestart = Util.EnvironmentTickCount(); |
1562 | ++Frame; | 1479 | ++Frame; |
@@ -1755,19 +1672,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
1755 | 1672 | ||
1756 | private void CheckAtTargets() | 1673 | private void CheckAtTargets() |
1757 | { | 1674 | { |
1758 | List<SceneObjectGroup> objs = null; | 1675 | List<SceneObjectGroup> objs = new List<SceneObjectGroup>(); |
1759 | |||
1760 | lock (m_groupsWithTargets) | 1676 | lock (m_groupsWithTargets) |
1761 | { | 1677 | { |
1762 | if (m_groupsWithTargets.Count != 0) | 1678 | foreach (SceneObjectGroup grp in m_groupsWithTargets.Values) |
1763 | objs = new List<SceneObjectGroup>(m_groupsWithTargets.Values); | 1679 | objs.Add(grp); |
1764 | } | 1680 | } |
1765 | 1681 | ||
1766 | if (objs != null) | 1682 | foreach (SceneObjectGroup entry in objs) |
1767 | { | 1683 | entry.checkAtTargets(); |
1768 | foreach (SceneObjectGroup entry in objs) | ||
1769 | entry.checkAtTargets(); | ||
1770 | } | ||
1771 | } | 1684 | } |
1772 | 1685 | ||
1773 | /// <summary> | 1686 | /// <summary> |
@@ -2280,14 +2193,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
2280 | public bool AddRestoredSceneObject( | 2193 | public bool AddRestoredSceneObject( |
2281 | SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) | 2194 | SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) |
2282 | { | 2195 | { |
2283 | if (m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates)) | 2196 | bool result = m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); |
2284 | { | 2197 | if (result) |
2285 | sceneObject.IsDeleted = false; | 2198 | sceneObject.IsDeleted = false; |
2286 | EventManager.TriggerObjectAddedToScene(sceneObject); | 2199 | return result; |
2287 | return true; | ||
2288 | } | ||
2289 | |||
2290 | return false; | ||
2291 | } | 2200 | } |
2292 | 2201 | ||
2293 | /// <summary> | 2202 | /// <summary> |
@@ -2928,89 +2837,77 @@ namespace OpenSim.Region.Framework.Scenes | |||
2928 | 2837 | ||
2929 | public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type) | 2838 | public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type) |
2930 | { | 2839 | { |
2931 | ScenePresence sp; | ||
2932 | bool vialogin; | ||
2933 | |||
2934 | // Validation occurs in LLUDPServer | 2840 | // Validation occurs in LLUDPServer |
2935 | // | ||
2936 | // XXX: A race condition exists here where two simultaneous calls to AddNewClient can interfere with | ||
2937 | // each other. In practice, this does not currently occur in the code. | ||
2938 | AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode); | 2841 | AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode); |
2939 | 2842 | ||
2940 | // We lock here on AgentCircuitData to prevent a race condition between the thread adding a new connection | 2843 | bool vialogin |
2941 | // and a simultaneous one that removes it (as can happen if the client is closed at a particular point | 2844 | = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 |
2942 | // whilst connecting). | 2845 | || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; |
2943 | // | ||
2944 | // It would be easier to lock across all NewUserConnection(), AddNewClient() and | ||
2945 | // RemoveClient() calls for all agents, but this would allow a slow call (e.g. because of slow service | ||
2946 | // response in some module listening to AddNewClient()) from holding up unrelated agent calls. | ||
2947 | // | ||
2948 | // In practice, the lock (this) in LLUDPServer.AddNewClient() currently lock across all | ||
2949 | // AddNewClient() operations (though not other ops). | ||
2950 | // In the future this can be relieved once locking per agent (not necessarily on AgentCircuitData) is improved. | ||
2951 | lock (aCircuit) | ||
2952 | { | ||
2953 | vialogin | ||
2954 | = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 | ||
2955 | || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; | ||
2956 | |||
2957 | CheckHeartbeat(); | ||
2958 | |||
2959 | sp = GetScenePresence(client.AgentId); | ||
2960 | 2846 | ||
2961 | // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this | 2847 | CheckHeartbeat(); |
2962 | // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause | 2848 | |
2963 | // other problems, and possible the code calling AddNewClient() should ensure that no client is already | 2849 | ScenePresence sp = GetScenePresence(client.AgentId); |
2964 | // connected. | 2850 | |
2965 | if (sp == null) | 2851 | // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this |
2966 | { | 2852 | // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause |
2967 | m_log.DebugFormat( | 2853 | // other problems, and possible the code calling AddNewClient() should ensure that no client is already |
2968 | "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}", | 2854 | // connected. |
2969 | client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos); | 2855 | if (sp == null) |
2970 | 2856 | { | |
2971 | m_clientManager.Add(client); | 2857 | m_log.DebugFormat( |
2972 | SubscribeToClientEvents(client); | 2858 | "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}", |
2973 | 2859 | client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos); | |
2974 | sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type); | 2860 | |
2975 | m_eventManager.TriggerOnNewPresence(sp); | 2861 | m_clientManager.Add(client); |
2976 | 2862 | SubscribeToClientEvents(client); | |
2977 | sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags; | 2863 | |
2978 | 2864 | sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type); | |
2979 | // The first agent upon login is a root agent by design. | 2865 | m_eventManager.TriggerOnNewPresence(sp); |
2980 | // For this agent we will have to rez the attachments. | 2866 | |
2981 | // All other AddNewClient calls find aCircuit.child to be true. | 2867 | sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags; |
2982 | if (aCircuit.child == false) | 2868 | |
2983 | { | 2869 | // The first agent upon login is a root agent by design. |
2984 | // We have to set SP to be a root agent here so that SP.MakeRootAgent() will later not try to | 2870 | // For this agent we will have to rez the attachments. |
2985 | // start the scripts again (since this is done in RezAttachments()). | 2871 | // All other AddNewClient calls find aCircuit.child to be true. |
2986 | // XXX: This is convoluted. | 2872 | if (aCircuit.child == false) |
2987 | sp.IsChildAgent = false; | ||
2988 | |||
2989 | if (AttachmentsModule != null) | ||
2990 | Util.FireAndForget(delegate(object o) { AttachmentsModule.RezAttachments(sp); }); | ||
2991 | } | ||
2992 | } | ||
2993 | else | ||
2994 | { | 2873 | { |
2995 | m_log.WarnFormat( | 2874 | // We have to set SP to be a root agent here so that SP.MakeRootAgent() will later not try to |
2996 | "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence", | 2875 | // start the scripts again (since this is done in RezAttachments()). |
2997 | sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName); | 2876 | // XXX: This is convoluted. |
2998 | } | 2877 | sp.IsChildAgent = false; |
2999 | |||
3000 | // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the | ||
3001 | // client is for a root or child agent. | ||
3002 | client.SceneAgent = sp; | ||
3003 | 2878 | ||
3004 | // Cache the user's name | 2879 | if (AttachmentsModule != null) |
3005 | CacheUserName(sp, aCircuit); | 2880 | Util.FireAndForget(delegate(object o) { AttachmentsModule.RezAttachments(sp); }); |
3006 | 2881 | } | |
3007 | EventManager.TriggerOnNewClient(client); | 2882 | } |
3008 | if (vialogin) | 2883 | else |
3009 | EventManager.TriggerOnClientLogin(client); | 2884 | { |
2885 | m_log.WarnFormat( | ||
2886 | "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence", | ||
2887 | sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName); | ||
3010 | } | 2888 | } |
3011 | 2889 | ||
2890 | // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the | ||
2891 | // client is for a root or child agent. | ||
2892 | client.SceneAgent = sp; | ||
2893 | |||
3012 | m_LastLogin = Util.EnvironmentTickCount(); | 2894 | m_LastLogin = Util.EnvironmentTickCount(); |
3013 | 2895 | ||
2896 | // Cache the user's name | ||
2897 | CacheUserName(sp, aCircuit); | ||
2898 | |||
2899 | EventManager.TriggerOnNewClient(client); | ||
2900 | if (vialogin) | ||
2901 | { | ||
2902 | EventManager.TriggerOnClientLogin(client); | ||
2903 | // Send initial parcel data | ||
2904 | /* this is done on TriggerOnNewClient by landmanegement respective event handler | ||
2905 | Vector3 pos = sp.AbsolutePosition; | ||
2906 | ILandObject land = LandChannel.GetLandObject(pos.X, pos.Y); | ||
2907 | land.SendLandUpdateToClient(client); | ||
2908 | */ | ||
2909 | } | ||
2910 | |||
3014 | return sp; | 2911 | return sp; |
3015 | } | 2912 | } |
3016 | 2913 | ||
@@ -3550,132 +3447,110 @@ namespace OpenSim.Region.Framework.Scenes | |||
3550 | { | 3447 | { |
3551 | // CheckHeartbeat(); | 3448 | // CheckHeartbeat(); |
3552 | bool isChildAgent = false; | 3449 | bool isChildAgent = false; |
3553 | AgentCircuitData acd; | 3450 | ScenePresence avatar = GetScenePresence(agentID); |
3554 | 3451 | ||
3555 | lock (m_removeClientLock) | 3452 | if (avatar == null) |
3556 | { | 3453 | { |
3557 | acd = m_authenticateHandler.GetAgentCircuitData(agentID); | 3454 | m_log.WarnFormat( |
3455 | "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID); | ||
3558 | 3456 | ||
3559 | if (acd == null) | 3457 | return; |
3560 | { | ||
3561 | m_log.ErrorFormat("[SCENE]: No agent circuit found for {0}, aborting Scene.RemoveClient", agentID); | ||
3562 | return; | ||
3563 | } | ||
3564 | else | ||
3565 | { | ||
3566 | // We remove the acd up here to avoid later race conditions if two RemoveClient() calls occurred | ||
3567 | // simultaneously. | ||
3568 | // We also need to remove by agent ID since NPCs will have no circuit code. | ||
3569 | m_authenticateHandler.RemoveCircuit(agentID); | ||
3570 | } | ||
3571 | } | 3458 | } |
3572 | 3459 | ||
3573 | lock (acd) | 3460 | try |
3574 | { | 3461 | { |
3575 | ScenePresence avatar = GetScenePresence(agentID); | 3462 | isChildAgent = avatar.IsChildAgent; |
3576 | |||
3577 | if (avatar == null) | ||
3578 | { | ||
3579 | m_log.WarnFormat( | ||
3580 | "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID); | ||
3581 | |||
3582 | return; | ||
3583 | } | ||
3584 | |||
3585 | try | ||
3586 | { | ||
3587 | isChildAgent = avatar.IsChildAgent; | ||
3588 | 3463 | ||
3589 | m_log.DebugFormat( | 3464 | m_log.DebugFormat( |
3590 | "[SCENE]: Removing {0} agent {1} {2} from {3}", | 3465 | "[SCENE]: Removing {0} agent {1} {2} from {3}", |
3591 | (isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName); | 3466 | (isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName); |
3592 | 3467 | ||
3593 | // Don't do this to root agents, it's not nice for the viewer | 3468 | // Don't do this to root agents, it's not nice for the viewer |
3594 | if (closeChildAgents && isChildAgent) | 3469 | if (closeChildAgents && isChildAgent) |
3470 | { | ||
3471 | // Tell a single agent to disconnect from the region. | ||
3472 | IEventQueue eq = RequestModuleInterface<IEventQueue>(); | ||
3473 | if (eq != null) | ||
3595 | { | 3474 | { |
3596 | // Tell a single agent to disconnect from the region. | 3475 | eq.DisableSimulator(RegionInfo.RegionHandle, avatar.UUID); |
3597 | IEventQueue eq = RequestModuleInterface<IEventQueue>(); | ||
3598 | if (eq != null) | ||
3599 | { | ||
3600 | eq.DisableSimulator(RegionInfo.RegionHandle, avatar.UUID); | ||
3601 | } | ||
3602 | else | ||
3603 | { | ||
3604 | avatar.ControllingClient.SendShutdownConnectionNotice(); | ||
3605 | } | ||
3606 | } | 3476 | } |
3607 | 3477 | else | |
3608 | // Only applies to root agents. | ||
3609 | if (avatar.ParentID != 0) | ||
3610 | { | 3478 | { |
3611 | avatar.StandUp(); | 3479 | avatar.ControllingClient.SendShutdownConnectionNotice(); |
3612 | } | 3480 | } |
3613 | 3481 | } | |
3614 | m_sceneGraph.removeUserCount(!isChildAgent); | 3482 | |
3615 | 3483 | // Only applies to root agents. | |
3616 | // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop | 3484 | if (avatar.ParentID != 0) |
3617 | // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI | 3485 | { |
3618 | if (closeChildAgents && CapsModule != null) | 3486 | avatar.StandUp(); |
3619 | CapsModule.RemoveCaps(agentID); | 3487 | } |
3620 | 3488 | ||
3621 | // // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever | 3489 | m_sceneGraph.removeUserCount(!isChildAgent); |
3622 | // // this method is doing is HORRIBLE!!! | 3490 | |
3623 | // Commented pending deletion since this method no longer appears to do anything at all | 3491 | // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop |
3624 | // avatar.Scene.NeedSceneCacheClear(avatar.UUID); | 3492 | // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI |
3625 | 3493 | if (closeChildAgents && CapsModule != null) | |
3626 | if (closeChildAgents && !isChildAgent) | 3494 | CapsModule.RemoveCaps(agentID); |
3495 | |||
3496 | // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever | ||
3497 | // this method is doing is HORRIBLE!!! | ||
3498 | avatar.Scene.NeedSceneCacheClear(avatar.UUID); | ||
3499 | |||
3500 | if (closeChildAgents && !isChildAgent) | ||
3501 | { | ||
3502 | List<ulong> regions = avatar.KnownRegionHandles; | ||
3503 | regions.Remove(RegionInfo.RegionHandle); | ||
3504 | m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); | ||
3505 | } | ||
3506 | |||
3507 | m_eventManager.TriggerClientClosed(agentID, this); | ||
3508 | m_eventManager.TriggerOnRemovePresence(agentID); | ||
3509 | |||
3510 | if (!isChildAgent) | ||
3511 | { | ||
3512 | if (AttachmentsModule != null) | ||
3627 | { | 3513 | { |
3628 | List<ulong> regions = avatar.KnownRegionHandles; | 3514 | AttachmentsModule.DeRezAttachments(avatar); |
3629 | regions.Remove(RegionInfo.RegionHandle); | ||
3630 | m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); | ||
3631 | } | 3515 | } |
3632 | 3516 | ||
3633 | m_eventManager.TriggerClientClosed(agentID, this); | 3517 | ForEachClient( |
3634 | m_eventManager.TriggerOnRemovePresence(agentID); | 3518 | delegate(IClientAPI client) |
3635 | |||
3636 | if (!isChildAgent) | ||
3637 | { | ||
3638 | if (AttachmentsModule != null) | ||
3639 | { | 3519 | { |
3640 | AttachmentsModule.DeRezAttachments(avatar); | 3520 | //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway |
3641 | } | 3521 | try { client.SendKillObject(avatar.RegionHandle, new List<uint> { avatar.LocalId }); } |
3522 | catch (NullReferenceException) { } | ||
3523 | }); | ||
3524 | } | ||
3642 | 3525 | ||
3643 | ForEachClient( | 3526 | // It's possible for child agents to have transactions if changes are being made cross-border. |
3644 | delegate(IClientAPI client) | 3527 | if (AgentTransactionsModule != null) |
3645 | { | 3528 | AgentTransactionsModule.RemoveAgentAssetTransactions(agentID); |
3646 | //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway | 3529 | |
3647 | try { client.SendKillObject(avatar.RegionHandle, new List<uint> { avatar.LocalId }); } | 3530 | m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); |
3648 | catch (NullReferenceException) { } | 3531 | m_log.Debug("[Scene] The avatar has left the building"); |
3649 | }); | 3532 | } |
3650 | } | 3533 | catch (Exception e) |
3534 | { | ||
3535 | m_log.Error( | ||
3536 | string.Format("[SCENE]: Exception removing {0} from {1}. Cleaning up. Exception ", avatar.Name, Name), e); | ||
3537 | } | ||
3538 | finally | ||
3539 | { | ||
3540 | try | ||
3541 | { | ||
3542 | // Always clean these structures up so that any failure above doesn't cause them to remain in the | ||
3543 | // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering | ||
3544 | // the same cleanup exception continually. | ||
3545 | m_sceneGraph.RemoveScenePresence(agentID); | ||
3546 | m_clientManager.Remove(agentID); | ||
3651 | 3547 | ||
3652 | // It's possible for child agents to have transactions if changes are being made cross-border. | 3548 | avatar.Close(); |
3653 | if (AgentTransactionsModule != null) | ||
3654 | AgentTransactionsModule.RemoveAgentAssetTransactions(agentID); | ||
3655 | m_log.Debug("[Scene] The avatar has left the building"); | ||
3656 | } | 3549 | } |
3657 | catch (Exception e) | 3550 | catch (Exception e) |
3658 | { | 3551 | { |
3659 | m_log.Error( | 3552 | m_log.Error( |
3660 | string.Format("[SCENE]: Exception removing {0} from {1}. Cleaning up. Exception ", avatar.Name, Name), e); | 3553 | string.Format("[SCENE]: Exception in final clean up of {0} in {1}. Exception ", avatar.Name, Name), e); |
3661 | } | ||
3662 | finally | ||
3663 | { | ||
3664 | try | ||
3665 | { | ||
3666 | // Always clean these structures up so that any failure above doesn't cause them to remain in the | ||
3667 | // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering | ||
3668 | // the same cleanup exception continually. | ||
3669 | m_sceneGraph.RemoveScenePresence(agentID); | ||
3670 | m_clientManager.Remove(agentID); | ||
3671 | |||
3672 | avatar.Close(); | ||
3673 | } | ||
3674 | catch (Exception e) | ||
3675 | { | ||
3676 | m_log.Error( | ||
3677 | string.Format("[SCENE]: Exception in final clean up of {0} in {1}. Exception ", avatar.Name, Name), e); | ||
3678 | } | ||
3679 | } | 3554 | } |
3680 | } | 3555 | } |
3681 | 3556 | ||
@@ -3734,9 +3609,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
3734 | 3609 | ||
3735 | /// <summary> | 3610 | /// <summary> |
3736 | /// Do the work necessary to initiate a new user connection for a particular scene. | 3611 | /// Do the work necessary to initiate a new user connection for a particular scene. |
3612 | /// At the moment, this consists of setting up the caps infrastructure | ||
3613 | /// The return bool should allow for connections to be refused, but as not all calling paths | ||
3614 | /// take proper notice of it let, we allowed banned users in still. | ||
3737 | /// </summary> | 3615 | /// </summary> |
3738 | /// <param name="agent">CircuitData of the agent who is connecting</param> | 3616 | /// <param name="agent">CircuitData of the agent who is connecting</param> |
3739 | /// <param name="teleportFlags"></param> | ||
3740 | /// <param name="reason">Outputs the reason for the false response on this string</param> | 3617 | /// <param name="reason">Outputs the reason for the false response on this string</param> |
3741 | /// <returns>True if the region accepts this agent. False if it does not. False will | 3618 | /// <returns>True if the region accepts this agent. False if it does not. False will |
3742 | /// also return a reason.</returns> | 3619 | /// also return a reason.</returns> |
@@ -3747,20 +3624,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
3747 | 3624 | ||
3748 | /// <summary> | 3625 | /// <summary> |
3749 | /// Do the work necessary to initiate a new user connection for a particular scene. | 3626 | /// Do the work necessary to initiate a new user connection for a particular scene. |
3750 | /// </summary> | 3627 | /// At the moment, this consists of setting up the caps infrastructure |
3751 | /// <remarks> | ||
3752 | /// The return bool should allow for connections to be refused, but as not all calling paths | ||
3753 | /// take proper notice of it yet, we still allowed banned users in. | ||
3754 | /// | ||
3755 | /// At the moment this method consists of setting up the caps infrastructure | ||
3756 | /// The return bool should allow for connections to be refused, but as not all calling paths | 3628 | /// The return bool should allow for connections to be refused, but as not all calling paths |
3757 | /// take proper notice of it let, we allowed banned users in still. | 3629 | /// take proper notice of it let, we allowed banned users in still. |
3758 | /// | 3630 | /// </summary> |
3759 | /// This method is called by the login service (in the case of login) or another simulator (in the case of region | ||
3760 | /// cross or teleport) to initiate the connection. It is not triggered by the viewer itself - the connection | ||
3761 | /// is activated later when the viewer sends the initial UseCircuitCodePacket UDP packet (in the case of | ||
3762 | /// the LLUDP stack). | ||
3763 | /// </remarks> | ||
3764 | /// <param name="agent">CircuitData of the agent who is connecting</param> | 3631 | /// <param name="agent">CircuitData of the agent who is connecting</param> |
3765 | /// <param name="reason">Outputs the reason for the false response on this string</param> | 3632 | /// <param name="reason">Outputs the reason for the false response on this string</param> |
3766 | /// <param name="requirePresenceLookup">True for normal presence. False for NPC | 3633 | /// <param name="requirePresenceLookup">True for normal presence. False for NPC |
@@ -3859,86 +3726,83 @@ namespace OpenSim.Region.Framework.Scenes | |||
3859 | "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.", | 3726 | "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.", |
3860 | sp.Name, sp.UUID, RegionInfo.RegionName); | 3727 | sp.Name, sp.UUID, RegionInfo.RegionName); |
3861 | 3728 | ||
3862 | sp.ControllingClient.Close(true, true); | 3729 | sp.ControllingClient.Close(); |
3863 | sp = null; | 3730 | sp = null; |
3864 | } | 3731 | } |
3865 | 3732 | ||
3866 | lock (agent) | 3733 | |
3734 | //On login test land permisions | ||
3735 | if (vialogin) | ||
3867 | { | 3736 | { |
3868 | //On login test land permisions | 3737 | IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>(); |
3869 | if (vialogin) | 3738 | if (cache != null) |
3739 | cache.Remove(agent.firstname + " " + agent.lastname); | ||
3740 | if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y)) | ||
3870 | { | 3741 | { |
3871 | IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>(); | 3742 | m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString()); |
3872 | if (cache != null) | 3743 | return false; |
3873 | cache.Remove(agent.firstname + " " + agent.lastname); | ||
3874 | if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y)) | ||
3875 | { | ||
3876 | m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString()); | ||
3877 | return false; | ||
3878 | } | ||
3879 | } | 3744 | } |
3745 | } | ||
3880 | 3746 | ||
3881 | if (sp == null) // We don't have an [child] agent here already | 3747 | if (sp == null) // We don't have an [child] agent here already |
3748 | { | ||
3749 | if (requirePresenceLookup) | ||
3882 | { | 3750 | { |
3883 | if (requirePresenceLookup) | ||
3884 | { | ||
3885 | try | ||
3886 | { | ||
3887 | if (!VerifyUserPresence(agent, out reason)) | ||
3888 | return false; | ||
3889 | } catch (Exception e) | ||
3890 | { | ||
3891 | m_log.ErrorFormat( | ||
3892 | "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace); | ||
3893 | return false; | ||
3894 | } | ||
3895 | } | ||
3896 | |||
3897 | try | 3751 | try |
3898 | { | 3752 | { |
3899 | // Always check estate if this is a login. Always | 3753 | if (!VerifyUserPresence(agent, out reason)) |
3900 | // check if banned regions are to be blacked out. | 3754 | return false; |
3901 | if (vialogin || (!m_seeIntoBannedRegion)) | 3755 | } catch (Exception e) |
3902 | { | ||
3903 | if (!AuthorizeUser(agent, out reason)) | ||
3904 | return false; | ||
3905 | } | ||
3906 | } | ||
3907 | catch (Exception e) | ||
3908 | { | 3756 | { |
3909 | m_log.ErrorFormat( | 3757 | m_log.ErrorFormat( |
3910 | "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); | 3758 | "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace); |
3911 | return false; | 3759 | return false; |
3912 | } | 3760 | } |
3761 | } | ||
3913 | 3762 | ||
3914 | m_log.InfoFormat( | 3763 | try |
3915 | "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})", | 3764 | { |
3916 | RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname, | 3765 | // Always check estate if this is a login. Always |
3917 | agent.AgentID, agent.circuitcode); | 3766 | // check if banned regions are to be blacked out. |
3918 | 3767 | if (vialogin || (!m_seeIntoBannedRegion)) | |
3919 | if (CapsModule != null) | ||
3920 | { | 3768 | { |
3921 | CapsModule.SetAgentCapsSeeds(agent); | 3769 | if (!AuthorizeUser(agent, out reason)) |
3922 | CapsModule.CreateCaps(agent.AgentID); | 3770 | return false; |
3923 | } | 3771 | } |
3924 | } | 3772 | } |
3925 | else | 3773 | catch (Exception e) |
3926 | { | 3774 | { |
3927 | // Let the SP know how we got here. This has a lot of interesting | 3775 | m_log.ErrorFormat( |
3928 | // uses down the line. | 3776 | "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); |
3929 | sp.TeleportFlags = (TPFlags)teleportFlags; | 3777 | return false; |
3778 | } | ||
3930 | 3779 | ||
3931 | if (sp.IsChildAgent) | 3780 | m_log.InfoFormat( |
3932 | { | 3781 | "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})", |
3933 | m_log.DebugFormat( | 3782 | RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname, |
3934 | "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", | 3783 | agent.AgentID, agent.circuitcode); |
3935 | agent.AgentID, RegionInfo.RegionName); | ||
3936 | 3784 | ||
3937 | sp.AdjustKnownSeeds(); | 3785 | if (CapsModule != null) |
3786 | { | ||
3787 | CapsModule.SetAgentCapsSeeds(agent); | ||
3788 | CapsModule.CreateCaps(agent.AgentID); | ||
3789 | } | ||
3790 | } else | ||
3791 | { | ||
3792 | // Let the SP know how we got here. This has a lot of interesting | ||
3793 | // uses down the line. | ||
3794 | sp.TeleportFlags = (TPFlags)teleportFlags; | ||
3938 | 3795 | ||
3939 | if (CapsModule != null) | 3796 | if (sp.IsChildAgent) |
3940 | CapsModule.SetAgentCapsSeeds(agent); | 3797 | { |
3941 | } | 3798 | m_log.DebugFormat( |
3799 | "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", | ||
3800 | agent.AgentID, RegionInfo.RegionName); | ||
3801 | |||
3802 | sp.AdjustKnownSeeds(); | ||
3803 | |||
3804 | if (CapsModule != null) | ||
3805 | CapsModule.SetAgentCapsSeeds(agent); | ||
3942 | } | 3806 | } |
3943 | } | 3807 | } |
3944 | 3808 | ||
@@ -4369,9 +4233,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
4369 | return false; | 4233 | return false; |
4370 | } | 4234 | } |
4371 | 4235 | ||
4372 | // We have to wait until the viewer contacts this region | 4236 | // We have to wait until the viewer contacts this region after receiving EAC. |
4373 | // after receiving the EnableSimulator HTTP Event Queue message. This triggers the viewer to send | 4237 | // That calls AddNewClient, which finally creates the ScenePresence |
4374 | // a UseCircuitCode packet which in turn calls AddNewClient which finally creates the ScenePresence. | ||
4375 | ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); | 4238 | ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); |
4376 | 4239 | ||
4377 | if (childAgentUpdate != null) | 4240 | if (childAgentUpdate != null) |
@@ -4466,18 +4329,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
4466 | /// Tell a single agent to disconnect from the region. | 4329 | /// Tell a single agent to disconnect from the region. |
4467 | /// </summary> | 4330 | /// </summary> |
4468 | /// <param name="agentID"></param> | 4331 | /// <param name="agentID"></param> |
4469 | /// <param name="force"> | 4332 | /// <param name="childOnly"></param> |
4470 | /// Force the agent to close even if it might be in the middle of some other operation. You do not want to | 4333 | public bool IncomingCloseAgent(UUID agentID, bool childOnly) |
4471 | /// force unless you are absolutely sure that the agent is dead and a normal close is not working. | ||
4472 | /// </param> | ||
4473 | public bool IncomingCloseAgent(UUID agentID, bool force) | ||
4474 | { | 4334 | { |
4475 | //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); | 4335 | //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); |
4476 | 4336 | ||
4477 | ScenePresence presence = m_sceneGraph.GetScenePresence(agentID); | 4337 | ScenePresence presence = m_sceneGraph.GetScenePresence(agentID); |
4478 | if (presence != null) | 4338 | if (presence != null) |
4479 | { | 4339 | { |
4480 | presence.ControllingClient.Close(force, force); | 4340 | presence.ControllingClient.Close(false); |
4481 | return true; | 4341 | return true; |
4482 | } | 4342 | } |
4483 | 4343 | ||
@@ -4683,16 +4543,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
4683 | return LandChannel.GetLandObject(x, y).LandData; | 4543 | return LandChannel.GetLandObject(x, y).LandData; |
4684 | } | 4544 | } |
4685 | 4545 | ||
4686 | /// <summary> | ||
4687 | /// Get LandData by position. | ||
4688 | /// </summary> | ||
4689 | /// <param name="pos"></param> | ||
4690 | /// <returns></returns> | ||
4691 | public LandData GetLandData(Vector3 pos) | ||
4692 | { | ||
4693 | return GetLandData(pos.X, pos.Y); | ||
4694 | } | ||
4695 | |||
4696 | public LandData GetLandData(uint x, uint y) | 4546 | public LandData GetLandData(uint x, uint y) |
4697 | { | 4547 | { |
4698 | m_log.DebugFormat("[SCENE]: returning land for {0},{1}", x, y); | 4548 | m_log.DebugFormat("[SCENE]: returning land for {0},{1}", x, y); |
@@ -4923,24 +4773,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
4923 | /// Get a group via its UUID | 4773 | /// Get a group via its UUID |
4924 | /// </summary> | 4774 | /// </summary> |
4925 | /// <param name="fullID"></param> | 4775 | /// <param name="fullID"></param> |
4926 | /// <returns>null if no group with that id exists</returns> | 4776 | /// <returns>null if no group with that name exists</returns> |
4927 | public SceneObjectGroup GetSceneObjectGroup(UUID fullID) | 4777 | public SceneObjectGroup GetSceneObjectGroup(UUID fullID) |
4928 | { | 4778 | { |
4929 | return m_sceneGraph.GetSceneObjectGroup(fullID); | 4779 | return m_sceneGraph.GetSceneObjectGroup(fullID); |
4930 | } | 4780 | } |
4931 | 4781 | ||
4932 | /// <summary> | 4782 | /// <summary> |
4933 | /// Get a group via its local ID | ||
4934 | /// </summary> | ||
4935 | /// <remarks>This will only return a group if the local ID matches a root part</remarks> | ||
4936 | /// <param name="localID"></param> | ||
4937 | /// <returns>null if no group with that id exists</returns> | ||
4938 | public SceneObjectGroup GetSceneObjectGroup(uint localID) | ||
4939 | { | ||
4940 | return m_sceneGraph.GetSceneObjectGroup(localID); | ||
4941 | } | ||
4942 | |||
4943 | /// <summary> | ||
4944 | /// Get a group by name from the scene (will return the first | 4783 | /// Get a group by name from the scene (will return the first |
4945 | /// found, if there are more than one prim with the same name) | 4784 | /// found, if there are more than one prim with the same name) |
4946 | /// </summary> | 4785 | /// </summary> |
@@ -4952,18 +4791,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
4952 | } | 4791 | } |
4953 | 4792 | ||
4954 | /// <summary> | 4793 | /// <summary> |
4955 | /// Attempt to get the SOG via its UUID | ||
4956 | /// </summary> | ||
4957 | /// <param name="fullID"></param> | ||
4958 | /// <param name="sog"></param> | ||
4959 | /// <returns></returns> | ||
4960 | public bool TryGetSceneObjectGroup(UUID fullID, out SceneObjectGroup sog) | ||
4961 | { | ||
4962 | sog = GetSceneObjectGroup(fullID); | ||
4963 | return sog != null; | ||
4964 | } | ||
4965 | |||
4966 | /// <summary> | ||
4967 | /// Get a prim by name from the scene (will return the first | 4794 | /// Get a prim by name from the scene (will return the first |
4968 | /// found, if there are more than one prim with the same name) | 4795 | /// found, if there are more than one prim with the same name) |
4969 | /// </summary> | 4796 | /// </summary> |
@@ -4995,18 +4822,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
4995 | } | 4822 | } |
4996 | 4823 | ||
4997 | /// <summary> | 4824 | /// <summary> |
4998 | /// Attempt to get a prim via its UUID | ||
4999 | /// </summary> | ||
5000 | /// <param name="fullID"></param> | ||
5001 | /// <param name="sop"></param> | ||
5002 | /// <returns></returns> | ||
5003 | public bool TryGetSceneObjectPart(UUID fullID, out SceneObjectPart sop) | ||
5004 | { | ||
5005 | sop = GetSceneObjectPart(fullID); | ||
5006 | return sop != null; | ||
5007 | } | ||
5008 | |||
5009 | /// <summary> | ||
5010 | /// Get a scene object group that contains the prim with the given local id | 4825 | /// Get a scene object group that contains the prim with the given local id |
5011 | /// </summary> | 4826 | /// </summary> |
5012 | /// <param name="localID"></param> | 4827 | /// <param name="localID"></param> |
@@ -5100,15 +4915,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
5100 | client.SendRegionHandle(regionID, handle); | 4915 | client.SendRegionHandle(regionID, handle); |
5101 | } | 4916 | } |
5102 | 4917 | ||
5103 | // Commented pending deletion since this method no longer appears to do anything at all | 4918 | public bool NeedSceneCacheClear(UUID agentID) |
5104 | // public bool NeedSceneCacheClear(UUID agentID) | 4919 | { |
5105 | // { | 4920 | IInventoryTransferModule inv = RequestModuleInterface<IInventoryTransferModule>(); |
5106 | // IInventoryTransferModule inv = RequestModuleInterface<IInventoryTransferModule>(); | 4921 | if (inv == null) |
5107 | // if (inv == null) | 4922 | return true; |
5108 | // return true; | 4923 | |
5109 | // | 4924 | return inv.NeedSceneCacheClear(agentID, this); |
5110 | // return inv.NeedSceneCacheClear(agentID, this); | 4925 | } |
5111 | // } | ||
5112 | 4926 | ||
5113 | public void CleanTempObjects() | 4927 | public void CleanTempObjects() |
5114 | { | 4928 | { |
@@ -6062,9 +5876,6 @@ Environment.Exit(1); | |||
6062 | 5876 | ||
6063 | public string GetExtraSetting(string name) | 5877 | public string GetExtraSetting(string name) |
6064 | { | 5878 | { |
6065 | if (m_extraSettings == null) | ||
6066 | return String.Empty; | ||
6067 | |||
6068 | string val; | 5879 | string val; |
6069 | 5880 | ||
6070 | if (!m_extraSettings.TryGetValue(name, out val)) | 5881 | if (!m_extraSettings.TryGetValue(name, out val)) |
@@ -6075,9 +5886,6 @@ Environment.Exit(1); | |||
6075 | 5886 | ||
6076 | public void StoreExtraSetting(string name, string val) | 5887 | public void StoreExtraSetting(string name, string val) |
6077 | { | 5888 | { |
6078 | if (m_extraSettings == null) | ||
6079 | return; | ||
6080 | |||
6081 | string oldVal; | 5889 | string oldVal; |
6082 | 5890 | ||
6083 | if (m_extraSettings.TryGetValue(name, out oldVal)) | 5891 | if (m_extraSettings.TryGetValue(name, out oldVal)) |
@@ -6095,9 +5903,6 @@ Environment.Exit(1); | |||
6095 | 5903 | ||
6096 | public void RemoveExtraSetting(string name) | 5904 | public void RemoveExtraSetting(string name) |
6097 | { | 5905 | { |
6098 | if (m_extraSettings == null) | ||
6099 | return; | ||
6100 | |||
6101 | if (!m_extraSettings.ContainsKey(name)) | 5906 | if (!m_extraSettings.ContainsKey(name)) |
6102 | return; | 5907 | return; |
6103 | 5908 | ||
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index e599e90..af13b46 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs | |||
@@ -342,7 +342,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
342 | public bool AddNewSceneObject( | 342 | public bool AddNewSceneObject( |
343 | SceneObjectGroup sceneObject, bool attachToBackup, Vector3? pos, Quaternion? rot, Vector3 vel) | 343 | SceneObjectGroup sceneObject, bool attachToBackup, Vector3? pos, Quaternion? rot, Vector3 vel) |
344 | { | 344 | { |
345 | AddNewSceneObject(sceneObject, attachToBackup, false); | 345 | AddNewSceneObject(sceneObject, true, false); |
346 | 346 | ||
347 | if (pos != null) | 347 | if (pos != null) |
348 | sceneObject.AbsolutePosition = (Vector3)pos; | 348 | sceneObject.AbsolutePosition = (Vector3)pos; |
@@ -421,9 +421,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
421 | { | 421 | { |
422 | Vector3 scale = part.Shape.Scale; | 422 | Vector3 scale = part.Shape.Scale; |
423 | 423 | ||
424 | scale.X = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.X)); | 424 | if (scale.X > m_parentScene.m_maxNonphys) |
425 | scale.Y = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Y)); | 425 | scale.X = m_parentScene.m_maxNonphys; |
426 | scale.Z = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Z)); | 426 | if (scale.Y > m_parentScene.m_maxNonphys) |
427 | scale.Y = m_parentScene.m_maxNonphys; | ||
428 | if (scale.Z > m_parentScene.m_maxNonphys) | ||
429 | scale.Z = m_parentScene.m_maxNonphys; | ||
427 | 430 | ||
428 | part.Shape.Scale = scale; | 431 | part.Shape.Scale = scale; |
429 | } | 432 | } |
@@ -1063,30 +1066,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
1063 | } | 1066 | } |
1064 | 1067 | ||
1065 | /// <summary> | 1068 | /// <summary> |
1066 | /// Get a group in the scene | ||
1067 | /// </summary> | ||
1068 | /// <remarks> | ||
1069 | /// This will only return a group if the local ID matches the root part, not other parts. | ||
1070 | /// </remarks> | ||
1071 | /// <param name="localID">Local id of the root part of the group</param> | ||
1072 | /// <returns>null if no such group was found</returns> | ||
1073 | protected internal SceneObjectGroup GetSceneObjectGroup(uint localID) | ||
1074 | { | ||
1075 | lock (SceneObjectGroupsByLocalPartID) | ||
1076 | { | ||
1077 | if (SceneObjectGroupsByLocalPartID.ContainsKey(localID)) | ||
1078 | { | ||
1079 | SceneObjectGroup so = SceneObjectGroupsByLocalPartID[localID]; | ||
1080 | |||
1081 | if (so.LocalId == localID) | ||
1082 | return so; | ||
1083 | } | ||
1084 | } | ||
1085 | |||
1086 | return null; | ||
1087 | } | ||
1088 | |||
1089 | /// <summary> | ||
1090 | /// Get a group by name from the scene (will return the first | 1069 | /// Get a group by name from the scene (will return the first |
1091 | /// found, if there are more than one prim with the same name) | 1070 | /// found, if there are more than one prim with the same name) |
1092 | /// </summary> | 1071 | /// </summary> |
diff --git a/OpenSim/Region/Framework/Scenes/SceneManager.cs b/OpenSim/Region/Framework/Scenes/SceneManager.cs index dba3a61..f1b09ca 100644 --- a/OpenSim/Region/Framework/Scenes/SceneManager.cs +++ b/OpenSim/Region/Framework/Scenes/SceneManager.cs | |||
@@ -92,11 +92,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
92 | private static SceneManager m_instance = null; | 92 | private static SceneManager m_instance = null; |
93 | public static SceneManager Instance | 93 | public static SceneManager Instance |
94 | { | 94 | { |
95 | get { | 95 | get { return m_instance; } |
96 | if (m_instance == null) | ||
97 | m_instance = new SceneManager(); | ||
98 | return m_instance; | ||
99 | } | ||
100 | } | 96 | } |
101 | 97 | ||
102 | private readonly DoubleDictionary<UUID, string, Scene> m_localScenes = new DoubleDictionary<UUID, string, Scene>(); | 98 | private readonly DoubleDictionary<UUID, string, Scene> m_localScenes = new DoubleDictionary<UUID, string, Scene>(); |
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 74d2629..ee61de6 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | |||
@@ -2747,25 +2747,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
2747 | if (objectGroup == this) | 2747 | if (objectGroup == this) |
2748 | return; | 2748 | return; |
2749 | 2749 | ||
2750 | // If the configured linkset capacity is greater than zero, | ||
2751 | // and the new linkset would have a prim count higher than this | ||
2752 | // value, do not link it. | ||
2753 | if (m_scene.m_linksetCapacity > 0 && | ||
2754 | (PrimCount + objectGroup.PrimCount) > | ||
2755 | m_scene.m_linksetCapacity) | ||
2756 | { | ||
2757 | m_log.DebugFormat( | ||
2758 | "[SCENE OBJECT GROUP]: Cannot link group with root" + | ||
2759 | " part {0}, {1} ({2} prims) to group with root part" + | ||
2760 | " {3}, {4} ({5} prims) because the new linkset" + | ||
2761 | " would exceed the configured maximum of {6}", | ||
2762 | objectGroup.RootPart.Name, objectGroup.RootPart.UUID, | ||
2763 | objectGroup.PrimCount, RootPart.Name, RootPart.UUID, | ||
2764 | PrimCount, m_scene.m_linksetCapacity); | ||
2765 | |||
2766 | return; | ||
2767 | } | ||
2768 | |||
2769 | // 'linkPart' == the root of the group being linked into this group | 2750 | // 'linkPart' == the root of the group being linked into this group |
2770 | SceneObjectPart linkPart = objectGroup.m_rootPart; | 2751 | SceneObjectPart linkPart = objectGroup.m_rootPart; |
2771 | 2752 | ||
@@ -3511,33 +3492,27 @@ namespace OpenSim.Region.Framework.Scenes | |||
3511 | /// <param name="scale"></param> | 3492 | /// <param name="scale"></param> |
3512 | public void GroupResize(Vector3 scale) | 3493 | public void GroupResize(Vector3 scale) |
3513 | { | 3494 | { |
3514 | // m_log.DebugFormat( | 3495 | scale.X = Math.Min(scale.X, Scene.m_maxNonphys); |
3515 | // "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale); | 3496 | scale.Y = Math.Min(scale.Y, Scene.m_maxNonphys); |
3497 | scale.Z = Math.Min(scale.Z, Scene.m_maxNonphys); | ||
3516 | 3498 | ||
3517 | PhysicsActor pa = m_rootPart.PhysActor; | 3499 | PhysicsActor pa = m_rootPart.PhysActor; |
3518 | 3500 | ||
3519 | if (Scene != null) | 3501 | if (pa != null && pa.IsPhysical) |
3520 | { | 3502 | { |
3521 | scale.X = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.X)); | 3503 | scale.X = Math.Min(scale.X, Scene.m_maxPhys); |
3522 | scale.Y = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.Y)); | 3504 | scale.Y = Math.Min(scale.Y, Scene.m_maxPhys); |
3523 | scale.Z = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.Z)); | 3505 | scale.Z = Math.Min(scale.Z, Scene.m_maxPhys); |
3524 | |||
3525 | if (pa != null && pa.IsPhysical) | ||
3526 | { | ||
3527 | scale.X = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.X)); | ||
3528 | scale.Y = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.Y)); | ||
3529 | scale.Z = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.Z)); | ||
3530 | } | ||
3531 | } | 3506 | } |
3532 | 3507 | ||
3533 | float x = (scale.X / RootPart.Scale.X); | 3508 | float x = (scale.X / RootPart.Scale.X); |
3534 | float y = (scale.Y / RootPart.Scale.Y); | 3509 | float y = (scale.Y / RootPart.Scale.Y); |
3535 | float z = (scale.Z / RootPart.Scale.Z); | 3510 | float z = (scale.Z / RootPart.Scale.Z); |
3536 | 3511 | ||
3537 | SceneObjectPart[] parts = m_parts.GetArray(); | 3512 | SceneObjectPart[] parts; |
3538 | 3513 | if (x > 1.0f || y > 1.0f || z > 1.0f) | |
3539 | if (Scene != null & (x > 1.0f || y > 1.0f || z > 1.0f)) | ||
3540 | { | 3514 | { |
3515 | parts = m_parts.GetArray(); | ||
3541 | for (int i = 0; i < parts.Length; i++) | 3516 | for (int i = 0; i < parts.Length; i++) |
3542 | { | 3517 | { |
3543 | SceneObjectPart obPart = parts[i]; | 3518 | SceneObjectPart obPart = parts[i]; |
@@ -3550,7 +3525,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3550 | 3525 | ||
3551 | if (pa != null && pa.IsPhysical) | 3526 | if (pa != null && pa.IsPhysical) |
3552 | { | 3527 | { |
3553 | if (oldSize.X * x > Scene.m_maxPhys) | 3528 | if (oldSize.X * x > m_scene.m_maxPhys) |
3554 | { | 3529 | { |
3555 | f = m_scene.m_maxPhys / oldSize.X; | 3530 | f = m_scene.m_maxPhys / oldSize.X; |
3556 | a = f / x; | 3531 | a = f / x; |
@@ -3558,16 +3533,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
3558 | y *= a; | 3533 | y *= a; |
3559 | z *= a; | 3534 | z *= a; |
3560 | } | 3535 | } |
3561 | else if (oldSize.X * x < Scene.m_minPhys) | ||
3562 | { | ||
3563 | f = m_scene.m_minPhys / oldSize.X; | ||
3564 | a = f / x; | ||
3565 | x *= a; | ||
3566 | y *= a; | ||
3567 | z *= a; | ||
3568 | } | ||
3569 | 3536 | ||
3570 | if (oldSize.Y * y > Scene.m_maxPhys) | 3537 | if (oldSize.Y * y > m_scene.m_maxPhys) |
3571 | { | 3538 | { |
3572 | f = m_scene.m_maxPhys / oldSize.Y; | 3539 | f = m_scene.m_maxPhys / oldSize.Y; |
3573 | a = f / y; | 3540 | a = f / y; |
@@ -3575,16 +3542,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
3575 | y *= a; | 3542 | y *= a; |
3576 | z *= a; | 3543 | z *= a; |
3577 | } | 3544 | } |
3578 | else if (oldSize.Y * y < Scene.m_minPhys) | ||
3579 | { | ||
3580 | f = m_scene.m_minPhys / oldSize.Y; | ||
3581 | a = f / y; | ||
3582 | x *= a; | ||
3583 | y *= a; | ||
3584 | z *= a; | ||
3585 | } | ||
3586 | 3545 | ||
3587 | if (oldSize.Z * z > Scene.m_maxPhys) | 3546 | if (oldSize.Z * z > m_scene.m_maxPhys) |
3588 | { | 3547 | { |
3589 | f = m_scene.m_maxPhys / oldSize.Z; | 3548 | f = m_scene.m_maxPhys / oldSize.Z; |
3590 | a = f / z; | 3549 | a = f / z; |
@@ -3592,18 +3551,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
3592 | y *= a; | 3551 | y *= a; |
3593 | z *= a; | 3552 | z *= a; |
3594 | } | 3553 | } |
3595 | else if (oldSize.Z * z < Scene.m_minPhys) | ||
3596 | { | ||
3597 | f = m_scene.m_minPhys / oldSize.Z; | ||
3598 | a = f / z; | ||
3599 | x *= a; | ||
3600 | y *= a; | ||
3601 | z *= a; | ||
3602 | } | ||
3603 | } | 3554 | } |
3604 | else | 3555 | else |
3605 | { | 3556 | { |
3606 | if (oldSize.X * x > Scene.m_maxNonphys) | 3557 | if (oldSize.X * x > m_scene.m_maxNonphys) |
3607 | { | 3558 | { |
3608 | f = m_scene.m_maxNonphys / oldSize.X; | 3559 | f = m_scene.m_maxNonphys / oldSize.X; |
3609 | a = f / x; | 3560 | a = f / x; |
@@ -3611,16 +3562,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
3611 | y *= a; | 3562 | y *= a; |
3612 | z *= a; | 3563 | z *= a; |
3613 | } | 3564 | } |
3614 | else if (oldSize.X * x < Scene.m_minNonphys) | ||
3615 | { | ||
3616 | f = m_scene.m_minNonphys / oldSize.X; | ||
3617 | a = f / x; | ||
3618 | x *= a; | ||
3619 | y *= a; | ||
3620 | z *= a; | ||
3621 | } | ||
3622 | 3565 | ||
3623 | if (oldSize.Y * y > Scene.m_maxNonphys) | 3566 | if (oldSize.Y * y > m_scene.m_maxNonphys) |
3624 | { | 3567 | { |
3625 | f = m_scene.m_maxNonphys / oldSize.Y; | 3568 | f = m_scene.m_maxNonphys / oldSize.Y; |
3626 | a = f / y; | 3569 | a = f / y; |
@@ -3628,16 +3571,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
3628 | y *= a; | 3571 | y *= a; |
3629 | z *= a; | 3572 | z *= a; |
3630 | } | 3573 | } |
3631 | else if (oldSize.Y * y < Scene.m_minNonphys) | ||
3632 | { | ||
3633 | f = m_scene.m_minNonphys / oldSize.Y; | ||
3634 | a = f / y; | ||
3635 | x *= a; | ||
3636 | y *= a; | ||
3637 | z *= a; | ||
3638 | } | ||
3639 | 3574 | ||
3640 | if (oldSize.Z * z > Scene.m_maxNonphys) | 3575 | if (oldSize.Z * z > m_scene.m_maxNonphys) |
3641 | { | 3576 | { |
3642 | f = m_scene.m_maxNonphys / oldSize.Z; | 3577 | f = m_scene.m_maxNonphys / oldSize.Z; |
3643 | a = f / z; | 3578 | a = f / z; |
@@ -3645,14 +3580,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
3645 | y *= a; | 3580 | y *= a; |
3646 | z *= a; | 3581 | z *= a; |
3647 | } | 3582 | } |
3648 | else if (oldSize.Z * z < Scene.m_minNonphys) | ||
3649 | { | ||
3650 | f = m_scene.m_minNonphys / oldSize.Z; | ||
3651 | a = f / z; | ||
3652 | x *= a; | ||
3653 | y *= a; | ||
3654 | z *= a; | ||
3655 | } | ||
3656 | } | 3583 | } |
3657 | } | 3584 | } |
3658 | } | 3585 | } |
@@ -3665,6 +3592,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3665 | 3592 | ||
3666 | RootPart.Resize(prevScale); | 3593 | RootPart.Resize(prevScale); |
3667 | 3594 | ||
3595 | parts = m_parts.GetArray(); | ||
3668 | for (int i = 0; i < parts.Length; i++) | 3596 | for (int i = 0; i < parts.Length; i++) |
3669 | { | 3597 | { |
3670 | SceneObjectPart obPart = parts[i]; | 3598 | SceneObjectPart obPart = parts[i]; |
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 2191cfa..165dd85 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | |||
@@ -790,7 +790,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
790 | } | 790 | } |
791 | catch (Exception e) | 791 | catch (Exception e) |
792 | { | 792 | { |
793 | m_log.ErrorFormat("[SCENEOBJECTPART]: GROUP POSITION. {0}", e); | 793 | m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message); |
794 | } | 794 | } |
795 | } | 795 | } |
796 | } | 796 | } |
@@ -2864,35 +2864,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
2864 | SendLandCollisionEvent(scriptEvents.land_collision_end, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd); | 2864 | SendLandCollisionEvent(scriptEvents.land_collision_end, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd); |
2865 | } | 2865 | } |
2866 | 2866 | ||
2867 | // The Collision sounds code calls this | ||
2868 | public void SendCollisionSound(UUID soundID, double volume, Vector3 position) | ||
2869 | { | ||
2870 | if (soundID == UUID.Zero) | ||
2871 | return; | ||
2872 | |||
2873 | ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface<ISoundModule>(); | ||
2874 | if (soundModule == null) | ||
2875 | return; | ||
2876 | |||
2877 | if (volume > 1) | ||
2878 | volume = 1; | ||
2879 | if (volume < 0) | ||
2880 | volume = 0; | ||
2881 | |||
2882 | int now = Util.EnvironmentTickCount(); | ||
2883 | if(Util.EnvironmentTickCountSubtract(now,LastColSoundSentTime) <200) | ||
2884 | return; | ||
2885 | |||
2886 | LastColSoundSentTime = now; | ||
2887 | |||
2888 | UUID ownerID = OwnerID; | ||
2889 | UUID objectID = ParentGroup.RootPart.UUID; | ||
2890 | UUID parentID = ParentGroup.UUID; | ||
2891 | ulong regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle; | ||
2892 | |||
2893 | soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, 0 ); | ||
2894 | } | ||
2895 | |||
2896 | public void PhysicsOutOfBounds(Vector3 pos) | 2867 | public void PhysicsOutOfBounds(Vector3 pos) |
2897 | { | 2868 | { |
2898 | m_log.Error("[PHYSICS]: Physical Object went out of bounds."); | 2869 | m_log.Error("[PHYSICS]: Physical Object went out of bounds."); |
@@ -2924,6 +2895,38 @@ namespace OpenSim.Region.Framework.Scenes | |||
2924 | ScheduleTerseUpdate(); | 2895 | ScheduleTerseUpdate(); |
2925 | } | 2896 | } |
2926 | 2897 | ||
2898 | public void PreloadSound(string sound) | ||
2899 | { | ||
2900 | // UUID ownerID = OwnerID; | ||
2901 | UUID objectID = ParentGroup.RootPart.UUID; | ||
2902 | UUID soundID = UUID.Zero; | ||
2903 | |||
2904 | if (!UUID.TryParse(sound, out soundID)) | ||
2905 | { | ||
2906 | //Trys to fetch sound id from prim's inventory. | ||
2907 | //Prim's inventory doesn't support non script items yet | ||
2908 | |||
2909 | TaskInventory.LockItemsForRead(true); | ||
2910 | |||
2911 | foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) | ||
2912 | { | ||
2913 | if (item.Value.Name == sound) | ||
2914 | { | ||
2915 | soundID = item.Value.ItemID; | ||
2916 | break; | ||
2917 | } | ||
2918 | } | ||
2919 | |||
2920 | TaskInventory.LockItemsForRead(false); | ||
2921 | } | ||
2922 | |||
2923 | ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp) | ||
2924 | { | ||
2925 | if (!(Util.GetDistanceTo(sp.AbsolutePosition, AbsolutePosition) >= 100)) | ||
2926 | sp.ControllingClient.SendPreLoadSound(objectID, objectID, soundID); | ||
2927 | }); | ||
2928 | } | ||
2929 | |||
2927 | public void RemFlag(PrimFlags flag) | 2930 | public void RemFlag(PrimFlags flag) |
2928 | { | 2931 | { |
2929 | // PrimFlags prevflag = Flags; | 2932 | // PrimFlags prevflag = Flags; |
@@ -2976,20 +2979,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
2976 | /// <param name="scale"></param> | 2979 | /// <param name="scale"></param> |
2977 | public void Resize(Vector3 scale) | 2980 | public void Resize(Vector3 scale) |
2978 | { | 2981 | { |
2982 | scale.X = Math.Min(scale.X, ParentGroup.Scene.m_maxNonphys); | ||
2983 | scale.Y = Math.Min(scale.Y, ParentGroup.Scene.m_maxNonphys); | ||
2984 | scale.Z = Math.Min(scale.Z, ParentGroup.Scene.m_maxNonphys); | ||
2985 | |||
2979 | PhysicsActor pa = PhysActor; | 2986 | PhysicsActor pa = PhysActor; |
2980 | 2987 | ||
2981 | if (ParentGroup.Scene != null) | 2988 | if (pa != null && pa.IsPhysical) |
2982 | { | 2989 | { |
2983 | scale.X = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.X)); | 2990 | scale.X = Math.Min(scale.X, ParentGroup.Scene.m_maxPhys); |
2984 | scale.Y = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Y)); | 2991 | scale.Y = Math.Min(scale.Y, ParentGroup.Scene.m_maxPhys); |
2985 | scale.Z = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Z)); | 2992 | scale.Z = Math.Min(scale.Z, ParentGroup.Scene.m_maxPhys); |
2986 | |||
2987 | if (pa != null && pa.IsPhysical) | ||
2988 | { | ||
2989 | scale.X = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.X)); | ||
2990 | scale.Y = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.Y)); | ||
2991 | scale.Z = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.Z)); | ||
2992 | } | ||
2993 | } | 2993 | } |
2994 | 2994 | ||
2995 | // m_log.DebugFormat("[SCENE OBJECT PART]: Resizing {0} {1} to {2}", Name, LocalId, scale); | 2995 | // m_log.DebugFormat("[SCENE OBJECT PART]: Resizing {0} {1} to {2}", Name, LocalId, scale); |
@@ -3086,7 +3086,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3086 | // UUID, Name, TimeStampFull); | 3086 | // UUID, Name, TimeStampFull); |
3087 | 3087 | ||
3088 | if (ParentGroup.Scene != null) | 3088 | if (ParentGroup.Scene != null) |
3089 | ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, true); | 3089 | ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this); |
3090 | } | 3090 | } |
3091 | 3091 | ||
3092 | /// <summary> | 3092 | /// <summary> |
@@ -3120,7 +3120,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3120 | } | 3120 | } |
3121 | 3121 | ||
3122 | if (ParentGroup.Scene != null) | 3122 | if (ParentGroup.Scene != null) |
3123 | ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, false); | 3123 | ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this); |
3124 | } | 3124 | } |
3125 | 3125 | ||
3126 | public void ScriptSetPhysicsStatus(bool UsePhysics) | 3126 | public void ScriptSetPhysicsStatus(bool UsePhysics) |
@@ -3295,6 +3295,126 @@ namespace OpenSim.Region.Framework.Scenes | |||
3295 | } | 3295 | } |
3296 | 3296 | ||
3297 | /// <summary> | 3297 | /// <summary> |
3298 | /// Trigger or play an attached sound in this part's inventory. | ||
3299 | /// </summary> | ||
3300 | /// <param name="sound"></param> | ||
3301 | /// <param name="volume"></param> | ||
3302 | /// <param name="triggered"></param> | ||
3303 | /// <param name="flags"></param> | ||
3304 | public void SendSound(string sound, double volume, bool triggered, byte flags, float radius, bool useMaster, bool isMaster) | ||
3305 | { | ||
3306 | if (volume > 1) | ||
3307 | volume = 1; | ||
3308 | if (volume < 0) | ||
3309 | volume = 0; | ||
3310 | |||
3311 | UUID ownerID = OwnerID; | ||
3312 | UUID objectID = ParentGroup.RootPart.UUID; | ||
3313 | UUID parentID = ParentGroup.UUID; | ||
3314 | |||
3315 | UUID soundID = UUID.Zero; | ||
3316 | Vector3 position = AbsolutePosition; // region local | ||
3317 | ulong regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle; | ||
3318 | |||
3319 | if (!UUID.TryParse(sound, out soundID)) | ||
3320 | { | ||
3321 | // search sound file from inventory | ||
3322 | TaskInventory.LockItemsForRead(true); | ||
3323 | foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) | ||
3324 | { | ||
3325 | if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) | ||
3326 | { | ||
3327 | soundID = item.Value.ItemID; | ||
3328 | break; | ||
3329 | } | ||
3330 | } | ||
3331 | TaskInventory.LockItemsForRead(false); | ||
3332 | } | ||
3333 | |||
3334 | if (soundID == UUID.Zero) | ||
3335 | return; | ||
3336 | |||
3337 | ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface<ISoundModule>(); | ||
3338 | if (soundModule != null) | ||
3339 | { | ||
3340 | if (useMaster) | ||
3341 | { | ||
3342 | if (isMaster) | ||
3343 | { | ||
3344 | if (triggered) | ||
3345 | soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius); | ||
3346 | else | ||
3347 | soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius); | ||
3348 | ParentGroup.PlaySoundMasterPrim = this; | ||
3349 | ownerID = OwnerID; | ||
3350 | objectID = ParentGroup.RootPart.UUID; | ||
3351 | parentID = ParentGroup.UUID; | ||
3352 | position = AbsolutePosition; // region local | ||
3353 | regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle; | ||
3354 | if (triggered) | ||
3355 | soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius); | ||
3356 | else | ||
3357 | soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius); | ||
3358 | foreach (SceneObjectPart prim in ParentGroup.PlaySoundSlavePrims) | ||
3359 | { | ||
3360 | ownerID = prim.OwnerID; | ||
3361 | objectID = prim.ParentGroup.RootPart.UUID; | ||
3362 | parentID = prim.ParentGroup.UUID; | ||
3363 | position = prim.AbsolutePosition; // region local | ||
3364 | regionHandle = prim.ParentGroup.Scene.RegionInfo.RegionHandle; | ||
3365 | if (triggered) | ||
3366 | soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius); | ||
3367 | else | ||
3368 | soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius); | ||
3369 | } | ||
3370 | ParentGroup.PlaySoundSlavePrims.Clear(); | ||
3371 | ParentGroup.PlaySoundMasterPrim = null; | ||
3372 | } | ||
3373 | else | ||
3374 | { | ||
3375 | ParentGroup.PlaySoundSlavePrims.Add(this); | ||
3376 | } | ||
3377 | } | ||
3378 | else | ||
3379 | { | ||
3380 | if (triggered) | ||
3381 | soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius); | ||
3382 | else | ||
3383 | soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius); | ||
3384 | } | ||
3385 | } | ||
3386 | } | ||
3387 | |||
3388 | public void SendCollisionSound(UUID soundID, double volume, Vector3 position) | ||
3389 | { | ||
3390 | if (soundID == UUID.Zero) | ||
3391 | return; | ||
3392 | |||
3393 | ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface<ISoundModule>(); | ||
3394 | if (soundModule == null) | ||
3395 | return; | ||
3396 | |||
3397 | if (volume > 1) | ||
3398 | volume = 1; | ||
3399 | if (volume < 0) | ||
3400 | volume = 0; | ||
3401 | |||
3402 | int now = Util.EnvironmentTickCount(); | ||
3403 | if(Util.EnvironmentTickCountSubtract(now,LastColSoundSentTime) <200) | ||
3404 | return; | ||
3405 | |||
3406 | LastColSoundSentTime = now; | ||
3407 | |||
3408 | UUID ownerID = OwnerID; | ||
3409 | UUID objectID = ParentGroup.RootPart.UUID; | ||
3410 | UUID parentID = ParentGroup.UUID; | ||
3411 | ulong regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle; | ||
3412 | |||
3413 | soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, 0 ); | ||
3414 | } | ||
3415 | |||
3416 | |||
3417 | /// <summary> | ||
3298 | /// Send a terse update to all clients | 3418 | /// Send a terse update to all clients |
3299 | /// </summary> | 3419 | /// </summary> |
3300 | public void SendTerseUpdateToAllClients() | 3420 | public void SendTerseUpdateToAllClients() |
@@ -3455,32 +3575,23 @@ namespace OpenSim.Region.Framework.Scenes | |||
3455 | } | 3575 | } |
3456 | 3576 | ||
3457 | /// <summary> | 3577 | /// <summary> |
3458 | /// Set the color & alpha of prim faces | 3578 | /// Set the color of prim faces |
3459 | /// </summary> | 3579 | /// </summary> |
3460 | /// <param name="face"></param> | ||
3461 | /// <param name="color"></param> | 3580 | /// <param name="color"></param> |
3462 | /// <param name="alpha"></param> | 3581 | /// <param name="face"></param> |
3463 | public void SetFaceColorAlpha(int face, Vector3 color, double ?alpha) | 3582 | public void SetFaceColor(Vector3 color, int face) |
3464 | { | 3583 | { |
3465 | Vector3 clippedColor = Util.Clip(color, 0.0f, 1.0f); | ||
3466 | float clippedAlpha = alpha.HasValue ? | ||
3467 | Util.Clip((float)alpha.Value, 0.0f, 1.0f) : 0; | ||
3468 | |||
3469 | // The only way to get a deep copy/ If we don't do this, we can | 3584 | // The only way to get a deep copy/ If we don't do this, we can |
3470 | // never detect color changes further down. | 3585 | // mever detect color changes further down. |
3471 | Byte[] buf = Shape.Textures.GetBytes(); | 3586 | Byte[] buf = Shape.Textures.GetBytes(); |
3472 | Primitive.TextureEntry tex = new Primitive.TextureEntry(buf, 0, buf.Length); | 3587 | Primitive.TextureEntry tex = new Primitive.TextureEntry(buf, 0, buf.Length); |
3473 | Color4 texcolor; | 3588 | Color4 texcolor; |
3474 | if (face >= 0 && face < GetNumberOfSides()) | 3589 | if (face >= 0 && face < GetNumberOfSides()) |
3475 | { | 3590 | { |
3476 | texcolor = tex.CreateFace((uint)face).RGBA; | 3591 | texcolor = tex.CreateFace((uint)face).RGBA; |
3477 | texcolor.R = clippedColor.X; | 3592 | texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f); |
3478 | texcolor.G = clippedColor.Y; | 3593 | texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f); |
3479 | texcolor.B = clippedColor.Z; | 3594 | texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f); |
3480 | if (alpha.HasValue) | ||
3481 | { | ||
3482 | texcolor.A = clippedAlpha; | ||
3483 | } | ||
3484 | tex.FaceTextures[face].RGBA = texcolor; | 3595 | tex.FaceTextures[face].RGBA = texcolor; |
3485 | UpdateTextureEntry(tex.GetBytes()); | 3596 | UpdateTextureEntry(tex.GetBytes()); |
3486 | return; | 3597 | return; |
@@ -3492,23 +3603,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
3492 | if (tex.FaceTextures[i] != null) | 3603 | if (tex.FaceTextures[i] != null) |
3493 | { | 3604 | { |
3494 | texcolor = tex.FaceTextures[i].RGBA; | 3605 | texcolor = tex.FaceTextures[i].RGBA; |
3495 | texcolor.R = clippedColor.X; | 3606 | texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f); |
3496 | texcolor.G = clippedColor.Y; | 3607 | texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f); |
3497 | texcolor.B = clippedColor.Z; | 3608 | texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f); |
3498 | if (alpha.HasValue) | ||
3499 | { | ||
3500 | texcolor.A = clippedAlpha; | ||
3501 | } | ||
3502 | tex.FaceTextures[i].RGBA = texcolor; | 3609 | tex.FaceTextures[i].RGBA = texcolor; |
3503 | } | 3610 | } |
3504 | texcolor = tex.DefaultTexture.RGBA; | 3611 | texcolor = tex.DefaultTexture.RGBA; |
3505 | texcolor.R = clippedColor.X; | 3612 | texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f); |
3506 | texcolor.G = clippedColor.Y; | 3613 | texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f); |
3507 | texcolor.B = clippedColor.Z; | 3614 | texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f); |
3508 | if (alpha.HasValue) | ||
3509 | { | ||
3510 | texcolor.A = clippedAlpha; | ||
3511 | } | ||
3512 | tex.DefaultTexture.RGBA = texcolor; | 3615 | tex.DefaultTexture.RGBA = texcolor; |
3513 | } | 3616 | } |
3514 | UpdateTextureEntry(tex.GetBytes()); | 3617 | UpdateTextureEntry(tex.GetBytes()); |
@@ -4796,57 +4899,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
4796 | ScheduleFullUpdate(); | 4899 | ScheduleFullUpdate(); |
4797 | } | 4900 | } |
4798 | 4901 | ||
4799 | public void UpdateSlice(float begin, float end) | ||
4800 | { | ||
4801 | if (end < begin) | ||
4802 | { | ||
4803 | float temp = begin; | ||
4804 | begin = end; | ||
4805 | end = temp; | ||
4806 | } | ||
4807 | end = Math.Min(1f, Math.Max(0f, end)); | ||
4808 | begin = Math.Min(Math.Min(1f, Math.Max(0f, begin)), end - 0.02f); | ||
4809 | if (begin < 0.02f && end < 0.02f) | ||
4810 | { | ||
4811 | begin = 0f; | ||
4812 | end = 0.02f; | ||
4813 | } | ||
4814 | |||
4815 | ushort uBegin = (ushort)(50000.0 * begin); | ||
4816 | ushort uEnd = (ushort)(50000.0 * (1f - end)); | ||
4817 | bool updatePossiblyNeeded = false; | ||
4818 | PrimType primType = GetPrimType(); | ||
4819 | if (primType == PrimType.SPHERE || primType == PrimType.TORUS || primType == PrimType.TUBE || primType == PrimType.RING) | ||
4820 | { | ||
4821 | if (m_shape.ProfileBegin != uBegin || m_shape.ProfileEnd != uEnd) | ||
4822 | { | ||
4823 | m_shape.ProfileBegin = uBegin; | ||
4824 | m_shape.ProfileEnd = uEnd; | ||
4825 | updatePossiblyNeeded = true; | ||
4826 | } | ||
4827 | } | ||
4828 | else if (m_shape.PathBegin != uBegin || m_shape.PathEnd != uEnd) | ||
4829 | { | ||
4830 | m_shape.PathBegin = uBegin; | ||
4831 | m_shape.PathEnd = uEnd; | ||
4832 | updatePossiblyNeeded = true; | ||
4833 | } | ||
4834 | |||
4835 | if (updatePossiblyNeeded && ParentGroup != null) | ||
4836 | { | ||
4837 | ParentGroup.HasGroupChanged = true; | ||
4838 | } | ||
4839 | if (updatePossiblyNeeded && PhysActor != null) | ||
4840 | { | ||
4841 | PhysActor.Shape = m_shape; | ||
4842 | ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); | ||
4843 | } | ||
4844 | if (updatePossiblyNeeded) | ||
4845 | { | ||
4846 | ScheduleFullUpdate(); | ||
4847 | } | ||
4848 | } | ||
4849 | |||
4850 | /// <summary> | 4902 | /// <summary> |
4851 | /// If the part is a sculpt/mesh, retrieve the mesh data and reinsert it into the shape so that the physics | 4903 | /// If the part is a sculpt/mesh, retrieve the mesh data and reinsert it into the shape so that the physics |
4852 | /// engine can use it. | 4904 | /// engine can use it. |
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 3a9a146..e010864 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs | |||
@@ -97,15 +97,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
97 | QueryScriptStates(); | 97 | QueryScriptStates(); |
98 | } | 98 | } |
99 | } | 99 | } |
100 | |||
101 | public int Count | ||
102 | { | ||
103 | get | ||
104 | { | ||
105 | lock (m_items) | ||
106 | return m_items.Count; | ||
107 | } | ||
108 | } | ||
109 | 100 | ||
110 | /// <summary> | 101 | /// <summary> |
111 | /// Constructor | 102 | /// Constructor |
@@ -244,52 +235,31 @@ namespace OpenSim.Region.Framework.Scenes | |||
244 | if (m_part == null || m_part.ParentGroup == null || m_part.ParentGroup.Scene == null) | 235 | if (m_part == null || m_part.ParentGroup == null || m_part.ParentGroup.Scene == null) |
245 | return; | 236 | return; |
246 | 237 | ||
238 | IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>(); | ||
239 | if (engines == null) // No engine at all | ||
240 | return; | ||
241 | |||
247 | Items.LockItemsForRead(true); | 242 | Items.LockItemsForRead(true); |
248 | foreach (TaskInventoryItem item in Items.Values) | 243 | foreach (TaskInventoryItem item in Items.Values) |
249 | { | 244 | { |
250 | if (item.InvType == (int)InventoryType.LSL) | 245 | if (item.InvType == (int)InventoryType.LSL) |
251 | { | 246 | { |
252 | bool running; | 247 | foreach (IScriptModule e in engines) |
253 | if (TryGetScriptInstanceRunning(m_part.ParentGroup.Scene, item, out running)) | 248 | { |
254 | item.ScriptRunning = running; | 249 | bool running; |
250 | |||
251 | if (e.HasScript(item.ItemID, out running)) | ||
252 | { | ||
253 | item.ScriptRunning = running; | ||
254 | break; | ||
255 | } | ||
256 | } | ||
255 | } | 257 | } |
256 | } | 258 | } |
257 | 259 | ||
258 | Items.LockItemsForRead(false); | 260 | Items.LockItemsForRead(false); |
259 | } | 261 | } |
260 | 262 | ||
261 | public bool TryGetScriptInstanceRunning(UUID itemId, out bool running) | ||
262 | { | ||
263 | running = false; | ||
264 | |||
265 | TaskInventoryItem item = GetInventoryItem(itemId); | ||
266 | |||
267 | if (item == null) | ||
268 | return false; | ||
269 | |||
270 | return TryGetScriptInstanceRunning(m_part.ParentGroup.Scene, item, out running); | ||
271 | } | ||
272 | |||
273 | public static bool TryGetScriptInstanceRunning(Scene scene, TaskInventoryItem item, out bool running) | ||
274 | { | ||
275 | running = false; | ||
276 | |||
277 | if (item.InvType != (int)InventoryType.LSL) | ||
278 | return false; | ||
279 | |||
280 | IScriptModule[] engines = scene.RequestModuleInterfaces<IScriptModule>(); | ||
281 | if (engines == null) // No engine at all | ||
282 | return false; | ||
283 | |||
284 | foreach (IScriptModule e in engines) | ||
285 | { | ||
286 | if (e.HasScript(item.ItemID, out running)) | ||
287 | return true; | ||
288 | } | ||
289 | |||
290 | return false; | ||
291 | } | ||
292 | |||
293 | public int CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource) | 263 | public int CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource) |
294 | { | 264 | { |
295 | int scriptsValidForStarting = 0; | 265 | int scriptsValidForStarting = 0; |
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 25a53b4..2b9665c 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs | |||
@@ -1,4 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) Contributors, http://opensimulator.org/ | 2 | * Copyright (c) Contributors, http://opensimulator.org/ |
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | 3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. |
4 | * | 4 | * |
@@ -69,15 +69,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
69 | public ScriptControlled eventControls; | 69 | public ScriptControlled eventControls; |
70 | } | 70 | } |
71 | 71 | ||
72 | public delegate void SendCoarseLocationsMethod(UUID scene, ScenePresence presence, List<Vector3> coarseLocations, List<UUID> avatarUUIDs); | 72 | public delegate void SendCourseLocationsMethod(UUID scene, ScenePresence presence, List<Vector3> coarseLocations, List<UUID> avatarUUIDs); |
73 | 73 | ||
74 | public class ScenePresence : EntityBase, IScenePresence | 74 | public class ScenePresence : EntityBase, IScenePresence |
75 | { | 75 | { |
76 | // ~ScenePresence() | 76 | // ~ScenePresence() |
77 | // { | 77 | // { |
78 | // m_log.DebugFormat("[SCENE PRESENCE]: Destructor called on {0}", Name); | 78 | // m_log.Debug("[SCENE PRESENCE] Destructor called"); |
79 | // } | 79 | // } |
80 | |||
81 | private void TriggerScenePresenceUpdated() | 80 | private void TriggerScenePresenceUpdated() |
82 | { | 81 | { |
83 | if (m_scene != null) | 82 | if (m_scene != null) |
@@ -189,7 +188,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
189 | /// </summary> | 188 | /// </summary> |
190 | public bool SitGround { get; private set; } | 189 | public bool SitGround { get; private set; } |
191 | 190 | ||
192 | private SendCoarseLocationsMethod m_sendCoarseLocationsMethod; | 191 | private SendCourseLocationsMethod m_sendCourseLocationsMethod; |
193 | 192 | ||
194 | //private Vector3 m_requestedSitOffset = new Vector3(); | 193 | //private Vector3 m_requestedSitOffset = new Vector3(); |
195 | 194 | ||
@@ -547,7 +546,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
547 | { | 546 | { |
548 | try | 547 | try |
549 | { | 548 | { |
550 | PhysicsActor.TargetVelocity = value; | 549 | PhysicsActor.Velocity = value; |
551 | } | 550 | } |
552 | catch (Exception e) | 551 | catch (Exception e) |
553 | { | 552 | { |
@@ -712,7 +711,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
712 | AttachmentsSyncLock = new Object(); | 711 | AttachmentsSyncLock = new Object(); |
713 | AllowMovement = true; | 712 | AllowMovement = true; |
714 | IsChildAgent = true; | 713 | IsChildAgent = true; |
715 | m_sendCoarseLocationsMethod = SendCoarseLocationsDefault; | 714 | m_sendCourseLocationsMethod = SendCoarseLocationsDefault; |
716 | Animator = new ScenePresenceAnimator(this); | 715 | Animator = new ScenePresenceAnimator(this); |
717 | PresenceType = type; | 716 | PresenceType = type; |
718 | DrawDistance = world.DefaultDrawDistance; | 717 | DrawDistance = world.DefaultDrawDistance; |
@@ -976,9 +975,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
976 | { | 975 | { |
977 | if (wasChild && HasAttachments()) | 976 | if (wasChild && HasAttachments()) |
978 | { | 977 | { |
979 | m_log.DebugFormat( | 978 | m_log.DebugFormat("[SCENE PRESENCE]: Restarting scripts in attachments..."); |
980 | "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name); | ||
981 | |||
982 | // Resume scripts | 979 | // Resume scripts |
983 | Util.FireAndForget(delegate(object x) { | 980 | Util.FireAndForget(delegate(object x) { |
984 | foreach (SceneObjectGroup sog in m_attachments) | 981 | foreach (SceneObjectGroup sog in m_attachments) |
@@ -1534,22 +1531,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
1534 | bool DCFlagKeyPressed = false; | 1531 | bool DCFlagKeyPressed = false; |
1535 | Vector3 agent_control_v3 = Vector3.Zero; | 1532 | Vector3 agent_control_v3 = Vector3.Zero; |
1536 | 1533 | ||
1537 | bool newFlying = actor.Flying; | 1534 | bool oldflying = Flying; |
1538 | 1535 | ||
1539 | if (ForceFly) | 1536 | if (ForceFly) |
1540 | newFlying = true; | 1537 | actor.Flying = true; |
1541 | else if (FlyDisabled) | 1538 | else if (FlyDisabled) |
1542 | newFlying = false; | 1539 | actor.Flying = false; |
1543 | else | 1540 | else |
1544 | newFlying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); | 1541 | actor.Flying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); |
1545 | 1542 | ||
1546 | if (actor.Flying != newFlying) | 1543 | if (actor.Flying != oldflying) |
1547 | { | ||
1548 | // Note: ScenePresence.Flying is actually fetched from the physical actor | ||
1549 | // so setting PhysActor.Flying here also sets the ScenePresence's value. | ||
1550 | actor.Flying = newFlying; | ||
1551 | update_movementflag = true; | 1544 | update_movementflag = true; |
1552 | } | ||
1553 | 1545 | ||
1554 | if (ParentID == 0) | 1546 | if (ParentID == 0) |
1555 | { | 1547 | { |
@@ -2631,17 +2623,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
2631 | 2623 | ||
2632 | public void SendCoarseLocations(List<Vector3> coarseLocations, List<UUID> avatarUUIDs) | 2624 | public void SendCoarseLocations(List<Vector3> coarseLocations, List<UUID> avatarUUIDs) |
2633 | { | 2625 | { |
2634 | SendCoarseLocationsMethod d = m_sendCoarseLocationsMethod; | 2626 | SendCourseLocationsMethod d = m_sendCourseLocationsMethod; |
2635 | if (d != null) | 2627 | if (d != null) |
2636 | { | 2628 | { |
2637 | d.Invoke(m_scene.RegionInfo.originRegionID, this, coarseLocations, avatarUUIDs); | 2629 | d.Invoke(m_scene.RegionInfo.originRegionID, this, coarseLocations, avatarUUIDs); |
2638 | } | 2630 | } |
2639 | } | 2631 | } |
2640 | 2632 | ||
2641 | public void SetSendCoarseLocationMethod(SendCoarseLocationsMethod d) | 2633 | public void SetSendCourseLocationMethod(SendCourseLocationsMethod d) |
2642 | { | 2634 | { |
2643 | if (d != null) | 2635 | if (d != null) |
2644 | m_sendCoarseLocationsMethod = d; | 2636 | m_sendCourseLocationsMethod = d; |
2645 | } | 2637 | } |
2646 | 2638 | ||
2647 | public void SendCoarseLocationsDefault(UUID sceneId, ScenePresence p, List<Vector3> coarseLocations, List<UUID> avatarUUIDs) | 2639 | public void SendCoarseLocationsDefault(UUID sceneId, ScenePresence p, List<Vector3> coarseLocations, List<UUID> avatarUUIDs) |
@@ -2845,7 +2837,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2845 | #region Significant Movement Method | 2837 | #region Significant Movement Method |
2846 | 2838 | ||
2847 | /// <summary> | 2839 | /// <summary> |
2848 | /// This checks for a significant movement and sends a coarselocationchange update | 2840 | /// This checks for a significant movement and sends a courselocationchange update |
2849 | /// </summary> | 2841 | /// </summary> |
2850 | protected void CheckForSignificantMovement() | 2842 | protected void CheckForSignificantMovement() |
2851 | { | 2843 | { |
@@ -3282,7 +3274,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
3282 | } | 3274 | } |
3283 | catch { } | 3275 | catch { } |
3284 | cAgent.DefaultAnim = Animator.Animations.DefaultAnimation; | 3276 | cAgent.DefaultAnim = Animator.Animations.DefaultAnimation; |
3285 | cAgent.AnimState = Animator.Animations.ImplicitDefaultAnimation; | ||
3286 | 3277 | ||
3287 | if (Scene.AttachmentsModule != null) | 3278 | if (Scene.AttachmentsModule != null) |
3288 | Scene.AttachmentsModule.CopyAttachments(this, cAgent); | 3279 | Scene.AttachmentsModule.CopyAttachments(this, cAgent); |
@@ -3359,8 +3350,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
3359 | Animator.Animations.FromArray(cAgent.Anims); | 3350 | Animator.Animations.FromArray(cAgent.Anims); |
3360 | if (cAgent.DefaultAnim != null) | 3351 | if (cAgent.DefaultAnim != null) |
3361 | Animator.Animations.SetDefaultAnimation(cAgent.DefaultAnim.AnimID, cAgent.DefaultAnim.SequenceNum, UUID.Zero); | 3352 | Animator.Animations.SetDefaultAnimation(cAgent.DefaultAnim.AnimID, cAgent.DefaultAnim.SequenceNum, UUID.Zero); |
3362 | if (cAgent.AnimState != null) | ||
3363 | Animator.Animations.SetImplicitDefaultAnimation(cAgent.AnimState.AnimID, cAgent.AnimState.SequenceNum, UUID.Zero); | ||
3364 | 3353 | ||
3365 | if (Scene.AttachmentsModule != null) | 3354 | if (Scene.AttachmentsModule != null) |
3366 | Scene.AttachmentsModule.CopyAttachments(cAgent, this); | 3355 | Scene.AttachmentsModule.CopyAttachments(cAgent, this); |
@@ -3643,16 +3632,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
3643 | public List<SceneObjectGroup> GetAttachments(uint attachmentPoint) | 3632 | public List<SceneObjectGroup> GetAttachments(uint attachmentPoint) |
3644 | { | 3633 | { |
3645 | List<SceneObjectGroup> attachments = new List<SceneObjectGroup>(); | 3634 | List<SceneObjectGroup> attachments = new List<SceneObjectGroup>(); |
3646 | 3635 | ||
3647 | if (attachmentPoint >= 0) | 3636 | lock (m_attachments) |
3648 | { | 3637 | { |
3649 | lock (m_attachments) | 3638 | foreach (SceneObjectGroup so in m_attachments) |
3650 | { | 3639 | { |
3651 | foreach (SceneObjectGroup so in m_attachments) | 3640 | if (attachmentPoint == so.AttachmentPoint) |
3652 | { | 3641 | attachments.Add(so); |
3653 | if (attachmentPoint == so.AttachmentPoint) | ||
3654 | attachments.Add(so); | ||
3655 | } | ||
3656 | } | 3642 | } |
3657 | } | 3643 | } |
3658 | 3644 | ||
diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs index 5398ab9..756b1f4 100644 --- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs +++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs | |||
@@ -47,7 +47,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
47 | = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | 47 | = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); |
48 | 48 | ||
49 | public const string LastReportedObjectUpdateStatName = "LastReportedObjectUpdates"; | 49 | public const string LastReportedObjectUpdateStatName = "LastReportedObjectUpdates"; |
50 | public const string SlowFramesStatName = "SlowFrames"; | ||
51 | 50 | ||
52 | public delegate void SendStatResult(SimStats stats); | 51 | public delegate void SendStatResult(SimStats stats); |
53 | 52 | ||
@@ -130,16 +129,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
130 | } | 129 | } |
131 | 130 | ||
132 | /// <summary> | 131 | /// <summary> |
133 | /// Number of frames that have taken longer to process than Scene.MIN_FRAME_TIME | ||
134 | /// </summary> | ||
135 | public Stat SlowFramesStat { get; private set; } | ||
136 | |||
137 | /// <summary> | ||
138 | /// The threshold at which we log a slow frame. | ||
139 | /// </summary> | ||
140 | public int SlowFramesStatReportThreshold { get; private set; } | ||
141 | |||
142 | /// <summary> | ||
143 | /// Extra sim statistics that are used by monitors but not sent to the client. | 132 | /// Extra sim statistics that are used by monitors but not sent to the client. |
144 | /// </summary> | 133 | /// </summary> |
145 | /// <value> | 134 | /// <value> |
@@ -237,24 +226,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
237 | 226 | ||
238 | if (StatsManager.SimExtraStats != null) | 227 | if (StatsManager.SimExtraStats != null) |
239 | OnSendStatsResult += StatsManager.SimExtraStats.ReceiveClassicSimStatsPacket; | 228 | OnSendStatsResult += StatsManager.SimExtraStats.ReceiveClassicSimStatsPacket; |
240 | |||
241 | /// At the moment, we'll only report if a frame is over 120% of target, since commonly frames are a bit | ||
242 | /// longer than ideal (which in itself is a concern). | ||
243 | SlowFramesStatReportThreshold = (int)Math.Ceiling(m_scene.MinFrameTime * 1000 * 1.2); | ||
244 | |||
245 | SlowFramesStat | ||
246 | = new Stat( | ||
247 | "SlowFrames", | ||
248 | "Slow Frames", | ||
249 | "Number of frames where frame time has been significantly longer than the desired frame time.", | ||
250 | " frames", | ||
251 | "scene", | ||
252 | m_scene.Name, | ||
253 | StatType.Push, | ||
254 | null, | ||
255 | StatVerbosity.Info); | ||
256 | |||
257 | StatsManager.RegisterStat(SlowFramesStat); | ||
258 | } | 229 | } |
259 | 230 | ||
260 | public void Close() | 231 | public void Close() |
@@ -472,7 +443,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
472 | lock (m_lastReportedExtraSimStats) | 443 | lock (m_lastReportedExtraSimStats) |
473 | { | 444 | { |
474 | m_lastReportedExtraSimStats[LastReportedObjectUpdateStatName] = m_objectUpdates / m_statsUpdateFactor; | 445 | m_lastReportedExtraSimStats[LastReportedObjectUpdateStatName] = m_objectUpdates / m_statsUpdateFactor; |
475 | m_lastReportedExtraSimStats[SlowFramesStat.ShortName] = (float)SlowFramesStat.Value; | ||
476 | 446 | ||
477 | Dictionary<string, float> physicsStats = m_scene.PhysicsScene.GetStats(); | 447 | Dictionary<string, float> physicsStats = m_scene.PhysicsScene.GetStats(); |
478 | 448 | ||
@@ -593,11 +563,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
593 | public void addFrameMS(int ms) | 563 | public void addFrameMS(int ms) |
594 | { | 564 | { |
595 | m_frameMS += ms; | 565 | m_frameMS += ms; |
596 | |||
597 | // At the moment, we'll only report if a frame is over 120% of target, since commonly frames are a bit | ||
598 | // longer than ideal due to the inaccuracy of the Sleep in Scene.Update() (which in itself is a concern). | ||
599 | if (ms > SlowFramesStatReportThreshold) | ||
600 | SlowFramesStat.Value++; | ||
601 | } | 566 | } |
602 | 567 | ||
603 | public void addNetMS(int ms) | 568 | public void addNetMS(int ms) |
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs index 5faf131..5758869 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs | |||
@@ -141,7 +141,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests | |||
141 | TestScene scene = new SceneHelpers().SetupScene(); | 141 | TestScene scene = new SceneHelpers().SetupScene(); |
142 | ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1)); | 142 | ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1)); |
143 | 143 | ||
144 | scene.IncomingCloseAgent(sp.UUID, false); | 144 | scene.IncomingCloseAgent(sp.UUID); |
145 | 145 | ||
146 | Assert.That(scene.GetScenePresence(sp.UUID), Is.Null); | 146 | Assert.That(scene.GetScenePresence(sp.UUID), Is.Null); |
147 | Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID), Is.Null); | 147 | Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID), Is.Null); |
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs index ac3da1e..d722a09 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs | |||
@@ -65,22 +65,5 @@ namespace OpenSim.Region.Framework.Scenes.Tests | |||
65 | 65 | ||
66 | Assert.That(scene.Frame, Is.EqualTo(1)); | 66 | Assert.That(scene.Frame, Is.EqualTo(1)); |
67 | } | 67 | } |
68 | |||
69 | [Test] | ||
70 | public void TestShutdownScene() | ||
71 | { | ||
72 | TestHelpers.InMethod(); | ||
73 | |||
74 | Scene scene = new SceneHelpers().SetupScene(); | ||
75 | scene.Close(); | ||
76 | |||
77 | Assert.That(scene.ShuttingDown, Is.True); | ||
78 | Assert.That(scene.Active, Is.False); | ||
79 | |||
80 | // Trying to update a shutdown scene should result in no update | ||
81 | scene.Update(1); | ||
82 | |||
83 | Assert.That(scene.Frame, Is.EqualTo(0)); | ||
84 | } | ||
85 | } | 68 | } |
86 | } \ No newline at end of file | 69 | } \ No newline at end of file |
diff --git a/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs index 9457ebb..44d2d45 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs | |||
@@ -50,41 +50,9 @@ using OpenSim.Tests.Common.Mock; | |||
50 | namespace OpenSim.Region.Framework.Tests | 50 | namespace OpenSim.Region.Framework.Tests |
51 | { | 51 | { |
52 | [TestFixture] | 52 | [TestFixture] |
53 | public class UserInventoryTests : OpenSimTestCase | 53 | public class UserInventoryTests |
54 | { | 54 | { |
55 | [Test] | 55 | [Test] |
56 | public void TestCreateInventoryFolders() | ||
57 | { | ||
58 | TestHelpers.InMethod(); | ||
59 | // TestHelpers.EnableLogging(); | ||
60 | |||
61 | // For this test both folders will have the same name which is legal in SL user inventories. | ||
62 | string foldersName = "f1"; | ||
63 | |||
64 | Scene scene = new SceneHelpers().SetupScene(); | ||
65 | UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1001)); | ||
66 | |||
67 | UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, user1.PrincipalID, foldersName); | ||
68 | |||
69 | List<InventoryFolderBase> oneFolder | ||
70 | = UserInventoryHelpers.GetInventoryFolders(scene.InventoryService, user1.PrincipalID, foldersName); | ||
71 | |||
72 | Assert.That(oneFolder.Count, Is.EqualTo(1)); | ||
73 | InventoryFolderBase firstRetrievedFolder = oneFolder[0]; | ||
74 | Assert.That(firstRetrievedFolder.Name, Is.EqualTo(foldersName)); | ||
75 | |||
76 | UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, user1.PrincipalID, foldersName); | ||
77 | |||
78 | List<InventoryFolderBase> twoFolders | ||
79 | = UserInventoryHelpers.GetInventoryFolders(scene.InventoryService, user1.PrincipalID, foldersName); | ||
80 | |||
81 | Assert.That(twoFolders.Count, Is.EqualTo(2)); | ||
82 | Assert.That(twoFolders[0].Name, Is.EqualTo(foldersName)); | ||
83 | Assert.That(twoFolders[1].Name, Is.EqualTo(foldersName)); | ||
84 | Assert.That(twoFolders[0].ID, Is.Not.EqualTo(twoFolders[1].ID)); | ||
85 | } | ||
86 | |||
87 | [Test] | ||
88 | public void TestGiveInventoryItem() | 56 | public void TestGiveInventoryItem() |
89 | { | 57 | { |
90 | TestHelpers.InMethod(); | 58 | TestHelpers.InMethod(); |
@@ -115,7 +83,7 @@ namespace OpenSim.Region.Framework.Tests | |||
115 | public void TestGiveInventoryFolder() | 83 | public void TestGiveInventoryFolder() |
116 | { | 84 | { |
117 | TestHelpers.InMethod(); | 85 | TestHelpers.InMethod(); |
118 | // TestHelpers.EnableLogging(); | 86 | // log4net.Config.XmlConfigurator.Configure(); |
119 | 87 | ||
120 | Scene scene = new SceneHelpers().SetupScene(); | 88 | Scene scene = new SceneHelpers().SetupScene(); |
121 | UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1001)); | 89 | UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1001)); |
diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs index 2279e62..411e421 100644 --- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs +++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs | |||
@@ -52,23 +52,26 @@ namespace OpenSim.Region.Framework.Scenes | |||
52 | public class UuidGatherer | 52 | public class UuidGatherer |
53 | { | 53 | { |
54 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 54 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
55 | |||
56 | /// <summary> | ||
57 | /// Asset cache used for gathering assets | ||
58 | /// </summary> | ||
59 | protected IAssetService m_assetCache; | ||
60 | |||
61 | /// <summary> | ||
62 | /// Used as a temporary store of an asset which represents an object. This can be a null if no appropriate | ||
63 | /// asset was found by the asset service. | ||
64 | /// </summary> | ||
65 | private AssetBase m_requestedObjectAsset; | ||
55 | 66 | ||
56 | protected IAssetService m_assetService; | 67 | /// <summary> |
57 | 68 | /// Signal whether we are currently waiting for the asset service to deliver an asset. | |
58 | // /// <summary> | 69 | /// </summary> |
59 | // /// Used as a temporary store of an asset which represents an object. This can be a null if no appropriate | 70 | private bool m_waitingForObjectAsset; |
60 | // /// asset was found by the asset service. | ||
61 | // /// </summary> | ||
62 | // private AssetBase m_requestedObjectAsset; | ||
63 | // | ||
64 | // /// <summary> | ||
65 | // /// Signal whether we are currently waiting for the asset service to deliver an asset. | ||
66 | // /// </summary> | ||
67 | // private bool m_waitingForObjectAsset; | ||
68 | 71 | ||
69 | public UuidGatherer(IAssetService assetService) | 72 | public UuidGatherer(IAssetService assetCache) |
70 | { | 73 | { |
71 | m_assetService = assetService; | 74 | m_assetCache = assetCache; |
72 | } | 75 | } |
73 | 76 | ||
74 | /// <summary> | 77 | /// <summary> |
@@ -188,18 +191,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
188 | } | 191 | } |
189 | } | 192 | } |
190 | 193 | ||
191 | // /// <summary> | 194 | /// <summary> |
192 | // /// The callback made when we request the asset for an object from the asset service. | 195 | /// The callback made when we request the asset for an object from the asset service. |
193 | // /// </summary> | 196 | /// </summary> |
194 | // private void AssetReceived(string id, Object sender, AssetBase asset) | 197 | private void AssetReceived(string id, Object sender, AssetBase asset) |
195 | // { | 198 | { |
196 | // lock (this) | 199 | lock (this) |
197 | // { | 200 | { |
198 | // m_requestedObjectAsset = asset; | 201 | m_requestedObjectAsset = asset; |
199 | // m_waitingForObjectAsset = false; | 202 | m_waitingForObjectAsset = false; |
200 | // Monitor.Pulse(this); | 203 | Monitor.Pulse(this); |
201 | // } | 204 | } |
202 | // } | 205 | } |
203 | 206 | ||
204 | /// <summary> | 207 | /// <summary> |
205 | /// Get an asset synchronously, potentially using an asynchronous callback. If the | 208 | /// Get an asset synchronously, potentially using an asynchronous callback. If the |
@@ -209,29 +212,25 @@ namespace OpenSim.Region.Framework.Scenes | |||
209 | /// <returns></returns> | 212 | /// <returns></returns> |
210 | protected virtual AssetBase GetAsset(UUID uuid) | 213 | protected virtual AssetBase GetAsset(UUID uuid) |
211 | { | 214 | { |
212 | return m_assetService.Get(uuid.ToString()); | 215 | m_waitingForObjectAsset = true; |
216 | m_assetCache.Get(uuid.ToString(), this, AssetReceived); | ||
217 | |||
218 | // The asset cache callback can either | ||
219 | // | ||
220 | // 1. Complete on the same thread (if the asset is already in the cache) or | ||
221 | // 2. Come in via a different thread (if we need to go fetch it). | ||
222 | // | ||
223 | // The code below handles both these alternatives. | ||
224 | lock (this) | ||
225 | { | ||
226 | if (m_waitingForObjectAsset) | ||
227 | { | ||
228 | Monitor.Wait(this); | ||
229 | m_waitingForObjectAsset = false; | ||
230 | } | ||
231 | } | ||
213 | 232 | ||
214 | // XXX: Switching to do this synchronously where the call was async before but we always waited for it | 233 | return m_requestedObjectAsset; |
215 | // to complete anyway! | ||
216 | // m_waitingForObjectAsset = true; | ||
217 | // m_assetCache.Get(uuid.ToString(), this, AssetReceived); | ||
218 | // | ||
219 | // // The asset cache callback can either | ||
220 | // // | ||
221 | // // 1. Complete on the same thread (if the asset is already in the cache) or | ||
222 | // // 2. Come in via a different thread (if we need to go fetch it). | ||
223 | // // | ||
224 | // // The code below handles both these alternatives. | ||
225 | // lock (this) | ||
226 | // { | ||
227 | // if (m_waitingForObjectAsset) | ||
228 | // { | ||
229 | // Monitor.Wait(this); | ||
230 | // m_waitingForObjectAsset = false; | ||
231 | // } | ||
232 | // } | ||
233 | // | ||
234 | // return m_requestedObjectAsset; | ||
235 | } | 234 | } |
236 | 235 | ||
237 | /// <summary> | 236 | /// <summary> |
@@ -362,47 +361,4 @@ namespace OpenSim.Region.Framework.Scenes | |||
362 | } | 361 | } |
363 | } | 362 | } |
364 | } | 363 | } |
365 | |||
366 | public class HGUuidGatherer : UuidGatherer | ||
367 | { | ||
368 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
369 | |||
370 | protected string m_assetServerURL; | ||
371 | |||
372 | public HGUuidGatherer(IAssetService assetService, string assetServerURL) | ||
373 | : base(assetService) | ||
374 | { | ||
375 | m_assetServerURL = assetServerURL; | ||
376 | if (!m_assetServerURL.EndsWith("/") && !m_assetServerURL.EndsWith("=")) | ||
377 | m_assetServerURL = m_assetServerURL + "/"; | ||
378 | } | ||
379 | |||
380 | protected override AssetBase GetAsset(UUID uuid) | ||
381 | { | ||
382 | if (string.Empty == m_assetServerURL) | ||
383 | return base.GetAsset(uuid); | ||
384 | else | ||
385 | return FetchAsset(uuid); | ||
386 | } | ||
387 | |||
388 | public AssetBase FetchAsset(UUID assetID) | ||
389 | { | ||
390 | |||
391 | // Test if it's already here | ||
392 | AssetBase asset = m_assetService.Get(assetID.ToString()); | ||
393 | if (asset == null) | ||
394 | { | ||
395 | // It's not, so fetch it from abroad | ||
396 | asset = m_assetService.Get(m_assetServerURL + assetID.ToString()); | ||
397 | if (asset != null) | ||
398 | m_log.DebugFormat("[HGUUIDGatherer]: Copied asset {0} from {1} to local asset server", assetID, m_assetServerURL); | ||
399 | else | ||
400 | m_log.DebugFormat("[HGUUIDGatherer]: Failed to fetch asset {0} from {1}", assetID, m_assetServerURL); | ||
401 | } | ||
402 | //else | ||
403 | // m_log.DebugFormat("[HGUUIDGatherer]: Asset {0} from {1} was already here", assetID, m_assetServerURL); | ||
404 | |||
405 | return asset; | ||
406 | } | ||
407 | } | ||
408 | } | 364 | } |
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index 254eeb4..28b8293 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs | |||
@@ -891,10 +891,10 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server | |||
891 | 891 | ||
892 | public void Close() | 892 | public void Close() |
893 | { | 893 | { |
894 | Close(true, false); | 894 | Close(true); |
895 | } | 895 | } |
896 | 896 | ||
897 | public void Close(bool sendStop, bool force) | 897 | public void Close(bool sendStop) |
898 | { | 898 | { |
899 | Disconnect(); | 899 | Disconnect(); |
900 | } | 900 | } |
@@ -959,8 +959,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server | |||
959 | 959 | ||
960 | } | 960 | } |
961 | 961 | ||
962 | public void SendChatMessage( | 962 | public void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName, UUID fromAgentID, byte source, byte audible) |
963 | string message, byte type, Vector3 fromPos, string fromName, UUID fromAgentID, UUID ownerID, byte source, byte audible) | ||
964 | { | 963 | { |
965 | if (audible > 0 && message.Length > 0) | 964 | if (audible > 0 && message.Length > 0) |
966 | IRC_SendChannelPrivmsg(fromName, message); | 965 | IRC_SendChannelPrivmsg(fromName, message); |
diff --git a/OpenSim/Region/OptionalModules/Asset/AssetInfoModule.cs b/OpenSim/Region/OptionalModules/Asset/AssetInfoModule.cs index 7639c6c..41ec14f 100644 --- a/OpenSim/Region/OptionalModules/Asset/AssetInfoModule.cs +++ b/OpenSim/Region/OptionalModules/Asset/AssetInfoModule.cs | |||
@@ -127,9 +127,6 @@ namespace OpenSim.Region.OptionalModules.Asset | |||
127 | } | 127 | } |
128 | 128 | ||
129 | string fileName = rawAssetId; | 129 | string fileName = rawAssetId; |
130 | |||
131 | if (!ConsoleUtil.CheckFileDoesNotExist(MainConsole.Instance, fileName)) | ||
132 | return; | ||
133 | 130 | ||
134 | using (FileStream fs = new FileStream(fileName, FileMode.CreateNew)) | 131 | using (FileStream fs = new FileStream(fileName, FileMode.CreateNew)) |
135 | { | 132 | { |
diff --git a/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs b/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs index 68bcb4a..d68aabc 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs | |||
@@ -146,7 +146,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments | |||
146 | sb.AppendFormat("Attachments for {0}\n", sp.Name); | 146 | sb.AppendFormat("Attachments for {0}\n", sp.Name); |
147 | 147 | ||
148 | ConsoleDisplayTable ct = new ConsoleDisplayTable() { Indent = 2 }; | 148 | ConsoleDisplayTable ct = new ConsoleDisplayTable() { Indent = 2 }; |
149 | ct.Columns.Add(new ConsoleDisplayTableColumn("Attachment Name", 50)); | 149 | ct.Columns.Add(new ConsoleDisplayTableColumn("Attachment Name", 36)); |
150 | ct.Columns.Add(new ConsoleDisplayTableColumn("Local ID", 10)); | 150 | ct.Columns.Add(new ConsoleDisplayTableColumn("Local ID", 10)); |
151 | ct.Columns.Add(new ConsoleDisplayTableColumn("Item ID", 36)); | 151 | ct.Columns.Add(new ConsoleDisplayTableColumn("Item ID", 36)); |
152 | ct.Columns.Add(new ConsoleDisplayTableColumn("Attach Point", 14)); | 152 | ct.Columns.Add(new ConsoleDisplayTableColumn("Attach Point", 14)); |
diff --git a/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs b/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs index 17971e3..31d0034 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs | |||
@@ -130,37 +130,37 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments | |||
130 | SendConsoleOutput(agentID, String.Format("auto_grant_attach_perms set to {0}", val)); | 130 | SendConsoleOutput(agentID, String.Format("auto_grant_attach_perms set to {0}", val)); |
131 | } | 131 | } |
132 | 132 | ||
133 | private int llAttachToAvatarTemp(UUID host, UUID script, int attachmentPoint) | 133 | private void llAttachToAvatarTemp(UUID host, UUID script, int attachmentPoint) |
134 | { | 134 | { |
135 | SceneObjectPart hostPart = m_scene.GetSceneObjectPart(host); | 135 | SceneObjectPart hostPart = m_scene.GetSceneObjectPart(host); |
136 | 136 | ||
137 | if (hostPart == null) | 137 | if (hostPart == null) |
138 | return 0; | 138 | return; |
139 | 139 | ||
140 | if (hostPart.ParentGroup.IsAttachment) | 140 | if (hostPart.ParentGroup.IsAttachment) |
141 | return 0; | 141 | return; |
142 | 142 | ||
143 | IAttachmentsModule attachmentsModule = m_scene.RequestModuleInterface<IAttachmentsModule>(); | 143 | IAttachmentsModule attachmentsModule = m_scene.RequestModuleInterface<IAttachmentsModule>(); |
144 | if (attachmentsModule == null) | 144 | if (attachmentsModule == null) |
145 | return 0; | 145 | return; |
146 | 146 | ||
147 | TaskInventoryItem item = hostPart.Inventory.GetInventoryItem(script); | 147 | TaskInventoryItem item = hostPart.Inventory.GetInventoryItem(script); |
148 | if (item == null) | 148 | if (item == null) |
149 | return 0; | 149 | return; |
150 | 150 | ||
151 | if ((item.PermsMask & 32) == 0) // PERMISSION_ATTACH | 151 | if ((item.PermsMask & 32) == 0) // PERMISSION_ATTACH |
152 | return 0; | 152 | return; |
153 | 153 | ||
154 | ScenePresence target; | 154 | ScenePresence target; |
155 | if (!m_scene.TryGetScenePresence(item.PermsGranter, out target)) | 155 | if (!m_scene.TryGetScenePresence(item.PermsGranter, out target)) |
156 | return 0; | 156 | return; |
157 | 157 | ||
158 | if (target.UUID != hostPart.ParentGroup.OwnerID) | 158 | if (target.UUID != hostPart.ParentGroup.OwnerID) |
159 | { | 159 | { |
160 | uint effectivePerms = hostPart.ParentGroup.GetEffectivePermissions(); | 160 | uint effectivePerms = hostPart.ParentGroup.GetEffectivePermissions(); |
161 | 161 | ||
162 | if ((effectivePerms & (uint)PermissionMask.Transfer) == 0) | 162 | if ((effectivePerms & (uint)PermissionMask.Transfer) == 0) |
163 | return 0; | 163 | return; |
164 | 164 | ||
165 | hostPart.ParentGroup.SetOwnerId(target.UUID); | 165 | hostPart.ParentGroup.SetOwnerId(target.UUID); |
166 | hostPart.ParentGroup.SetRootPartOwner(hostPart.ParentGroup.RootPart, target.UUID, target.ControllingClient.ActiveGroupId); | 166 | hostPart.ParentGroup.SetRootPartOwner(hostPart.ParentGroup.RootPart, target.UUID, target.ControllingClient.ActiveGroupId); |
@@ -183,7 +183,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments | |||
183 | hostPart.ParentGroup.RootPart.ScheduleFullUpdate(); | 183 | hostPart.ParentGroup.RootPart.ScheduleFullUpdate(); |
184 | } | 184 | } |
185 | 185 | ||
186 | return attachmentsModule.AttachObject(target, hostPart.ParentGroup, (uint)attachmentPoint, false, true, true) ? 1 : 0; | 186 | attachmentsModule.AttachObject(target, hostPart.ParentGroup, (uint)attachmentPoint, false, true, true); |
187 | } | 187 | } |
188 | } | 188 | } |
189 | } | 189 | } |
diff --git a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs index a014798..ca956fb 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs | |||
@@ -231,12 +231,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat | |||
231 | if (m_server == null || m_baseNick == null || m_ircChannel == null || m_user == null) | 231 | if (m_server == null || m_baseNick == null || m_ircChannel == null || m_user == null) |
232 | throw new Exception("Invalid connector configuration"); | 232 | throw new Exception("Invalid connector configuration"); |
233 | 233 | ||
234 | // Generate an initial nickname | 234 | // Generate an initial nickname if randomizing is enabled |
235 | 235 | ||
236 | if (m_randomizeNick) | 236 | if (m_randomizeNick) |
237 | { | ||
237 | m_nick = m_baseNick + Util.RandomClass.Next(1, 99); | 238 | m_nick = m_baseNick + Util.RandomClass.Next(1, 99); |
238 | else | 239 | } |
239 | m_nick = m_baseNick; | ||
240 | 240 | ||
241 | m_log.InfoFormat("[IRC-Connector-{0}]: Initialization complete", idn); | 241 | m_log.InfoFormat("[IRC-Connector-{0}]: Initialization complete", idn); |
242 | 242 | ||
diff --git a/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs b/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs index 5c3be29..e22618d 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs | |||
@@ -546,9 +546,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Concierge | |||
546 | c.SenderUUID = UUID.Zero; | 546 | c.SenderUUID = UUID.Zero; |
547 | c.Scene = agent.Scene; | 547 | c.Scene = agent.Scene; |
548 | 548 | ||
549 | agent.ControllingClient.SendChatMessage( | 549 | agent.ControllingClient.SendChatMessage(msg, (byte) ChatTypeEnum.Say, PosOfGod, m_whoami, UUID.Zero, |
550 | msg, (byte) ChatTypeEnum.Say, PosOfGod, m_whoami, UUID.Zero, UUID.Zero, | 550 | (byte)ChatSourceType.Object, (byte)ChatAudibleLevel.Fully); |
551 | (byte)ChatSourceType.Object, (byte)ChatAudibleLevel.Fully); | ||
552 | } | 551 | } |
553 | 552 | ||
554 | private static void checkStringParameters(XmlRpcRequest request, string[] param) | 553 | private static void checkStringParameters(XmlRpcRequest request, string[] param) |
diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs index f292a75..7b20446 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs | |||
@@ -447,7 +447,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice | |||
447 | // settings allow voice, then whether parcel allows | 447 | // settings allow voice, then whether parcel allows |
448 | // voice, if all do retrieve or obtain the parcel | 448 | // voice, if all do retrieve or obtain the parcel |
449 | // voice channel | 449 | // voice channel |
450 | LandData land = scene.GetLandData(avatar.AbsolutePosition); | 450 | LandData land = scene.GetLandData(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); |
451 | 451 | ||
452 | //m_log.DebugFormat("[FreeSwitchVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": request: {4}, path: {5}, param: {6}", | 452 | //m_log.DebugFormat("[FreeSwitchVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": request: {4}, path: {5}, param: {6}", |
453 | // scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, request, path, param); | 453 | // scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, request, path, param); |
diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs index 8a8a31c..a30a38d 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs | |||
@@ -623,7 +623,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice | |||
623 | // settings allow voice, then whether parcel allows | 623 | // settings allow voice, then whether parcel allows |
624 | // voice, if all do retrieve or obtain the parcel | 624 | // voice, if all do retrieve or obtain the parcel |
625 | // voice channel | 625 | // voice channel |
626 | LandData land = scene.GetLandData(avatar.AbsolutePosition); | 626 | LandData land = scene.GetLandData(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); |
627 | 627 | ||
628 | // m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": request: {4}, path: {5}, param: {6}", | 628 | // m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": request: {4}, path: {5}, param: {6}", |
629 | // scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, request, path, param); | 629 | // scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, request, path, param); |
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs index 1528330..10b83e6 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs | |||
@@ -27,7 +27,6 @@ | |||
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.Linq; | ||
31 | using System.Reflection; | 30 | using System.Reflection; |
32 | using log4net; | 31 | using log4net; |
33 | using Mono.Addins; | 32 | using Mono.Addins; |
@@ -37,8 +36,6 @@ using OpenMetaverse.StructuredData; | |||
37 | using OpenSim.Framework; | 36 | using OpenSim.Framework; |
38 | using OpenSim.Region.Framework.Interfaces; | 37 | using OpenSim.Region.Framework.Interfaces; |
39 | using OpenSim.Region.Framework.Scenes; | 38 | using OpenSim.Region.Framework.Scenes; |
40 | using OpenSim.Services.Interfaces; | ||
41 | using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; | ||
42 | 39 | ||
43 | namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups | 40 | namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups |
44 | { | 41 | { |
@@ -48,7 +45,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups | |||
48 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 45 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
49 | 46 | ||
50 | private List<Scene> m_sceneList = new List<Scene>(); | 47 | private List<Scene> m_sceneList = new List<Scene>(); |
51 | private IPresenceService m_presenceService; | ||
52 | 48 | ||
53 | private IMessageTransferModule m_msgTransferModule = null; | 49 | private IMessageTransferModule m_msgTransferModule = null; |
54 | 50 | ||
@@ -58,27 +54,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups | |||
58 | private bool m_groupMessagingEnabled = false; | 54 | private bool m_groupMessagingEnabled = false; |
59 | private bool m_debugEnabled = true; | 55 | private bool m_debugEnabled = true; |
60 | 56 | ||
61 | /// <summary> | ||
62 | /// If enabled, module only tries to send group IMs to online users by querying cached presence information. | ||
63 | /// </summary> | ||
64 | private bool m_messageOnlineAgentsOnly; | ||
65 | |||
66 | /// <summary> | ||
67 | /// Cache for online users. | ||
68 | /// </summary> | ||
69 | /// <remarks> | ||
70 | /// Group ID is key, presence information for online members is value. | ||
71 | /// Will only be non-null if m_messageOnlineAgentsOnly = true | ||
72 | /// We cache here so that group messages don't constantly have to re-request the online user list to avoid | ||
73 | /// attempted expensive sending of messages to offline users. | ||
74 | /// The tradeoff is that a user that comes online will not receive messages consistently from all other users | ||
75 | /// until caches have updated. | ||
76 | /// Therefore, we set the cache expiry to just 20 seconds. | ||
77 | /// </remarks> | ||
78 | private ExpiringCache<UUID, PresenceInfo[]> m_usersOnlineCache; | ||
79 | |||
80 | private int m_usersOnlineCacheExpirySeconds = 20; | ||
81 | |||
82 | #region IRegionModuleBase Members | 57 | #region IRegionModuleBase Members |
83 | 58 | ||
84 | public void Initialise(IConfigSource config) | 59 | public void Initialise(IConfigSource config) |
@@ -108,17 +83,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups | |||
108 | return; | 83 | return; |
109 | } | 84 | } |
110 | 85 | ||
111 | m_messageOnlineAgentsOnly = groupsConfig.GetBoolean("MessageOnlineUsersOnly", false); | ||
112 | |||
113 | if (m_messageOnlineAgentsOnly) | ||
114 | m_usersOnlineCache = new ExpiringCache<UUID, PresenceInfo[]>(); | ||
115 | |||
116 | m_debugEnabled = groupsConfig.GetBoolean("DebugEnabled", true); | 86 | m_debugEnabled = groupsConfig.GetBoolean("DebugEnabled", true); |
117 | } | 87 | } |
118 | 88 | ||
119 | m_log.InfoFormat( | 89 | m_log.Info("[GROUPS-MESSAGING]: GroupsMessagingModule starting up"); |
120 | "[GROUPS-MESSAGING]: GroupsMessagingModule enabled with MessageOnlineOnly = {0}, DebugEnabled = {1}", | ||
121 | m_messageOnlineAgentsOnly, m_debugEnabled); | ||
122 | } | 90 | } |
123 | 91 | ||
124 | public void AddRegion(Scene scene) | 92 | public void AddRegion(Scene scene) |
@@ -158,8 +126,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups | |||
158 | return; | 126 | return; |
159 | } | 127 | } |
160 | 128 | ||
161 | if (m_presenceService == null) | ||
162 | m_presenceService = scene.PresenceService; | ||
163 | 129 | ||
164 | m_sceneList.Add(scene); | 130 | m_sceneList.Add(scene); |
165 | 131 | ||
@@ -241,42 +207,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups | |||
241 | public void SendMessageToGroup(GridInstantMessage im, UUID groupID) | 207 | public void SendMessageToGroup(GridInstantMessage im, UUID groupID) |
242 | { | 208 | { |
243 | List<GroupMembersData> groupMembers = m_groupData.GetGroupMembers(new UUID(im.fromAgentID), groupID); | 209 | List<GroupMembersData> groupMembers = m_groupData.GetGroupMembers(new UUID(im.fromAgentID), groupID); |
244 | int groupMembersCount = groupMembers.Count; | 210 | |
245 | 211 | if (m_debugEnabled) | |
246 | if (m_messageOnlineAgentsOnly) | 212 | m_log.DebugFormat( |
247 | { | 213 | "[GROUPS-MESSAGING]: SendMessageToGroup called for group {0} with {1} visible members", |
248 | string[] t1 = groupMembers.ConvertAll<string>(gmd => gmd.AgentID.ToString()).ToArray(); | 214 | groupID, groupMembers.Count); |
249 | 215 | ||
250 | // We cache in order not to overwhlem the presence service on large grids with many groups. This does | ||
251 | // mean that members coming online will not see all group members until after m_usersOnlineCacheExpirySeconds has elapsed. | ||
252 | // (assuming this is the same across all grid simulators). | ||
253 | PresenceInfo[] onlineAgents; | ||
254 | if (!m_usersOnlineCache.TryGetValue(groupID, out onlineAgents)) | ||
255 | { | ||
256 | onlineAgents = m_presenceService.GetAgents(t1); | ||
257 | m_usersOnlineCache.Add(groupID, onlineAgents, m_usersOnlineCacheExpirySeconds); | ||
258 | } | ||
259 | |||
260 | HashSet<string> onlineAgentsUuidSet = new HashSet<string>(); | ||
261 | Array.ForEach<PresenceInfo>(onlineAgents, pi => onlineAgentsUuidSet.Add(pi.UserID)); | ||
262 | |||
263 | groupMembers = groupMembers.Where(gmd => onlineAgentsUuidSet.Contains(gmd.AgentID.ToString())).ToList(); | ||
264 | |||
265 | // if (m_debugEnabled) | ||
266 | // m_log.DebugFormat( | ||
267 | // "[GROUPS-MESSAGING]: SendMessageToGroup called for group {0} with {1} visible members, {2} online", | ||
268 | // groupID, groupMembersCount, groupMembers.Count()); | ||
269 | } | ||
270 | else | ||
271 | { | ||
272 | if (m_debugEnabled) | ||
273 | m_log.DebugFormat( | ||
274 | "[GROUPS-MESSAGING]: SendMessageToGroup called for group {0} with {1} visible members", | ||
275 | groupID, groupMembers.Count); | ||
276 | } | ||
277 | |||
278 | int requestStartTick = Environment.TickCount; | ||
279 | |||
280 | foreach (GroupMembersData member in groupMembers) | 216 | foreach (GroupMembersData member in groupMembers) |
281 | { | 217 | { |
282 | if (m_groupData.hasAgentDroppedGroupChatSession(member.AgentID, groupID)) | 218 | if (m_groupData.hasAgentDroppedGroupChatSession(member.AgentID, groupID)) |
@@ -318,12 +254,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups | |||
318 | ProcessMessageFromGroupSession(msg); | 254 | ProcessMessageFromGroupSession(msg); |
319 | } | 255 | } |
320 | } | 256 | } |
321 | |||
322 | // Temporary for assessing how long it still takes to send messages to large online groups. | ||
323 | if (m_messageOnlineAgentsOnly) | ||
324 | m_log.DebugFormat( | ||
325 | "[GROUPS-MESSAGING]: SendMessageToGroup for group {0} with {1} visible members, {2} online took {3}ms", | ||
326 | groupID, groupMembersCount, groupMembers.Count(), Environment.TickCount - requestStartTick); | ||
327 | } | 257 | } |
328 | 258 | ||
329 | #region SimGridEventHandlers | 259 | #region SimGridEventHandlers |
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs index 79e9994..65bd26c 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs | |||
@@ -123,36 +123,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups | |||
123 | public void AddRegion(Scene scene) | 123 | public void AddRegion(Scene scene) |
124 | { | 124 | { |
125 | if (m_groupsEnabled) | 125 | if (m_groupsEnabled) |
126 | { | ||
127 | scene.RegisterModuleInterface<IGroupsModule>(this); | 126 | scene.RegisterModuleInterface<IGroupsModule>(this); |
128 | scene.AddCommand( | ||
129 | "debug", | ||
130 | this, | ||
131 | "debug groups verbose", | ||
132 | "debug groups verbose <true|false>", | ||
133 | "This setting turns on very verbose groups debugging", | ||
134 | HandleDebugGroupsVerbose); | ||
135 | } | ||
136 | } | ||
137 | |||
138 | private void HandleDebugGroupsVerbose(object modules, string[] args) | ||
139 | { | ||
140 | if (args.Length < 4) | ||
141 | { | ||
142 | MainConsole.Instance.Output("Usage: debug groups verbose <true|false>"); | ||
143 | return; | ||
144 | } | ||
145 | |||
146 | bool verbose = false; | ||
147 | if (!bool.TryParse(args[3], out verbose)) | ||
148 | { | ||
149 | MainConsole.Instance.Output("Usage: debug groups verbose <true|false>"); | ||
150 | return; | ||
151 | } | ||
152 | |||
153 | m_debugEnabled = verbose; | ||
154 | |||
155 | MainConsole.Instance.OutputFormat("{0} verbose logging set to {1}", Name, m_debugEnabled); | ||
156 | } | 127 | } |
157 | 128 | ||
158 | public void RegionLoaded(Scene scene) | 129 | public void RegionLoaded(Scene scene) |
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs index 732c28f..311531c 100644 --- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs | |||
@@ -175,15 +175,14 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore | |||
175 | /// | 175 | /// |
176 | /// </summary> | 176 | /// </summary> |
177 | // ----------------------------------------------------------------- | 177 | // ----------------------------------------------------------------- |
178 | public bool CreateStore(string value, ref UUID result) | 178 | public bool CreateStore(string value, out UUID result) |
179 | { | 179 | { |
180 | if (result == UUID.Zero) | 180 | result = UUID.Zero; |
181 | result = UUID.Random(); | ||
182 | |||
183 | JsonStore map = null; | ||
184 | 181 | ||
185 | if (! m_enabled) return false; | 182 | if (! m_enabled) return false; |
186 | 183 | ||
184 | UUID uuid = UUID.Random(); | ||
185 | JsonStore map = null; | ||
187 | 186 | ||
188 | try | 187 | try |
189 | { | 188 | { |
@@ -196,8 +195,9 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore | |||
196 | } | 195 | } |
197 | 196 | ||
198 | lock (m_JsonValueStore) | 197 | lock (m_JsonValueStore) |
199 | m_JsonValueStore.Add(result,map); | 198 | m_JsonValueStore.Add(uuid,map); |
200 | 199 | ||
200 | result = uuid; | ||
201 | return true; | 201 | return true; |
202 | } | 202 | } |
203 | 203 | ||
@@ -231,7 +231,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore | |||
231 | if (! m_JsonValueStore.TryGetValue(storeID,out map)) | 231 | if (! m_JsonValueStore.TryGetValue(storeID,out map)) |
232 | { | 232 | { |
233 | m_log.InfoFormat("[JsonStore] Missing store {0}",storeID); | 233 | m_log.InfoFormat("[JsonStore] Missing store {0}",storeID); |
234 | return false; | 234 | return true; |
235 | } | 235 | } |
236 | } | 236 | } |
237 | 237 | ||
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs index 6910d14..eaba816 100644 --- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs | |||
@@ -227,7 +227,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore | |||
227 | protected UUID JsonCreateStore(UUID hostID, UUID scriptID, string value) | 227 | protected UUID JsonCreateStore(UUID hostID, UUID scriptID, string value) |
228 | { | 228 | { |
229 | UUID uuid = UUID.Zero; | 229 | UUID uuid = UUID.Zero; |
230 | if (! m_store.CreateStore(value, ref uuid)) | 230 | if (! m_store.CreateStore(value, out uuid)) |
231 | GenerateRuntimeError("Failed to create Json store"); | 231 | GenerateRuntimeError("Failed to create Json store"); |
232 | 232 | ||
233 | return uuid; | 233 | return uuid; |
diff --git a/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs b/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs index 5ed1514..aa23fee 100644 --- a/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs +++ b/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs | |||
@@ -821,11 +821,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule | |||
821 | { | 821 | { |
822 | if (!CanEdit()) | 822 | if (!CanEdit()) |
823 | return; | 823 | return; |
824 | ISoundModule module = m_rootScene.RequestModuleInterface<ISoundModule>(); | 824 | |
825 | if (module != null) | 825 | GetSOP().SendSound(asset.ToString(), volume, true, 0, 0, false, false); |
826 | { | ||
827 | module.SendSound(GetSOP().UUID, asset, volume, true, 0, 0, false, false); | ||
828 | } | ||
829 | } | 826 | } |
830 | 827 | ||
831 | #endregion | 828 | #endregion |
diff --git a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs index bad75f7..fff3a32 100644 --- a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs | |||
@@ -181,7 +181,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady | |||
181 | } | 181 | } |
182 | } | 182 | } |
183 | 183 | ||
184 | void OnOarFileLoaded(Guid requestId, List<UUID> loadedScenes, string message) | 184 | void OnOarFileLoaded(Guid requestId, string message) |
185 | { | 185 | { |
186 | m_oarFileLoading = true; | 186 | m_oarFileLoading = true; |
187 | 187 | ||
diff --git a/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs index dc54c3f..c5c96a9 100644 --- a/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs | |||
@@ -130,25 +130,13 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms | |||
130 | m_scriptModule.PostScriptEvent(script, "link_message", args); | 130 | m_scriptModule.PostScriptEvent(script, "link_message", args); |
131 | } | 131 | } |
132 | 132 | ||
133 | private static MethodInfo GetMethodInfoFromType(Type target, string meth, bool searchInstanceMethods) | ||
134 | { | ||
135 | BindingFlags getMethodFlags = | ||
136 | BindingFlags.NonPublic | BindingFlags.Public; | ||
137 | |||
138 | if (searchInstanceMethods) | ||
139 | getMethodFlags |= BindingFlags.Instance; | ||
140 | else | ||
141 | getMethodFlags |= BindingFlags.Static; | ||
142 | |||
143 | return target.GetMethod(meth, getMethodFlags); | ||
144 | } | ||
145 | |||
146 | public void RegisterScriptInvocation(object target, string meth) | 133 | public void RegisterScriptInvocation(object target, string meth) |
147 | { | 134 | { |
148 | MethodInfo mi = GetMethodInfoFromType(target.GetType(), meth, true); | 135 | MethodInfo mi = target.GetType().GetMethod(meth, |
136 | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); | ||
149 | if (mi == null) | 137 | if (mi == null) |
150 | { | 138 | { |
151 | m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}", meth); | 139 | m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}",meth); |
152 | return; | 140 | return; |
153 | } | 141 | } |
154 | 142 | ||
@@ -163,71 +151,38 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms | |||
163 | 151 | ||
164 | public void RegisterScriptInvocation(object target, MethodInfo mi) | 152 | public void RegisterScriptInvocation(object target, MethodInfo mi) |
165 | { | 153 | { |
166 | m_log.DebugFormat("[MODULE COMMANDS] Register method {0} from type {1}", mi.Name, (target is Type) ? ((Type)target).Name : target.GetType().Name); | 154 | m_log.DebugFormat("[MODULE COMMANDS] Register method {0} from type {1}", mi.Name, target.GetType().Name); |
167 | 155 | ||
168 | Type delegateType; | 156 | Type delegateType; |
169 | List<Type> typeArgs = mi.GetParameters() | 157 | var typeArgs = mi.GetParameters() |
170 | .Select(p => p.ParameterType) | 158 | .Select(p => p.ParameterType) |
171 | .ToList(); | 159 | .ToList(); |
172 | 160 | ||
173 | if (mi.ReturnType == typeof(void)) | 161 | if (mi.ReturnType == typeof(void)) |
174 | { | 162 | { |
175 | delegateType = Expression.GetActionType(typeArgs.ToArray()); | 163 | delegateType = Expression.GetActionType(typeArgs.ToArray()); |
176 | } | 164 | } |
177 | else | 165 | else |
178 | { | 166 | { |
179 | typeArgs.Add(mi.ReturnType); | 167 | typeArgs.Add(mi.ReturnType); |
180 | delegateType = Expression.GetFuncType(typeArgs.ToArray()); | 168 | delegateType = Expression.GetFuncType(typeArgs.ToArray()); |
181 | } | 169 | } |
182 | 170 | ||
183 | Delegate fcall; | 171 | Delegate fcall = Delegate.CreateDelegate(delegateType, target, mi); |
184 | if (!(target is Type)) | ||
185 | fcall = Delegate.CreateDelegate(delegateType, target, mi); | ||
186 | else | ||
187 | fcall = Delegate.CreateDelegate(delegateType, (Type)target, mi.Name); | ||
188 | 172 | ||
189 | lock (m_scriptInvocation) | 173 | lock (m_scriptInvocation) |
190 | { | 174 | { |
191 | ParameterInfo[] parameters = fcall.Method.GetParameters(); | 175 | ParameterInfo[] parameters = fcall.Method.GetParameters (); |
192 | if (parameters.Length < 2) // Must have two UUID params | 176 | if (parameters.Length < 2) // Must have two UUID params |
193 | return; | 177 | return; |
194 | 178 | ||
195 | // Hide the first two parameters | 179 | // Hide the first two parameters |
196 | Type[] parmTypes = new Type[parameters.Length - 2]; | 180 | Type[] parmTypes = new Type[parameters.Length - 2]; |
197 | for (int i = 2; i < parameters.Length; i++) | 181 | for (int i = 2 ; i < parameters.Length ; i++) |
198 | parmTypes[i - 2] = parameters[i].ParameterType; | 182 | parmTypes[i - 2] = parameters[i].ParameterType; |
199 | m_scriptInvocation[fcall.Method.Name] = new ScriptInvocationData(fcall.Method.Name, fcall, parmTypes, fcall.Method.ReturnType); | 183 | m_scriptInvocation[fcall.Method.Name] = new ScriptInvocationData(fcall.Method.Name, fcall, parmTypes, fcall.Method.ReturnType); |
200 | } | 184 | } |
201 | } | 185 | } |
202 | |||
203 | public void RegisterScriptInvocation(Type target, string[] methods) | ||
204 | { | ||
205 | foreach (string method in methods) | ||
206 | { | ||
207 | MethodInfo mi = GetMethodInfoFromType(target, method, false); | ||
208 | if (mi == null) | ||
209 | m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}", method); | ||
210 | else | ||
211 | RegisterScriptInvocation(target, mi); | ||
212 | } | ||
213 | } | ||
214 | |||
215 | public void RegisterScriptInvocations(IRegionModuleBase target) | ||
216 | { | ||
217 | foreach(MethodInfo method in target.GetType().GetMethods( | ||
218 | BindingFlags.Public | BindingFlags.Instance | | ||
219 | BindingFlags.Static)) | ||
220 | { | ||
221 | if(method.GetCustomAttributes( | ||
222 | typeof(ScriptInvocationAttribute), true).Any()) | ||
223 | { | ||
224 | if(method.IsStatic) | ||
225 | RegisterScriptInvocation(target.GetType(), method); | ||
226 | else | ||
227 | RegisterScriptInvocation(target, method); | ||
228 | } | ||
229 | } | ||
230 | } | ||
231 | 186 | ||
232 | public Delegate[] GetScriptInvocationList() | 187 | public Delegate[] GetScriptInvocationList() |
233 | { | 188 | { |
@@ -330,20 +285,6 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms | |||
330 | } | 285 | } |
331 | } | 286 | } |
332 | 287 | ||
333 | public void RegisterConstants(IRegionModuleBase target) | ||
334 | { | ||
335 | foreach (FieldInfo field in target.GetType().GetFields( | ||
336 | BindingFlags.Public | BindingFlags.Static | | ||
337 | BindingFlags.Instance)) | ||
338 | { | ||
339 | if (field.GetCustomAttributes( | ||
340 | typeof(ScriptConstantAttribute), true).Any()) | ||
341 | { | ||
342 | RegisterConstant(field.Name, field.GetValue(target)); | ||
343 | } | ||
344 | } | ||
345 | } | ||
346 | |||
347 | /// <summary> | 288 | /// <summary> |
348 | /// Operation to check for a registered constant | 289 | /// Operation to check for a registered constant |
349 | /// </summary> | 290 | /// </summary> |
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index 3a03101..6c8e2fc 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs | |||
@@ -148,7 +148,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC | |||
148 | OnInstantMessage(this, new GridInstantMessage(m_scene, | 148 | OnInstantMessage(this, new GridInstantMessage(m_scene, |
149 | m_uuid, m_firstname + " " + m_lastname, | 149 | m_uuid, m_firstname + " " + m_lastname, |
150 | target, 0, false, message, | 150 | target, 0, false, message, |
151 | UUID.Zero, false, Position, new byte[0], true)); | 151 | UUID.Zero, false, Position, new byte[0])); |
152 | } | 152 | } |
153 | 153 | ||
154 | public void SendAgentOffline(UUID[] agentIDs) | 154 | public void SendAgentOffline(UUID[] agentIDs) |
@@ -607,15 +607,13 @@ namespace OpenSim.Region.OptionalModules.World.NPC | |||
607 | { | 607 | { |
608 | } | 608 | } |
609 | 609 | ||
610 | public virtual void SendChatMessage( | 610 | public virtual void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName, |
611 | string message, byte type, Vector3 fromPos, string fromName, | 611 | UUID fromAgentID, byte source, byte audible) |
612 | UUID fromAgentID, UUID ownerID, byte source, byte audible) | ||
613 | { | 612 | { |
614 | } | 613 | } |
615 | 614 | ||
616 | public virtual void SendChatMessage( | 615 | public virtual void SendChatMessage(byte[] message, byte type, Vector3 fromPos, string fromName, |
617 | byte[] message, byte type, Vector3 fromPos, string fromName, | 616 | UUID fromAgentID, byte source, byte audible) |
618 | UUID fromAgentID, UUID ownerID, byte source, byte audible) | ||
619 | { | 617 | { |
620 | } | 618 | } |
621 | 619 | ||
@@ -911,13 +909,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC | |||
911 | 909 | ||
912 | public void Close() | 910 | public void Close() |
913 | { | 911 | { |
914 | Close(true, false); | 912 | Close(true); |
915 | } | 913 | } |
916 | 914 | ||
917 | public void Close(bool sendStop, bool force) | 915 | public void Close(bool sendStop) |
918 | { | 916 | { |
919 | // Remove ourselves from the scene | ||
920 | m_scene.RemoveClient(AgentId, false); | ||
921 | } | 917 | } |
922 | 918 | ||
923 | public void Start() | 919 | public void Start() |
diff --git a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs index 52ed846..9179966 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs | |||
@@ -117,12 +117,6 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests | |||
117 | Assert.That(npc, Is.Not.Null); | 117 | Assert.That(npc, Is.Not.Null); |
118 | Assert.That(npc.Appearance.Texture.FaceTextures[8].TextureID, Is.EqualTo(originalFace8TextureId)); | 118 | Assert.That(npc.Appearance.Texture.FaceTextures[8].TextureID, Is.EqualTo(originalFace8TextureId)); |
119 | Assert.That(m_umMod.GetUserName(npc.UUID), Is.EqualTo(string.Format("{0} {1}", npc.Firstname, npc.Lastname))); | 119 | Assert.That(m_umMod.GetUserName(npc.UUID), Is.EqualTo(string.Format("{0} {1}", npc.Firstname, npc.Lastname))); |
120 | |||
121 | IClientAPI client; | ||
122 | Assert.That(m_scene.TryGetClient(npcId, out client), Is.True); | ||
123 | |||
124 | // Have to account for both SP and NPC. | ||
125 | Assert.That(m_scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(2)); | ||
126 | } | 120 | } |
127 | 121 | ||
128 | [Test] | 122 | [Test] |
@@ -142,11 +136,6 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests | |||
142 | ScenePresence deletedNpc = m_scene.GetScenePresence(npcId); | 136 | ScenePresence deletedNpc = m_scene.GetScenePresence(npcId); |
143 | 137 | ||
144 | Assert.That(deletedNpc, Is.Null); | 138 | Assert.That(deletedNpc, Is.Null); |
145 | IClientAPI client; | ||
146 | Assert.That(m_scene.TryGetClient(npcId, out client), Is.False); | ||
147 | |||
148 | // Have to account for SP still present. | ||
149 | Assert.That(m_scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1)); | ||
150 | } | 139 | } |
151 | 140 | ||
152 | [Test] | 141 | [Test] |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs b/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs index 23ef052..683bc51 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs | |||
@@ -32,14 +32,10 @@ using OpenMetaverse; | |||
32 | namespace OpenSim.Region.Physics.BulletSPlugin | 32 | namespace OpenSim.Region.Physics.BulletSPlugin |
33 | { | 33 | { |
34 | 34 | ||
35 | public sealed class BSConstraint6Dof : BSConstraint | 35 | public class BS6DofConstraint : BSConstraint |
36 | { | 36 | { |
37 | private static string LogHeader = "[BULLETSIM 6DOF CONSTRAINT]"; | ||
38 | |||
39 | public override ConstraintType Type { get { return ConstraintType.D6_CONSTRAINT_TYPE; } } | ||
40 | |||
41 | // Create a btGeneric6DofConstraint | 37 | // Create a btGeneric6DofConstraint |
42 | public BSConstraint6Dof(BulletSim world, BulletBody obj1, BulletBody obj2, | 38 | public BS6DofConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, |
43 | Vector3 frame1, Quaternion frame1rot, | 39 | Vector3 frame1, Quaternion frame1rot, |
44 | Vector3 frame2, Quaternion frame2rot, | 40 | Vector3 frame2, Quaternion frame2rot, |
45 | bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) | 41 | bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) |
@@ -48,52 +44,25 @@ public sealed class BSConstraint6Dof : BSConstraint | |||
48 | m_body1 = obj1; | 44 | m_body1 = obj1; |
49 | m_body2 = obj2; | 45 | m_body2 = obj2; |
50 | m_constraint = new BulletConstraint( | 46 | m_constraint = new BulletConstraint( |
51 | BulletSimAPI.Create6DofConstraint2(m_world.ptr, m_body1.ptr, m_body2.ptr, | 47 | BulletSimAPI.Create6DofConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr, |
52 | frame1, frame1rot, | 48 | frame1, frame1rot, |
53 | frame2, frame2rot, | 49 | frame2, frame2rot, |
54 | useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); | 50 | useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); |
55 | m_enabled = true; | 51 | m_enabled = true; |
56 | world.physicsScene.DetailLog("{0},BS6DofConstraint,createFrame,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", | ||
57 | BSScene.DetailLogZero, world.worldID, | ||
58 | obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X")); | ||
59 | } | 52 | } |
60 | 53 | ||
61 | public BSConstraint6Dof(BulletSim world, BulletBody obj1, BulletBody obj2, | 54 | public BS6DofConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, |
62 | Vector3 joinPoint, | 55 | Vector3 joinPoint, |
63 | bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) | 56 | bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) |
64 | { | 57 | { |
65 | m_world = world; | 58 | m_world = world; |
66 | m_body1 = obj1; | 59 | m_body1 = obj1; |
67 | m_body2 = obj2; | 60 | m_body2 = obj2; |
68 | if (obj1.ptr == IntPtr.Zero || obj2.ptr == IntPtr.Zero) | 61 | m_constraint = new BulletConstraint( |
69 | { | 62 | BulletSimAPI.Create6DofConstraintToPoint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr, |
70 | world.physicsScene.DetailLog("{0},BS6DOFConstraint,badBodyPtr,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", | 63 | joinPoint, |
71 | BSScene.DetailLogZero, world.worldID, | 64 | useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); |
72 | obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X")); | 65 | m_enabled = true; |
73 | world.physicsScene.Logger.ErrorFormat("{0} Attempt to build 6DOF constraint with missing bodies: wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", | ||
74 | LogHeader, world.worldID, obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X")); | ||
75 | m_enabled = false; | ||
76 | } | ||
77 | else | ||
78 | { | ||
79 | m_constraint = new BulletConstraint( | ||
80 | BulletSimAPI.Create6DofConstraintToPoint2(m_world.ptr, m_body1.ptr, m_body2.ptr, | ||
81 | joinPoint, | ||
82 | useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); | ||
83 | world.physicsScene.DetailLog("{0},BS6DofConstraint,createMidPoint,wID={1}, csrt={2}, rID={3}, rBody={4}, cID={5}, cBody={6}", | ||
84 | BSScene.DetailLogZero, world.worldID, m_constraint.ptr.ToString("X"), | ||
85 | obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X")); | ||
86 | if (m_constraint.ptr == IntPtr.Zero) | ||
87 | { | ||
88 | world.physicsScene.Logger.ErrorFormat("{0} Failed creation of 6Dof constraint. rootID={1}, childID={2}", | ||
89 | LogHeader, obj1.ID, obj2.ID); | ||
90 | m_enabled = false; | ||
91 | } | ||
92 | else | ||
93 | { | ||
94 | m_enabled = true; | ||
95 | } | ||
96 | } | ||
97 | } | 66 | } |
98 | 67 | ||
99 | public bool SetFrames(Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot) | 68 | public bool SetFrames(Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot) |
@@ -101,7 +70,7 @@ public sealed class BSConstraint6Dof : BSConstraint | |||
101 | bool ret = false; | 70 | bool ret = false; |
102 | if (m_enabled) | 71 | if (m_enabled) |
103 | { | 72 | { |
104 | BulletSimAPI.SetFrames2(m_constraint.ptr, frameA, frameArot, frameB, frameBrot); | 73 | BulletSimAPI.SetFrames2(m_constraint.Ptr, frameA, frameArot, frameB, frameBrot); |
105 | ret = true; | 74 | ret = true; |
106 | } | 75 | } |
107 | return ret; | 76 | return ret; |
@@ -112,9 +81,9 @@ public sealed class BSConstraint6Dof : BSConstraint | |||
112 | bool ret = false; | 81 | bool ret = false; |
113 | if (m_enabled) | 82 | if (m_enabled) |
114 | { | 83 | { |
115 | BulletSimAPI.SetConstraintParam2(m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL); | 84 | BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL); |
116 | BulletSimAPI.SetConstraintParam2(m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL); | 85 | BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL); |
117 | BulletSimAPI.SetConstraintParam2(m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL); | 86 | BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL); |
118 | ret = true; | 87 | ret = true; |
119 | } | 88 | } |
120 | return ret; | 89 | return ret; |
@@ -125,7 +94,7 @@ public sealed class BSConstraint6Dof : BSConstraint | |||
125 | bool ret = false; | 94 | bool ret = false; |
126 | float onOff = useOffset ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; | 95 | float onOff = useOffset ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; |
127 | if (m_enabled) | 96 | if (m_enabled) |
128 | ret = BulletSimAPI.UseFrameOffset2(m_constraint.ptr, onOff); | 97 | ret = BulletSimAPI.UseFrameOffset2(m_constraint.Ptr, onOff); |
129 | return ret; | 98 | return ret; |
130 | } | 99 | } |
131 | 100 | ||
@@ -134,11 +103,7 @@ public sealed class BSConstraint6Dof : BSConstraint | |||
134 | bool ret = false; | 103 | bool ret = false; |
135 | float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; | 104 | float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; |
136 | if (m_enabled) | 105 | if (m_enabled) |
137 | { | 106 | ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.Ptr, onOff, targetVelocity, maxMotorForce); |
138 | ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.ptr, onOff, targetVelocity, maxMotorForce); | ||
139 | m_world.physicsScene.DetailLog("{0},BS6DOFConstraint,TransLimitMotor,enable={1},vel={2},maxForce={3}", | ||
140 | BSScene.DetailLogZero, enable, targetVelocity, maxMotorForce); | ||
141 | } | ||
142 | return ret; | 107 | return ret; |
143 | } | 108 | } |
144 | 109 | ||
@@ -146,7 +111,7 @@ public sealed class BSConstraint6Dof : BSConstraint | |||
146 | { | 111 | { |
147 | bool ret = false; | 112 | bool ret = false; |
148 | if (m_enabled) | 113 | if (m_enabled) |
149 | ret = BulletSimAPI.SetBreakingImpulseThreshold2(m_constraint.ptr, threshold); | 114 | ret = BulletSimAPI.SetBreakingImpulseThreshold2(m_constraint.Ptr, threshold); |
150 | return ret; | 115 | return ret; |
151 | } | 116 | } |
152 | } | 117 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 2a5397e..e2f7af9 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | |||
@@ -28,48 +28,62 @@ using System; | |||
28 | using System.Collections.Generic; | 28 | using System.Collections.Generic; |
29 | using System.Reflection; | 29 | using System.Reflection; |
30 | using log4net; | 30 | using log4net; |
31 | using OMV = OpenMetaverse; | 31 | using OpenMetaverse; |
32 | using OpenSim.Framework; | 32 | using OpenSim.Framework; |
33 | using OpenSim.Region.Physics.Manager; | 33 | using OpenSim.Region.Physics.Manager; |
34 | 34 | ||
35 | namespace OpenSim.Region.Physics.BulletSPlugin | 35 | namespace OpenSim.Region.Physics.BulletSPlugin |
36 | { | 36 | { |
37 | public sealed class BSCharacter : BSPhysObject | 37 | public class BSCharacter : PhysicsActor |
38 | { | 38 | { |
39 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 39 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
40 | private static readonly string LogHeader = "[BULLETS CHAR]"; | 40 | private static readonly string LogHeader = "[BULLETS CHAR]"; |
41 | 41 | ||
42 | private BSScene _scene; | ||
43 | public BSScene Scene { get { return _scene; } } | ||
44 | private String _avName; | ||
42 | // private bool _stopped; | 45 | // private bool _stopped; |
43 | private OMV.Vector3 _size; | 46 | private Vector3 _size; |
47 | private Vector3 _scale; | ||
48 | private PrimitiveBaseShape _pbs; | ||
49 | private uint _localID = 0; | ||
44 | private bool _grabbed; | 50 | private bool _grabbed; |
45 | private bool _selected; | 51 | private bool _selected; |
46 | private OMV.Vector3 _position; | 52 | private Vector3 _position; |
47 | private float _mass; | 53 | private float _mass; |
48 | private float _avatarDensity; | 54 | public float _density; |
49 | private float _avatarVolume; | 55 | public float _avatarVolume; |
50 | private OMV.Vector3 _force; | 56 | private Vector3 _force; |
51 | private OMV.Vector3 _velocity; | 57 | private Vector3 _velocity; |
52 | private OMV.Vector3 _torque; | 58 | private Vector3 _torque; |
53 | private float _collisionScore; | 59 | private float _collisionScore; |
54 | private OMV.Vector3 _acceleration; | 60 | private Vector3 _acceleration; |
55 | private OMV.Quaternion _orientation; | 61 | private Quaternion _orientation; |
56 | private int _physicsActorType; | 62 | private int _physicsActorType; |
57 | private bool _isPhysical; | 63 | private bool _isPhysical; |
58 | private bool _flying; | 64 | private bool _flying; |
59 | private bool _setAlwaysRun; | 65 | private bool _setAlwaysRun; |
60 | private bool _throttleUpdates; | 66 | private bool _throttleUpdates; |
61 | private bool _isColliding; | 67 | private bool _isColliding; |
68 | private long _collidingStep; | ||
69 | private bool _collidingGround; | ||
70 | private long _collidingGroundStep; | ||
62 | private bool _collidingObj; | 71 | private bool _collidingObj; |
63 | private bool _floatOnWater; | 72 | private bool _floatOnWater; |
64 | private OMV.Vector3 _rotationalVelocity; | 73 | private Vector3 _rotationalVelocity; |
65 | private bool _kinematic; | 74 | private bool _kinematic; |
66 | private float _buoyancy; | 75 | private float _buoyancy; |
67 | 76 | ||
68 | // The friction and velocity of the avatar is modified depending on whether walking or not. | 77 | private BulletBody m_body; |
69 | private OMV.Vector3 _appliedVelocity; // the last velocity applied to the avatar | 78 | public BulletBody Body { |
70 | private float _currentFriction; // the friction currently being used (changed by setVelocity). | 79 | get { return m_body; } |
80 | set { m_body = value; } | ||
81 | } | ||
82 | |||
83 | private int _subscribedEventsMs = 0; | ||
84 | private int _nextCollisionOkTime = 0; | ||
71 | 85 | ||
72 | private OMV.Vector3 _PIDTarget; | 86 | private Vector3 _PIDTarget; |
73 | private bool _usePID; | 87 | private bool _usePID; |
74 | private float _PIDTau; | 88 | private float _PIDTau; |
75 | private bool _useHoverPID; | 89 | private bool _useHoverPID; |
@@ -77,507 +91,332 @@ public sealed class BSCharacter : BSPhysObject | |||
77 | private PIDHoverType _PIDHoverType; | 91 | private PIDHoverType _PIDHoverType; |
78 | private float _PIDHoverTao; | 92 | private float _PIDHoverTao; |
79 | 93 | ||
80 | public BSCharacter(uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, bool isFlying) | 94 | public BSCharacter(uint localID, String avName, BSScene parent_scene, Vector3 pos, Vector3 size, bool isFlying) |
81 | { | 95 | { |
82 | base.BaseInitialize(parent_scene, localID, avName, "BSCharacter"); | 96 | _localID = localID; |
83 | _physicsActorType = (int)ActorTypes.Agent; | 97 | _avName = avName; |
98 | _scene = parent_scene; | ||
84 | _position = pos; | 99 | _position = pos; |
85 | _size = size; | 100 | _size = size; |
86 | _flying = isFlying; | 101 | _flying = isFlying; |
87 | _orientation = OMV.Quaternion.Identity; | 102 | _orientation = Quaternion.Identity; |
88 | _velocity = OMV.Vector3.Zero; | 103 | _velocity = Vector3.Zero; |
89 | _appliedVelocity = OMV.Vector3.Zero; | ||
90 | _buoyancy = ComputeBuoyancyFromFlying(isFlying); | 104 | _buoyancy = ComputeBuoyancyFromFlying(isFlying); |
91 | _currentFriction = PhysicsScene.Params.avatarStandingFriction; | ||
92 | _avatarDensity = PhysicsScene.Params.avatarDensity; | ||
93 | |||
94 | // The dimensions of the avatar capsule are kept in the scale. | 105 | // The dimensions of the avatar capsule are kept in the scale. |
95 | // Physics creates a unit capsule which is scaled by the physics engine. | 106 | // Physics creates a unit capsule which is scaled by the physics engine. |
96 | ComputeAvatarScale(_size); | 107 | _scale = new Vector3(_scene.Params.avatarCapsuleRadius, _scene.Params.avatarCapsuleRadius, size.Z); |
97 | // set _avatarVolume and _mass based on capsule size, _density and Scale | 108 | _density = _scene.Params.avatarDensity; |
98 | ComputeAvatarVolumeAndMass(); | 109 | ComputeAvatarVolumeAndMass(); // set _avatarVolume and _mass based on capsule size, _density and _scale |
99 | DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}", | 110 | |
100 | LocalID, _size, Scale, _avatarDensity, _avatarVolume, RawMass); | 111 | ShapeData shapeData = new ShapeData(); |
112 | shapeData.ID = _localID; | ||
113 | shapeData.Type = ShapeData.PhysicsShapeType.SHAPE_AVATAR; | ||
114 | shapeData.Position = _position; | ||
115 | shapeData.Rotation = _orientation; | ||
116 | shapeData.Velocity = _velocity; | ||
117 | shapeData.Scale = _scale; | ||
118 | shapeData.Mass = _mass; | ||
119 | shapeData.Buoyancy = _buoyancy; | ||
120 | shapeData.Static = ShapeData.numericFalse; | ||
121 | shapeData.Friction = _scene.Params.avatarFriction; | ||
122 | shapeData.Restitution = _scene.Params.avatarRestitution; | ||
101 | 123 | ||
102 | // do actual create at taint time | 124 | // do actual create at taint time |
103 | PhysicsScene.TaintedObject("BSCharacter.create", delegate() | 125 | _scene.TaintedObject("BSCharacter.create", delegate() |
104 | { | 126 | { |
105 | DetailLog("{0},BSCharacter.create,taint", LocalID); | 127 | BulletSimAPI.CreateObject(parent_scene.WorldID, shapeData); |
106 | // New body and shape into BSBody and BSShape | ||
107 | PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this, null, null); | ||
108 | 128 | ||
109 | SetPhysicalProperties(); | 129 | m_body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); |
130 | // avatars get all collisions no matter what | ||
131 | BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); | ||
110 | }); | 132 | }); |
133 | |||
111 | return; | 134 | return; |
112 | } | 135 | } |
113 | 136 | ||
114 | // called when this character is being destroyed and the resources should be released | 137 | // called when this character is being destroyed and the resources should be released |
115 | public override void Destroy() | 138 | public void Destroy() |
116 | { | 139 | { |
117 | DetailLog("{0},BSCharacter.Destroy", LocalID); | 140 | // DetailLog("{0},BSCharacter.Destroy", LocalID); |
118 | PhysicsScene.TaintedObject("BSCharacter.destroy", delegate() | 141 | _scene.TaintedObject("BSCharacter.destroy", delegate() |
119 | { | 142 | { |
120 | PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null); | 143 | BulletSimAPI.DestroyObject(_scene.WorldID, _localID); |
121 | PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null); | ||
122 | }); | 144 | }); |
123 | } | 145 | } |
124 | 146 | ||
125 | private void SetPhysicalProperties() | ||
126 | { | ||
127 | BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, PhysBody.ptr); | ||
128 | |||
129 | ZeroMotion(); | ||
130 | ForcePosition = _position; | ||
131 | // Set the velocity and compute the proper friction | ||
132 | ForceVelocity = _velocity; | ||
133 | |||
134 | BulletSimAPI.SetRestitution2(PhysBody.ptr, PhysicsScene.Params.avatarRestitution); | ||
135 | BulletSimAPI.SetMargin2(PhysShape.ptr, PhysicsScene.Params.collisionMargin); | ||
136 | BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale); | ||
137 | BulletSimAPI.SetContactProcessingThreshold2(PhysBody.ptr, PhysicsScene.Params.contactProcessingThreshold); | ||
138 | if (PhysicsScene.Params.ccdMotionThreshold > 0f) | ||
139 | { | ||
140 | BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, PhysicsScene.Params.ccdMotionThreshold); | ||
141 | BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); | ||
142 | } | ||
143 | |||
144 | UpdatePhysicalMassProperties(RawMass); | ||
145 | |||
146 | // Make so capsule does not fall over | ||
147 | BulletSimAPI.SetAngularFactorV2(PhysBody.ptr, OMV.Vector3.Zero); | ||
148 | |||
149 | BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_CHARACTER_OBJECT); | ||
150 | |||
151 | BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, PhysBody.ptr); | ||
152 | |||
153 | // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ACTIVE_TAG); | ||
154 | BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.DISABLE_DEACTIVATION); | ||
155 | BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr); | ||
156 | |||
157 | // Do this after the object has been added to the world | ||
158 | BulletSimAPI.SetCollisionFilterMask2(PhysBody.ptr, | ||
159 | (uint)CollisionFilterGroups.AvatarFilter, | ||
160 | (uint)CollisionFilterGroups.AvatarMask); | ||
161 | } | ||
162 | |||
163 | public override void RequestPhysicsterseUpdate() | 147 | public override void RequestPhysicsterseUpdate() |
164 | { | 148 | { |
165 | base.RequestPhysicsterseUpdate(); | 149 | base.RequestPhysicsterseUpdate(); |
166 | } | 150 | } |
167 | // No one calls this method so I don't know what it could possibly mean | 151 | // No one calls this method so I don't know what it could possibly mean |
168 | public override bool Stopped { get { return false; } } | 152 | public override bool Stopped { |
169 | 153 | get { return false; } | |
170 | public override OMV.Vector3 Size { | 154 | } |
155 | public override Vector3 Size { | ||
171 | get | 156 | get |
172 | { | 157 | { |
173 | // Avatar capsule size is kept in the scale parameter. | 158 | // Avatar capsule size is kept in the scale parameter. |
174 | // return _size; | 159 | return new Vector3(_scale.X * 2, _scale.Y * 2, _scale.Z); |
175 | return new OMV.Vector3(Scale.X * 2f, Scale.Y * 2f, Scale.Z); | ||
176 | } | 160 | } |
177 | 161 | ||
178 | set { | 162 | set { |
179 | // When an avatar's size is set, only the height is changed. | 163 | // When an avatar's size is set, only the height is changed |
164 | // and that really only depends on the radius. | ||
180 | _size = value; | 165 | _size = value; |
181 | ComputeAvatarScale(_size); | 166 | _scale.Z = (_size.Z * 1.15f) - (_scale.X + _scale.Y); |
167 | |||
168 | // TODO: something has to be done with the avatar's vertical position | ||
169 | |||
182 | ComputeAvatarVolumeAndMass(); | 170 | ComputeAvatarVolumeAndMass(); |
183 | DetailLog("{0},BSCharacter.setSize,call,scale={1},density={2},volume={3},mass={4}", | ||
184 | LocalID, Scale, _avatarDensity, _avatarVolume, RawMass); | ||
185 | 171 | ||
186 | PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() | 172 | _scene.TaintedObject("BSCharacter.setSize", delegate() |
187 | { | 173 | { |
188 | BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale); | 174 | BulletSimAPI.SetObjectScaleMass(_scene.WorldID, LocalID, _scale, _mass, true); |
189 | UpdatePhysicalMassProperties(RawMass); | ||
190 | }); | 175 | }); |
191 | 176 | ||
192 | } | 177 | } |
193 | } | 178 | } |
194 | 179 | public override PrimitiveBaseShape Shape { | |
195 | public override OMV.Vector3 Scale { get; set; } | 180 | set { _pbs = value; |
196 | 181 | } | |
197 | public override PrimitiveBaseShape Shape | ||
198 | { | ||
199 | set { BaseShape = value; } | ||
200 | } | 182 | } |
201 | // I want the physics engine to make an avatar capsule | 183 | public override uint LocalID { |
202 | public override ShapeData.PhysicsShapeType PreferredPhysicalShape | 184 | set { _localID = value; |
203 | { | 185 | } |
204 | get {return ShapeData.PhysicsShapeType.SHAPE_AVATAR; } | 186 | get { return _localID; } |
205 | } | 187 | } |
206 | 188 | public override bool Grabbed { | |
207 | public override bool Grabbed { | 189 | set { _grabbed = value; |
208 | set { _grabbed = value; } | 190 | } |
209 | } | 191 | } |
210 | public override bool Selected { | 192 | public override bool Selected { |
211 | set { _selected = value; } | 193 | set { _selected = value; |
194 | } | ||
212 | } | 195 | } |
213 | public override void CrossingFailure() { return; } | 196 | public override void CrossingFailure() { return; } |
214 | public override void link(PhysicsActor obj) { return; } | 197 | public override void link(PhysicsActor obj) { return; } |
215 | public override void delink() { return; } | 198 | public override void delink() { return; } |
199 | public override void LockAngularMotion(Vector3 axis) { return; } | ||
216 | 200 | ||
217 | // Set motion values to zero. | 201 | public override Vector3 Position { |
218 | // Do it to the properties so the values get set in the physics engine. | ||
219 | // Push the setting of the values to the viewer. | ||
220 | // Called at taint time! | ||
221 | public override void ZeroMotion() | ||
222 | { | ||
223 | _velocity = OMV.Vector3.Zero; | ||
224 | _acceleration = OMV.Vector3.Zero; | ||
225 | _rotationalVelocity = OMV.Vector3.Zero; | ||
226 | |||
227 | // Zero some other properties directly into the physics engine | ||
228 | BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, OMV.Vector3.Zero); | ||
229 | BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero); | ||
230 | BulletSimAPI.SetInterpolationVelocity2(PhysBody.ptr, OMV.Vector3.Zero, OMV.Vector3.Zero); | ||
231 | BulletSimAPI.ClearForces2(PhysBody.ptr); | ||
232 | } | ||
233 | |||
234 | public override void LockAngularMotion(OMV.Vector3 axis) { return; } | ||
235 | |||
236 | public override OMV.Vector3 RawPosition | ||
237 | { | ||
238 | get { return _position; } | ||
239 | set { _position = value; } | ||
240 | } | ||
241 | public override OMV.Vector3 Position { | ||
242 | get { | 202 | get { |
243 | // Don't refetch the position because this function is called a zillion times | 203 | // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); |
244 | // _position = BulletSimAPI.GetObjectPosition2(Scene.World.ptr, LocalID); | 204 | return _position; |
245 | return _position; | 205 | } |
246 | } | ||
247 | set { | 206 | set { |
248 | _position = value; | 207 | _position = value; |
249 | PositionSanityCheck(); | 208 | PositionSanityCheck(); |
250 | 209 | ||
251 | PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate() | 210 | _scene.TaintedObject("BSCharacter.setPosition", delegate() |
252 | { | 211 | { |
253 | DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); | 212 | DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); |
254 | BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); | 213 | BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); |
255 | }); | 214 | }); |
256 | } | 215 | } |
257 | } | ||
258 | public override OMV.Vector3 ForcePosition { | ||
259 | get { | ||
260 | _position = BulletSimAPI.GetPosition2(PhysBody.ptr); | ||
261 | return _position; | ||
262 | } | ||
263 | set { | ||
264 | _position = value; | ||
265 | PositionSanityCheck(); | ||
266 | BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); | ||
267 | } | ||
268 | } | 216 | } |
269 | 217 | ||
270 | |||
271 | // Check that the current position is sane and, if not, modify the position to make it so. | 218 | // Check that the current position is sane and, if not, modify the position to make it so. |
272 | // Check for being below terrain or on water. | 219 | // Check for being below terrain and being out of bounds. |
273 | // Returns 'true' of the position was made sane by some action. | 220 | // Returns 'true' of the position was made sane by some action. |
274 | private bool PositionSanityCheck() | 221 | private bool PositionSanityCheck() |
275 | { | 222 | { |
276 | bool ret = false; | 223 | bool ret = false; |
277 | 224 | ||
278 | // If below the ground, move the avatar up | 225 | // If below the ground, move the avatar up |
279 | float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); | 226 | float terrainHeight = Scene.GetTerrainHeightAtXYZ(_position); |
280 | if (Position.Z < terrainHeight) | 227 | if (_position.Z < terrainHeight) |
281 | { | 228 | { |
282 | DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); | 229 | DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},orient={2}", LocalID, _position, _orientation); |
283 | _position.Z = terrainHeight + 2.0f; | 230 | _position.Z = terrainHeight + 2.0f; |
284 | ret = true; | 231 | ret = true; |
285 | } | 232 | } |
286 | if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) | ||
287 | { | ||
288 | float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position); | ||
289 | if (Position.Z < waterHeight) | ||
290 | { | ||
291 | _position.Z = waterHeight; | ||
292 | ret = true; | ||
293 | } | ||
294 | } | ||
295 | 233 | ||
296 | // TODO: check for out of bounds | 234 | // TODO: check for out of bounds |
297 | return ret; | ||
298 | } | ||
299 | 235 | ||
300 | // A version of the sanity check that also makes sure a new position value is | ||
301 | // pushed back to the physics engine. This routine would be used by anyone | ||
302 | // who is not already pushing the value. | ||
303 | private bool PositionSanityCheck(bool inTaintTime) | ||
304 | { | ||
305 | bool ret = false; | ||
306 | if (PositionSanityCheck()) | ||
307 | { | ||
308 | // The new position value must be pushed into the physics engine but we can't | ||
309 | // just assign to "Position" because of potential call loops. | ||
310 | PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.PositionSanityCheck", delegate() | ||
311 | { | ||
312 | DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); | ||
313 | BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); | ||
314 | }); | ||
315 | ret = true; | ||
316 | } | ||
317 | return ret; | 236 | return ret; |
318 | } | 237 | } |
319 | 238 | ||
320 | public override float Mass { get { return _mass; } } | 239 | public override float Mass { |
321 | 240 | get { | |
322 | // used when we only want this prim's mass and not the linkset thing | 241 | return _mass; |
323 | public override float RawMass { | 242 | } |
324 | get {return _mass; } | ||
325 | } | ||
326 | public override void UpdatePhysicalMassProperties(float physMass) | ||
327 | { | ||
328 | OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(PhysShape.ptr, physMass); | ||
329 | BulletSimAPI.SetMassProps2(PhysBody.ptr, physMass, localInertia); | ||
330 | } | 243 | } |
331 | 244 | public override Vector3 Force { | |
332 | public override OMV.Vector3 Force { | 245 | get { return _force; } |
333 | get { return _force; } | ||
334 | set { | 246 | set { |
335 | _force = value; | 247 | _force = value; |
336 | // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force); | 248 | // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force); |
337 | PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate() | 249 | Scene.TaintedObject("BSCharacter.SetForce", delegate() |
338 | { | 250 | { |
339 | DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force); | 251 | DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force); |
340 | BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force); | 252 | BulletSimAPI.SetObjectForce(Scene.WorldID, LocalID, _force); |
341 | }); | 253 | }); |
342 | } | 254 | } |
343 | } | 255 | } |
344 | 256 | ||
345 | // Avatars don't do vehicles | 257 | public override int VehicleType { |
346 | public override int VehicleType { get { return (int)Vehicle.TYPE_NONE; } set { return; } } | 258 | get { return 0; } |
259 | set { return; } | ||
260 | } | ||
347 | public override void VehicleFloatParam(int param, float value) { } | 261 | public override void VehicleFloatParam(int param, float value) { } |
348 | public override void VehicleVectorParam(int param, OMV.Vector3 value) {} | 262 | public override void VehicleVectorParam(int param, Vector3 value) {} |
349 | public override void VehicleRotationParam(int param, OMV.Quaternion rotation) { } | 263 | public override void VehicleRotationParam(int param, Quaternion rotation) { } |
350 | public override void VehicleFlags(int param, bool remove) { } | 264 | public override void VehicleFlags(int param, bool remove) { } |
351 | 265 | ||
352 | // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more | 266 | // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more |
353 | public override void SetVolumeDetect(int param) { return; } | 267 | public override void SetVolumeDetect(int param) { return; } |
354 | 268 | ||
355 | public override OMV.Vector3 GeometricCenter { get { return OMV.Vector3.Zero; } } | 269 | public override Vector3 GeometricCenter { get { return Vector3.Zero; } } |
356 | public override OMV.Vector3 CenterOfMass { get { return OMV.Vector3.Zero; } } | 270 | public override Vector3 CenterOfMass { get { return Vector3.Zero; } } |
357 | public override OMV.Vector3 Velocity { | 271 | public override Vector3 Velocity { |
358 | get { return _velocity; } | 272 | get { return _velocity; } |
359 | set { | 273 | set { |
360 | _velocity = value; | 274 | _velocity = value; |
361 | // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity); | 275 | // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity); |
362 | PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate() | 276 | _scene.TaintedObject("BSCharacter.setVelocity", delegate() |
363 | { | 277 | { |
364 | DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity); | 278 | DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity); |
365 | ForceVelocity = _velocity; | 279 | BulletSimAPI.SetObjectVelocity(_scene.WorldID, _localID, _velocity); |
366 | }); | 280 | }); |
367 | } | 281 | } |
368 | } | ||
369 | public override OMV.Vector3 ForceVelocity { | ||
370 | get { return _velocity; } | ||
371 | set { | ||
372 | // Depending on whether the avatar is moving or not, change the friction | ||
373 | // to keep the avatar from slipping around | ||
374 | if (_velocity.Length() == 0) | ||
375 | { | ||
376 | if (_currentFriction != PhysicsScene.Params.avatarStandingFriction) | ||
377 | { | ||
378 | _currentFriction = PhysicsScene.Params.avatarStandingFriction; | ||
379 | BulletSimAPI.SetFriction2(PhysBody.ptr, _currentFriction); | ||
380 | } | ||
381 | } | ||
382 | else | ||
383 | { | ||
384 | if (_currentFriction != PhysicsScene.Params.avatarFriction) | ||
385 | { | ||
386 | _currentFriction = PhysicsScene.Params.avatarFriction; | ||
387 | BulletSimAPI.SetFriction2(PhysBody.ptr, _currentFriction); | ||
388 | } | ||
389 | } | ||
390 | _velocity = value; | ||
391 | // Remember the set velocity so we can suppress the reduction by friction, ... | ||
392 | _appliedVelocity = value; | ||
393 | |||
394 | BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity); | ||
395 | BulletSimAPI.Activate2(PhysBody.ptr, true); | ||
396 | } | ||
397 | } | 282 | } |
398 | public override OMV.Vector3 Torque { | 283 | public override Vector3 Torque { |
399 | get { return _torque; } | 284 | get { return _torque; } |
400 | set { _torque = value; | 285 | set { _torque = value; |
401 | } | 286 | } |
402 | } | 287 | } |
403 | public override float CollisionScore { | 288 | public override float CollisionScore { |
404 | get { return _collisionScore; } | 289 | get { return _collisionScore; } |
405 | set { _collisionScore = value; | 290 | set { _collisionScore = value; |
406 | } | 291 | } |
407 | } | 292 | } |
408 | public override OMV.Vector3 Acceleration { | 293 | public override Vector3 Acceleration { |
409 | get { return _acceleration; } | 294 | get { return _acceleration; } |
410 | set { _acceleration = value; } | 295 | set { _acceleration = value; } |
411 | } | 296 | } |
412 | public override OMV.Quaternion RawOrientation | 297 | public override Quaternion Orientation { |
413 | { | 298 | get { return _orientation; } |
414 | get { return _orientation; } | ||
415 | set { _orientation = value; } | ||
416 | } | ||
417 | public override OMV.Quaternion Orientation { | ||
418 | get { return _orientation; } | ||
419 | set { | 299 | set { |
420 | _orientation = value; | 300 | _orientation = value; |
421 | // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation); | 301 | // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation); |
422 | PhysicsScene.TaintedObject("BSCharacter.setOrientation", delegate() | 302 | _scene.TaintedObject("BSCharacter.setOrientation", delegate() |
423 | { | 303 | { |
424 | // _position = BulletSimAPI.GetPosition2(BSBody.ptr); | 304 | // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); |
425 | BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); | 305 | BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); |
426 | }); | 306 | }); |
427 | } | 307 | } |
428 | } | 308 | } |
429 | // Go directly to Bullet to get/set the value. | 309 | public override int PhysicsActorType { |
430 | public override OMV.Quaternion ForceOrientation | 310 | get { return _physicsActorType; } |
431 | { | 311 | set { _physicsActorType = value; |
432 | get | 312 | } |
433 | { | ||
434 | _orientation = BulletSimAPI.GetOrientation2(PhysBody.ptr); | ||
435 | return _orientation; | ||
436 | } | ||
437 | set | ||
438 | { | ||
439 | _orientation = value; | ||
440 | BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); | ||
441 | } | ||
442 | } | ||
443 | public override int PhysicsActorType { | ||
444 | get { return _physicsActorType; } | ||
445 | set { _physicsActorType = value; | ||
446 | } | ||
447 | } | 313 | } |
448 | public override bool IsPhysical { | 314 | public override bool IsPhysical { |
449 | get { return _isPhysical; } | 315 | get { return _isPhysical; } |
450 | set { _isPhysical = value; | 316 | set { _isPhysical = value; |
451 | } | 317 | } |
452 | } | ||
453 | public override bool IsSolid { | ||
454 | get { return true; } | ||
455 | } | 318 | } |
456 | public override bool IsStatic { | 319 | public override bool Flying { |
457 | get { return false; } | 320 | get { return _flying; } |
458 | } | ||
459 | public override bool Flying { | ||
460 | get { return _flying; } | ||
461 | set { | 321 | set { |
462 | _flying = value; | 322 | if (_flying != value) |
463 | // simulate flying by changing the effect of gravity | 323 | { |
464 | Buoyancy = ComputeBuoyancyFromFlying(_flying); | 324 | _flying = value; |
465 | } | 325 | // simulate flying by changing the effect of gravity |
326 | this.Buoyancy = ComputeBuoyancyFromFlying(_flying); | ||
327 | } | ||
328 | } | ||
466 | } | 329 | } |
467 | // Flying is implimented by changing the avatar's buoyancy. | ||
468 | // Would this be done better with a vehicle type? | ||
469 | private float ComputeBuoyancyFromFlying(bool ifFlying) { | 330 | private float ComputeBuoyancyFromFlying(bool ifFlying) { |
470 | return ifFlying ? 1f : 0f; | 331 | return ifFlying ? 1f : 0f; |
471 | } | 332 | } |
472 | public override bool | 333 | public override bool |
473 | SetAlwaysRun { | 334 | SetAlwaysRun { |
474 | get { return _setAlwaysRun; } | 335 | get { return _setAlwaysRun; } |
475 | set { _setAlwaysRun = value; } | 336 | set { _setAlwaysRun = value; } |
476 | } | 337 | } |
477 | public override bool ThrottleUpdates { | 338 | public override bool ThrottleUpdates { |
478 | get { return _throttleUpdates; } | 339 | get { return _throttleUpdates; } |
479 | set { _throttleUpdates = value; } | 340 | set { _throttleUpdates = value; } |
480 | } | 341 | } |
481 | public override bool IsColliding { | 342 | public override bool IsColliding { |
482 | get { return (CollidingStep == PhysicsScene.SimulationStep); } | 343 | get { return (_collidingStep == _scene.SimulationStep); } |
483 | set { _isColliding = value; } | 344 | set { _isColliding = value; } |
484 | } | 345 | } |
485 | public override bool CollidingGround { | 346 | public override bool CollidingGround { |
486 | get { return (CollidingGroundStep == PhysicsScene.SimulationStep); } | 347 | get { return (_collidingGroundStep == _scene.SimulationStep); } |
487 | set { CollidingGround = value; } | 348 | set { _collidingGround = value; } |
488 | } | ||
489 | public override bool CollidingObj { | ||
490 | get { return _collidingObj; } | ||
491 | set { _collidingObj = value; } | ||
492 | } | 349 | } |
493 | public override bool FloatOnWater { | 350 | public override bool CollidingObj { |
494 | set { | 351 | get { return _collidingObj; } |
495 | _floatOnWater = value; | 352 | set { _collidingObj = value; } |
496 | PhysicsScene.TaintedObject("BSCharacter.setFloatOnWater", delegate() | ||
497 | { | ||
498 | if (_floatOnWater) | ||
499 | CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); | ||
500 | else | ||
501 | CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); | ||
502 | }); | ||
503 | } | ||
504 | } | 353 | } |
505 | public override OMV.Vector3 RotationalVelocity { | 354 | public override bool FloatOnWater { |
506 | get { return _rotationalVelocity; } | 355 | set { _floatOnWater = value; } |
507 | set { _rotationalVelocity = value; } | ||
508 | } | 356 | } |
509 | public override OMV.Vector3 ForceRotationalVelocity { | 357 | public override Vector3 RotationalVelocity { |
510 | get { return _rotationalVelocity; } | 358 | get { return _rotationalVelocity; } |
511 | set { _rotationalVelocity = value; } | 359 | set { _rotationalVelocity = value; } |
512 | } | 360 | } |
513 | public override bool Kinematic { | 361 | public override bool Kinematic { |
514 | get { return _kinematic; } | 362 | get { return _kinematic; } |
515 | set { _kinematic = value; } | 363 | set { _kinematic = value; } |
516 | } | 364 | } |
517 | // neg=fall quickly, 0=1g, 1=0g, pos=float up | 365 | // neg=fall quickly, 0=1g, 1=0g, pos=float up |
518 | public override float Buoyancy { | 366 | public override float Buoyancy { |
519 | get { return _buoyancy; } | 367 | get { return _buoyancy; } |
520 | set { _buoyancy = value; | 368 | set { _buoyancy = value; |
521 | PhysicsScene.TaintedObject("BSCharacter.setBuoyancy", delegate() | 369 | _scene.TaintedObject("BSCharacter.setBuoyancy", delegate() |
522 | { | 370 | { |
523 | DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy); | 371 | DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy); |
524 | ForceBuoyancy = _buoyancy; | 372 | BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, LocalID, _buoyancy); |
525 | }); | 373 | }); |
526 | } | 374 | } |
527 | } | ||
528 | public override float ForceBuoyancy { | ||
529 | get { return _buoyancy; } | ||
530 | set { _buoyancy = value; | ||
531 | DetailLog("{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); | ||
532 | // Buoyancy is faked by changing the gravity applied to the object | ||
533 | float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); | ||
534 | BulletSimAPI.SetGravity2(PhysBody.ptr, new OMV.Vector3(0f, 0f, grav)); | ||
535 | } | ||
536 | } | 375 | } |
537 | 376 | ||
538 | // Used for MoveTo | 377 | // Used for MoveTo |
539 | public override OMV.Vector3 PIDTarget { | 378 | public override Vector3 PIDTarget { |
540 | set { _PIDTarget = value; } | 379 | set { _PIDTarget = value; } |
541 | } | 380 | } |
542 | public override bool PIDActive { | 381 | public override bool PIDActive { |
543 | set { _usePID = value; } | 382 | set { _usePID = value; } |
544 | } | 383 | } |
545 | public override float PIDTau { | 384 | public override float PIDTau { |
546 | set { _PIDTau = value; } | 385 | set { _PIDTau = value; } |
547 | } | 386 | } |
548 | 387 | ||
549 | // Used for llSetHoverHeight and maybe vehicle height | 388 | // Used for llSetHoverHeight and maybe vehicle height |
550 | // Hover Height will override MoveTo target's Z | 389 | // Hover Height will override MoveTo target's Z |
551 | public override bool PIDHoverActive { | 390 | public override bool PIDHoverActive { |
552 | set { _useHoverPID = value; } | 391 | set { _useHoverPID = value; } |
553 | } | 392 | } |
554 | public override float PIDHoverHeight { | 393 | public override float PIDHoverHeight { |
555 | set { _PIDHoverHeight = value; } | 394 | set { _PIDHoverHeight = value; } |
556 | } | 395 | } |
557 | public override PIDHoverType PIDHoverType { | 396 | public override PIDHoverType PIDHoverType { |
558 | set { _PIDHoverType = value; } | 397 | set { _PIDHoverType = value; } |
559 | } | 398 | } |
560 | public override float PIDHoverTau { | 399 | public override float PIDHoverTau { |
561 | set { _PIDHoverTao = value; } | 400 | set { _PIDHoverTao = value; } |
562 | } | 401 | } |
563 | 402 | ||
564 | // For RotLookAt | 403 | // For RotLookAt |
565 | public override OMV.Quaternion APIDTarget { set { return; } } | 404 | public override Quaternion APIDTarget { set { return; } } |
566 | public override bool APIDActive { set { return; } } | 405 | public override bool APIDActive { set { return; } } |
567 | public override float APIDStrength { set { return; } } | 406 | public override float APIDStrength { set { return; } } |
568 | public override float APIDDamping { set { return; } } | 407 | public override float APIDDamping { set { return; } } |
569 | 408 | ||
570 | public override void AddForce(OMV.Vector3 force, bool pushforce) { | 409 | public override void AddForce(Vector3 force, bool pushforce) { |
571 | if (force.IsFinite()) | 410 | if (force.IsFinite()) |
572 | { | 411 | { |
573 | _force.X += force.X; | 412 | _force.X += force.X; |
574 | _force.Y += force.Y; | 413 | _force.Y += force.Y; |
575 | _force.Z += force.Z; | 414 | _force.Z += force.Z; |
576 | // m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force); | 415 | // m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force); |
577 | PhysicsScene.TaintedObject("BSCharacter.AddForce", delegate() | 416 | _scene.TaintedObject("BSCharacter.AddForce", delegate() |
578 | { | 417 | { |
579 | DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force); | 418 | DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force); |
580 | BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force); | 419 | BulletSimAPI.AddObjectForce2(Body.Ptr, _force); |
581 | }); | 420 | }); |
582 | } | 421 | } |
583 | else | 422 | else |
@@ -587,75 +426,129 @@ public sealed class BSCharacter : BSPhysObject | |||
587 | //m_lastUpdateSent = false; | 426 | //m_lastUpdateSent = false; |
588 | } | 427 | } |
589 | 428 | ||
590 | public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { | 429 | public override void AddAngularForce(Vector3 force, bool pushforce) { |
591 | } | 430 | } |
592 | public override void SetMomentum(OMV.Vector3 momentum) { | 431 | public override void SetMomentum(Vector3 momentum) { |
593 | } | 432 | } |
594 | 433 | ||
595 | private void ComputeAvatarScale(OMV.Vector3 size) | 434 | // Turn on collision events at a rate no faster than one every the given milliseconds |
596 | { | 435 | public override void SubscribeEvents(int ms) { |
597 | // The 'size' given by the simulator is the mid-point of the avatar | 436 | _subscribedEventsMs = ms; |
598 | // and X and Y are unspecified. | 437 | if (ms > 0) |
599 | 438 | { | |
600 | OMV.Vector3 newScale = OMV.Vector3.Zero; | 439 | // make sure first collision happens |
601 | newScale.X = PhysicsScene.Params.avatarCapsuleRadius; | 440 | _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs; |
602 | newScale.Y = PhysicsScene.Params.avatarCapsuleRadius; | ||
603 | 441 | ||
604 | // From the total height, remove the capsule half spheres that are at each end | 442 | Scene.TaintedObject("BSCharacter.SubscribeEvents", delegate() |
605 | newScale.Z = size.Z- (newScale.X + newScale.Y); | 443 | { |
606 | Scale = newScale; | 444 | BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); |
445 | }); | ||
446 | } | ||
447 | } | ||
448 | // Stop collision events | ||
449 | public override void UnSubscribeEvents() { | ||
450 | _subscribedEventsMs = 0; | ||
451 | // Avatars get all their collision events | ||
452 | // Scene.TaintedObject("BSCharacter.UnSubscribeEvents", delegate() | ||
453 | // { | ||
454 | // BulletSimAPI.RemoveFromCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); | ||
455 | // }); | ||
456 | } | ||
457 | // Return 'true' if someone has subscribed to events | ||
458 | public override bool SubscribedEvents() { | ||
459 | return (_subscribedEventsMs > 0); | ||
607 | } | 460 | } |
608 | 461 | ||
609 | // set _avatarVolume and _mass based on capsule size, _density and Scale | 462 | // set _avatarVolume and _mass based on capsule size, _density and _scale |
610 | private void ComputeAvatarVolumeAndMass() | 463 | private void ComputeAvatarVolumeAndMass() |
611 | { | 464 | { |
612 | _avatarVolume = (float)( | 465 | _avatarVolume = (float)( |
613 | Math.PI | 466 | Math.PI |
614 | * Scale.X | 467 | * _scale.X |
615 | * Scale.Y // the area of capsule cylinder | 468 | * _scale.Y // the area of capsule cylinder |
616 | * Scale.Z // times height of capsule cylinder | 469 | * _scale.Z // times height of capsule cylinder |
617 | + 1.33333333f | 470 | + 1.33333333f |
618 | * Math.PI | 471 | * Math.PI |
619 | * Scale.X | 472 | * _scale.X |
620 | * Math.Min(Scale.X, Scale.Y) | 473 | * Math.Min(_scale.X, _scale.Y) |
621 | * Scale.Y // plus the volume of the capsule end caps | 474 | * _scale.Y // plus the volume of the capsule end caps |
622 | ); | 475 | ); |
623 | _mass = _avatarDensity * _avatarVolume; | 476 | _mass = _density * _avatarVolume; |
624 | } | 477 | } |
625 | 478 | ||
626 | // The physics engine says that properties have updated. Update same and inform | 479 | // The physics engine says that properties have updated. Update same and inform |
627 | // the world that things have changed. | 480 | // the world that things have changed. |
628 | public override void UpdateProperties(EntityProperties entprop) | 481 | public void UpdateProperties(EntityProperties entprop) |
629 | { | 482 | { |
630 | _position = entprop.Position; | 483 | _position = entprop.Position; |
631 | _orientation = entprop.Rotation; | 484 | _orientation = entprop.Rotation; |
632 | _velocity = entprop.Velocity; | 485 | _velocity = entprop.Velocity; |
633 | _acceleration = entprop.Acceleration; | 486 | _acceleration = entprop.Acceleration; |
634 | _rotationalVelocity = entprop.RotationalVelocity; | 487 | _rotationalVelocity = entprop.RotationalVelocity; |
635 | // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. | 488 | // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. |
636 | PositionSanityCheck(true); | 489 | // base.RequestPhysicsterseUpdate(); |
490 | |||
491 | /* | ||
492 | DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", | ||
493 | LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, | ||
494 | entprop.Acceleration, entprop.RotationalVelocity); | ||
495 | */ | ||
496 | } | ||
637 | 497 | ||
638 | // remember the current and last set values | 498 | // Called by the scene when a collision with this object is reported |
639 | LastEntityProperties = CurrentEntityProperties; | 499 | // The collision, if it should be reported to the character, is placed in a collection |
640 | CurrentEntityProperties = entprop; | 500 | // that will later be sent to the simulator when SendCollisions() is called. |
501 | CollisionEventUpdate collisionCollection = null; | ||
502 | public void Collide(uint collidingWith, ActorTypes type, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth) | ||
503 | { | ||
504 | // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith); | ||
641 | 505 | ||
642 | if (entprop.Velocity != LastEntityProperties.Velocity) | 506 | // The following makes IsColliding() and IsCollidingGround() work |
507 | _collidingStep = _scene.SimulationStep; | ||
508 | if (collidingWith == BSScene.TERRAIN_ID || collidingWith == BSScene.GROUNDPLANE_ID) | ||
643 | { | 509 | { |
644 | // Changes in the velocity are suppressed in avatars. | 510 | _collidingGroundStep = _scene.SimulationStep; |
645 | // That's just the way they are defined. | ||
646 | OMV.Vector3 avVel = new OMV.Vector3(_appliedVelocity.X, _appliedVelocity.Y, entprop.Velocity.Z); | ||
647 | _velocity = avVel; | ||
648 | BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, avVel); | ||
649 | } | 511 | } |
512 | // DetailLog("{0},BSCharacter.Collison,call,with={1}", LocalID, collidingWith); | ||
650 | 513 | ||
651 | // Tell the linkset about value changes | 514 | // throttle collisions to the rate specified in the subscription |
652 | Linkset.UpdateProperties(this); | 515 | if (_subscribedEventsMs != 0) { |
516 | int nowTime = _scene.SimulationNowTime; | ||
517 | if (nowTime >= _nextCollisionOkTime) { | ||
518 | _nextCollisionOkTime = nowTime + _subscribedEventsMs; | ||
653 | 519 | ||
654 | // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. | 520 | if (collisionCollection == null) |
655 | // base.RequestPhysicsterseUpdate(); | 521 | collisionCollection = new CollisionEventUpdate(); |
522 | collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); | ||
523 | } | ||
524 | } | ||
525 | } | ||
656 | 526 | ||
657 | DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", | 527 | public void SendCollisions() |
658 | LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); | 528 | { |
529 | /* | ||
530 | if (collisionCollection != null && collisionCollection.Count > 0) | ||
531 | { | ||
532 | base.SendCollisionUpdate(collisionCollection); | ||
533 | collisionCollection = null; | ||
534 | } | ||
535 | */ | ||
536 | // Kludge to make a collision call even if there are no collisions. | ||
537 | // This causes the avatar animation to get updated. | ||
538 | if (collisionCollection == null) | ||
539 | collisionCollection = new CollisionEventUpdate(); | ||
540 | base.SendCollisionUpdate(collisionCollection); | ||
541 | // If there were any collisions in the collection, make sure we don't use the | ||
542 | // same instance next time. | ||
543 | if (collisionCollection.Count > 0) | ||
544 | collisionCollection = null; | ||
545 | // End kludge | ||
546 | } | ||
547 | |||
548 | // Invoke the detailed logger and output something if it's enabled. | ||
549 | private void DetailLog(string msg, params Object[] args) | ||
550 | { | ||
551 | Scene.PhysicsLogging.Write(msg, args); | ||
659 | } | 552 | } |
660 | } | 553 | } |
661 | } | 554 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs index 65fac00..25084d8 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs | |||
@@ -34,20 +34,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
34 | 34 | ||
35 | public abstract class BSConstraint : IDisposable | 35 | public abstract class BSConstraint : IDisposable |
36 | { | 36 | { |
37 | private static string LogHeader = "[BULLETSIM CONSTRAINT]"; | ||
38 | |||
39 | protected BulletSim m_world; | 37 | protected BulletSim m_world; |
40 | protected BulletBody m_body1; | 38 | protected BulletBody m_body1; |
41 | protected BulletBody m_body2; | 39 | protected BulletBody m_body2; |
42 | protected BulletConstraint m_constraint; | 40 | protected BulletConstraint m_constraint; |
43 | protected bool m_enabled = false; | 41 | protected bool m_enabled = false; |
44 | 42 | ||
45 | public BulletBody Body1 { get { return m_body1; } } | ||
46 | public BulletBody Body2 { get { return m_body2; } } | ||
47 | public BulletConstraint Constraint { get { return m_constraint; } } | ||
48 | public abstract ConstraintType Type { get; } | ||
49 | public bool IsEnabled { get { return m_enabled; } } | ||
50 | |||
51 | public BSConstraint() | 43 | public BSConstraint() |
52 | { | 44 | { |
53 | } | 45 | } |
@@ -56,25 +48,22 @@ public abstract class BSConstraint : IDisposable | |||
56 | { | 48 | { |
57 | if (m_enabled) | 49 | if (m_enabled) |
58 | { | 50 | { |
51 | // BulletSimAPI.RemoveConstraint(m_world.ID, m_body1.ID, m_body2.ID); | ||
52 | bool success = BulletSimAPI.DestroyConstraint2(m_world.Ptr, m_constraint.Ptr); | ||
53 | m_world.scene.DetailLog("{0},BSConstraint.Dispose,taint,body1={1},body2={2},success={3}", BSScene.DetailLogZero, m_body1.ID, m_body2.ID, success); | ||
54 | m_constraint.Ptr = System.IntPtr.Zero; | ||
59 | m_enabled = false; | 55 | m_enabled = false; |
60 | if (m_constraint.ptr != IntPtr.Zero) | ||
61 | { | ||
62 | bool success = BulletSimAPI.DestroyConstraint2(m_world.ptr, m_constraint.ptr); | ||
63 | m_world.physicsScene.DetailLog("{0},BSConstraint.Dispose,taint,id1={1},body1={2},id2={3},body2={4},success={5}", | ||
64 | BSScene.DetailLogZero, | ||
65 | m_body1.ID, m_body1.ptr.ToString("X"), | ||
66 | m_body2.ID, m_body2.ptr.ToString("X"), | ||
67 | success); | ||
68 | m_constraint.ptr = System.IntPtr.Zero; | ||
69 | } | ||
70 | } | 56 | } |
71 | } | 57 | } |
72 | 58 | ||
59 | public BulletBody Body1 { get { return m_body1; } } | ||
60 | public BulletBody Body2 { get { return m_body2; } } | ||
61 | |||
73 | public virtual bool SetLinearLimits(Vector3 low, Vector3 high) | 62 | public virtual bool SetLinearLimits(Vector3 low, Vector3 high) |
74 | { | 63 | { |
75 | bool ret = false; | 64 | bool ret = false; |
76 | if (m_enabled) | 65 | if (m_enabled) |
77 | ret = BulletSimAPI.SetLinearLimits2(m_constraint.ptr, low, high); | 66 | ret = BulletSimAPI.SetLinearLimits2(m_constraint.Ptr, low, high); |
78 | return ret; | 67 | return ret; |
79 | } | 68 | } |
80 | 69 | ||
@@ -82,18 +71,7 @@ public abstract class BSConstraint : IDisposable | |||
82 | { | 71 | { |
83 | bool ret = false; | 72 | bool ret = false; |
84 | if (m_enabled) | 73 | if (m_enabled) |
85 | ret = BulletSimAPI.SetAngularLimits2(m_constraint.ptr, low, high); | 74 | ret = BulletSimAPI.SetAngularLimits2(m_constraint.Ptr, low, high); |
86 | return ret; | ||
87 | } | ||
88 | |||
89 | public virtual bool SetSolverIterations(float cnt) | ||
90 | { | ||
91 | bool ret = false; | ||
92 | if (m_enabled) | ||
93 | { | ||
94 | BulletSimAPI.SetConstraintNumSolverIterations2(m_constraint.ptr, cnt); | ||
95 | ret = true; | ||
96 | } | ||
97 | return ret; | 75 | return ret; |
98 | } | 76 | } |
99 | 77 | ||
@@ -103,7 +81,7 @@ public abstract class BSConstraint : IDisposable | |||
103 | if (m_enabled) | 81 | if (m_enabled) |
104 | { | 82 | { |
105 | // Recompute the internal transforms | 83 | // Recompute the internal transforms |
106 | BulletSimAPI.CalculateTransforms2(m_constraint.ptr); | 84 | BulletSimAPI.CalculateTransforms2(m_constraint.Ptr); |
107 | ret = true; | 85 | ret = true; |
108 | } | 86 | } |
109 | return ret; | 87 | return ret; |
@@ -119,14 +97,13 @@ public abstract class BSConstraint : IDisposable | |||
119 | ret = CalculateTransforms(); | 97 | ret = CalculateTransforms(); |
120 | if (ret) | 98 | if (ret) |
121 | { | 99 | { |
122 | // Setting an object's mass to zero (making it static like when it's selected) | 100 | // m_world.scene.PhysicsLogging.Write("{0},BSConstraint.RecomputeConstraintVariables,taint,enabling,A={1},B={2}", |
123 | // automatically disables the constraints. | 101 | // BSScene.DetailLogZero, Body1.ID, Body2.ID); |
124 | // If the link is enabled, be sure to set the constraint itself to enabled. | 102 | BulletSimAPI.SetConstraintEnable2(m_constraint.Ptr, m_world.scene.NumericBool(true)); |
125 | BulletSimAPI.SetConstraintEnable2(m_constraint.ptr, m_world.physicsScene.NumericBool(true)); | ||
126 | } | 103 | } |
127 | else | 104 | else |
128 | { | 105 | { |
129 | m_world.physicsScene.Logger.ErrorFormat("{0} CalculateTransforms failed. A={1}, B={2}", LogHeader, Body1.ID, Body2.ID); | 106 | m_world.scene.Logger.ErrorFormat("[BULLETSIM CONSTRAINT] CalculateTransforms failed. A={0}, B={1}", Body1.ID, Body2.ID); |
130 | } | 107 | } |
131 | } | 108 | } |
132 | return ret; | 109 | return ret; |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs index a9fd826..22ea367 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs | |||
@@ -33,7 +33,7 @@ using OpenMetaverse; | |||
33 | namespace OpenSim.Region.Physics.BulletSPlugin | 33 | namespace OpenSim.Region.Physics.BulletSPlugin |
34 | { | 34 | { |
35 | 35 | ||
36 | public sealed class BSConstraintCollection : IDisposable | 36 | public class BSConstraintCollection : IDisposable |
37 | { | 37 | { |
38 | // private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | 38 | // private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); |
39 | // private static readonly string LogHeader = "[CONSTRAINT COLLECTION]"; | 39 | // private static readonly string LogHeader = "[CONSTRAINT COLLECTION]"; |
@@ -143,6 +143,8 @@ public sealed class BSConstraintCollection : IDisposable | |||
143 | // Return 'true' if any constraints were destroyed. | 143 | // Return 'true' if any constraints were destroyed. |
144 | public bool RemoveAndDestroyConstraint(BulletBody body1) | 144 | public bool RemoveAndDestroyConstraint(BulletBody body1) |
145 | { | 145 | { |
146 | // return BulletSimAPI.RemoveConstraintByID(m_world.ID, obj.ID); | ||
147 | |||
146 | List<BSConstraint> toRemove = new List<BSConstraint>(); | 148 | List<BSConstraint> toRemove = new List<BSConstraint>(); |
147 | uint lookingID = body1.ID; | 149 | uint lookingID = body1.ID; |
148 | lock (m_constraints) | 150 | lock (m_constraints) |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 819635a..5a9f135 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | |||
@@ -23,7 +23,7 @@ | |||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 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 | 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. | 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | * | 26 | */ |
27 | 27 | ||
28 | /* RA: June 14, 2011. Copied from ODEDynamics.cs and converted to | 28 | /* RA: June 14, 2011. Copied from ODEDynamics.cs and converted to |
29 | * call the BulletSim system. | 29 | * call the BulletSim system. |
@@ -52,15 +52,19 @@ using OpenSim.Region.Physics.Manager; | |||
52 | 52 | ||
53 | namespace OpenSim.Region.Physics.BulletSPlugin | 53 | namespace OpenSim.Region.Physics.BulletSPlugin |
54 | { | 54 | { |
55 | public sealed class BSDynamics | 55 | public class BSDynamics |
56 | { | 56 | { |
57 | private BSScene PhysicsScene { get; set; } | 57 | private int frcount = 0; // Used to limit dynamics debug output to |
58 | // the prim this dynamic controller belongs to | 58 | // every 100th frame |
59 | private BSPrim Prim { get; set; } | ||
60 | 59 | ||
61 | // Vehicle properties | 60 | private BSPrim m_prim; // the prim this dynamic controller belongs to |
62 | public Vehicle Type { get; set; } | ||
63 | 61 | ||
62 | // Vehicle properties | ||
63 | private Vehicle m_type = Vehicle.TYPE_NONE; // If a 'VEHICLE', and what kind | ||
64 | public Vehicle Type | ||
65 | { | ||
66 | get { return m_type; } | ||
67 | } | ||
64 | // private Quaternion m_referenceFrame = Quaternion.Identity; // Axis modifier | 68 | // private Quaternion m_referenceFrame = Quaternion.Identity; // Axis modifier |
65 | private VehicleFlag m_flags = (VehicleFlag) 0; // Boolean settings: | 69 | private VehicleFlag m_flags = (VehicleFlag) 0; // Boolean settings: |
66 | // HOVER_TERRAIN_ONLY | 70 | // HOVER_TERRAIN_ONLY |
@@ -70,15 +74,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
70 | // HOVER_UP_ONLY | 74 | // HOVER_UP_ONLY |
71 | // LIMIT_MOTOR_UP | 75 | // LIMIT_MOTOR_UP |
72 | // LIMIT_ROLL_ONLY | 76 | // LIMIT_ROLL_ONLY |
77 | private VehicleFlag m_Hoverflags = (VehicleFlag)0; | ||
73 | private Vector3 m_BlockingEndPoint = Vector3.Zero; | 78 | private Vector3 m_BlockingEndPoint = Vector3.Zero; |
74 | private Quaternion m_RollreferenceFrame = Quaternion.Identity; | 79 | private Quaternion m_RollreferenceFrame = Quaternion.Identity; |
75 | private Quaternion m_referenceFrame = Quaternion.Identity; | ||
76 | |||
77 | // Linear properties | 80 | // Linear properties |
78 | private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time | 81 | private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time |
79 | private Vector3 m_linearMotorOffset = Vector3.Zero; // the point of force can be offset from the center | ||
80 | private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL | 82 | private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL |
81 | private Vector3 m_newVelocity = Vector3.Zero; // velocity computed to be applied to body | 83 | private Vector3 m_dir = Vector3.Zero; // velocity applied to body |
82 | private Vector3 m_linearFrictionTimescale = Vector3.Zero; | 84 | private Vector3 m_linearFrictionTimescale = Vector3.Zero; |
83 | private float m_linearMotorDecayTimescale = 0; | 85 | private float m_linearMotorDecayTimescale = 0; |
84 | private float m_linearMotorTimescale = 0; | 86 | private float m_linearMotorTimescale = 0; |
@@ -89,28 +91,28 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
89 | 91 | ||
90 | //Angular properties | 92 | //Angular properties |
91 | private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor | 93 | private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor |
92 | // private int m_angularMotorApply = 0; // application frame counter | 94 | private int m_angularMotorApply = 0; // application frame counter |
93 | private Vector3 m_angularMotorVelocity = Vector3.Zero; // current angular motor velocity | 95 | private Vector3 m_angularMotorVelocity = Vector3.Zero; // current angular motor velocity |
94 | private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate | 96 | private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate |
95 | private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate | 97 | private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate |
96 | private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate | 98 | private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate |
97 | private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body | 99 | private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body |
98 | private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body | 100 | // private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body |
99 | 101 | ||
100 | //Deflection properties | 102 | //Deflection properties |
101 | private float m_angularDeflectionEfficiency = 0; | 103 | // private float m_angularDeflectionEfficiency = 0; |
102 | private float m_angularDeflectionTimescale = 0; | 104 | // private float m_angularDeflectionTimescale = 0; |
103 | private float m_linearDeflectionEfficiency = 0; | 105 | // private float m_linearDeflectionEfficiency = 0; |
104 | private float m_linearDeflectionTimescale = 0; | 106 | // private float m_linearDeflectionTimescale = 0; |
105 | 107 | ||
106 | //Banking properties | 108 | //Banking properties |
107 | private float m_bankingEfficiency = 0; | 109 | // private float m_bankingEfficiency = 0; |
108 | private float m_bankingMix = 0; | 110 | // private float m_bankingMix = 0; |
109 | private float m_bankingTimescale = 0; | 111 | // private float m_bankingTimescale = 0; |
110 | 112 | ||
111 | //Hover and Buoyancy properties | 113 | //Hover and Buoyancy properties |
112 | private float m_VhoverHeight = 0f; | 114 | private float m_VhoverHeight = 0f; |
113 | private float m_VhoverEfficiency = 0f; | 115 | // private float m_VhoverEfficiency = 0f; |
114 | private float m_VhoverTimescale = 0f; | 116 | private float m_VhoverTimescale = 0f; |
115 | private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height | 117 | private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height |
116 | private float m_VehicleBuoyancy = 0f; //KF: m_VehicleBuoyancy is set by VEHICLE_BUOYANCY for a vehicle. | 118 | private float m_VehicleBuoyancy = 0f; //KF: m_VehicleBuoyancy is set by VEHICLE_BUOYANCY for a vehicle. |
@@ -122,74 +124,86 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
122 | private float m_verticalAttractionEfficiency = 1.0f; // damped | 124 | private float m_verticalAttractionEfficiency = 1.0f; // damped |
123 | private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor. | 125 | private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor. |
124 | 126 | ||
125 | public BSDynamics(BSScene myScene, BSPrim myPrim) | 127 | public BSDynamics(BSPrim myPrim) |
126 | { | ||
127 | PhysicsScene = myScene; | ||
128 | Prim = myPrim; | ||
129 | Type = Vehicle.TYPE_NONE; | ||
130 | } | ||
131 | |||
132 | // Return 'true' if this vehicle is doing vehicle things | ||
133 | public bool IsActive | ||
134 | { | 128 | { |
135 | get { return Type != Vehicle.TYPE_NONE; } | 129 | m_prim = myPrim; |
130 | m_type = Vehicle.TYPE_NONE; | ||
136 | } | 131 | } |
137 | 132 | ||
138 | internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue) | 133 | internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue, float timestep) |
139 | { | 134 | { |
140 | VDetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue); | 135 | DetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); |
141 | switch (pParam) | 136 | switch (pParam) |
142 | { | 137 | { |
143 | case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: | 138 | case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: |
144 | m_angularDeflectionEfficiency = Math.Max(pValue, 0.01f); | 139 | if (pValue < 0.01f) pValue = 0.01f; |
140 | // m_angularDeflectionEfficiency = pValue; | ||
145 | break; | 141 | break; |
146 | case Vehicle.ANGULAR_DEFLECTION_TIMESCALE: | 142 | case Vehicle.ANGULAR_DEFLECTION_TIMESCALE: |
147 | m_angularDeflectionTimescale = Math.Max(pValue, 0.01f); | 143 | if (pValue < 0.01f) pValue = 0.01f; |
144 | // m_angularDeflectionTimescale = pValue; | ||
148 | break; | 145 | break; |
149 | case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE: | 146 | case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE: |
150 | m_angularMotorDecayTimescale = Math.Max(pValue, 0.01f); | 147 | if (pValue < 0.01f) pValue = 0.01f; |
148 | m_angularMotorDecayTimescale = pValue; | ||
151 | break; | 149 | break; |
152 | case Vehicle.ANGULAR_MOTOR_TIMESCALE: | 150 | case Vehicle.ANGULAR_MOTOR_TIMESCALE: |
153 | m_angularMotorTimescale = Math.Max(pValue, 0.01f); | 151 | if (pValue < 0.01f) pValue = 0.01f; |
152 | m_angularMotorTimescale = pValue; | ||
154 | break; | 153 | break; |
155 | case Vehicle.BANKING_EFFICIENCY: | 154 | case Vehicle.BANKING_EFFICIENCY: |
156 | m_bankingEfficiency = Math.Max(-1f, Math.Min(pValue, 1f)); | 155 | if (pValue < 0.01f) pValue = 0.01f; |
156 | // m_bankingEfficiency = pValue; | ||
157 | break; | 157 | break; |
158 | case Vehicle.BANKING_MIX: | 158 | case Vehicle.BANKING_MIX: |
159 | m_bankingMix = Math.Max(pValue, 0.01f); | 159 | if (pValue < 0.01f) pValue = 0.01f; |
160 | // m_bankingMix = pValue; | ||
160 | break; | 161 | break; |
161 | case Vehicle.BANKING_TIMESCALE: | 162 | case Vehicle.BANKING_TIMESCALE: |
162 | m_bankingTimescale = Math.Max(pValue, 0.01f); | 163 | if (pValue < 0.01f) pValue = 0.01f; |
164 | // m_bankingTimescale = pValue; | ||
163 | break; | 165 | break; |
164 | case Vehicle.BUOYANCY: | 166 | case Vehicle.BUOYANCY: |
165 | m_VehicleBuoyancy = Math.Max(-1f, Math.Min(pValue, 1f)); | 167 | if (pValue < -1f) pValue = -1f; |
166 | break; | 168 | if (pValue > 1f) pValue = 1f; |
167 | case Vehicle.HOVER_EFFICIENCY: | 169 | m_VehicleBuoyancy = pValue; |
168 | m_VhoverEfficiency = Math.Max(0f, Math.Min(pValue, 1f)); | 170 | break; |
169 | break; | 171 | // case Vehicle.HOVER_EFFICIENCY: |
172 | // if (pValue < 0f) pValue = 0f; | ||
173 | // if (pValue > 1f) pValue = 1f; | ||
174 | // m_VhoverEfficiency = pValue; | ||
175 | // break; | ||
170 | case Vehicle.HOVER_HEIGHT: | 176 | case Vehicle.HOVER_HEIGHT: |
171 | m_VhoverHeight = pValue; | 177 | m_VhoverHeight = pValue; |
172 | break; | 178 | break; |
173 | case Vehicle.HOVER_TIMESCALE: | 179 | case Vehicle.HOVER_TIMESCALE: |
174 | m_VhoverTimescale = Math.Max(pValue, 0.01f); | 180 | if (pValue < 0.01f) pValue = 0.01f; |
181 | m_VhoverTimescale = pValue; | ||
175 | break; | 182 | break; |
176 | case Vehicle.LINEAR_DEFLECTION_EFFICIENCY: | 183 | case Vehicle.LINEAR_DEFLECTION_EFFICIENCY: |
177 | m_linearDeflectionEfficiency = Math.Max(pValue, 0.01f); | 184 | if (pValue < 0.01f) pValue = 0.01f; |
185 | // m_linearDeflectionEfficiency = pValue; | ||
178 | break; | 186 | break; |
179 | case Vehicle.LINEAR_DEFLECTION_TIMESCALE: | 187 | case Vehicle.LINEAR_DEFLECTION_TIMESCALE: |
180 | m_linearDeflectionTimescale = Math.Max(pValue, 0.01f); | 188 | if (pValue < 0.01f) pValue = 0.01f; |
189 | // m_linearDeflectionTimescale = pValue; | ||
181 | break; | 190 | break; |
182 | case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE: | 191 | case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE: |
183 | m_linearMotorDecayTimescale = Math.Max(pValue, 0.01f); | 192 | if (pValue < 0.01f) pValue = 0.01f; |
193 | m_linearMotorDecayTimescale = pValue; | ||
184 | break; | 194 | break; |
185 | case Vehicle.LINEAR_MOTOR_TIMESCALE: | 195 | case Vehicle.LINEAR_MOTOR_TIMESCALE: |
186 | m_linearMotorTimescale = Math.Max(pValue, 0.01f); | 196 | if (pValue < 0.01f) pValue = 0.01f; |
197 | m_linearMotorTimescale = pValue; | ||
187 | break; | 198 | break; |
188 | case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY: | 199 | case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY: |
189 | m_verticalAttractionEfficiency = Math.Max(0.1f, Math.Min(pValue, 1f)); | 200 | if (pValue < 0.1f) pValue = 0.1f; // Less goes unstable |
201 | if (pValue > 1.0f) pValue = 1.0f; | ||
202 | m_verticalAttractionEfficiency = pValue; | ||
190 | break; | 203 | break; |
191 | case Vehicle.VERTICAL_ATTRACTION_TIMESCALE: | 204 | case Vehicle.VERTICAL_ATTRACTION_TIMESCALE: |
192 | m_verticalAttractionTimescale = Math.Max(pValue, 0.01f); | 205 | if (pValue < 0.01f) pValue = 0.01f; |
206 | m_verticalAttractionTimescale = pValue; | ||
193 | break; | 207 | break; |
194 | 208 | ||
195 | // These are vector properties but the engine lets you use a single float value to | 209 | // These are vector properties but the engine lets you use a single float value to |
@@ -199,7 +213,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
199 | break; | 213 | break; |
200 | case Vehicle.ANGULAR_MOTOR_DIRECTION: | 214 | case Vehicle.ANGULAR_MOTOR_DIRECTION: |
201 | m_angularMotorDirection = new Vector3(pValue, pValue, pValue); | 215 | m_angularMotorDirection = new Vector3(pValue, pValue, pValue); |
202 | // m_angularMotorApply = 100; | 216 | m_angularMotorApply = 10; |
203 | break; | 217 | break; |
204 | case Vehicle.LINEAR_FRICTION_TIMESCALE: | 218 | case Vehicle.LINEAR_FRICTION_TIMESCALE: |
205 | m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue); | 219 | m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue); |
@@ -209,27 +223,30 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
209 | m_linearMotorDirectionLASTSET = new Vector3(pValue, pValue, pValue); | 223 | m_linearMotorDirectionLASTSET = new Vector3(pValue, pValue, pValue); |
210 | break; | 224 | break; |
211 | case Vehicle.LINEAR_MOTOR_OFFSET: | 225 | case Vehicle.LINEAR_MOTOR_OFFSET: |
212 | m_linearMotorOffset = new Vector3(pValue, pValue, pValue); | 226 | // m_linearMotorOffset = new Vector3(pValue, pValue, pValue); |
213 | break; | 227 | break; |
214 | 228 | ||
215 | } | 229 | } |
216 | }//end ProcessFloatVehicleParam | 230 | }//end ProcessFloatVehicleParam |
217 | 231 | ||
218 | internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue) | 232 | internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue, float timestep) |
219 | { | 233 | { |
220 | VDetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue); | 234 | DetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); |
221 | switch (pParam) | 235 | switch (pParam) |
222 | { | 236 | { |
223 | case Vehicle.ANGULAR_FRICTION_TIMESCALE: | 237 | case Vehicle.ANGULAR_FRICTION_TIMESCALE: |
224 | m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); | 238 | m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); |
225 | break; | 239 | break; |
226 | case Vehicle.ANGULAR_MOTOR_DIRECTION: | 240 | case Vehicle.ANGULAR_MOTOR_DIRECTION: |
227 | // Limit requested angular speed to 2 rps= 4 pi rads/sec | ||
228 | pValue.X = Math.Max(-12.56f, Math.Min(pValue.X, 12.56f)); | ||
229 | pValue.Y = Math.Max(-12.56f, Math.Min(pValue.Y, 12.56f)); | ||
230 | pValue.Z = Math.Max(-12.56f, Math.Min(pValue.Z, 12.56f)); | ||
231 | m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); | 241 | m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); |
232 | // m_angularMotorApply = 100; | 242 | // Limit requested angular speed to 2 rps= 4 pi rads/sec |
243 | if (m_angularMotorDirection.X > 12.56f) m_angularMotorDirection.X = 12.56f; | ||
244 | if (m_angularMotorDirection.X < - 12.56f) m_angularMotorDirection.X = - 12.56f; | ||
245 | if (m_angularMotorDirection.Y > 12.56f) m_angularMotorDirection.Y = 12.56f; | ||
246 | if (m_angularMotorDirection.Y < - 12.56f) m_angularMotorDirection.Y = - 12.56f; | ||
247 | if (m_angularMotorDirection.Z > 12.56f) m_angularMotorDirection.Z = 12.56f; | ||
248 | if (m_angularMotorDirection.Z < - 12.56f) m_angularMotorDirection.Z = - 12.56f; | ||
249 | m_angularMotorApply = 10; | ||
233 | break; | 250 | break; |
234 | case Vehicle.LINEAR_FRICTION_TIMESCALE: | 251 | case Vehicle.LINEAR_FRICTION_TIMESCALE: |
235 | m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); | 252 | m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); |
@@ -239,7 +256,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
239 | m_linearMotorDirectionLASTSET = new Vector3(pValue.X, pValue.Y, pValue.Z); | 256 | m_linearMotorDirectionLASTSET = new Vector3(pValue.X, pValue.Y, pValue.Z); |
240 | break; | 257 | break; |
241 | case Vehicle.LINEAR_MOTOR_OFFSET: | 258 | case Vehicle.LINEAR_MOTOR_OFFSET: |
242 | m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z); | 259 | // m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z); |
243 | break; | 260 | break; |
244 | case Vehicle.BLOCK_EXIT: | 261 | case Vehicle.BLOCK_EXIT: |
245 | m_BlockingEndPoint = new Vector3(pValue.X, pValue.Y, pValue.Z); | 262 | m_BlockingEndPoint = new Vector3(pValue.X, pValue.Y, pValue.Z); |
@@ -249,11 +266,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
249 | 266 | ||
250 | internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue) | 267 | internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue) |
251 | { | 268 | { |
252 | VDetailLog("{0},ProcessRotationalVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue); | 269 | DetailLog("{0},ProcessRotationalVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); |
253 | switch (pParam) | 270 | switch (pParam) |
254 | { | 271 | { |
255 | case Vehicle.REFERENCE_FRAME: | 272 | case Vehicle.REFERENCE_FRAME: |
256 | m_referenceFrame = pValue; | 273 | // m_referenceFrame = pValue; |
257 | break; | 274 | break; |
258 | case Vehicle.ROLL_FRAME: | 275 | case Vehicle.ROLL_FRAME: |
259 | m_RollreferenceFrame = pValue; | 276 | m_RollreferenceFrame = pValue; |
@@ -263,492 +280,575 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
263 | 280 | ||
264 | internal void ProcessVehicleFlags(int pParam, bool remove) | 281 | internal void ProcessVehicleFlags(int pParam, bool remove) |
265 | { | 282 | { |
266 | VDetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", Prim.LocalID, pParam, remove); | 283 | DetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", m_prim.LocalID, pParam, remove); |
267 | VehicleFlag parm = (VehicleFlag)pParam; | 284 | if (remove) |
268 | if (pParam == -1) | 285 | { |
269 | m_flags = (VehicleFlag)0; | 286 | if (pParam == -1) |
287 | { | ||
288 | m_flags = (VehicleFlag)0; | ||
289 | m_Hoverflags = (VehicleFlag)0; | ||
290 | return; | ||
291 | } | ||
292 | if ((pParam & (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) == (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) | ||
293 | { | ||
294 | if ((m_Hoverflags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != (VehicleFlag)0) | ||
295 | m_Hoverflags &= ~(VehicleFlag.HOVER_GLOBAL_HEIGHT); | ||
296 | } | ||
297 | if ((pParam & (int)VehicleFlag.HOVER_TERRAIN_ONLY) == (int)VehicleFlag.HOVER_TERRAIN_ONLY) | ||
298 | { | ||
299 | if ((m_Hoverflags & VehicleFlag.HOVER_TERRAIN_ONLY) != (VehicleFlag)0) | ||
300 | m_Hoverflags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY); | ||
301 | } | ||
302 | if ((pParam & (int)VehicleFlag.HOVER_UP_ONLY) == (int)VehicleFlag.HOVER_UP_ONLY) | ||
303 | { | ||
304 | if ((m_Hoverflags & VehicleFlag.HOVER_UP_ONLY) != (VehicleFlag)0) | ||
305 | m_Hoverflags &= ~(VehicleFlag.HOVER_UP_ONLY); | ||
306 | } | ||
307 | if ((pParam & (int)VehicleFlag.HOVER_WATER_ONLY) == (int)VehicleFlag.HOVER_WATER_ONLY) | ||
308 | { | ||
309 | if ((m_Hoverflags & VehicleFlag.HOVER_WATER_ONLY) != (VehicleFlag)0) | ||
310 | m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY); | ||
311 | } | ||
312 | if ((pParam & (int)VehicleFlag.LIMIT_MOTOR_UP) == (int)VehicleFlag.LIMIT_MOTOR_UP) | ||
313 | { | ||
314 | if ((m_flags & VehicleFlag.LIMIT_MOTOR_UP) != (VehicleFlag)0) | ||
315 | m_flags &= ~(VehicleFlag.LIMIT_MOTOR_UP); | ||
316 | } | ||
317 | if ((pParam & (int)VehicleFlag.LIMIT_ROLL_ONLY) == (int)VehicleFlag.LIMIT_ROLL_ONLY) | ||
318 | { | ||
319 | if ((m_flags & VehicleFlag.LIMIT_ROLL_ONLY) != (VehicleFlag)0) | ||
320 | m_flags &= ~(VehicleFlag.LIMIT_ROLL_ONLY); | ||
321 | } | ||
322 | if ((pParam & (int)VehicleFlag.MOUSELOOK_BANK) == (int)VehicleFlag.MOUSELOOK_BANK) | ||
323 | { | ||
324 | if ((m_flags & VehicleFlag.MOUSELOOK_BANK) != (VehicleFlag)0) | ||
325 | m_flags &= ~(VehicleFlag.MOUSELOOK_BANK); | ||
326 | } | ||
327 | if ((pParam & (int)VehicleFlag.MOUSELOOK_STEER) == (int)VehicleFlag.MOUSELOOK_STEER) | ||
328 | { | ||
329 | if ((m_flags & VehicleFlag.MOUSELOOK_STEER) != (VehicleFlag)0) | ||
330 | m_flags &= ~(VehicleFlag.MOUSELOOK_STEER); | ||
331 | } | ||
332 | if ((pParam & (int)VehicleFlag.NO_DEFLECTION_UP) == (int)VehicleFlag.NO_DEFLECTION_UP) | ||
333 | { | ||
334 | if ((m_flags & VehicleFlag.NO_DEFLECTION_UP) != (VehicleFlag)0) | ||
335 | m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP); | ||
336 | } | ||
337 | if ((pParam & (int)VehicleFlag.CAMERA_DECOUPLED) == (int)VehicleFlag.CAMERA_DECOUPLED) | ||
338 | { | ||
339 | if ((m_flags & VehicleFlag.CAMERA_DECOUPLED) != (VehicleFlag)0) | ||
340 | m_flags &= ~(VehicleFlag.CAMERA_DECOUPLED); | ||
341 | } | ||
342 | if ((pParam & (int)VehicleFlag.NO_X) == (int)VehicleFlag.NO_X) | ||
343 | { | ||
344 | if ((m_flags & VehicleFlag.NO_X) != (VehicleFlag)0) | ||
345 | m_flags &= ~(VehicleFlag.NO_X); | ||
346 | } | ||
347 | if ((pParam & (int)VehicleFlag.NO_Y) == (int)VehicleFlag.NO_Y) | ||
348 | { | ||
349 | if ((m_flags & VehicleFlag.NO_Y) != (VehicleFlag)0) | ||
350 | m_flags &= ~(VehicleFlag.NO_Y); | ||
351 | } | ||
352 | if ((pParam & (int)VehicleFlag.NO_Z) == (int)VehicleFlag.NO_Z) | ||
353 | { | ||
354 | if ((m_flags & VehicleFlag.NO_Z) != (VehicleFlag)0) | ||
355 | m_flags &= ~(VehicleFlag.NO_Z); | ||
356 | } | ||
357 | if ((pParam & (int)VehicleFlag.LOCK_HOVER_HEIGHT) == (int)VehicleFlag.LOCK_HOVER_HEIGHT) | ||
358 | { | ||
359 | if ((m_Hoverflags & VehicleFlag.LOCK_HOVER_HEIGHT) != (VehicleFlag)0) | ||
360 | m_Hoverflags &= ~(VehicleFlag.LOCK_HOVER_HEIGHT); | ||
361 | } | ||
362 | if ((pParam & (int)VehicleFlag.NO_DEFLECTION) == (int)VehicleFlag.NO_DEFLECTION) | ||
363 | { | ||
364 | if ((m_flags & VehicleFlag.NO_DEFLECTION) != (VehicleFlag)0) | ||
365 | m_flags &= ~(VehicleFlag.NO_DEFLECTION); | ||
366 | } | ||
367 | if ((pParam & (int)VehicleFlag.LOCK_ROTATION) == (int)VehicleFlag.LOCK_ROTATION) | ||
368 | { | ||
369 | if ((m_flags & VehicleFlag.LOCK_ROTATION) != (VehicleFlag)0) | ||
370 | m_flags &= ~(VehicleFlag.LOCK_ROTATION); | ||
371 | } | ||
372 | } | ||
270 | else | 373 | else |
271 | { | 374 | { |
272 | if (remove) | 375 | if ((pParam & (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) == (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) |
273 | m_flags &= ~parm; | 376 | { |
274 | else | 377 | m_Hoverflags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT | m_flags); |
275 | m_flags |= parm; | 378 | } |
379 | if ((pParam & (int)VehicleFlag.HOVER_TERRAIN_ONLY) == (int)VehicleFlag.HOVER_TERRAIN_ONLY) | ||
380 | { | ||
381 | m_Hoverflags |= (VehicleFlag.HOVER_TERRAIN_ONLY | m_flags); | ||
382 | } | ||
383 | if ((pParam & (int)VehicleFlag.HOVER_UP_ONLY) == (int)VehicleFlag.HOVER_UP_ONLY) | ||
384 | { | ||
385 | m_Hoverflags |= (VehicleFlag.HOVER_UP_ONLY | m_flags); | ||
386 | } | ||
387 | if ((pParam & (int)VehicleFlag.HOVER_WATER_ONLY) == (int)VehicleFlag.HOVER_WATER_ONLY) | ||
388 | { | ||
389 | m_Hoverflags |= (VehicleFlag.HOVER_WATER_ONLY | m_flags); | ||
390 | } | ||
391 | if ((pParam & (int)VehicleFlag.LIMIT_MOTOR_UP) == (int)VehicleFlag.LIMIT_MOTOR_UP) | ||
392 | { | ||
393 | m_flags |= (VehicleFlag.LIMIT_MOTOR_UP | m_flags); | ||
394 | } | ||
395 | if ((pParam & (int)VehicleFlag.MOUSELOOK_BANK) == (int)VehicleFlag.MOUSELOOK_BANK) | ||
396 | { | ||
397 | m_flags |= (VehicleFlag.MOUSELOOK_BANK | m_flags); | ||
398 | } | ||
399 | if ((pParam & (int)VehicleFlag.MOUSELOOK_STEER) == (int)VehicleFlag.MOUSELOOK_STEER) | ||
400 | { | ||
401 | m_flags |= (VehicleFlag.MOUSELOOK_STEER | m_flags); | ||
402 | } | ||
403 | if ((pParam & (int)VehicleFlag.NO_DEFLECTION_UP) == (int)VehicleFlag.NO_DEFLECTION_UP) | ||
404 | { | ||
405 | m_flags |= (VehicleFlag.NO_DEFLECTION_UP | m_flags); | ||
406 | } | ||
407 | if ((pParam & (int)VehicleFlag.CAMERA_DECOUPLED) == (int)VehicleFlag.CAMERA_DECOUPLED) | ||
408 | { | ||
409 | m_flags |= (VehicleFlag.CAMERA_DECOUPLED | m_flags); | ||
410 | } | ||
411 | if ((pParam & (int)VehicleFlag.NO_X) == (int)VehicleFlag.NO_X) | ||
412 | { | ||
413 | m_flags |= (VehicleFlag.NO_X); | ||
414 | } | ||
415 | if ((pParam & (int)VehicleFlag.NO_Y) == (int)VehicleFlag.NO_Y) | ||
416 | { | ||
417 | m_flags |= (VehicleFlag.NO_Y); | ||
418 | } | ||
419 | if ((pParam & (int)VehicleFlag.NO_Z) == (int)VehicleFlag.NO_Z) | ||
420 | { | ||
421 | m_flags |= (VehicleFlag.NO_Z); | ||
422 | } | ||
423 | if ((pParam & (int)VehicleFlag.LOCK_HOVER_HEIGHT) == (int)VehicleFlag.LOCK_HOVER_HEIGHT) | ||
424 | { | ||
425 | m_Hoverflags |= (VehicleFlag.LOCK_HOVER_HEIGHT); | ||
426 | } | ||
427 | if ((pParam & (int)VehicleFlag.NO_DEFLECTION) == (int)VehicleFlag.NO_DEFLECTION) | ||
428 | { | ||
429 | m_flags |= (VehicleFlag.NO_DEFLECTION); | ||
430 | } | ||
431 | if ((pParam & (int)VehicleFlag.LOCK_ROTATION) == (int)VehicleFlag.LOCK_ROTATION) | ||
432 | { | ||
433 | m_flags |= (VehicleFlag.LOCK_ROTATION); | ||
434 | } | ||
276 | } | 435 | } |
277 | } | 436 | }//end ProcessVehicleFlags |
278 | 437 | ||
279 | internal void ProcessTypeChange(Vehicle pType) | 438 | internal void ProcessTypeChange(Vehicle pType) |
280 | { | 439 | { |
281 | VDetailLog("{0},ProcessTypeChange,type={1}", Prim.LocalID, pType); | 440 | DetailLog("{0},ProcessTypeChange,type={1}", m_prim.LocalID, pType); |
282 | // Set Defaults For Type | 441 | // Set Defaults For Type |
283 | Type = pType; | 442 | m_type = pType; |
284 | switch (pType) | 443 | switch (pType) |
285 | { | 444 | { |
286 | case Vehicle.TYPE_NONE: | 445 | case Vehicle.TYPE_NONE: |
446 | m_linearFrictionTimescale = new Vector3(0, 0, 0); | ||
447 | m_angularFrictionTimescale = new Vector3(0, 0, 0); | ||
287 | m_linearMotorDirection = Vector3.Zero; | 448 | m_linearMotorDirection = Vector3.Zero; |
288 | m_linearMotorTimescale = 0; | 449 | m_linearMotorTimescale = 0; |
289 | m_linearMotorDecayTimescale = 0; | 450 | m_linearMotorDecayTimescale = 0; |
290 | m_linearFrictionTimescale = new Vector3(0, 0, 0); | ||
291 | |||
292 | m_angularMotorDirection = Vector3.Zero; | 451 | m_angularMotorDirection = Vector3.Zero; |
293 | m_angularMotorDecayTimescale = 0; | ||
294 | m_angularMotorTimescale = 0; | 452 | m_angularMotorTimescale = 0; |
295 | m_angularFrictionTimescale = new Vector3(0, 0, 0); | 453 | m_angularMotorDecayTimescale = 0; |
296 | |||
297 | m_VhoverHeight = 0; | 454 | m_VhoverHeight = 0; |
298 | m_VhoverEfficiency = 0; | ||
299 | m_VhoverTimescale = 0; | 455 | m_VhoverTimescale = 0; |
300 | m_VehicleBuoyancy = 0; | 456 | m_VehicleBuoyancy = 0; |
301 | |||
302 | m_linearDeflectionEfficiency = 1; | ||
303 | m_linearDeflectionTimescale = 1; | ||
304 | |||
305 | m_angularDeflectionEfficiency = 0; | ||
306 | m_angularDeflectionTimescale = 1000; | ||
307 | |||
308 | m_verticalAttractionEfficiency = 0; | ||
309 | m_verticalAttractionTimescale = 0; | ||
310 | |||
311 | m_bankingEfficiency = 0; | ||
312 | m_bankingTimescale = 1000; | ||
313 | m_bankingMix = 1; | ||
314 | |||
315 | m_referenceFrame = Quaternion.Identity; | ||
316 | m_flags = (VehicleFlag)0; | 457 | m_flags = (VehicleFlag)0; |
317 | break; | 458 | break; |
318 | 459 | ||
319 | case Vehicle.TYPE_SLED: | 460 | case Vehicle.TYPE_SLED: |
461 | m_linearFrictionTimescale = new Vector3(30, 1, 1000); | ||
462 | m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); | ||
320 | m_linearMotorDirection = Vector3.Zero; | 463 | m_linearMotorDirection = Vector3.Zero; |
321 | m_linearMotorTimescale = 1000; | 464 | m_linearMotorTimescale = 1000; |
322 | m_linearMotorDecayTimescale = 120; | 465 | m_linearMotorDecayTimescale = 120; |
323 | m_linearFrictionTimescale = new Vector3(30, 1, 1000); | ||
324 | |||
325 | m_angularMotorDirection = Vector3.Zero; | 466 | m_angularMotorDirection = Vector3.Zero; |
326 | m_angularMotorTimescale = 1000; | 467 | m_angularMotorTimescale = 1000; |
327 | m_angularMotorDecayTimescale = 120; | 468 | m_angularMotorDecayTimescale = 120; |
328 | m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); | ||
329 | |||
330 | m_VhoverHeight = 0; | 469 | m_VhoverHeight = 0; |
331 | m_VhoverEfficiency = 10; // TODO: this looks wrong!! | 470 | // m_VhoverEfficiency = 1; |
332 | m_VhoverTimescale = 10; | 471 | m_VhoverTimescale = 10; |
333 | m_VehicleBuoyancy = 0; | 472 | m_VehicleBuoyancy = 0; |
334 | 473 | // m_linearDeflectionEfficiency = 1; | |
335 | m_linearDeflectionEfficiency = 1; | 474 | // m_linearDeflectionTimescale = 1; |
336 | m_linearDeflectionTimescale = 1; | 475 | // m_angularDeflectionEfficiency = 1; |
337 | 476 | // m_angularDeflectionTimescale = 1000; | |
338 | m_angularDeflectionEfficiency = 1; | 477 | // m_bankingEfficiency = 0; |
339 | m_angularDeflectionTimescale = 1000; | 478 | // m_bankingMix = 1; |
340 | 479 | // m_bankingTimescale = 10; | |
341 | m_verticalAttractionEfficiency = 0; | 480 | // m_referenceFrame = Quaternion.Identity; |
342 | m_verticalAttractionTimescale = 0; | 481 | m_Hoverflags &= |
343 | |||
344 | m_bankingEfficiency = 0; | ||
345 | m_bankingTimescale = 10; | ||
346 | m_bankingMix = 1; | ||
347 | |||
348 | m_referenceFrame = Quaternion.Identity; | ||
349 | m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP); | ||
350 | m_flags &= | ||
351 | ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | | 482 | ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | |
352 | VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); | 483 | VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); |
484 | m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP); | ||
353 | break; | 485 | break; |
354 | case Vehicle.TYPE_CAR: | 486 | case Vehicle.TYPE_CAR: |
487 | m_linearFrictionTimescale = new Vector3(100, 2, 1000); | ||
488 | m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); | ||
355 | m_linearMotorDirection = Vector3.Zero; | 489 | m_linearMotorDirection = Vector3.Zero; |
356 | m_linearMotorTimescale = 1; | 490 | m_linearMotorTimescale = 1; |
357 | m_linearMotorDecayTimescale = 60; | 491 | m_linearMotorDecayTimescale = 60; |
358 | m_linearFrictionTimescale = new Vector3(100, 2, 1000); | ||
359 | |||
360 | m_angularMotorDirection = Vector3.Zero; | 492 | m_angularMotorDirection = Vector3.Zero; |
361 | m_angularMotorTimescale = 1; | 493 | m_angularMotorTimescale = 1; |
362 | m_angularMotorDecayTimescale = 0.8f; | 494 | m_angularMotorDecayTimescale = 0.8f; |
363 | m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); | ||
364 | |||
365 | m_VhoverHeight = 0; | 495 | m_VhoverHeight = 0; |
366 | m_VhoverEfficiency = 0; | 496 | // m_VhoverEfficiency = 0; |
367 | m_VhoverTimescale = 1000; | 497 | m_VhoverTimescale = 1000; |
368 | m_VehicleBuoyancy = 0; | 498 | m_VehicleBuoyancy = 0; |
369 | 499 | // // m_linearDeflectionEfficiency = 1; | |
370 | m_linearDeflectionEfficiency = 1; | 500 | // // m_linearDeflectionTimescale = 2; |
371 | m_linearDeflectionTimescale = 2; | 501 | // // m_angularDeflectionEfficiency = 0; |
372 | 502 | // m_angularDeflectionTimescale = 10; | |
373 | m_angularDeflectionEfficiency = 0; | ||
374 | m_angularDeflectionTimescale = 10; | ||
375 | |||
376 | m_verticalAttractionEfficiency = 1f; | 503 | m_verticalAttractionEfficiency = 1f; |
377 | m_verticalAttractionTimescale = 10f; | 504 | m_verticalAttractionTimescale = 10f; |
378 | 505 | // m_bankingEfficiency = -0.2f; | |
379 | m_bankingEfficiency = -0.2f; | 506 | // m_bankingMix = 1; |
380 | m_bankingMix = 1; | 507 | // m_bankingTimescale = 1; |
381 | m_bankingTimescale = 1; | 508 | // m_referenceFrame = Quaternion.Identity; |
382 | 509 | m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT); | |
383 | m_referenceFrame = Quaternion.Identity; | 510 | m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | |
384 | m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | 511 | VehicleFlag.LIMIT_MOTOR_UP); |
385 | | VehicleFlag.HOVER_TERRAIN_ONLY | 512 | m_Hoverflags |= (VehicleFlag.HOVER_UP_ONLY); |
386 | | VehicleFlag.HOVER_GLOBAL_HEIGHT); | ||
387 | m_flags |= (VehicleFlag.NO_DEFLECTION_UP | ||
388 | | VehicleFlag.LIMIT_ROLL_ONLY | ||
389 | | VehicleFlag.LIMIT_MOTOR_UP | ||
390 | | VehicleFlag.HOVER_UP_ONLY); | ||
391 | break; | 513 | break; |
392 | case Vehicle.TYPE_BOAT: | 514 | case Vehicle.TYPE_BOAT: |
515 | m_linearFrictionTimescale = new Vector3(10, 3, 2); | ||
516 | m_angularFrictionTimescale = new Vector3(10,10,10); | ||
393 | m_linearMotorDirection = Vector3.Zero; | 517 | m_linearMotorDirection = Vector3.Zero; |
394 | m_linearMotorTimescale = 5; | 518 | m_linearMotorTimescale = 5; |
395 | m_linearMotorDecayTimescale = 60; | 519 | m_linearMotorDecayTimescale = 60; |
396 | m_linearFrictionTimescale = new Vector3(10, 3, 2); | ||
397 | |||
398 | m_angularMotorDirection = Vector3.Zero; | 520 | m_angularMotorDirection = Vector3.Zero; |
399 | m_angularMotorTimescale = 4; | 521 | m_angularMotorTimescale = 4; |
400 | m_angularMotorDecayTimescale = 4; | 522 | m_angularMotorDecayTimescale = 4; |
401 | m_angularFrictionTimescale = new Vector3(10,10,10); | ||
402 | |||
403 | m_VhoverHeight = 0; | 523 | m_VhoverHeight = 0; |
404 | m_VhoverEfficiency = 0.5f; | 524 | // m_VhoverEfficiency = 0.5f; |
405 | m_VhoverTimescale = 2; | 525 | m_VhoverTimescale = 2; |
406 | m_VehicleBuoyancy = 1; | 526 | m_VehicleBuoyancy = 1; |
407 | 527 | // m_linearDeflectionEfficiency = 0.5f; | |
408 | m_linearDeflectionEfficiency = 0.5f; | 528 | // m_linearDeflectionTimescale = 3; |
409 | m_linearDeflectionTimescale = 3; | 529 | // m_angularDeflectionEfficiency = 0.5f; |
410 | 530 | // m_angularDeflectionTimescale = 5; | |
411 | m_angularDeflectionEfficiency = 0.5f; | ||
412 | m_angularDeflectionTimescale = 5; | ||
413 | |||
414 | m_verticalAttractionEfficiency = 0.5f; | 531 | m_verticalAttractionEfficiency = 0.5f; |
415 | m_verticalAttractionTimescale = 5f; | 532 | m_verticalAttractionTimescale = 5f; |
416 | 533 | // m_bankingEfficiency = -0.3f; | |
417 | m_bankingEfficiency = -0.3f; | 534 | // m_bankingMix = 0.8f; |
418 | m_bankingMix = 0.8f; | 535 | // m_bankingTimescale = 1; |
419 | m_bankingTimescale = 1; | 536 | // m_referenceFrame = Quaternion.Identity; |
420 | 537 | m_Hoverflags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY | | |
421 | m_referenceFrame = Quaternion.Identity; | 538 | VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); |
422 | m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY | 539 | m_flags &= ~(VehicleFlag.LIMIT_ROLL_ONLY); |
423 | | VehicleFlag.HOVER_GLOBAL_HEIGHT | 540 | m_flags |= (VehicleFlag.NO_DEFLECTION_UP | |
424 | | VehicleFlag.LIMIT_ROLL_ONLY | 541 | VehicleFlag.LIMIT_MOTOR_UP); |
425 | | VehicleFlag.HOVER_UP_ONLY); | 542 | m_Hoverflags |= (VehicleFlag.HOVER_WATER_ONLY); |
426 | m_flags |= (VehicleFlag.NO_DEFLECTION_UP | ||
427 | | VehicleFlag.LIMIT_MOTOR_UP | ||
428 | | VehicleFlag.HOVER_WATER_ONLY); | ||
429 | break; | 543 | break; |
430 | case Vehicle.TYPE_AIRPLANE: | 544 | case Vehicle.TYPE_AIRPLANE: |
545 | m_linearFrictionTimescale = new Vector3(200, 10, 5); | ||
546 | m_angularFrictionTimescale = new Vector3(20, 20, 20); | ||
431 | m_linearMotorDirection = Vector3.Zero; | 547 | m_linearMotorDirection = Vector3.Zero; |
432 | m_linearMotorTimescale = 2; | 548 | m_linearMotorTimescale = 2; |
433 | m_linearMotorDecayTimescale = 60; | 549 | m_linearMotorDecayTimescale = 60; |
434 | m_linearFrictionTimescale = new Vector3(200, 10, 5); | ||
435 | |||
436 | m_angularMotorDirection = Vector3.Zero; | 550 | m_angularMotorDirection = Vector3.Zero; |
437 | m_angularMotorTimescale = 4; | 551 | m_angularMotorTimescale = 4; |
438 | m_angularMotorDecayTimescale = 4; | 552 | m_angularMotorDecayTimescale = 4; |
439 | m_angularFrictionTimescale = new Vector3(20, 20, 20); | ||
440 | |||
441 | m_VhoverHeight = 0; | 553 | m_VhoverHeight = 0; |
442 | m_VhoverEfficiency = 0.5f; | 554 | // m_VhoverEfficiency = 0.5f; |
443 | m_VhoverTimescale = 1000; | 555 | m_VhoverTimescale = 1000; |
444 | m_VehicleBuoyancy = 0; | 556 | m_VehicleBuoyancy = 0; |
445 | 557 | // m_linearDeflectionEfficiency = 0.5f; | |
446 | m_linearDeflectionEfficiency = 0.5f; | 558 | // m_linearDeflectionTimescale = 3; |
447 | m_linearDeflectionTimescale = 3; | 559 | // m_angularDeflectionEfficiency = 1; |
448 | 560 | // m_angularDeflectionTimescale = 2; | |
449 | m_angularDeflectionEfficiency = 1; | ||
450 | m_angularDeflectionTimescale = 2; | ||
451 | |||
452 | m_verticalAttractionEfficiency = 0.9f; | 561 | m_verticalAttractionEfficiency = 0.9f; |
453 | m_verticalAttractionTimescale = 2f; | 562 | m_verticalAttractionTimescale = 2f; |
454 | 563 | // m_bankingEfficiency = 1; | |
455 | m_bankingEfficiency = 1; | 564 | // m_bankingMix = 0.7f; |
456 | m_bankingMix = 0.7f; | 565 | // m_bankingTimescale = 2; |
457 | m_bankingTimescale = 2; | 566 | // m_referenceFrame = Quaternion.Identity; |
458 | 567 | m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | | |
459 | m_referenceFrame = Quaternion.Identity; | 568 | VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); |
460 | m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | 569 | m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP); |
461 | | VehicleFlag.HOVER_TERRAIN_ONLY | ||
462 | | VehicleFlag.HOVER_GLOBAL_HEIGHT | ||
463 | | VehicleFlag.HOVER_UP_ONLY | ||
464 | | VehicleFlag.NO_DEFLECTION_UP | ||
465 | | VehicleFlag.LIMIT_MOTOR_UP); | ||
466 | m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); | 570 | m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); |
467 | break; | 571 | break; |
468 | case Vehicle.TYPE_BALLOON: | 572 | case Vehicle.TYPE_BALLOON: |
573 | m_linearFrictionTimescale = new Vector3(5, 5, 5); | ||
574 | m_angularFrictionTimescale = new Vector3(10, 10, 10); | ||
469 | m_linearMotorDirection = Vector3.Zero; | 575 | m_linearMotorDirection = Vector3.Zero; |
470 | m_linearMotorTimescale = 5; | 576 | m_linearMotorTimescale = 5; |
471 | m_linearFrictionTimescale = new Vector3(5, 5, 5); | ||
472 | m_linearMotorDecayTimescale = 60; | 577 | m_linearMotorDecayTimescale = 60; |
473 | |||
474 | m_angularMotorDirection = Vector3.Zero; | 578 | m_angularMotorDirection = Vector3.Zero; |
475 | m_angularMotorTimescale = 6; | 579 | m_angularMotorTimescale = 6; |
476 | m_angularFrictionTimescale = new Vector3(10, 10, 10); | ||
477 | m_angularMotorDecayTimescale = 10; | 580 | m_angularMotorDecayTimescale = 10; |
478 | |||
479 | m_VhoverHeight = 5; | 581 | m_VhoverHeight = 5; |
480 | m_VhoverEfficiency = 0.8f; | 582 | // m_VhoverEfficiency = 0.8f; |
481 | m_VhoverTimescale = 10; | 583 | m_VhoverTimescale = 10; |
482 | m_VehicleBuoyancy = 1; | 584 | m_VehicleBuoyancy = 1; |
483 | 585 | // m_linearDeflectionEfficiency = 0; | |
484 | m_linearDeflectionEfficiency = 0; | 586 | // m_linearDeflectionTimescale = 5; |
485 | m_linearDeflectionTimescale = 5; | 587 | // m_angularDeflectionEfficiency = 0; |
486 | 588 | // m_angularDeflectionTimescale = 5; | |
487 | m_angularDeflectionEfficiency = 0; | ||
488 | m_angularDeflectionTimescale = 5; | ||
489 | |||
490 | m_verticalAttractionEfficiency = 1f; | 589 | m_verticalAttractionEfficiency = 1f; |
491 | m_verticalAttractionTimescale = 100f; | 590 | m_verticalAttractionTimescale = 100f; |
492 | 591 | // m_bankingEfficiency = 0; | |
493 | m_bankingEfficiency = 0; | 592 | // m_bankingMix = 0.7f; |
494 | m_bankingMix = 0.7f; | 593 | // m_bankingTimescale = 5; |
495 | m_bankingTimescale = 5; | 594 | // m_referenceFrame = Quaternion.Identity; |
496 | m_referenceFrame = Quaternion.Identity; | 595 | m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | |
497 | 596 | VehicleFlag.HOVER_UP_ONLY); | |
498 | m_referenceFrame = Quaternion.Identity; | 597 | m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP); |
499 | m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | 598 | m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); |
500 | | VehicleFlag.HOVER_TERRAIN_ONLY | 599 | m_Hoverflags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT); |
501 | | VehicleFlag.HOVER_UP_ONLY | ||
502 | | VehicleFlag.NO_DEFLECTION_UP | ||
503 | | VehicleFlag.LIMIT_MOTOR_UP); | ||
504 | m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY | ||
505 | | VehicleFlag.HOVER_GLOBAL_HEIGHT); | ||
506 | break; | 600 | break; |
507 | } | 601 | } |
508 | } | 602 | }//end SetDefaultsForType |
509 | 603 | ||
510 | // Some of the properties of this prim may have changed. | ||
511 | // Do any updating needed for a vehicle | ||
512 | public void Refresh() | ||
513 | { | ||
514 | if (IsActive) | ||
515 | { | ||
516 | // Friction effects are handled by this vehicle code | ||
517 | BulletSimAPI.SetFriction2(Prim.PhysBody.ptr, 0f); | ||
518 | BulletSimAPI.SetHitFraction2(Prim.PhysBody.ptr, 0f); | ||
519 | } | ||
520 | } | ||
521 | |||
522 | // One step of the vehicle properties for the next 'pTimestep' seconds. | ||
523 | internal void Step(float pTimestep) | 604 | internal void Step(float pTimestep) |
524 | { | 605 | { |
525 | if (!IsActive) return; | 606 | if (m_type == Vehicle.TYPE_NONE) return; |
526 | 607 | ||
527 | // DEBUG | 608 | frcount++; // used to limit debug comment output |
528 | // Because Bullet does apply forces to the vehicle, our last computed | 609 | if (frcount > 100) |
529 | // linear and angular velocities are not what is happening now. | 610 | frcount = 0; |
530 | // Vector3 externalAngularVelocity = Prim.ForceRotationalVelocity - m_lastAngularVelocity; | ||
531 | // m_lastAngularVelocity += (externalAngularVelocity * 0.5f) * pTimestep; | ||
532 | // m_lastAngularVelocity = Prim.ForceRotationalVelocity; // DEBUG: account for what Bullet did last time | ||
533 | // m_lastLinearVelocityVector = Prim.ForceVelocity * Quaternion.Inverse(Prim.ForceOrientation); // DEBUG: | ||
534 | // END DEBUG | ||
535 | 611 | ||
536 | MoveLinear(pTimestep); | 612 | MoveLinear(pTimestep); |
537 | MoveAngular(pTimestep); | 613 | MoveAngular(pTimestep); |
538 | LimitRotation(pTimestep); | 614 | LimitRotation(pTimestep); |
539 | 615 | ||
540 | // DEBUG: Trying to figure out why Bullet goes crazy when the root prim is moved. | 616 | DetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", |
541 | // BulletSimAPI.SetInterpolationVelocity2(Prim.BSBody.ptr, m_newVelocity, m_lastAngularVelocity); // DEBUG DEBUG DEBUG | 617 | m_prim.LocalID, m_prim.Position, m_prim.Force, m_prim.Velocity, m_prim.RotationalVelocity); |
542 | |||
543 | // remember the position so next step we can limit absolute movement effects | ||
544 | m_lastPositionVector = Prim.ForcePosition; | ||
545 | |||
546 | VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", | ||
547 | Prim.LocalID, Prim.ForcePosition, Prim.Force, Prim.ForceVelocity, Prim.RotationalVelocity); | ||
548 | }// end Step | 618 | }// end Step |
549 | 619 | ||
550 | // Apply the effect of the linear motor. | ||
551 | // Also does hover and float. | ||
552 | private void MoveLinear(float pTimestep) | 620 | private void MoveLinear(float pTimestep) |
553 | { | 621 | { |
554 | // m_linearMotorDirection is the target direction we are moving relative to the vehicle coordinates | 622 | // requested m_linearMotorDirection is significant |
555 | // m_lastLinearVelocityVector is the current speed we are moving in that direction | 623 | // if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f)) |
556 | if (m_linearMotorDirection.LengthSquared() > 0.001f) | 624 | if (m_linearMotorDirection.LengthSquared() > 0.0001f) |
557 | { | 625 | { |
558 | Vector3 origDir = m_linearMotorDirection; | 626 | Vector3 origDir = m_linearMotorDirection; |
559 | Vector3 origVel = m_lastLinearVelocityVector; | 627 | Vector3 origVel = m_lastLinearVelocityVector; |
560 | Vector3 vehicleVelocity = Prim.ForceVelocity * Quaternion.Inverse(Prim.ForceOrientation); // DEBUG | ||
561 | 628 | ||
562 | // add drive to body | 629 | // add drive to body |
563 | Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/(m_linearMotorTimescale) * pTimestep; | 630 | // Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale/pTimestep); |
564 | // lastLinearVelocityVector is the current body velocity vector | 631 | Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale); |
632 | // lastLinearVelocityVector is the current body velocity vector? | ||
633 | // RA: Not sure what the *10 is for. A correction for pTimestep? | ||
634 | // m_lastLinearVelocityVector += (addAmount*10); | ||
635 | m_lastLinearVelocityVector += addAmount; | ||
636 | |||
637 | // This will work temporarily, but we really need to compare speed on an axis | ||
638 | // KF: Limit body velocity to applied velocity? | ||
639 | // Limit the velocity vector to less than the last set linear motor direction | ||
640 | if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X)) | ||
641 | m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X; | ||
642 | if (Math.Abs(m_lastLinearVelocityVector.Y) > Math.Abs(m_linearMotorDirectionLASTSET.Y)) | ||
643 | m_lastLinearVelocityVector.Y = m_linearMotorDirectionLASTSET.Y; | ||
644 | if (Math.Abs(m_lastLinearVelocityVector.Z) > Math.Abs(m_linearMotorDirectionLASTSET.Z)) | ||
645 | m_lastLinearVelocityVector.Z = m_linearMotorDirectionLASTSET.Z; | ||
646 | |||
647 | // decay applied velocity | ||
648 | Vector3 decayfraction = ((Vector3.One/(m_linearMotorDecayTimescale/pTimestep))); | ||
649 | m_linearMotorDirection -= m_linearMotorDirection * decayfraction * 0.5f; | ||
650 | |||
651 | /* | ||
652 | Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/m_linearMotorTimescale; | ||
565 | m_lastLinearVelocityVector += addAmount; | 653 | m_lastLinearVelocityVector += addAmount; |
566 | 654 | ||
567 | float decayFactor = (1.0f / m_linearMotorDecayTimescale) * pTimestep; | 655 | float decayfraction = (1.0f - 1.0f / m_linearMotorDecayTimescale); |
568 | m_linearMotorDirection *= (1f - decayFactor); | 656 | m_linearMotorDirection *= decayfraction; |
569 | 657 | ||
570 | Vector3 frictionFactor = (Vector3.One / m_linearFrictionTimescale) * pTimestep; | 658 | */ |
571 | m_lastLinearVelocityVector *= (Vector3.One - frictionFactor); | ||
572 | 659 | ||
573 | // Rotate new object velocity from vehicle relative to world coordinates | 660 | DetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},add={3},decay={4},dir={5},vel={6}", |
574 | m_newVelocity = m_lastLinearVelocityVector * Prim.ForceOrientation; | 661 | m_prim.LocalID, origDir, origVel, addAmount, decayfraction, m_linearMotorDirection, m_lastLinearVelocityVector); |
575 | |||
576 | VDetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},vehVel={3},add={4},decay={5},frict={6},lmDir={7},lmVel={8},newVel={9}", | ||
577 | Prim.LocalID, origDir, origVel, vehicleVelocity, addAmount, decayFactor, frictionFactor, | ||
578 | m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity); | ||
579 | } | 662 | } |
580 | else | 663 | else |
581 | { | 664 | { |
582 | // if what remains of direction is very small, zero it. | 665 | // if what remains of applied is small, zero it. |
666 | // if (m_lastLinearVelocityVector.ApproxEquals(Vector3.Zero, 0.01f)) | ||
667 | // m_lastLinearVelocityVector = Vector3.Zero; | ||
583 | m_linearMotorDirection = Vector3.Zero; | 668 | m_linearMotorDirection = Vector3.Zero; |
584 | m_lastLinearVelocityVector = Vector3.Zero; | 669 | m_lastLinearVelocityVector = Vector3.Zero; |
585 | m_newVelocity = Vector3.Zero; | ||
586 | |||
587 | VDetailLog("{0},MoveLinear,zeroed", Prim.LocalID); | ||
588 | } | 670 | } |
589 | 671 | ||
590 | // m_newVelocity is velocity computed from linear motor in world coordinates | 672 | // convert requested object velocity to world-referenced vector |
673 | Quaternion rotq = m_prim.Orientation; | ||
674 | m_dir = m_lastLinearVelocityVector * rotq; | ||
591 | 675 | ||
592 | // Gravity and Buoyancy | 676 | // Add the various forces into m_dir which will be our new direction vector (velocity) |
677 | |||
678 | // add Gravity and Buoyancy | ||
679 | // KF: So far I have found no good method to combine a script-requested | ||
680 | // .Z velocity and gravity. Therefore only 0g will used script-requested | ||
681 | // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only. | ||
682 | Vector3 grav = Vector3.Zero; | ||
593 | // There is some gravity, make a gravity force vector that is applied after object velocity. | 683 | // There is some gravity, make a gravity force vector that is applied after object velocity. |
594 | // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; | 684 | // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; |
595 | Vector3 grav = Prim.PhysicsScene.DefaultGravity * (1f - m_VehicleBuoyancy); | 685 | grav.Z = m_prim.Scene.DefaultGravity.Z * m_prim.Mass * (1f - m_VehicleBuoyancy); |
596 | |||
597 | /* | ||
598 | * RA: Not sure why one would do this unless we are hoping external forces are doing gravity, ... | ||
599 | // Preserve the current Z velocity | 686 | // Preserve the current Z velocity |
600 | Vector3 vel_now = m_prim.Velocity; | 687 | Vector3 vel_now = m_prim.Velocity; |
601 | m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity | 688 | m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity |
602 | */ | ||
603 | 689 | ||
604 | Vector3 pos = Prim.ForcePosition; | 690 | Vector3 pos = m_prim.Position; |
691 | Vector3 posChange = pos; | ||
605 | // Vector3 accel = new Vector3(-(m_dir.X - m_lastLinearVelocityVector.X / 0.1f), -(m_dir.Y - m_lastLinearVelocityVector.Y / 0.1f), m_dir.Z - m_lastLinearVelocityVector.Z / 0.1f); | 692 | // Vector3 accel = new Vector3(-(m_dir.X - m_lastLinearVelocityVector.X / 0.1f), -(m_dir.Y - m_lastLinearVelocityVector.Y / 0.1f), m_dir.Z - m_lastLinearVelocityVector.Z / 0.1f); |
693 | double Zchange = Math.Abs(posChange.Z); | ||
694 | if (m_BlockingEndPoint != Vector3.Zero) | ||
695 | { | ||
696 | bool changed = false; | ||
697 | if (pos.X >= (m_BlockingEndPoint.X - (float)1)) | ||
698 | { | ||
699 | pos.X -= posChange.X + 1; | ||
700 | changed = true; | ||
701 | } | ||
702 | if (pos.Y >= (m_BlockingEndPoint.Y - (float)1)) | ||
703 | { | ||
704 | pos.Y -= posChange.Y + 1; | ||
705 | changed = true; | ||
706 | } | ||
707 | if (pos.Z >= (m_BlockingEndPoint.Z - (float)1)) | ||
708 | { | ||
709 | pos.Z -= posChange.Z + 1; | ||
710 | changed = true; | ||
711 | } | ||
712 | if (pos.X <= 0) | ||
713 | { | ||
714 | pos.X += posChange.X + 1; | ||
715 | changed = true; | ||
716 | } | ||
717 | if (pos.Y <= 0) | ||
718 | { | ||
719 | pos.Y += posChange.Y + 1; | ||
720 | changed = true; | ||
721 | } | ||
722 | if (changed) | ||
723 | { | ||
724 | m_prim.Position = pos; | ||
725 | DetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}", | ||
726 | m_prim.LocalID, m_BlockingEndPoint, posChange, pos); | ||
727 | } | ||
728 | } | ||
606 | 729 | ||
607 | // If below the terrain, move us above the ground a little. | 730 | // If below the terrain, move us above the ground a little. |
608 | float terrainHeight = Prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos); | 731 | if (pos.Z < m_prim.Scene.GetTerrainHeightAtXYZ(pos)) |
609 | // Taking the rotated size doesn't work here because m_prim.Size is the size of the root prim and not the linkset. | ||
610 | // Need to add a m_prim.LinkSet.Size similar to m_prim.LinkSet.Mass. | ||
611 | // Vector3 rotatedSize = m_prim.Size * m_prim.ForceOrientation; | ||
612 | // if (rotatedSize.Z < terrainHeight) | ||
613 | if (pos.Z < terrainHeight) | ||
614 | { | 732 | { |
615 | pos.Z = terrainHeight + 2; | 733 | pos.Z = m_prim.Scene.GetTerrainHeightAtXYZ(pos) + 2; |
616 | Prim.ForcePosition = pos; | 734 | m_prim.Position = pos; |
617 | VDetailLog("{0},MoveLinear,terrainHeight,terrainHeight={1},pos={2}", Prim.LocalID, terrainHeight, pos); | 735 | DetailLog("{0},MoveLinear,terrainHeight,pos={1}", m_prim.LocalID, pos); |
618 | } | 736 | } |
619 | 737 | ||
620 | // Check if hovering | 738 | // Check if hovering |
621 | // m_VhoverEfficiency: 0=bouncy, 1=totally damped | 739 | if ((m_Hoverflags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0) |
622 | // m_VhoverTimescale: time to achieve height | ||
623 | if ((m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0) | ||
624 | { | 740 | { |
625 | // We should hover, get the target height | 741 | // We should hover, get the target height |
626 | if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0) | 742 | if ((m_Hoverflags & VehicleFlag.HOVER_WATER_ONLY) != 0) |
627 | { | 743 | { |
628 | m_VhoverTargetHeight = Prim.PhysicsScene.GetWaterLevelAtXYZ(pos) + m_VhoverHeight; | 744 | m_VhoverTargetHeight = m_prim.Scene.GetWaterLevel() + m_VhoverHeight; |
629 | } | 745 | } |
630 | if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0) | 746 | if ((m_Hoverflags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0) |
631 | { | 747 | { |
632 | m_VhoverTargetHeight = terrainHeight + m_VhoverHeight; | 748 | m_VhoverTargetHeight = m_prim.Scene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight; |
633 | } | 749 | } |
634 | if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0) | 750 | if ((m_Hoverflags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0) |
635 | { | 751 | { |
636 | m_VhoverTargetHeight = m_VhoverHeight; | 752 | m_VhoverTargetHeight = m_VhoverHeight; |
637 | } | 753 | } |
638 | 754 | ||
639 | if ((m_flags & VehicleFlag.HOVER_UP_ONLY) != 0) | 755 | if ((m_Hoverflags & VehicleFlag.HOVER_UP_ONLY) != 0) |
640 | { | 756 | { |
641 | // If body is aready heigher, use its height as target height | 757 | // If body is aready heigher, use its height as target height |
642 | if (pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z; | 758 | if (pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z; |
643 | } | 759 | } |
644 | if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0) | 760 | if ((m_Hoverflags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0) |
645 | { | 761 | { |
646 | if ((pos.Z - m_VhoverTargetHeight) > .2 || (pos.Z - m_VhoverTargetHeight) < -.2) | 762 | if ((pos.Z - m_VhoverTargetHeight) > .2 || (pos.Z - m_VhoverTargetHeight) < -.2) |
647 | { | 763 | { |
648 | Prim.ForcePosition = pos; | 764 | m_prim.Position = pos; |
649 | } | 765 | } |
650 | } | 766 | } |
651 | else | 767 | else |
652 | { | 768 | { |
653 | float verticalError = pos.Z - m_VhoverTargetHeight; | 769 | float herr0 = pos.Z - m_VhoverTargetHeight; |
654 | // RA: where does the 50 come from? | ||
655 | float verticalCorrectionVelocity = pTimestep * ((verticalError * 50.0f) / m_VhoverTimescale); | ||
656 | // Replace Vertical speed with correction figure if significant | 770 | // Replace Vertical speed with correction figure if significant |
657 | if (Math.Abs(verticalError) > 0.01f) | 771 | if (Math.Abs(herr0) > 0.01f) |
658 | { | 772 | { |
659 | m_newVelocity.Z += verticalCorrectionVelocity; | 773 | m_dir.Z = -((herr0 * pTimestep * 50.0f) / m_VhoverTimescale); |
660 | //KF: m_VhoverEfficiency is not yet implemented | 774 | //KF: m_VhoverEfficiency is not yet implemented |
661 | } | 775 | } |
662 | else if (verticalError < -0.01) | ||
663 | { | ||
664 | m_newVelocity.Z -= verticalCorrectionVelocity; | ||
665 | } | ||
666 | else | 776 | else |
667 | { | 777 | { |
668 | m_newVelocity.Z = 0f; | 778 | m_dir.Z = 0f; |
669 | } | 779 | } |
670 | } | 780 | } |
671 | 781 | ||
672 | VDetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", Prim.LocalID, pos, m_newVelocity, m_VhoverHeight, m_VhoverTargetHeight); | 782 | DetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", m_prim.LocalID, pos, m_dir, m_VhoverHeight, m_VhoverTargetHeight); |
673 | } | ||
674 | 783 | ||
675 | Vector3 posChange = pos - m_lastPositionVector; | 784 | // m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped |
676 | if (m_BlockingEndPoint != Vector3.Zero) | 785 | // m_VhoverTimescale = 0f; // time to acheive height |
677 | { | 786 | // pTimestep is time since last frame,in secs |
678 | bool changed = false; | ||
679 | if (pos.X >= (m_BlockingEndPoint.X - (float)1)) | ||
680 | { | ||
681 | pos.X -= posChange.X + 1; | ||
682 | changed = true; | ||
683 | } | ||
684 | if (pos.Y >= (m_BlockingEndPoint.Y - (float)1)) | ||
685 | { | ||
686 | pos.Y -= posChange.Y + 1; | ||
687 | changed = true; | ||
688 | } | ||
689 | if (pos.Z >= (m_BlockingEndPoint.Z - (float)1)) | ||
690 | { | ||
691 | pos.Z -= posChange.Z + 1; | ||
692 | changed = true; | ||
693 | } | ||
694 | if (pos.X <= 0) | ||
695 | { | ||
696 | pos.X += posChange.X + 1; | ||
697 | changed = true; | ||
698 | } | ||
699 | if (pos.Y <= 0) | ||
700 | { | ||
701 | pos.Y += posChange.Y + 1; | ||
702 | changed = true; | ||
703 | } | ||
704 | if (changed) | ||
705 | { | ||
706 | Prim.ForcePosition = pos; | ||
707 | VDetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}", | ||
708 | Prim.LocalID, m_BlockingEndPoint, posChange, pos); | ||
709 | } | ||
710 | } | 787 | } |
711 | 788 | ||
712 | // Limit absolute vertical change | ||
713 | float Zchange = Math.Abs(posChange.Z); | ||
714 | if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) | 789 | if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) |
715 | { | 790 | { |
791 | //Start Experimental Values | ||
716 | if (Zchange > .3) | 792 | if (Zchange > .3) |
793 | { | ||
717 | grav.Z = (float)(grav.Z * 3); | 794 | grav.Z = (float)(grav.Z * 3); |
795 | } | ||
718 | if (Zchange > .15) | 796 | if (Zchange > .15) |
797 | { | ||
719 | grav.Z = (float)(grav.Z * 2); | 798 | grav.Z = (float)(grav.Z * 2); |
799 | } | ||
720 | if (Zchange > .75) | 800 | if (Zchange > .75) |
801 | { | ||
721 | grav.Z = (float)(grav.Z * 1.5); | 802 | grav.Z = (float)(grav.Z * 1.5); |
803 | } | ||
722 | if (Zchange > .05) | 804 | if (Zchange > .05) |
805 | { | ||
723 | grav.Z = (float)(grav.Z * 1.25); | 806 | grav.Z = (float)(grav.Z * 1.25); |
807 | } | ||
724 | if (Zchange > .025) | 808 | if (Zchange > .025) |
809 | { | ||
725 | grav.Z = (float)(grav.Z * 1.125); | 810 | grav.Z = (float)(grav.Z * 1.125); |
726 | float postemp = (pos.Z - terrainHeight); | 811 | } |
812 | float terraintemp = m_prim.Scene.GetTerrainHeightAtXYZ(pos); | ||
813 | float postemp = (pos.Z - terraintemp); | ||
727 | if (postemp > 2.5f) | 814 | if (postemp > 2.5f) |
815 | { | ||
728 | grav.Z = (float)(grav.Z * 1.037125); | 816 | grav.Z = (float)(grav.Z * 1.037125); |
729 | VDetailLog("{0},MoveLinear,limitMotorUp,grav={1}", Prim.LocalID, grav); | 817 | } |
818 | DetailLog("{0},MoveLinear,limitMotorUp,grav={1}", m_prim.LocalID, grav); | ||
819 | //End Experimental Values | ||
730 | } | 820 | } |
731 | |||
732 | // If not changing some axis, reduce out velocity | ||
733 | if ((m_flags & (VehicleFlag.NO_X)) != 0) | 821 | if ((m_flags & (VehicleFlag.NO_X)) != 0) |
734 | m_newVelocity.X = 0; | 822 | { |
823 | m_dir.X = 0; | ||
824 | } | ||
735 | if ((m_flags & (VehicleFlag.NO_Y)) != 0) | 825 | if ((m_flags & (VehicleFlag.NO_Y)) != 0) |
736 | m_newVelocity.Y = 0; | 826 | { |
827 | m_dir.Y = 0; | ||
828 | } | ||
737 | if ((m_flags & (VehicleFlag.NO_Z)) != 0) | 829 | if ((m_flags & (VehicleFlag.NO_Z)) != 0) |
738 | m_newVelocity.Z = 0; | 830 | { |
831 | m_dir.Z = 0; | ||
832 | } | ||
833 | |||
834 | m_lastPositionVector = m_prim.Position; | ||
739 | 835 | ||
740 | // Apply velocity | 836 | // Apply velocity |
741 | Prim.ForceVelocity = m_newVelocity; | 837 | m_prim.Velocity = m_dir; |
742 | // Prim.AddForce(m_newVelocity * Prim.Linkset.LinksetMass, false); | 838 | // apply gravity force |
743 | Prim.AddForce(grav * Prim.Linkset.LinksetMass, false); | 839 | // Why is this set here? The physics engine already does gravity. |
840 | // m_prim.AddForce(grav, false); | ||
841 | // m_prim.Force = grav; | ||
744 | 842 | ||
745 | VDetailLog("{0},MoveLinear,done,lmDir={1},lmVel={2},newVel={3},grav={4}", | 843 | // Apply friction |
746 | Prim.LocalID, m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity, grav); | 844 | Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep); |
845 | m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount; | ||
846 | |||
847 | DetailLog("{0},MoveLinear,done,pos={1},vel={2},force={3},decay={4}", | ||
848 | m_prim.LocalID, m_lastPositionVector, m_dir, grav, decayamount); | ||
747 | 849 | ||
748 | } // end MoveLinear() | 850 | } // end MoveLinear() |
749 | 851 | ||
750 | // ======================================================================= | ||
751 | // Apply the effect of the angular motor. | ||
752 | private void MoveAngular(float pTimestep) | 852 | private void MoveAngular(float pTimestep) |
753 | { | 853 | { |
754 | // m_angularMotorDirection // angular velocity requested by LSL motor | 854 | // m_angularMotorDirection // angular velocity requested by LSL motor |
@@ -759,223 +859,160 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
759 | // m_angularFrictionTimescale // body angular velocity decay rate | 859 | // m_angularFrictionTimescale // body angular velocity decay rate |
760 | // m_lastAngularVelocity // what was last applied to body | 860 | // m_lastAngularVelocity // what was last applied to body |
761 | 861 | ||
762 | if (m_angularMotorDirection.LengthSquared() > 0.0001) | 862 | // Get what the body is doing, this includes 'external' influences |
763 | { | 863 | Vector3 angularVelocity = m_prim.RotationalVelocity; |
764 | Vector3 origVel = m_angularMotorVelocity; | ||
765 | Vector3 origDir = m_angularMotorDirection; | ||
766 | |||
767 | // new velocity += error / ( time to get there / step interval) | ||
768 | // requested speed - last motor speed | ||
769 | m_angularMotorVelocity += (m_angularMotorDirection - m_angularMotorVelocity) / (m_angularMotorTimescale / pTimestep); | ||
770 | // decay requested direction | ||
771 | m_angularMotorDirection *= (1.0f - (pTimestep * 1.0f/m_angularMotorDecayTimescale)); | ||
772 | 864 | ||
773 | VDetailLog("{0},MoveAngular,angularMotorApply,angTScale={1},timeStep={2},origvel={3},origDir={4},vel={5}", | 865 | if (m_angularMotorApply > 0) |
774 | Prim.LocalID, m_angularMotorTimescale, pTimestep, origVel, origDir, m_angularMotorVelocity); | 866 | { |
867 | // Rather than snapping the angular motor velocity from the old value to | ||
868 | // a newly set velocity, this routine steps the value from the previous | ||
869 | // value (m_angularMotorVelocity) to the requested value (m_angularMotorDirection). | ||
870 | // There are m_angularMotorApply steps. | ||
871 | Vector3 origAngularVelocity = m_angularMotorVelocity; | ||
872 | // ramp up to new value | ||
873 | // current velocity += error / (time to get there / step interval) | ||
874 | // requested speed - last motor speed | ||
875 | m_angularMotorVelocity.X += (m_angularMotorDirection.X - m_angularMotorVelocity.X) / (m_angularMotorTimescale / pTimestep); | ||
876 | m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep); | ||
877 | m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep); | ||
878 | |||
879 | DetailLog("{0},MoveAngular,angularMotorApply,apply={1},origvel={2},dir={3},vel={4}", | ||
880 | m_prim.LocalID,m_angularMotorApply,origAngularVelocity, m_angularMotorDirection, m_angularMotorVelocity); | ||
881 | |||
882 | m_angularMotorApply--; // This is done so that if script request rate is less than phys frame rate the expected | ||
883 | // velocity may still be acheived. | ||
775 | } | 884 | } |
776 | else | 885 | else |
777 | { | 886 | { |
778 | m_angularMotorVelocity = Vector3.Zero; | 887 | // No motor recently applied, keep the body velocity |
779 | } | 888 | // and decay the velocity |
780 | 889 | m_angularMotorVelocity -= m_angularMotorVelocity / (m_angularMotorDecayTimescale / pTimestep); | |
781 | #region Vertical attactor | 890 | } // end motor section |
782 | 891 | ||
892 | // Vertical attractor section | ||
783 | Vector3 vertattr = Vector3.Zero; | 893 | Vector3 vertattr = Vector3.Zero; |
784 | Vector3 deflection = Vector3.Zero; | 894 | if (m_verticalAttractionTimescale < 300) |
785 | Vector3 banking = Vector3.Zero; | ||
786 | |||
787 | if (m_verticalAttractionTimescale < 300 && m_lastAngularVelocity != Vector3.Zero) | ||
788 | { | 895 | { |
789 | float VAservo = pTimestep * 0.2f / m_verticalAttractionTimescale; | 896 | float VAservo = 0.2f / (m_verticalAttractionTimescale * pTimestep); |
790 | if (Prim.Linkset.LinksetIsColliding) | 897 | // get present body rotation |
791 | VAservo = pTimestep * 0.05f / (m_verticalAttractionTimescale); | 898 | Quaternion rotq = m_prim.Orientation; |
792 | 899 | // make a vector pointing up | |
793 | VAservo *= (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency); | 900 | Vector3 verterr = Vector3.Zero; |
794 | 901 | verterr.Z = 1.0f; | |
795 | // Create a vector of the vehicle "up" in world coordinates | 902 | // rotate it to Body Angle |
796 | Vector3 verticalError = Vector3.UnitZ * Prim.ForceOrientation; | 903 | verterr = verterr * rotq; |
797 | // verticalError.X and .Y are the World error amounts. They are 0 when there is no | 904 | // verterr.X and .Y are the World error ammounts. They are 0 when there is no error (Vehicle Body is 'vertical'), and .Z will be 1. |
798 | // error (Vehicle Body is 'vertical'), and .Z will be 1. As the body leans to its | 905 | // As the body leans to its side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall and .Z will go |
799 | // side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall | 906 | // negative. Similar for tilt and |.Y|. .X and .Y must be modulated to prevent a stable inverted body. |
800 | // and .Z will go // negative. Similar for tilt and |.Y|. .X and .Y must be | 907 | if (verterr.Z < 0.0f) |
801 | // modulated to prevent a stable inverted body. | ||
802 | |||
803 | // Error is 0 (no error) to +/- 2 (max error) | ||
804 | if (verticalError.Z < 0.0f) | ||
805 | { | 908 | { |
806 | verticalError.X = 2.0f - verticalError.X; | 909 | verterr.X = 2.0f - verterr.X; |
807 | verticalError.Y = 2.0f - verticalError.Y; | 910 | verterr.Y = 2.0f - verterr.Y; |
808 | } | 911 | } |
912 | // Error is 0 (no error) to +/- 2 (max error) | ||
809 | // scale it by VAservo | 913 | // scale it by VAservo |
810 | verticalError = verticalError * VAservo; | 914 | verterr = verterr * VAservo; |
811 | 915 | ||
812 | // As the body rotates around the X axis, then verticalError.Y increases; Rotated around Y | 916 | // As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so |
813 | // then .X increases, so change Body angular velocity X based on Y, and Y based on X. | 917 | // Change Body angular velocity X based on Y, and Y based on X. Z is not changed. |
814 | // Z is not changed. | 918 | vertattr.X = verterr.Y; |
815 | vertattr.X = verticalError.Y; | 919 | vertattr.Y = - verterr.X; |
816 | vertattr.Y = - verticalError.X; | ||
817 | vertattr.Z = 0f; | 920 | vertattr.Z = 0f; |
818 | 921 | ||
819 | // scaling appears better usingsquare-law | 922 | // scaling appears better usingsquare-law |
820 | Vector3 angularVelocity = Prim.ForceRotationalVelocity; | ||
821 | float bounce = 1.0f - (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency); | 923 | float bounce = 1.0f - (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency); |
822 | vertattr.X += bounce * angularVelocity.X; | 924 | vertattr.X += bounce * angularVelocity.X; |
823 | vertattr.Y += bounce * angularVelocity.Y; | 925 | vertattr.Y += bounce * angularVelocity.Y; |
824 | 926 | ||
825 | VDetailLog("{0},MoveAngular,verticalAttraction,verticalError={1},bounce={2},vertattr={3}", | 927 | DetailLog("{0},MoveAngular,verticalAttraction,verterr={1},bounce={2},vertattr={3}", |
826 | Prim.LocalID, verticalError, bounce, vertattr); | 928 | m_prim.LocalID, verterr, bounce, vertattr); |
827 | |||
828 | } | ||
829 | #endregion // Vertical attactor | ||
830 | |||
831 | #region Deflection | ||
832 | |||
833 | //Forward is the prefered direction, but if the reference frame has changed, we need to take this into account as well | ||
834 | if (m_angularDeflectionEfficiency != 0) | ||
835 | { | ||
836 | Vector3 preferredAxisOfMotion = | ||
837 | new Vector3((pTimestep * 10 * (m_angularDeflectionEfficiency / m_angularDeflectionTimescale)), 0, 0); | ||
838 | preferredAxisOfMotion *= Quaternion.Add(Prim.ForceOrientation, m_referenceFrame); | ||
839 | |||
840 | deflection = (preferredAxisOfMotion * (m_angularDeflectionEfficiency) / m_angularDeflectionTimescale) * pTimestep; | ||
841 | |||
842 | VDetailLog("{0},MoveAngular,Deflection,perfAxis={1},deflection={2}", | ||
843 | Prim.LocalID, preferredAxisOfMotion, deflection); | ||
844 | } | ||
845 | |||
846 | #endregion | ||
847 | |||
848 | #region Banking | ||
849 | 929 | ||
850 | if (m_bankingEfficiency != 0) | 930 | } // else vertical attractor is off |
851 | { | ||
852 | Vector3 dir = Vector3.One * Prim.ForceOrientation; | ||
853 | float mult = (m_bankingMix*m_bankingMix)*-1*(m_bankingMix < 0 ? -1 : 1); | ||
854 | //Changes which way it banks in and out of turns | ||
855 | 931 | ||
856 | //Use the square of the efficiency, as it looks much more how SL banking works | 932 | // m_lastVertAttractor = vertattr; |
857 | float effSquared = (m_bankingEfficiency*m_bankingEfficiency); | ||
858 | if (m_bankingEfficiency < 0) | ||
859 | effSquared *= -1; //Keep the negative! | ||
860 | 933 | ||
861 | float mix = Math.Abs(m_bankingMix); | 934 | // Bank section tba |
862 | if (m_angularMotorVelocity.X == 0) | ||
863 | { | ||
864 | /*if (!parent.Orientation.ApproxEquals(this.m_referenceFrame, 0.25f)) | ||
865 | { | ||
866 | Vector3 axisAngle; | ||
867 | float angle; | ||
868 | parent.Orientation.GetAxisAngle(out axisAngle, out angle); | ||
869 | Vector3 rotatedVel = parent.Velocity * parent.Orientation; | ||
870 | if ((rotatedVel.X < 0 && axisAngle.Y > 0) || (rotatedVel.X > 0 && axisAngle.Y < 0)) | ||
871 | m_angularMotorVelocity.X += (effSquared * (mult * mix)) * (1f) * 10; | ||
872 | else | ||
873 | m_angularMotorVelocity.X += (effSquared * (mult * mix)) * (-1f) * 10; | ||
874 | }*/ | ||
875 | } | ||
876 | else | ||
877 | banking.Z += (effSquared*(mult*mix))*(m_angularMotorVelocity.X) * 4; | ||
878 | if (!Prim.Linkset.LinksetIsColliding && Math.Abs(m_angularMotorVelocity.X) > mix) | ||
879 | //If they are colliding, we probably shouldn't shove the prim around... probably | ||
880 | { | ||
881 | float angVelZ = m_angularMotorVelocity.X*-1; | ||
882 | /*if(angVelZ > mix) | ||
883 | angVelZ = mix; | ||
884 | else if(angVelZ < -mix) | ||
885 | angVelZ = -mix;*/ | ||
886 | //This controls how fast and how far the banking occurs | ||
887 | Vector3 bankingRot = new Vector3(angVelZ*(effSquared*mult), 0, 0); | ||
888 | if (bankingRot.X > 3) | ||
889 | bankingRot.X = 3; | ||
890 | else if (bankingRot.X < -3) | ||
891 | bankingRot.X = -3; | ||
892 | bankingRot *= Prim.ForceOrientation; | ||
893 | banking += bankingRot; | ||
894 | } | ||
895 | m_angularMotorVelocity.X *= m_bankingEfficiency == 1 ? 0.0f : 1 - m_bankingEfficiency; | ||
896 | VDetailLog("{0},MoveAngular,Banking,bEff={1},angMotVel={2},banking={3}", | ||
897 | Prim.LocalID, m_bankingEfficiency, m_angularMotorVelocity, banking); | ||
898 | } | ||
899 | |||
900 | #endregion | ||
901 | 935 | ||
902 | m_lastVertAttractor = vertattr; | 936 | // Deflection section tba |
903 | 937 | ||
904 | // Sum velocities | 938 | // Sum velocities |
905 | m_lastAngularVelocity = m_angularMotorVelocity + vertattr + banking + deflection; | 939 | m_lastAngularVelocity = m_angularMotorVelocity + vertattr; // + bank + deflection |
906 | 940 | ||
907 | if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0) | 941 | if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0) |
908 | { | 942 | { |
909 | m_lastAngularVelocity.X = 0; | 943 | m_lastAngularVelocity.X = 0; |
910 | m_lastAngularVelocity.Y = 0; | 944 | m_lastAngularVelocity.Y = 0; |
911 | VDetailLog("{0},MoveAngular,noDeflectionUp,lastAngular={1}", Prim.LocalID, m_lastAngularVelocity); | 945 | DetailLog("{0},MoveAngular,noDeflectionUp,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity); |
912 | } | 946 | } |
913 | 947 | ||
914 | if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f)) | 948 | if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f)) |
915 | { | 949 | { |
916 | m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero. | 950 | m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero. |
917 | VDetailLog("{0},MoveAngular,zeroSmallValues,lastAngular={1}", Prim.LocalID, m_lastAngularVelocity); | 951 | DetailLog("{0},MoveAngular,zeroSmallValues,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity); |
918 | } | 952 | } |
919 | 953 | ||
920 | // Apply to the body | 954 | // apply friction |
921 | // The above calculates the absolute angular velocity needed | 955 | Vector3 decayamount = Vector3.One / (m_angularFrictionTimescale / pTimestep); |
922 | // Prim.ForceRotationalVelocity = m_lastAngularVelocity; | 956 | m_lastAngularVelocity -= m_lastAngularVelocity * decayamount; |
923 | |||
924 | // Apply a force to overcome current angular velocity | ||
925 | Vector3 applyAngularForce = (m_lastAngularVelocity - Prim.ForceRotationalVelocity) * Prim.Linkset.LinksetMass; | ||
926 | // Vector3 applyAngularForce = (m_lastAngularVelocity - Prim.ForceRotationalVelocity); | ||
927 | // Prim.AddAngularForce(applyAngularForce, false); | ||
928 | Prim.ApplyTorqueImpulse(applyAngularForce, false); | ||
929 | 957 | ||
930 | // Apply friction for next time | 958 | // Apply to the body |
931 | Vector3 decayamount = (Vector3.One / m_angularFrictionTimescale) * pTimestep; | 959 | m_prim.RotationalVelocity = m_lastAngularVelocity; |
932 | m_lastAngularVelocity *= Vector3.One - decayamount; | ||
933 | 960 | ||
934 | VDetailLog("{0},MoveAngular,done,applyAForce={1},decay={2},lastAngular={3}", | 961 | DetailLog("{0},MoveAngular,done,decay={1},lastAngular={2}", m_prim.LocalID, decayamount, m_lastAngularVelocity); |
935 | Prim.LocalID, applyAngularForce, decayamount, m_lastAngularVelocity); | ||
936 | } //end MoveAngular | 962 | } //end MoveAngular |
937 | 963 | ||
938 | internal void LimitRotation(float timestep) | 964 | internal void LimitRotation(float timestep) |
939 | { | 965 | { |
940 | Quaternion rotq = Prim.ForceOrientation; | 966 | Quaternion rotq = m_prim.Orientation; |
941 | Quaternion m_rot = rotq; | 967 | Quaternion m_rot = rotq; |
968 | bool changed = false; | ||
942 | if (m_RollreferenceFrame != Quaternion.Identity) | 969 | if (m_RollreferenceFrame != Quaternion.Identity) |
943 | { | 970 | { |
944 | if (rotq.X >= m_RollreferenceFrame.X) | 971 | if (rotq.X >= m_RollreferenceFrame.X) |
945 | { | 972 | { |
946 | m_rot.X = rotq.X - (m_RollreferenceFrame.X / 2); | 973 | m_rot.X = rotq.X - (m_RollreferenceFrame.X / 2); |
974 | changed = true; | ||
947 | } | 975 | } |
948 | if (rotq.Y >= m_RollreferenceFrame.Y) | 976 | if (rotq.Y >= m_RollreferenceFrame.Y) |
949 | { | 977 | { |
950 | m_rot.Y = rotq.Y - (m_RollreferenceFrame.Y / 2); | 978 | m_rot.Y = rotq.Y - (m_RollreferenceFrame.Y / 2); |
979 | changed = true; | ||
951 | } | 980 | } |
952 | if (rotq.X <= -m_RollreferenceFrame.X) | 981 | if (rotq.X <= -m_RollreferenceFrame.X) |
953 | { | 982 | { |
954 | m_rot.X = rotq.X + (m_RollreferenceFrame.X / 2); | 983 | m_rot.X = rotq.X + (m_RollreferenceFrame.X / 2); |
984 | changed = true; | ||
955 | } | 985 | } |
956 | if (rotq.Y <= -m_RollreferenceFrame.Y) | 986 | if (rotq.Y <= -m_RollreferenceFrame.Y) |
957 | { | 987 | { |
958 | m_rot.Y = rotq.Y + (m_RollreferenceFrame.Y / 2); | 988 | m_rot.Y = rotq.Y + (m_RollreferenceFrame.Y / 2); |
989 | changed = true; | ||
959 | } | 990 | } |
991 | changed = true; | ||
960 | } | 992 | } |
961 | if ((m_flags & VehicleFlag.LOCK_ROTATION) != 0) | 993 | if ((m_flags & VehicleFlag.LOCK_ROTATION) != 0) |
962 | { | 994 | { |
963 | m_rot.X = 0; | 995 | m_rot.X = 0; |
964 | m_rot.Y = 0; | 996 | m_rot.Y = 0; |
997 | changed = true; | ||
965 | } | 998 | } |
966 | if (rotq != m_rot) | 999 | if ((m_flags & VehicleFlag.LOCK_ROTATION) != 0) |
967 | { | 1000 | { |
968 | Prim.ForceOrientation = m_rot; | 1001 | m_rot.X = 0; |
969 | VDetailLog("{0},LimitRotation,done,orig={1},new={2}", Prim.LocalID, rotq, m_rot); | 1002 | m_rot.Y = 0; |
1003 | changed = true; | ||
970 | } | 1004 | } |
1005 | if (changed) | ||
1006 | m_prim.Orientation = m_rot; | ||
971 | 1007 | ||
1008 | DetailLog("{0},LimitRotation,done,changed={1},orig={2},new={3}", m_prim.LocalID, changed, rotq, m_rot); | ||
972 | } | 1009 | } |
973 | 1010 | ||
974 | // Invoke the detailed logger and output something if it's enabled. | 1011 | // Invoke the detailed logger and output something if it's enabled. |
975 | private void VDetailLog(string msg, params Object[] args) | 1012 | private void DetailLog(string msg, params Object[] args) |
976 | { | 1013 | { |
977 | if (Prim.PhysicsScene.VehicleLoggingEnabled) | 1014 | if (m_prim.Scene.VehicleLoggingEnabled) |
978 | Prim.PhysicsScene.DetailLog(msg, args); | 1015 | m_prim.Scene.PhysicsLogging.Write(msg, args); |
979 | } | 1016 | } |
980 | } | 1017 | } |
981 | } | 1018 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs b/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs index ed3ffa7..d68048b 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs | |||
@@ -1,57 +1,55 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) Contributors, http://opensimulator.org/ | 2 | * Copyright (c) Contributors, http://opensimulator.org/ |
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | 3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. |
4 | * | 4 | * |
5 | * Redistribution and use in source and binary forms, with or without | 5 | * Redistribution and use in source and binary forms, with or without |
6 | * modification, are permitted provided that the following conditions are met: | 6 | * modification, are permitted provided that the following conditions are met: |
7 | * * Redistributions of source code must retain the above copyright | 7 | * * Redistributions of source code must retain the above copyright |
8 | * notice, this list of conditions and the following disclaimer. | 8 | * notice, this list of conditions and the following disclaimer. |
9 | * * Redistributions in binary form must reproduce the above copyrightD | 9 | * * Redistributions in binary form must reproduce the above copyrightD |
10 | * notice, this list of conditions and the following disclaimer in the | 10 | * notice, this list of conditions and the following disclaimer in the |
11 | * documentation and/or other materials provided with the distribution. | 11 | * documentation and/or other materials provided with the distribution. |
12 | * * Neither the name of the OpenSimulator Project nor the | 12 | * * Neither the name of the OpenSimulator Project nor the |
13 | * names of its contributors may be used to endorse or promote products | 13 | * names of its contributors may be used to endorse or promote products |
14 | * derived from this software without specific prior written permission. | 14 | * derived from this software without specific prior written permission. |
15 | * | 15 | * |
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | 16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY |
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | 19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY |
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 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 | 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 | 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 | 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. | 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ | 26 | */ |
27 | using System; | 27 | using System; |
28 | using System.Collections.Generic; | 28 | using System.Collections.Generic; |
29 | using System.Text; | 29 | using System.Text; |
30 | using OpenMetaverse; | 30 | using OpenMetaverse; |
31 | 31 | ||
32 | namespace OpenSim.Region.Physics.BulletSPlugin | 32 | namespace OpenSim.Region.Physics.BulletSPlugin |
33 | { | 33 | { |
34 | 34 | ||
35 | public sealed class BSConstraintHinge : BSConstraint | 35 | class BSHingeConstraint : BSConstraint |
36 | { | 36 | { |
37 | public override ConstraintType Type { get { return ConstraintType.HINGE_CONSTRAINT_TYPE; } } | 37 | public BSHingeConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, |
38 | 38 | Vector3 pivotInA, Vector3 pivotInB, | |
39 | public BSConstraintHinge(BulletSim world, BulletBody obj1, BulletBody obj2, | 39 | Vector3 axisInA, Vector3 axisInB, |
40 | Vector3 pivotInA, Vector3 pivotInB, | 40 | bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) |
41 | Vector3 axisInA, Vector3 axisInB, | 41 | { |
42 | bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) | 42 | m_world = world; |
43 | { | 43 | m_body1 = obj1; |
44 | m_world = world; | 44 | m_body2 = obj2; |
45 | m_body1 = obj1; | 45 | m_constraint = new BulletConstraint( |
46 | m_body2 = obj2; | 46 | BulletSimAPI.CreateHingeConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr, |
47 | m_constraint = new BulletConstraint( | 47 | pivotInA, pivotInB, |
48 | BulletSimAPI.CreateHingeConstraint2(m_world.ptr, m_body1.ptr, m_body2.ptr, | 48 | axisInA, axisInB, |
49 | pivotInA, pivotInB, | 49 | useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); |
50 | axisInA, axisInB, | 50 | m_enabled = true; |
51 | useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); | 51 | } |
52 | m_enabled = true; | 52 | |
53 | } | 53 | } |
54 | 54 | ||
55 | } | 55 | } |
56 | |||
57 | } | ||
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 3a92f93..087b9bb 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | |||
@@ -32,78 +32,35 @@ using OMV = OpenMetaverse; | |||
32 | 32 | ||
33 | namespace OpenSim.Region.Physics.BulletSPlugin | 33 | namespace OpenSim.Region.Physics.BulletSPlugin |
34 | { | 34 | { |
35 | public abstract class BSLinkset | 35 | public class BSLinkset |
36 | { | 36 | { |
37 | // private static string LogHeader = "[BULLETSIM LINKSET]"; | 37 | private static string LogHeader = "[BULLETSIM LINKSET]"; |
38 | 38 | ||
39 | public enum LinksetImplementation | 39 | private BSPrim m_linksetRoot; |
40 | { | 40 | public BSPrim LinksetRoot { get { return m_linksetRoot; } } |
41 | Constraint = 0, // linkset tied together with constraints | ||
42 | Compound = 1, // linkset tied together as a compound object | ||
43 | Manual = 2 // linkset tied together manually (code moves all the pieces) | ||
44 | } | ||
45 | // Create the correct type of linkset for this child | ||
46 | public static BSLinkset Factory(BSScene physScene, BSPhysObject parent) | ||
47 | { | ||
48 | BSLinkset ret = null; | ||
49 | |||
50 | switch ((int)physScene.Params.linksetImplementation) | ||
51 | { | ||
52 | case (int)LinksetImplementation.Compound: | ||
53 | ret = new BSLinksetCompound(physScene, parent); | ||
54 | break; | ||
55 | case (int)LinksetImplementation.Manual: | ||
56 | // ret = new BSLinksetManual(physScene, parent); | ||
57 | break; | ||
58 | default: | ||
59 | ret = new BSLinksetConstraints(physScene, parent); | ||
60 | break; | ||
61 | } | ||
62 | return ret; | ||
63 | } | ||
64 | |||
65 | public BSPhysObject LinksetRoot { get; protected set; } | ||
66 | 41 | ||
67 | public BSScene PhysicsScene { get; private set; } | 42 | private BSScene m_physicsScene; |
43 | public BSScene PhysicsScene { get { return m_physicsScene; } } | ||
68 | 44 | ||
69 | static int m_nextLinksetID = 1; | 45 | // The children under the root in this linkset |
70 | public int LinksetID { get; private set; } | 46 | private List<BSPrim> m_children; |
71 | |||
72 | // The children under the root in this linkset. | ||
73 | protected HashSet<BSPhysObject> m_children; | ||
74 | 47 | ||
75 | // We lock the diddling of linkset classes to prevent any badness. | 48 | // We lock the diddling of linkset classes to prevent any badness. |
76 | // This locks the modification of the instances of this class. Changes | 49 | // This locks the modification of the instances of this class. Changes |
77 | // to the physical representation is done via the tainting mechenism. | 50 | // to the physical representation is done via the tainting mechenism. |
78 | protected object m_linksetActivityLock = new Object(); | 51 | private object m_linksetActivityLock = new Object(); |
79 | |||
80 | // Some linksets have a preferred physical shape. | ||
81 | // Returns SHAPE_UNKNOWN if there is no preference. Causes the correct shape to be selected. | ||
82 | public virtual ShapeData.PhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor) | ||
83 | { | ||
84 | return ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; | ||
85 | } | ||
86 | 52 | ||
87 | // Linksets move around the children so the linkset might need to compute the child position | ||
88 | public virtual OMV.Vector3 Position(BSPhysObject member) | ||
89 | { return member.RawPosition; } | ||
90 | public virtual OMV.Quaternion Orientation(BSPhysObject member) | ||
91 | { return member.RawOrientation; } | ||
92 | // TODO: does this need to be done for Velocity and RotationalVelocityy? | ||
93 | |||
94 | // We keep the prim's mass in the linkset structure since it could be dependent on other prims | 53 | // We keep the prim's mass in the linkset structure since it could be dependent on other prims |
95 | protected float m_mass; | 54 | private float m_mass; |
96 | public float LinksetMass | 55 | public float LinksetMass |
97 | { | 56 | { |
98 | get | 57 | get |
99 | { | 58 | { |
100 | m_mass = ComputeLinksetMass(); | 59 | m_mass = ComputeLinksetMass(); |
101 | return m_mass; | 60 | return m_mass; |
102 | } | 61 | } |
103 | } | 62 | } |
104 | 63 | ||
105 | public virtual bool LinksetIsColliding { get { return false; } } | ||
106 | |||
107 | public OMV.Vector3 CenterOfMass | 64 | public OMV.Vector3 CenterOfMass |
108 | { | 65 | { |
109 | get { return ComputeLinksetCenterOfMass(); } | 66 | get { return ComputeLinksetCenterOfMass(); } |
@@ -114,30 +71,23 @@ public abstract class BSLinkset | |||
114 | get { return ComputeLinksetGeometricCenter(); } | 71 | get { return ComputeLinksetGeometricCenter(); } |
115 | } | 72 | } |
116 | 73 | ||
117 | protected void Initialize(BSScene scene, BSPhysObject parent) | 74 | public BSLinkset(BSScene scene, BSPrim parent) |
118 | { | 75 | { |
119 | // A simple linkset of one (no children) | 76 | // A simple linkset of one (no children) |
120 | LinksetID = m_nextLinksetID++; | 77 | m_physicsScene = scene; |
121 | // We create LOTS of linksets. | 78 | m_linksetRoot = parent; |
122 | if (m_nextLinksetID <= 0) | 79 | m_children = new List<BSPrim>(); |
123 | m_nextLinksetID = 1; | 80 | m_mass = parent.MassRaw; |
124 | PhysicsScene = scene; | ||
125 | LinksetRoot = parent; | ||
126 | m_children = new HashSet<BSPhysObject>(); | ||
127 | m_mass = parent.RawMass; | ||
128 | } | 81 | } |
129 | 82 | ||
130 | // Link to a linkset where the child knows the parent. | 83 | // Link to a linkset where the child knows the parent. |
131 | // Parent changing should not happen so do some sanity checking. | 84 | // Parent changing should not happen so do some sanity checking. |
132 | // We return the parent's linkset so the child can track its membership. | 85 | // We return the parent's linkset so the child can track its membership. |
133 | // Called at runtime. | 86 | public BSLinkset AddMeToLinkset(BSPrim child) |
134 | public BSLinkset AddMeToLinkset(BSPhysObject child) | ||
135 | { | 87 | { |
136 | lock (m_linksetActivityLock) | 88 | lock (m_linksetActivityLock) |
137 | { | 89 | { |
138 | // Don't add the root to its own linkset | 90 | AddChildToLinkset(child); |
139 | if (!IsRoot(child)) | ||
140 | AddChildToLinkset(child); | ||
141 | } | 91 | } |
142 | return this; | 92 | return this; |
143 | } | 93 | } |
@@ -145,27 +95,36 @@ public abstract class BSLinkset | |||
145 | // Remove a child from a linkset. | 95 | // Remove a child from a linkset. |
146 | // Returns a new linkset for the child which is a linkset of one (just the | 96 | // Returns a new linkset for the child which is a linkset of one (just the |
147 | // orphened child). | 97 | // orphened child). |
148 | // Called at runtime. | 98 | public BSLinkset RemoveMeFromLinkset(BSPrim child) |
149 | public BSLinkset RemoveMeFromLinkset(BSPhysObject child) | ||
150 | { | 99 | { |
151 | lock (m_linksetActivityLock) | 100 | lock (m_linksetActivityLock) |
152 | { | 101 | { |
153 | if (IsRoot(child)) | 102 | if (IsRoot(child)) |
154 | { | 103 | { |
155 | // Cannot remove the root from a linkset. | 104 | // if root of linkset, take the linkset apart |
156 | return this; | 105 | while (m_children.Count > 0) |
106 | { | ||
107 | // Note that we don't do a foreach because the remove routine | ||
108 | // takes it out of the list. | ||
109 | RemoveChildFromOtherLinkset(m_children[0]); | ||
110 | } | ||
111 | m_children.Clear(); // just to make sure | ||
112 | } | ||
113 | else | ||
114 | { | ||
115 | // Just removing a child from an existing linkset | ||
116 | RemoveChildFromLinkset(child); | ||
157 | } | 117 | } |
158 | RemoveChildFromLinkset(child); | ||
159 | } | 118 | } |
160 | 119 | ||
161 | // The child is down to a linkset of just itself | 120 | // The child is down to a linkset of just itself |
162 | return BSLinkset.Factory(PhysicsScene, child); | 121 | return new BSLinkset(PhysicsScene, child); |
163 | } | 122 | } |
164 | 123 | ||
165 | // Return 'true' if the passed object is the root object of this linkset | 124 | // Return 'true' if the passed object is the root object of this linkset |
166 | public bool IsRoot(BSPhysObject requestor) | 125 | public bool IsRoot(BSPrim requestor) |
167 | { | 126 | { |
168 | return (requestor.LocalID == LinksetRoot.LocalID); | 127 | return (requestor.LocalID == m_linksetRoot.LocalID); |
169 | } | 128 | } |
170 | 129 | ||
171 | public int NumberOfChildren { get { return m_children.Count; } } | 130 | public int NumberOfChildren { get { return m_children.Count; } } |
@@ -174,14 +133,12 @@ public abstract class BSLinkset | |||
174 | public bool HasAnyChildren { get { return (m_children.Count > 0); } } | 133 | public bool HasAnyChildren { get { return (m_children.Count > 0); } } |
175 | 134 | ||
176 | // Return 'true' if this child is in this linkset | 135 | // Return 'true' if this child is in this linkset |
177 | public bool HasChild(BSPhysObject child) | 136 | public bool HasChild(BSPrim child) |
178 | { | 137 | { |
179 | bool ret = false; | 138 | bool ret = false; |
180 | lock (m_linksetActivityLock) | 139 | lock (m_linksetActivityLock) |
181 | { | 140 | { |
182 | ret = m_children.Contains(child); | 141 | foreach (BSPrim bp in m_children) |
183 | /* Safer version but the above should work | ||
184 | foreach (BSPhysObject bp in m_children) | ||
185 | { | 142 | { |
186 | if (child.LocalID == bp.LocalID) | 143 | if (child.LocalID == bp.LocalID) |
187 | { | 144 | { |
@@ -189,132 +146,274 @@ public abstract class BSLinkset | |||
189 | break; | 146 | break; |
190 | } | 147 | } |
191 | } | 148 | } |
192 | */ | ||
193 | } | 149 | } |
194 | return ret; | 150 | return ret; |
195 | } | 151 | } |
196 | 152 | ||
197 | // Perform an action on each member of the linkset including root prim. | 153 | private float ComputeLinksetMass() |
198 | // Depends on the action on whether this should be done at taint time. | ||
199 | public delegate bool ForEachMemberAction(BSPhysObject obj); | ||
200 | public virtual bool ForEachMember(ForEachMemberAction action) | ||
201 | { | 154 | { |
202 | bool ret = false; | 155 | float mass = m_linksetRoot.MassRaw; |
156 | foreach (BSPrim bp in m_children) | ||
157 | { | ||
158 | mass += bp.MassRaw; | ||
159 | } | ||
160 | return mass; | ||
161 | } | ||
162 | |||
163 | private OMV.Vector3 ComputeLinksetCenterOfMass() | ||
164 | { | ||
165 | OMV.Vector3 com = m_linksetRoot.Position * m_linksetRoot.MassRaw; | ||
166 | float totalMass = m_linksetRoot.MassRaw; | ||
167 | |||
203 | lock (m_linksetActivityLock) | 168 | lock (m_linksetActivityLock) |
204 | { | 169 | { |
205 | action(LinksetRoot); | 170 | foreach (BSPrim bp in m_children) |
206 | foreach (BSPhysObject po in m_children) | ||
207 | { | 171 | { |
208 | if (action(po)) | 172 | com += bp.Position * bp.MassRaw; |
209 | break; | 173 | totalMass += bp.MassRaw; |
210 | } | 174 | } |
175 | if (totalMass != 0f) | ||
176 | com /= totalMass; | ||
211 | } | 177 | } |
212 | return ret; | 178 | |
179 | return com; | ||
213 | } | 180 | } |
214 | 181 | ||
215 | // I am the root of a linkset and a new child is being added | 182 | private OMV.Vector3 ComputeLinksetGeometricCenter() |
216 | // Called while LinkActivity is locked. | 183 | { |
217 | protected abstract void AddChildToLinkset(BSPhysObject child); | 184 | OMV.Vector3 com = m_linksetRoot.Position; |
218 | 185 | ||
219 | // I am the root of a linkset and one of my children is being removed. | 186 | lock (m_linksetActivityLock) |
220 | // Safe to call even if the child is not really in my linkset. | 187 | { |
221 | protected abstract void RemoveChildFromLinkset(BSPhysObject child); | 188 | foreach (BSPrim bp in m_children) |
189 | { | ||
190 | com += bp.Position * bp.MassRaw; | ||
191 | } | ||
192 | com /= (m_children.Count + 1); | ||
193 | } | ||
194 | |||
195 | return com; | ||
196 | } | ||
222 | 197 | ||
223 | // When physical properties are changed the linkset needs to recalculate | 198 | // When physical properties are changed the linkset needs to recalculate |
224 | // its internal properties. | 199 | // its internal properties. |
225 | // May be called at runtime or taint-time. | 200 | public void Refresh(BSPrim requestor) |
226 | public abstract void Refresh(BSPhysObject requestor); | ||
227 | |||
228 | // The object is going dynamic (physical). Do any setup necessary | ||
229 | // for a dynamic linkset. | ||
230 | // Only the state of the passed object can be modified. The rest of the linkset | ||
231 | // has not yet been fully constructed. | ||
232 | // Return 'true' if any properties updated on the passed object. | ||
233 | // Called at taint-time! | ||
234 | public abstract bool MakeDynamic(BSPhysObject child); | ||
235 | |||
236 | // The object is going static (non-physical). Do any setup necessary | ||
237 | // for a static linkset. | ||
238 | // Return 'true' if any properties updated on the passed object. | ||
239 | // Called at taint-time! | ||
240 | public abstract bool MakeStatic(BSPhysObject child); | ||
241 | |||
242 | // Called when a parameter update comes from the physics engine for any object | ||
243 | // of the linkset is received. | ||
244 | // Called at taint-time!! | ||
245 | public abstract void UpdateProperties(BSPhysObject physObject); | ||
246 | |||
247 | // Routine used when rebuilding the body of the root of the linkset | ||
248 | // Destroy all the constraints have have been made to root. | ||
249 | // This is called when the root body is changing. | ||
250 | // Returns 'true' of something was actually removed and would need restoring | ||
251 | // Called at taint-time!! | ||
252 | public abstract bool RemoveBodyDependencies(BSPrim child); | ||
253 | |||
254 | // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', | ||
255 | // this routine will restore the removed constraints. | ||
256 | // Called at taint-time!! | ||
257 | public abstract void RestoreBodyDependencies(BSPrim child); | ||
258 | |||
259 | // ================================================================ | ||
260 | protected virtual float ComputeLinksetMass() | ||
261 | { | 201 | { |
262 | float mass = LinksetRoot.RawMass; | 202 | // If there are no children, there aren't any constraints to recompute |
263 | if (HasAnyChildren) | 203 | if (!HasAnyChildren) |
204 | return; | ||
205 | |||
206 | // Only the root does the recomputation | ||
207 | if (IsRoot(requestor)) | ||
208 | { | ||
209 | PhysicsScene.TaintedObject("BSLinkSet.Refresh", delegate() | ||
210 | { | ||
211 | RecomputeLinksetConstraintVariables(); | ||
212 | }); | ||
213 | } | ||
214 | } | ||
215 | |||
216 | // Call each of the constraints that make up this linkset and recompute the | ||
217 | // various transforms and variables. Used when objects are added or removed | ||
218 | // from a linkset to make sure the constraints know about the new mass and | ||
219 | // geometry. | ||
220 | // Must only be called at taint time!! | ||
221 | private bool RecomputeLinksetConstraintVariables() | ||
222 | { | ||
223 | float linksetMass = LinksetMass; | ||
224 | lock (m_linksetActivityLock) | ||
264 | { | 225 | { |
265 | lock (m_linksetActivityLock) | 226 | foreach (BSPrim child in m_children) |
266 | { | 227 | { |
267 | foreach (BSPhysObject bp in m_children) | 228 | BSConstraint constrain; |
229 | if (m_physicsScene.Constraints.TryGetConstraint(LinksetRoot.Body, child.Body, out constrain)) | ||
230 | { | ||
231 | // DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}", | ||
232 | // LinksetRoot.LocalID, child.LocalID, linksetMass, constrain.Body1.ID, constrain.Body2.ID); | ||
233 | constrain.RecomputeConstraintVariables(linksetMass); | ||
234 | } | ||
235 | else | ||
268 | { | 236 | { |
269 | mass += bp.RawMass; | 237 | // Non-fatal error that can happen when children are being added to the linkset but |
238 | // their constraints have not been created yet. | ||
239 | // Caused by the fact that m_children is built at run time but building constraints | ||
240 | // happens at taint time. | ||
241 | // m_physicsScene.Logger.ErrorFormat("[BULLETSIM LINKSET] RecomputeLinksetConstraintVariables: constraint not found for root={0}, child={1}", | ||
242 | // m_linksetRoot.Body.ID, child.Body.ID); | ||
270 | } | 243 | } |
271 | } | 244 | } |
272 | } | 245 | } |
273 | return mass; | 246 | return false; |
274 | } | 247 | } |
275 | 248 | ||
276 | protected virtual OMV.Vector3 ComputeLinksetCenterOfMass() | 249 | // I am the root of a linkset and a new child is being added |
250 | // Called while LinkActivity is locked. | ||
251 | private void AddChildToLinkset(BSPrim child) | ||
277 | { | 252 | { |
278 | OMV.Vector3 com; | 253 | if (!HasChild(child)) |
279 | lock (m_linksetActivityLock) | ||
280 | { | 254 | { |
281 | com = LinksetRoot.Position * LinksetRoot.RawMass; | 255 | m_children.Add(child); |
282 | float totalMass = LinksetRoot.RawMass; | ||
283 | 256 | ||
284 | foreach (BSPhysObject bp in m_children) | 257 | BSPrim rootx = LinksetRoot; // capture the root as of now |
258 | BSPrim childx = child; | ||
259 | m_physicsScene.TaintedObject("AddChildToLinkset", delegate() | ||
285 | { | 260 | { |
286 | com += bp.Position * bp.RawMass; | 261 | // DebugLog("{0}: AddChildToLinkset: adding child {1} to {2}", LogHeader, child.LocalID, m_linksetRoot.LocalID); |
287 | totalMass += bp.RawMass; | 262 | // DetailLog("{0},AddChildToLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID); |
288 | } | 263 | PhysicallyLinkAChildToRoot(rootx, childx); // build the physical binding between me and the child |
289 | if (totalMass != 0f) | 264 | }); |
290 | com /= totalMass; | ||
291 | } | 265 | } |
266 | return; | ||
267 | } | ||
292 | 268 | ||
293 | return com; | 269 | // Forcefully removing a child from a linkset. |
270 | // This is not being called by the child so we have to make sure the child doesn't think | ||
271 | // it's still connected to the linkset. | ||
272 | // Normal OpenSimulator operation will never do this because other SceneObjectPart information | ||
273 | // has to be updated also (like pointer to prim's parent). | ||
274 | private void RemoveChildFromOtherLinkset(BSPrim pchild) | ||
275 | { | ||
276 | pchild.Linkset = new BSLinkset(m_physicsScene, pchild); | ||
277 | RemoveChildFromLinkset(pchild); | ||
294 | } | 278 | } |
295 | 279 | ||
296 | protected virtual OMV.Vector3 ComputeLinksetGeometricCenter() | 280 | // I am the root of a linkset and one of my children is being removed. |
281 | // Safe to call even if the child is not really in my linkset. | ||
282 | private void RemoveChildFromLinkset(BSPrim child) | ||
297 | { | 283 | { |
298 | OMV.Vector3 com; | 284 | if (m_children.Remove(child)) |
299 | lock (m_linksetActivityLock) | ||
300 | { | 285 | { |
301 | com = LinksetRoot.Position; | 286 | BSPrim rootx = LinksetRoot; // capture the root as of now |
302 | 287 | BSPrim childx = child; | |
303 | foreach (BSPhysObject bp in m_children) | 288 | m_physicsScene.TaintedObject("RemoveChildFromLinkset", delegate() |
304 | { | 289 | { |
305 | com += bp.Position * bp.RawMass; | 290 | // DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID); |
306 | } | 291 | // DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID); |
307 | com /= (m_children.Count + 1); | 292 | |
293 | PhysicallyUnlinkAChildFromRoot(rootx, childx); | ||
294 | }); | ||
295 | |||
296 | RecomputeLinksetConstraintVariables(); | ||
297 | } | ||
298 | else | ||
299 | { | ||
300 | // This will happen if we remove the root of the linkset first. Non-fatal occurance. | ||
301 | // PhysicsScene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader); | ||
308 | } | 302 | } |
303 | return; | ||
304 | } | ||
309 | 305 | ||
310 | return com; | 306 | // Create a constraint between me (root of linkset) and the passed prim (the child). |
307 | // Called at taint time! | ||
308 | private void PhysicallyLinkAChildToRoot(BSPrim rootPrim, BSPrim childPrim) | ||
309 | { | ||
310 | // Zero motion for children so they don't interpolate | ||
311 | childPrim.ZeroMotion(); | ||
312 | |||
313 | // Relative position normalized to the root prim | ||
314 | // Essentually a vector pointing from center of rootPrim to center of childPrim | ||
315 | OMV.Vector3 childRelativePosition = childPrim.Position - rootPrim.Position; | ||
316 | |||
317 | // real world coordinate of midpoint between the two objects | ||
318 | OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2); | ||
319 | |||
320 | // create a constraint that allows no freedom of movement between the two objects | ||
321 | // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 | ||
322 | // DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID); | ||
323 | DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2},rLoc={3},cLoc={4},midLoc={5}", | ||
324 | rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID, rootPrim.Position, childPrim.Position, midPoint); | ||
325 | BS6DofConstraint constrain = new BS6DofConstraint( | ||
326 | m_physicsScene.World, rootPrim.Body, childPrim.Body, | ||
327 | midPoint, | ||
328 | true, | ||
329 | true | ||
330 | ); | ||
331 | /* NOTE: attempt to build constraint with full frame computation, etc. | ||
332 | * Using the midpoint is easier since it lets the Bullet code use the transforms | ||
333 | * of the objects. | ||
334 | * Code left here as an example. | ||
335 | // ================================================================================== | ||
336 | // relative position normalized to the root prim | ||
337 | OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation); | ||
338 | OMV.Vector3 childRelativePosition = (childPrim.Position - rootPrim.Position) * invThisOrientation; | ||
339 | |||
340 | // relative rotation of the child to the parent | ||
341 | OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation; | ||
342 | OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation); | ||
343 | |||
344 | // create a constraint that allows no freedom of movement between the two objects | ||
345 | // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 | ||
346 | // DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID); | ||
347 | DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); | ||
348 | BS6DofConstraint constrain = new BS6DofConstraint( | ||
349 | PhysicsScene.World, rootPrim.Body, childPrim.Body, | ||
350 | OMV.Vector3.Zero, | ||
351 | OMV.Quaternion.Inverse(rootPrim.Orientation), | ||
352 | OMV.Vector3.Zero, | ||
353 | OMV.Quaternion.Inverse(childPrim.Orientation), | ||
354 | // A point half way between the parent and child | ||
355 | // childRelativePosition/2, | ||
356 | // childRelativeRotation, | ||
357 | // childRelativePosition/2, | ||
358 | // inverseChildRelativeRotation, | ||
359 | true, | ||
360 | true | ||
361 | ); | ||
362 | // ================================================================================== | ||
363 | */ | ||
364 | |||
365 | m_physicsScene.Constraints.AddConstraint(constrain); | ||
366 | |||
367 | // zero linear and angular limits makes the objects unable to move in relation to each other | ||
368 | constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); | ||
369 | constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); | ||
370 | |||
371 | // tweek the constraint to increase stability | ||
372 | constrain.UseFrameOffset(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintUseFrameOffset)); | ||
373 | constrain.TranslationalLimitMotor(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintEnableTransMotor), | ||
374 | PhysicsScene.Params.linkConstraintTransMotorMaxVel, | ||
375 | PhysicsScene.Params.linkConstraintTransMotorMaxForce); | ||
376 | constrain.SetCFMAndERP(PhysicsScene.Params.linkConstraintCFM, PhysicsScene.Params.linkConstraintERP); | ||
377 | |||
378 | RecomputeLinksetConstraintVariables(); | ||
379 | } | ||
380 | |||
381 | // Remove linkage between myself and a particular child | ||
382 | // Called at taint time! | ||
383 | private void PhysicallyUnlinkAChildFromRoot(BSPrim rootPrim, BSPrim childPrim) | ||
384 | { | ||
385 | // DebugLog("{0}: PhysicallyUnlinkAChildFromRoot: RemoveConstraint between root prim {1} and child prim {2}", | ||
386 | // LogHeader, rootPrim.LocalID, childPrim.LocalID); | ||
387 | DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); | ||
388 | |||
389 | // Find the constraint for this link and get rid of it from the overall collection and from my list | ||
390 | m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body, childPrim.Body); | ||
391 | |||
392 | // Make the child refresh its location | ||
393 | BulletSimAPI.PushUpdate2(childPrim.Body.Ptr); | ||
394 | } | ||
395 | |||
396 | // Remove linkage between myself and any possible children I might have | ||
397 | // Called at taint time! | ||
398 | private void PhysicallyUnlinkAllChildrenFromRoot(BSPrim rootPrim) | ||
399 | { | ||
400 | // DebugLog("{0}: PhysicallyUnlinkAllChildren:", LogHeader); | ||
401 | DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); | ||
402 | |||
403 | m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body); | ||
404 | } | ||
405 | |||
406 | // Invoke the detailed logger and output something if it's enabled. | ||
407 | private void DebugLog(string msg, params Object[] args) | ||
408 | { | ||
409 | if (m_physicsScene.ShouldDebugLog) | ||
410 | m_physicsScene.Logger.DebugFormat(msg, args); | ||
311 | } | 411 | } |
312 | 412 | ||
313 | // Invoke the detailed logger and output something if it's enabled. | 413 | // Invoke the detailed logger and output something if it's enabled. |
314 | protected void DetailLog(string msg, params Object[] args) | 414 | private void DetailLog(string msg, params Object[] args) |
315 | { | 415 | { |
316 | if (PhysicsScene.PhysicsLogging.Enabled) | 416 | m_physicsScene.PhysicsLogging.Write(msg, args); |
317 | PhysicsScene.DetailLog(msg, args); | ||
318 | } | 417 | } |
319 | 418 | ||
320 | } | 419 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs deleted file mode 100755 index 12c6d7a..0000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs +++ /dev/null | |||
@@ -1,273 +0,0 @@ | |||
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 copyrightD | ||
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 | using System; | ||
28 | using System.Collections.Generic; | ||
29 | using System.Text; | ||
30 | |||
31 | using OMV = OpenMetaverse; | ||
32 | |||
33 | namespace OpenSim.Region.Physics.BulletSPlugin | ||
34 | { | ||
35 | public sealed class BSLinksetCompound : BSLinkset | ||
36 | { | ||
37 | private static string LogHeader = "[BULLETSIM LINKSET COMPOUND]"; | ||
38 | |||
39 | public BSLinksetCompound(BSScene scene, BSPhysObject parent) | ||
40 | { | ||
41 | base.Initialize(scene, parent); | ||
42 | } | ||
43 | |||
44 | // For compound implimented linksets, if there are children, use compound shape for the root. | ||
45 | public override ShapeData.PhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor) | ||
46 | { | ||
47 | ShapeData.PhysicsShapeType ret = ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; | ||
48 | if (IsRoot(requestor) && HasAnyChildren) | ||
49 | { | ||
50 | ret = ShapeData.PhysicsShapeType.SHAPE_COMPOUND; | ||
51 | } | ||
52 | // DetailLog("{0},BSLinksetCompound.PreferredPhysicalShape,call,shape={1}", LinksetRoot.LocalID, ret); | ||
53 | return ret; | ||
54 | } | ||
55 | |||
56 | // When physical properties are changed the linkset needs to recalculate | ||
57 | // its internal properties. | ||
58 | // This is queued in the 'post taint' queue so the | ||
59 | // refresh will happen once after all the other taints are applied. | ||
60 | public override void Refresh(BSPhysObject requestor) | ||
61 | { | ||
62 | // External request for Refresh (from BSPrim) is not necessary | ||
63 | // InternalRefresh(requestor); | ||
64 | } | ||
65 | |||
66 | private void InternalRefresh(BSPhysObject requestor) | ||
67 | { | ||
68 | DetailLog("{0},BSLinksetCompound.Refresh,schedulingRefresh,requestor={1}", LinksetRoot.LocalID, requestor.LocalID); | ||
69 | // Queue to happen after all the other taint processing | ||
70 | PhysicsScene.PostTaintObject("BSLinksetCompound.Refresh", requestor.LocalID, delegate() | ||
71 | { | ||
72 | if (IsRoot(requestor) && HasAnyChildren) | ||
73 | RecomputeLinksetCompound(); | ||
74 | }); | ||
75 | } | ||
76 | |||
77 | // The object is going dynamic (physical). Do any setup necessary | ||
78 | // for a dynamic linkset. | ||
79 | // Only the state of the passed object can be modified. The rest of the linkset | ||
80 | // has not yet been fully constructed. | ||
81 | // Return 'true' if any properties updated on the passed object. | ||
82 | // Called at taint-time! | ||
83 | public override bool MakeDynamic(BSPhysObject child) | ||
84 | { | ||
85 | bool ret = false; | ||
86 | DetailLog("{0},BSLinksetCompound.MakeDynamic,call,IsRoot={1}", child.LocalID, IsRoot(child)); | ||
87 | if (!IsRoot(child)) | ||
88 | { | ||
89 | // Physical children are removed from the world as the shape ofthe root compound | ||
90 | // shape takes over. | ||
91 | BulletSimAPI.AddToCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); | ||
92 | BulletSimAPI.ForceActivationState2(child.PhysBody.ptr, ActivationState.DISABLE_SIMULATION); | ||
93 | ret = true; | ||
94 | } | ||
95 | return ret; | ||
96 | } | ||
97 | |||
98 | // The object is going static (non-physical). Do any setup necessary for a static linkset. | ||
99 | // Return 'true' if any properties updated on the passed object. | ||
100 | // This doesn't normally happen -- OpenSim removes the objects from the physical | ||
101 | // world if it is a static linkset. | ||
102 | // Called at taint-time! | ||
103 | public override bool MakeStatic(BSPhysObject child) | ||
104 | { | ||
105 | bool ret = false; | ||
106 | DetailLog("{0},BSLinksetCompound.MakeStatic,call,IsRoot={1}", child.LocalID, IsRoot(child)); | ||
107 | if (!IsRoot(child)) | ||
108 | { | ||
109 | // The non-physical children can come back to life. | ||
110 | BulletSimAPI.RemoveFromCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); | ||
111 | // Don't force activation so setting of DISABLE_SIMULATION can stay. | ||
112 | BulletSimAPI.Activate2(child.PhysBody.ptr, false); | ||
113 | ret = true; | ||
114 | } | ||
115 | return ret; | ||
116 | } | ||
117 | |||
118 | // Called at taint-time!! | ||
119 | public override void UpdateProperties(BSPhysObject updated) | ||
120 | { | ||
121 | // Nothing to do for constraints on property updates | ||
122 | } | ||
123 | |||
124 | // The children move around in relationship to the root. | ||
125 | // Just grab the current values of wherever it is right now. | ||
126 | public override OMV.Vector3 Position(BSPhysObject member) | ||
127 | { | ||
128 | return BulletSimAPI.GetPosition2(member.PhysBody.ptr); | ||
129 | } | ||
130 | |||
131 | public override OMV.Quaternion Orientation(BSPhysObject member) | ||
132 | { | ||
133 | return BulletSimAPI.GetOrientation2(member.PhysBody.ptr); | ||
134 | } | ||
135 | |||
136 | // Routine called when rebuilding the body of some member of the linkset. | ||
137 | // Since we don't keep in world relationships, do nothing unless it's a child changing. | ||
138 | // Returns 'true' of something was actually removed and would need restoring | ||
139 | // Called at taint-time!! | ||
140 | public override bool RemoveBodyDependencies(BSPrim child) | ||
141 | { | ||
142 | bool ret = false; | ||
143 | |||
144 | DetailLog("{0},BSLinksetCompound.RemoveBodyDependencies,refreshIfChild,rID={1},rBody={2},isRoot={3}", | ||
145 | child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), IsRoot(child)); | ||
146 | |||
147 | if (!IsRoot(child)) | ||
148 | { | ||
149 | // Cause the current shape to be freed and the new one to be built. | ||
150 | InternalRefresh(LinksetRoot); | ||
151 | ret = true; | ||
152 | } | ||
153 | |||
154 | return ret; | ||
155 | } | ||
156 | |||
157 | // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', | ||
158 | // this routine will restore the removed constraints. | ||
159 | // Called at taint-time!! | ||
160 | public override void RestoreBodyDependencies(BSPrim child) | ||
161 | { | ||
162 | // The Refresh operation queued by RemoveBodyDependencies() will build any missing constraints. | ||
163 | } | ||
164 | |||
165 | // ================================================================ | ||
166 | |||
167 | // Add a new child to the linkset. | ||
168 | // Called while LinkActivity is locked. | ||
169 | protected override void AddChildToLinkset(BSPhysObject child) | ||
170 | { | ||
171 | if (!HasChild(child)) | ||
172 | { | ||
173 | m_children.Add(child); | ||
174 | |||
175 | DetailLog("{0},BSLinksetCompound.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); | ||
176 | |||
177 | // Cause constraints and assorted properties to be recomputed before the next simulation step. | ||
178 | InternalRefresh(LinksetRoot); | ||
179 | } | ||
180 | return; | ||
181 | } | ||
182 | |||
183 | // Remove the specified child from the linkset. | ||
184 | // Safe to call even if the child is not really in my linkset. | ||
185 | protected override void RemoveChildFromLinkset(BSPhysObject child) | ||
186 | { | ||
187 | if (m_children.Remove(child)) | ||
188 | { | ||
189 | DetailLog("{0},BSLinksetCompound.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", | ||
190 | child.LocalID, | ||
191 | LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), | ||
192 | child.LocalID, child.PhysBody.ptr.ToString("X")); | ||
193 | |||
194 | // Cause the child's body to be rebuilt and thus restored to normal operation | ||
195 | child.ForceBodyShapeRebuild(false); | ||
196 | |||
197 | if (!HasAnyChildren) | ||
198 | { | ||
199 | // The linkset is now empty. The root needs rebuilding. | ||
200 | LinksetRoot.ForceBodyShapeRebuild(false); | ||
201 | } | ||
202 | else | ||
203 | { | ||
204 | // Schedule a rebuild of the linkset before the next simulation tick. | ||
205 | InternalRefresh(LinksetRoot); | ||
206 | } | ||
207 | } | ||
208 | return; | ||
209 | } | ||
210 | |||
211 | // Called before the simulation step to make sure the compound based linkset | ||
212 | // is all initialized. | ||
213 | // Constraint linksets are rebuilt every time. | ||
214 | // Note that this works for rebuilding just the root after a linkset is taken apart. | ||
215 | // Called at taint time!! | ||
216 | private void RecomputeLinksetCompound() | ||
217 | { | ||
218 | // Cause the root shape to be rebuilt as a compound object with just the root in it | ||
219 | LinksetRoot.ForceBodyShapeRebuild(true); | ||
220 | |||
221 | DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},rShape={2},numChildren={3}", | ||
222 | LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren); | ||
223 | |||
224 | // Add a shape for each of the other children in the linkset | ||
225 | ForEachMember(delegate(BSPhysObject cPrim) | ||
226 | { | ||
227 | if (!IsRoot(cPrim)) | ||
228 | { | ||
229 | // Each child position and rotation is given relative to the root. | ||
230 | OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation); | ||
231 | OMV.Vector3 displacementPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation; | ||
232 | OMV.Quaternion displacementRot = cPrim.RawOrientation * invRootOrientation; | ||
233 | |||
234 | DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addMemberToShape,mID={1},mShape={2},dispPos={3},dispRot={4}", | ||
235 | LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, displacementPos, displacementRot); | ||
236 | |||
237 | if (cPrim.PhysShape.isNativeShape) | ||
238 | { | ||
239 | // Native shapes are not shared so we need to create a new one. | ||
240 | // A mesh or hull is created because scale is not available on a native shape. | ||
241 | // (TODO: Bullet does have a btScaledCollisionShape. Can that be used?) | ||
242 | BulletShape saveShape = cPrim.PhysShape; | ||
243 | cPrim.PhysShape.ptr = IntPtr.Zero; // Don't let the create free the child's shape | ||
244 | PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null); | ||
245 | BulletShape newShape = cPrim.PhysShape; | ||
246 | cPrim.PhysShape = saveShape; | ||
247 | BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, newShape.ptr, displacementPos, displacementRot); | ||
248 | } | ||
249 | else | ||
250 | { | ||
251 | // For the shared shapes (meshes and hulls), just use the shape in the child. | ||
252 | if (PhysicsScene.Shapes.ReferenceShape(cPrim.PhysShape)) | ||
253 | { | ||
254 | PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}", | ||
255 | LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape); | ||
256 | } | ||
257 | BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, cPrim.PhysShape.ptr, displacementPos, displacementRot); | ||
258 | } | ||
259 | } | ||
260 | return false; // 'false' says to move onto the next child in the list | ||
261 | }); | ||
262 | |||
263 | // With all of the linkset packed into the root prim, it has the mass of everyone. | ||
264 | float linksetMass = LinksetMass; | ||
265 | LinksetRoot.UpdatePhysicalMassProperties(linksetMass); | ||
266 | |||
267 | // DEBUG: see of inter-linkset collisions are causing problems for constraint linksets. | ||
268 | // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, | ||
269 | // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); | ||
270 | |||
271 | } | ||
272 | } | ||
273 | } \ No newline at end of file | ||
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs deleted file mode 100755 index d2387fb..0000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs +++ /dev/null | |||
@@ -1,327 +0,0 @@ | |||
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 copyrightD | ||
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 | using System; | ||
28 | using System.Collections.Generic; | ||
29 | using System.Text; | ||
30 | |||
31 | using OMV = OpenMetaverse; | ||
32 | |||
33 | namespace OpenSim.Region.Physics.BulletSPlugin | ||
34 | { | ||
35 | public sealed class BSLinksetConstraints : BSLinkset | ||
36 | { | ||
37 | // private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINTS]"; | ||
38 | |||
39 | public BSLinksetConstraints(BSScene scene, BSPhysObject parent) | ||
40 | { | ||
41 | base.Initialize(scene, parent); | ||
42 | } | ||
43 | |||
44 | // When physical properties are changed the linkset needs to recalculate | ||
45 | // its internal properties. | ||
46 | // This is queued in the 'post taint' queue so the | ||
47 | // refresh will happen once after all the other taints are applied. | ||
48 | public override void Refresh(BSPhysObject requestor) | ||
49 | { | ||
50 | // Queue to happen after all the other taint processing | ||
51 | PhysicsScene.PostTaintObject("BSLinksetContraints.Refresh", requestor.LocalID, delegate() | ||
52 | { | ||
53 | if (HasAnyChildren && IsRoot(requestor)) | ||
54 | RecomputeLinksetConstraints(); | ||
55 | }); | ||
56 | } | ||
57 | |||
58 | // The object is going dynamic (physical). Do any setup necessary | ||
59 | // for a dynamic linkset. | ||
60 | // Only the state of the passed object can be modified. The rest of the linkset | ||
61 | // has not yet been fully constructed. | ||
62 | // Return 'true' if any properties updated on the passed object. | ||
63 | // Called at taint-time! | ||
64 | public override bool MakeDynamic(BSPhysObject child) | ||
65 | { | ||
66 | // What is done for each object in BSPrim is what we want. | ||
67 | return false; | ||
68 | } | ||
69 | |||
70 | // The object is going static (non-physical). Do any setup necessary for a static linkset. | ||
71 | // Return 'true' if any properties updated on the passed object. | ||
72 | // This doesn't normally happen -- OpenSim removes the objects from the physical | ||
73 | // world if it is a static linkset. | ||
74 | // Called at taint-time! | ||
75 | public override bool MakeStatic(BSPhysObject child) | ||
76 | { | ||
77 | // What is done for each object in BSPrim is what we want. | ||
78 | return false; | ||
79 | } | ||
80 | |||
81 | // Called at taint-time!! | ||
82 | public override void UpdateProperties(BSPhysObject updated) | ||
83 | { | ||
84 | // Nothing to do for constraints on property updates | ||
85 | } | ||
86 | |||
87 | // The children of the linkset are moved around by the constraints. | ||
88 | // Just grab the current values of wherever it is right now. | ||
89 | public override OMV.Vector3 Position(BSPhysObject member) | ||
90 | { | ||
91 | return BulletSimAPI.GetPosition2(member.PhysBody.ptr); | ||
92 | } | ||
93 | |||
94 | public override OMV.Quaternion Orientation(BSPhysObject member) | ||
95 | { | ||
96 | return BulletSimAPI.GetOrientation2(member.PhysBody.ptr); | ||
97 | } | ||
98 | |||
99 | // Routine called when rebuilding the body of some member of the linkset. | ||
100 | // Destroy all the constraints have have been made to root and set | ||
101 | // up to rebuild the constraints before the next simulation step. | ||
102 | // Returns 'true' of something was actually removed and would need restoring | ||
103 | // Called at taint-time!! | ||
104 | public override bool RemoveBodyDependencies(BSPrim child) | ||
105 | { | ||
106 | bool ret = false; | ||
107 | |||
108 | DetailLog("{0},BSLinksetConstraint.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", | ||
109 | child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X")); | ||
110 | |||
111 | lock (m_linksetActivityLock) | ||
112 | { | ||
113 | // Just undo all the constraints for this linkset. Rebuild at the end of the step. | ||
114 | ret = PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot); | ||
115 | // Cause the constraints, et al to be rebuilt before the next simulation step. | ||
116 | Refresh(LinksetRoot); | ||
117 | } | ||
118 | return ret; | ||
119 | } | ||
120 | |||
121 | // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', | ||
122 | // this routine will restore the removed constraints. | ||
123 | // Called at taint-time!! | ||
124 | public override void RestoreBodyDependencies(BSPrim child) | ||
125 | { | ||
126 | // The Refresh operation queued by RemoveBodyDependencies() will build any missing constraints. | ||
127 | } | ||
128 | |||
129 | // ================================================================ | ||
130 | |||
131 | // Add a new child to the linkset. | ||
132 | // Called while LinkActivity is locked. | ||
133 | protected override void AddChildToLinkset(BSPhysObject child) | ||
134 | { | ||
135 | if (!HasChild(child)) | ||
136 | { | ||
137 | m_children.Add(child); | ||
138 | |||
139 | DetailLog("{0},BSLinksetConstraints.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); | ||
140 | |||
141 | // Cause constraints and assorted properties to be recomputed before the next simulation step. | ||
142 | Refresh(LinksetRoot); | ||
143 | } | ||
144 | return; | ||
145 | } | ||
146 | |||
147 | // Remove the specified child from the linkset. | ||
148 | // Safe to call even if the child is not really in my linkset. | ||
149 | protected override void RemoveChildFromLinkset(BSPhysObject child) | ||
150 | { | ||
151 | if (m_children.Remove(child)) | ||
152 | { | ||
153 | BSPhysObject rootx = LinksetRoot; // capture the root and body as of now | ||
154 | BSPhysObject childx = child; | ||
155 | |||
156 | DetailLog("{0},BSLinksetConstraints.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", | ||
157 | childx.LocalID, | ||
158 | rootx.LocalID, rootx.PhysBody.ptr.ToString("X"), | ||
159 | childx.LocalID, childx.PhysBody.ptr.ToString("X")); | ||
160 | |||
161 | PhysicsScene.TaintedObject("BSLinksetConstraints.RemoveChildFromLinkset", delegate() | ||
162 | { | ||
163 | PhysicallyUnlinkAChildFromRoot(rootx, childx); | ||
164 | }); | ||
165 | // See that the linkset parameters are recomputed at the end of the taint time. | ||
166 | Refresh(LinksetRoot); | ||
167 | } | ||
168 | else | ||
169 | { | ||
170 | // Non-fatal occurance. | ||
171 | // PhysicsScene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader); | ||
172 | } | ||
173 | return; | ||
174 | } | ||
175 | |||
176 | // Create a constraint between me (root of linkset) and the passed prim (the child). | ||
177 | // Called at taint time! | ||
178 | private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BSPhysObject childPrim) | ||
179 | { | ||
180 | // Don't build the constraint when asked. Put it off until just before the simulation step. | ||
181 | Refresh(rootPrim); | ||
182 | } | ||
183 | |||
184 | private BSConstraint BuildConstraint(BSPhysObject rootPrim, BSPhysObject childPrim) | ||
185 | { | ||
186 | // Zero motion for children so they don't interpolate | ||
187 | childPrim.ZeroMotion(); | ||
188 | |||
189 | // Relative position normalized to the root prim | ||
190 | // Essentually a vector pointing from center of rootPrim to center of childPrim | ||
191 | OMV.Vector3 childRelativePosition = childPrim.Position - rootPrim.Position; | ||
192 | |||
193 | // real world coordinate of midpoint between the two objects | ||
194 | OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2); | ||
195 | |||
196 | DetailLog("{0},BSLinksetConstraint.BuildConstraint,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}", | ||
197 | rootPrim.LocalID, | ||
198 | rootPrim.LocalID, rootPrim.PhysBody.ptr.ToString("X"), | ||
199 | childPrim.LocalID, childPrim.PhysBody.ptr.ToString("X"), | ||
200 | rootPrim.Position, childPrim.Position, midPoint); | ||
201 | |||
202 | // create a constraint that allows no freedom of movement between the two objects | ||
203 | // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 | ||
204 | |||
205 | BSConstraint6Dof constrain = new BSConstraint6Dof( | ||
206 | PhysicsScene.World, rootPrim.PhysBody, childPrim.PhysBody, midPoint, true, true ); | ||
207 | // PhysicsScene.World, childPrim.BSBody, rootPrim.BSBody, midPoint, true, true ); | ||
208 | |||
209 | /* NOTE: below is an attempt to build constraint with full frame computation, etc. | ||
210 | * Using the midpoint is easier since it lets the Bullet code manipulate the transforms | ||
211 | * of the objects. | ||
212 | * Code left for future programmers. | ||
213 | // ================================================================================== | ||
214 | // relative position normalized to the root prim | ||
215 | OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation); | ||
216 | OMV.Vector3 childRelativePosition = (childPrim.Position - rootPrim.Position) * invThisOrientation; | ||
217 | |||
218 | // relative rotation of the child to the parent | ||
219 | OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation; | ||
220 | OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation); | ||
221 | |||
222 | DetailLog("{0},BSLinksetConstraint.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); | ||
223 | BS6DofConstraint constrain = new BS6DofConstraint( | ||
224 | PhysicsScene.World, rootPrim.Body, childPrim.Body, | ||
225 | OMV.Vector3.Zero, | ||
226 | OMV.Quaternion.Inverse(rootPrim.Orientation), | ||
227 | OMV.Vector3.Zero, | ||
228 | OMV.Quaternion.Inverse(childPrim.Orientation), | ||
229 | true, | ||
230 | true | ||
231 | ); | ||
232 | // ================================================================================== | ||
233 | */ | ||
234 | |||
235 | PhysicsScene.Constraints.AddConstraint(constrain); | ||
236 | |||
237 | // zero linear and angular limits makes the objects unable to move in relation to each other | ||
238 | constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); | ||
239 | constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); | ||
240 | |||
241 | // tweek the constraint to increase stability | ||
242 | constrain.UseFrameOffset(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintUseFrameOffset)); | ||
243 | constrain.TranslationalLimitMotor(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintEnableTransMotor), | ||
244 | PhysicsScene.Params.linkConstraintTransMotorMaxVel, | ||
245 | PhysicsScene.Params.linkConstraintTransMotorMaxForce); | ||
246 | constrain.SetCFMAndERP(PhysicsScene.Params.linkConstraintCFM, PhysicsScene.Params.linkConstraintERP); | ||
247 | if (PhysicsScene.Params.linkConstraintSolverIterations != 0f) | ||
248 | { | ||
249 | constrain.SetSolverIterations(PhysicsScene.Params.linkConstraintSolverIterations); | ||
250 | } | ||
251 | return constrain; | ||
252 | } | ||
253 | |||
254 | // Remove linkage between the linkset root and a particular child | ||
255 | // The root and child bodies are passed in because we need to remove the constraint between | ||
256 | // the bodies that were present at unlink time. | ||
257 | // Called at taint time! | ||
258 | private bool PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BSPhysObject childPrim) | ||
259 | { | ||
260 | bool ret = false; | ||
261 | DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}", | ||
262 | rootPrim.LocalID, | ||
263 | rootPrim.LocalID, rootPrim.PhysBody.ptr.ToString("X"), | ||
264 | childPrim.LocalID, childPrim.PhysBody.ptr.ToString("X")); | ||
265 | |||
266 | // Find the constraint for this link and get rid of it from the overall collection and from my list | ||
267 | if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody, childPrim.PhysBody)) | ||
268 | { | ||
269 | // Make the child refresh its location | ||
270 | BulletSimAPI.PushUpdate2(childPrim.PhysBody.ptr); | ||
271 | ret = true; | ||
272 | } | ||
273 | |||
274 | return ret; | ||
275 | } | ||
276 | |||
277 | // Remove linkage between myself and any possible children I might have. | ||
278 | // Returns 'true' of any constraints were destroyed. | ||
279 | // Called at taint time! | ||
280 | private bool PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim) | ||
281 | { | ||
282 | DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); | ||
283 | |||
284 | return PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody); | ||
285 | } | ||
286 | |||
287 | // Call each of the constraints that make up this linkset and recompute the | ||
288 | // various transforms and variables. Create constraints of not created yet. | ||
289 | // Called before the simulation step to make sure the constraint based linkset | ||
290 | // is all initialized. | ||
291 | // Called at taint time!! | ||
292 | private void RecomputeLinksetConstraints() | ||
293 | { | ||
294 | float linksetMass = LinksetMass; | ||
295 | LinksetRoot.UpdatePhysicalMassProperties(linksetMass); | ||
296 | |||
297 | // DEBUG: see of inter-linkset collisions are causing problems | ||
298 | // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, | ||
299 | // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); | ||
300 | DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraints,set,rBody={1},linksetMass={2}", | ||
301 | LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), linksetMass); | ||
302 | |||
303 | foreach (BSPhysObject child in m_children) | ||
304 | { | ||
305 | // A child in the linkset physically shows the mass of the whole linkset. | ||
306 | // This allows Bullet to apply enough force on the child to move the whole linkset. | ||
307 | // (Also do the mass stuff before recomputing the constraint so mass is not zero.) | ||
308 | child.UpdatePhysicalMassProperties(linksetMass); | ||
309 | |||
310 | BSConstraint constrain; | ||
311 | if (!PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.PhysBody, child.PhysBody, out constrain)) | ||
312 | { | ||
313 | // If constraint doesn't exist yet, create it. | ||
314 | constrain = BuildConstraint(LinksetRoot, child); | ||
315 | } | ||
316 | constrain.RecomputeConstraintVariables(linksetMass); | ||
317 | |||
318 | // DEBUG: see of inter-linkset collisions are causing problems | ||
319 | // BulletSimAPI.SetCollisionFilterMask2(child.BSBody.ptr, | ||
320 | // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); | ||
321 | |||
322 | // BulletSimAPI.DumpConstraint2(PhysicsScene.World.ptr, constrain.Constraint.ptr); // DEBUG DEBUG | ||
323 | } | ||
324 | |||
325 | } | ||
326 | } | ||
327 | } | ||
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs deleted file mode 100755 index 7127aaf..0000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ /dev/null | |||
@@ -1,248 +0,0 @@ | |||
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 copyrightD | ||
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 | using System; | ||
28 | using System.Collections.Generic; | ||
29 | using System.Text; | ||
30 | |||
31 | using OMV = OpenMetaverse; | ||
32 | using OpenSim.Framework; | ||
33 | using OpenSim.Region.Physics.Manager; | ||
34 | |||
35 | namespace OpenSim.Region.Physics.BulletSPlugin | ||
36 | { | ||
37 | // Class to wrap all objects. | ||
38 | // The rest of BulletSim doesn't need to keep checking for avatars or prims | ||
39 | // unless the difference is significant. | ||
40 | public abstract class BSPhysObject : PhysicsActor | ||
41 | { | ||
42 | protected void BaseInitialize(BSScene parentScene, uint localID, string name, string typeName) | ||
43 | { | ||
44 | PhysicsScene = parentScene; | ||
45 | LocalID = localID; | ||
46 | PhysObjectName = name; | ||
47 | TypeName = typeName; | ||
48 | |||
49 | Linkset = BSLinkset.Factory(PhysicsScene, this); | ||
50 | LastAssetBuildFailed = false; | ||
51 | |||
52 | CollisionCollection = new CollisionEventUpdate(); | ||
53 | SubscribedEventsMs = 0; | ||
54 | CollidingStep = 0; | ||
55 | CollidingGroundStep = 0; | ||
56 | } | ||
57 | |||
58 | public BSScene PhysicsScene { get; protected set; } | ||
59 | // public override uint LocalID { get; set; } // Use the LocalID definition in PhysicsActor | ||
60 | public string PhysObjectName { get; protected set; } | ||
61 | public string TypeName { get; protected set; } | ||
62 | |||
63 | public BSLinkset Linkset { get; set; } | ||
64 | |||
65 | // Return the object mass without calculating it or having side effects | ||
66 | public abstract float RawMass { get; } | ||
67 | // Set the raw mass but also update physical mass properties (inertia, ...) | ||
68 | public abstract void UpdatePhysicalMassProperties(float mass); | ||
69 | |||
70 | // Reference to the physical body (btCollisionObject) of this object | ||
71 | public BulletBody PhysBody; | ||
72 | // Reference to the physical shape (btCollisionShape) of this object | ||
73 | public BulletShape PhysShape; | ||
74 | |||
75 | // 'true' if the mesh's underlying asset failed to build. | ||
76 | // This will keep us from looping after the first time the build failed. | ||
77 | public bool LastAssetBuildFailed { get; set; } | ||
78 | |||
79 | // The objects base shape information. Null if not a prim type shape. | ||
80 | public PrimitiveBaseShape BaseShape { get; protected set; } | ||
81 | // Some types of objects have preferred physical representations. | ||
82 | // Returns SHAPE_UNKNOWN if there is no preference. | ||
83 | public virtual ShapeData.PhysicsShapeType PreferredPhysicalShape | ||
84 | { | ||
85 | get { return ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; } | ||
86 | } | ||
87 | |||
88 | // When the physical properties are updated, an EntityProperty holds the update values. | ||
89 | // Keep the current and last EntityProperties to enable computation of differences | ||
90 | // between the current update and the previous values. | ||
91 | public EntityProperties CurrentEntityProperties { get; set; } | ||
92 | public EntityProperties LastEntityProperties { get; set; } | ||
93 | |||
94 | public abstract OMV.Vector3 Scale { get; set; } | ||
95 | public abstract bool IsSolid { get; } | ||
96 | public abstract bool IsStatic { get; } | ||
97 | |||
98 | // Stop all physical motion. | ||
99 | public abstract void ZeroMotion(); | ||
100 | |||
101 | // Step the vehicle simulation for this object. A NOOP if the vehicle was not configured. | ||
102 | public virtual void StepVehicle(float timeStep) { } | ||
103 | |||
104 | // Update the physical location and motion of the object. Called with data from Bullet. | ||
105 | public abstract void UpdateProperties(EntityProperties entprop); | ||
106 | |||
107 | // Tell the object to clean up. | ||
108 | public abstract void Destroy(); | ||
109 | |||
110 | public abstract OMV.Vector3 RawPosition { get; set; } | ||
111 | public abstract OMV.Vector3 ForcePosition { get; set; } | ||
112 | |||
113 | public abstract OMV.Quaternion RawOrientation { get; set; } | ||
114 | public abstract OMV.Quaternion ForceOrientation { get; set; } | ||
115 | |||
116 | public abstract OMV.Vector3 ForceVelocity { get; set; } | ||
117 | |||
118 | public abstract OMV.Vector3 ForceRotationalVelocity { get; set; } | ||
119 | |||
120 | public abstract float ForceBuoyancy { get; set; } | ||
121 | |||
122 | public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; } | ||
123 | |||
124 | #region Collisions | ||
125 | |||
126 | // Requested number of milliseconds between collision events. Zero means disabled. | ||
127 | protected int SubscribedEventsMs { get; set; } | ||
128 | // Given subscription, the time that a collision may be passed up | ||
129 | protected int NextCollisionOkTime { get; set; } | ||
130 | // The simulation step that last had a collision | ||
131 | protected long CollidingStep { get; set; } | ||
132 | // The simulation step that last had a collision with the ground | ||
133 | protected long CollidingGroundStep { get; set; } | ||
134 | // The collision flags we think are set in Bullet | ||
135 | protected CollisionFlags CurrentCollisionFlags { get; set; } | ||
136 | |||
137 | // The collisions that have been collected this tick | ||
138 | protected CollisionEventUpdate CollisionCollection; | ||
139 | |||
140 | // The simulation step is telling this object about a collision. | ||
141 | // Return 'true' if a collision was processed and should be sent up. | ||
142 | // Called at taint time from within the Step() function | ||
143 | public virtual bool Collide(uint collidingWith, BSPhysObject collidee, | ||
144 | OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) | ||
145 | { | ||
146 | bool ret = false; | ||
147 | |||
148 | // The following lines make IsColliding() and IsCollidingGround() work | ||
149 | CollidingStep = PhysicsScene.SimulationStep; | ||
150 | if (collidingWith <= PhysicsScene.TerrainManager.HighestTerrainID) | ||
151 | { | ||
152 | CollidingGroundStep = PhysicsScene.SimulationStep; | ||
153 | } | ||
154 | |||
155 | // prims in the same linkset cannot collide with each other | ||
156 | if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID)) | ||
157 | { | ||
158 | return ret; | ||
159 | } | ||
160 | |||
161 | // if someone has subscribed for collision events.... | ||
162 | if (SubscribedEvents()) { | ||
163 | CollisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); | ||
164 | DetailLog("{0},{1}.Collison.AddCollider,call,with={2},point={3},normal={4},depth={5}", | ||
165 | LocalID, TypeName, collidingWith, contactPoint, contactNormal, pentrationDepth); | ||
166 | |||
167 | ret = true; | ||
168 | } | ||
169 | return ret; | ||
170 | } | ||
171 | |||
172 | // Send the collected collisions into the simulator. | ||
173 | // Called at taint time from within the Step() function thus no locking problems | ||
174 | // with CollisionCollection and ObjectsWithNoMoreCollisions. | ||
175 | // Return 'true' if there were some actual collisions passed up | ||
176 | public virtual bool SendCollisions() | ||
177 | { | ||
178 | bool ret = true; | ||
179 | // If the 'no collision' call, force it to happen right now so quick collision_end | ||
180 | bool force = CollisionCollection.Count == 0; | ||
181 | |||
182 | // throttle the collisions to the number of milliseconds specified in the subscription | ||
183 | if (force || (PhysicsScene.SimulationNowTime >= NextCollisionOkTime)) | ||
184 | { | ||
185 | NextCollisionOkTime = PhysicsScene.SimulationNowTime + SubscribedEventsMs; | ||
186 | |||
187 | // We are called if we previously had collisions. If there are no collisions | ||
188 | // this time, send up one last empty event so OpenSim can sense collision end. | ||
189 | if (CollisionCollection.Count == 0) | ||
190 | { | ||
191 | // If I have no collisions this time, remove me from the list of objects with collisions. | ||
192 | ret = false; | ||
193 | } | ||
194 | |||
195 | // DetailLog("{0},{1}.SendCollisionUpdate,call,numCollisions={2}", LocalID, TypeName, CollisionCollection.Count); | ||
196 | base.SendCollisionUpdate(CollisionCollection); | ||
197 | |||
198 | // The collisionCollection structure is passed around in the simulator. | ||
199 | // Make sure we don't have a handle to that one and that a new one is used for next time. | ||
200 | CollisionCollection = new CollisionEventUpdate(); | ||
201 | } | ||
202 | return ret; | ||
203 | } | ||
204 | |||
205 | // Subscribe for collision events. | ||
206 | // Parameter is the millisecond rate the caller wishes collision events to occur. | ||
207 | public override void SubscribeEvents(int ms) { | ||
208 | // DetailLog("{0},{1}.SubscribeEvents,subscribing,ms={2}", LocalID, TypeName, ms); | ||
209 | SubscribedEventsMs = ms; | ||
210 | if (ms > 0) | ||
211 | { | ||
212 | // make sure first collision happens | ||
213 | NextCollisionOkTime = Util.EnvironmentTickCountSubtract(SubscribedEventsMs); | ||
214 | |||
215 | PhysicsScene.TaintedObject(TypeName+".SubscribeEvents", delegate() | ||
216 | { | ||
217 | CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); | ||
218 | }); | ||
219 | } | ||
220 | else | ||
221 | { | ||
222 | // Subscribing for zero or less is the same as unsubscribing | ||
223 | UnSubscribeEvents(); | ||
224 | } | ||
225 | } | ||
226 | public override void UnSubscribeEvents() { | ||
227 | // DetailLog("{0},{1}.UnSubscribeEvents,unsubscribing", LocalID, TypeName); | ||
228 | SubscribedEventsMs = 0; | ||
229 | PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate() | ||
230 | { | ||
231 | CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); | ||
232 | }); | ||
233 | } | ||
234 | // Return 'true' if the simulator wants collision events | ||
235 | public override bool SubscribedEvents() { | ||
236 | return (SubscribedEventsMs > 0); | ||
237 | } | ||
238 | |||
239 | #endregion // Collisions | ||
240 | |||
241 | // High performance detailed logging routine used by the physical objects. | ||
242 | protected void DetailLog(string msg, params Object[] args) | ||
243 | { | ||
244 | if (PhysicsScene.PhysicsLogging.Enabled) | ||
245 | PhysicsScene.DetailLog(msg, args); | ||
246 | } | ||
247 | } | ||
248 | } | ||
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs index 20f5180..0f027b8 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs | |||
@@ -33,7 +33,7 @@ using OpenMetaverse; | |||
33 | namespace OpenSim.Region.Physics.BulletSPlugin | 33 | namespace OpenSim.Region.Physics.BulletSPlugin |
34 | { | 34 | { |
35 | /// <summary> | 35 | /// <summary> |
36 | /// Entry for a port of Bullet (http://bulletphysics.org/) to OpenSim. | 36 | /// Entry for a port of Bullet (http://bulletphysics.org/) to OpenSim. |
37 | /// This module interfaces to an unmanaged C++ library which makes the | 37 | /// This module interfaces to an unmanaged C++ library which makes the |
38 | /// actual calls into the Bullet physics engine. | 38 | /// actual calls into the Bullet physics engine. |
39 | /// The unmanaged library is found in opensim-libs::trunk/unmanaged/BulletSim/. | 39 | /// The unmanaged library is found in opensim-libs::trunk/unmanaged/BulletSim/. |
@@ -62,7 +62,7 @@ public class BSPlugin : IPhysicsPlugin | |||
62 | if (Util.IsWindows()) | 62 | if (Util.IsWindows()) |
63 | Util.LoadArchSpecificWindowsDll("BulletSim.dll"); | 63 | Util.LoadArchSpecificWindowsDll("BulletSim.dll"); |
64 | // If not Windows, loading is performed by the | 64 | // If not Windows, loading is performed by the |
65 | // Mono loader as specified in | 65 | // Mono loader as specified in |
66 | // "bin/Physics/OpenSim.Region.Physics.BulletSPlugin.dll.config". | 66 | // "bin/Physics/OpenSim.Region.Physics.BulletSPlugin.dll.config". |
67 | 67 | ||
68 | _mScene = new BSScene(sceneIdentifier); | 68 | _mScene = new BSScene(sceneIdentifier); |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index aaa0d93..9c20004 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | |||
@@ -24,9 +24,6 @@ | |||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | 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. | 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ | 26 | */ |
27 | |||
28 | // Uncomment this it enable code to do all shape an body memory management | ||
29 | // in the C# code. | ||
30 | using System; | 27 | using System; |
31 | using System.Reflection; | 28 | using System.Reflection; |
32 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
@@ -39,18 +36,32 @@ using OpenSim.Region.Physics.ConvexDecompositionDotNet; | |||
39 | 36 | ||
40 | namespace OpenSim.Region.Physics.BulletSPlugin | 37 | namespace OpenSim.Region.Physics.BulletSPlugin |
41 | { | 38 | { |
42 | |||
43 | [Serializable] | 39 | [Serializable] |
44 | public sealed class BSPrim : BSPhysObject | 40 | public sealed class BSPrim : PhysicsActor |
45 | { | 41 | { |
46 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 42 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
47 | private static readonly string LogHeader = "[BULLETS PRIM]"; | 43 | private static readonly string LogHeader = "[BULLETS PRIM]"; |
48 | 44 | ||
49 | // _size is what the user passed. Scale is what we pass to the physics engine with the mesh. | 45 | private void DebugLog(string mm, params Object[] xx) { if (_scene.ShouldDebugLog) m_log.DebugFormat(mm, xx); } |
50 | // Often Scale is unity because the meshmerizer will apply _size when creating the mesh. | 46 | |
47 | private IMesh _mesh; | ||
48 | private PrimitiveBaseShape _pbs; | ||
49 | private ShapeData.PhysicsShapeType _shapeType; | ||
50 | private ulong _meshKey; | ||
51 | private ulong _hullKey; | ||
52 | private List<ConvexResult> _hulls; | ||
53 | |||
54 | private BSScene _scene; | ||
55 | public BSScene Scene { get { return _scene; } } | ||
56 | private String _avName; | ||
57 | private uint _localID = 0; | ||
58 | |||
59 | // _size is what the user passed. _scale is what we pass to the physics engine with the mesh. | ||
60 | // Often _scale is unity because the meshmerizer will apply _size when creating the mesh. | ||
51 | private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user | 61 | private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user |
52 | // private OMV.Vector3 _scale; // the multiplier for each mesh dimension for the mesh as created by the meshmerizer | 62 | private OMV.Vector3 _scale; // the multiplier for each mesh dimension for the mesh as created by the meshmerizer |
53 | 63 | ||
64 | private bool _stopped; | ||
54 | private bool _grabbed; | 65 | private bool _grabbed; |
55 | private bool _isSelected; | 66 | private bool _isSelected; |
56 | private bool _isVolumeDetect; | 67 | private bool _isVolumeDetect; |
@@ -78,6 +89,25 @@ public sealed class BSPrim : BSPhysObject | |||
78 | private bool _kinematic; | 89 | private bool _kinematic; |
79 | private float _buoyancy; | 90 | private float _buoyancy; |
80 | 91 | ||
92 | // Membership in a linkset is controlled by this class. | ||
93 | private BSLinkset _linkset; | ||
94 | public BSLinkset Linkset | ||
95 | { | ||
96 | get { return _linkset; } | ||
97 | set { _linkset = value; } | ||
98 | } | ||
99 | |||
100 | private int _subscribedEventsMs = 0; | ||
101 | private int _nextCollisionOkTime = 0; | ||
102 | long _collidingStep; | ||
103 | long _collidingGroundStep; | ||
104 | |||
105 | private BulletBody m_body; | ||
106 | public BulletBody Body { | ||
107 | get { return m_body; } | ||
108 | set { m_body = value; } | ||
109 | } | ||
110 | |||
81 | private BSDynamics _vehicle; | 111 | private BSDynamics _vehicle; |
82 | 112 | ||
83 | private OMV.Vector3 _PIDTarget; | 113 | private OMV.Vector3 _PIDTarget; |
@@ -92,112 +122,108 @@ public sealed class BSPrim : BSPhysObject | |||
92 | OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) | 122 | OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) |
93 | { | 123 | { |
94 | // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID); | 124 | // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID); |
95 | base.BaseInitialize(parent_scene, localID, primName, "BSPrim"); | 125 | _localID = localID; |
96 | _physicsActorType = (int)ActorTypes.Prim; | 126 | _avName = primName; |
127 | _scene = parent_scene; | ||
97 | _position = pos; | 128 | _position = pos; |
98 | _size = size; | 129 | _size = size; |
99 | Scale = new OMV.Vector3(1f, 1f, 1f); // the scale will be set by CreateGeom depending on object type | 130 | _scale = new OMV.Vector3(1f, 1f, 1f); // the scale will be set by CreateGeom depending on object type |
100 | _orientation = rotation; | 131 | _orientation = rotation; |
101 | _buoyancy = 1f; | 132 | _buoyancy = 1f; |
102 | _velocity = OMV.Vector3.Zero; | 133 | _velocity = OMV.Vector3.Zero; |
103 | _rotationalVelocity = OMV.Vector3.Zero; | 134 | _rotationalVelocity = OMV.Vector3.Zero; |
104 | BaseShape = pbs; | 135 | _hullKey = 0; |
136 | _meshKey = 0; | ||
137 | _pbs = pbs; | ||
105 | _isPhysical = pisPhysical; | 138 | _isPhysical = pisPhysical; |
106 | _isVolumeDetect = false; | 139 | _isVolumeDetect = false; |
107 | _friction = PhysicsScene.Params.defaultFriction; // TODO: compute based on object material | 140 | _subscribedEventsMs = 0; |
108 | _density = PhysicsScene.Params.defaultDensity; // TODO: compute based on object material | 141 | _friction = _scene.Params.defaultFriction; // TODO: compute based on object material |
109 | _restitution = PhysicsScene.Params.defaultRestitution; | 142 | _density = _scene.Params.defaultDensity; // TODO: compute based on object material |
110 | _vehicle = new BSDynamics(PhysicsScene, this); // add vehicleness | 143 | _restitution = _scene.Params.defaultRestitution; |
144 | _linkset = new BSLinkset(_scene, this); // a linkset of one | ||
145 | _vehicle = new BSDynamics(this); // add vehicleness | ||
111 | _mass = CalculateMass(); | 146 | _mass = CalculateMass(); |
112 | |||
113 | // No body or shape yet | ||
114 | PhysBody = new BulletBody(LocalID, IntPtr.Zero); | ||
115 | PhysShape = new BulletShape(IntPtr.Zero); | ||
116 | |||
117 | DetailLog("{0},BSPrim.constructor,call", LocalID); | ||
118 | // do the actual object creation at taint time | 147 | // do the actual object creation at taint time |
119 | PhysicsScene.TaintedObject("BSPrim.create", delegate() | 148 | DetailLog("{0},BSPrim.constructor,call", LocalID); |
149 | _scene.TaintedObject("BSPrim.create", delegate() | ||
120 | { | 150 | { |
121 | CreateGeomAndObject(true); | 151 | RecreateGeomAndObject(); |
122 | 152 | ||
123 | CurrentCollisionFlags = BulletSimAPI.GetCollisionFlags2(PhysBody.ptr); | 153 | // Get the pointer to the physical body for this object. |
154 | // At the moment, we're still letting BulletSim manage the creation and destruction | ||
155 | // of the object. Someday we'll move that into the C# code. | ||
156 | m_body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); | ||
124 | }); | 157 | }); |
125 | } | 158 | } |
126 | 159 | ||
127 | // called when this prim is being destroyed and we should free all the resources | 160 | // called when this prim is being destroyed and we should free all the resources |
128 | public override void Destroy() | 161 | public void Destroy() |
129 | { | 162 | { |
130 | // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); | 163 | // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); |
131 | 164 | ||
132 | // Undo any links between me and any other object | 165 | // Undo any links between me and any other object |
133 | BSPhysObject parentBefore = Linkset.LinksetRoot; | 166 | BSPrim parentBefore = _linkset.LinksetRoot; |
134 | int childrenBefore = Linkset.NumberOfChildren; | 167 | int childrenBefore = _linkset.NumberOfChildren; |
135 | 168 | ||
136 | Linkset = Linkset.RemoveMeFromLinkset(this); | 169 | _linkset = _linkset.RemoveMeFromLinkset(this); |
137 | 170 | ||
138 | DetailLog("{0},BSPrim.Destroy,call,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}", | 171 | DetailLog("{0},BSPrim.Destroy,call,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}", |
139 | LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren); | 172 | LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren); |
140 | 173 | ||
141 | // Undo any vehicle properties | 174 | // Undo any vehicle properties |
142 | this.VehicleType = (int)Vehicle.TYPE_NONE; | 175 | this.VehicleType = (int)Vehicle.TYPE_NONE; |
143 | 176 | ||
144 | PhysicsScene.TaintedObject("BSPrim.destroy", delegate() | 177 | _scene.TaintedObject("BSPrim.destroy", delegate() |
145 | { | 178 | { |
146 | DetailLog("{0},BSPrim.Destroy,taint,", LocalID); | 179 | DetailLog("{0},BSPrim.Destroy,taint,", LocalID); |
147 | // If there are physical body and shape, release my use of same. | 180 | // everything in the C# world will get garbage collected. Tell the C++ world to free stuff. |
148 | PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null); | 181 | BulletSimAPI.DestroyObject(_scene.WorldID, LocalID); |
149 | PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null); | ||
150 | }); | 182 | }); |
151 | } | 183 | } |
152 | 184 | ||
153 | // No one uses this property. | 185 | public override bool Stopped { |
154 | public override bool Stopped { | 186 | get { return _stopped; } |
155 | get { return false; } | ||
156 | } | 187 | } |
157 | public override OMV.Vector3 Size { | 188 | public override OMV.Vector3 Size { |
158 | get { return _size; } | 189 | get { return _size; } |
159 | set { | 190 | set { |
160 | _size = value; | 191 | _size = value; |
161 | ForceBodyShapeRebuild(false); | 192 | _scene.TaintedObject("BSPrim.setSize", delegate() |
162 | } | 193 | { |
194 | _mass = CalculateMass(); // changing size changes the mass | ||
195 | BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, (IsPhysical ? _mass : 0f), IsPhysical); | ||
196 | // DetailLog("{0}: BSPrim.setSize: size={1}, mass={2}, physical={3}", LocalID, _size, _mass, IsPhysical); | ||
197 | RecreateGeomAndObject(); | ||
198 | }); | ||
199 | } | ||
163 | } | 200 | } |
164 | // Scale is what we set in the physics engine. It is different than 'size' in that | 201 | public override PrimitiveBaseShape Shape { |
165 | // 'size' can be encorporated into the mesh. In that case, the scale is <1,1,1>. | ||
166 | public override OMV.Vector3 Scale { get; set; } | ||
167 | |||
168 | public override PrimitiveBaseShape Shape { | ||
169 | set { | 202 | set { |
170 | BaseShape = value; | 203 | _pbs = value; |
171 | ForceBodyShapeRebuild(false); | 204 | _scene.TaintedObject("BSPrim.setShape", delegate() |
172 | } | 205 | { |
206 | _mass = CalculateMass(); // changing the shape changes the mass | ||
207 | RecreateGeomAndObject(); | ||
208 | }); | ||
209 | } | ||
173 | } | 210 | } |
174 | // Whatever the linkset wants is what I want. | 211 | public override uint LocalID { |
175 | public override ShapeData.PhysicsShapeType PreferredPhysicalShape | 212 | set { _localID = value; } |
176 | { get { return Linkset.PreferredPhysicalShape(this); } } | 213 | get { return _localID; } |
177 | |||
178 | public override bool ForceBodyShapeRebuild(bool inTaintTime) | ||
179 | { | ||
180 | LastAssetBuildFailed = false; | ||
181 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ForceBodyShapeRebuild", delegate() | ||
182 | { | ||
183 | _mass = CalculateMass(); // changing the shape changes the mass | ||
184 | CreateGeomAndObject(true); | ||
185 | }); | ||
186 | return true; | ||
187 | } | 214 | } |
188 | public override bool Grabbed { | 215 | public override bool Grabbed { |
189 | set { _grabbed = value; | 216 | set { _grabbed = value; |
190 | } | 217 | } |
191 | } | 218 | } |
192 | public override bool Selected { | 219 | public override bool Selected { |
193 | set { | 220 | set { |
194 | _isSelected = value; | 221 | _isSelected = value; |
195 | PhysicsScene.TaintedObject("BSPrim.setSelected", delegate() | 222 | _scene.TaintedObject("BSPrim.setSelected", delegate() |
196 | { | 223 | { |
197 | DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected); | 224 | SetObjectDynamic(); |
198 | SetObjectDynamic(false); | ||
199 | }); | 225 | }); |
200 | } | 226 | } |
201 | } | 227 | } |
202 | public override void CrossingFailure() { return; } | 228 | public override void CrossingFailure() { return; } |
203 | 229 | ||
@@ -206,255 +232,158 @@ public sealed class BSPrim : BSPhysObject | |||
206 | BSPrim parent = obj as BSPrim; | 232 | BSPrim parent = obj as BSPrim; |
207 | if (parent != null) | 233 | if (parent != null) |
208 | { | 234 | { |
209 | BSPhysObject parentBefore = Linkset.LinksetRoot; | 235 | DebugLog("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, parent.LocalID); |
210 | int childrenBefore = Linkset.NumberOfChildren; | 236 | BSPrim parentBefore = _linkset.LinksetRoot; |
237 | int childrenBefore = _linkset.NumberOfChildren; | ||
211 | 238 | ||
212 | Linkset = parent.Linkset.AddMeToLinkset(this); | 239 | _linkset = parent.Linkset.AddMeToLinkset(this); |
213 | 240 | ||
214 | DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}", | 241 | DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}", |
215 | LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren); | 242 | LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren); |
216 | } | 243 | } |
217 | return; | 244 | return; |
218 | } | 245 | } |
219 | 246 | ||
220 | // delink me from my linkset | 247 | // delink me from my linkset |
221 | public override void delink() { | 248 | public override void delink() { |
222 | // TODO: decide if this parent checking needs to happen at taint time | 249 | // TODO: decide if this parent checking needs to happen at taint time |
223 | // Race condition here: if link() and delink() in same simulation tick, the delink will not happen | 250 | // Race condition here: if link() and delink() in same simulation tick, the delink will not happen |
251 | DebugLog("{0}: delink {1}/{2}. Parent={3}", LogHeader, _avName, _localID, | ||
252 | _linkset.LinksetRoot._avName+"/"+_linkset.LinksetRoot.LocalID.ToString()); | ||
224 | 253 | ||
225 | BSPhysObject parentBefore = Linkset.LinksetRoot; | 254 | BSPrim parentBefore = _linkset.LinksetRoot; |
226 | int childrenBefore = Linkset.NumberOfChildren; | 255 | int childrenBefore = _linkset.NumberOfChildren; |
256 | |||
257 | _linkset = _linkset.RemoveMeFromLinkset(this); | ||
227 | 258 | ||
228 | Linkset = Linkset.RemoveMeFromLinkset(this); | 259 | DetailLog("{0},BSPrim.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ", |
229 | 260 | LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren); | |
230 | DetailLog("{0},BSPrim.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ", | 261 | return; |
231 | LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren); | ||
232 | return; | ||
233 | } | 262 | } |
234 | 263 | ||
235 | // Set motion values to zero. | 264 | // Set motion values to zero. |
236 | // Do it to the properties so the values get set in the physics engine. | 265 | // Do it to the properties so the values get set in the physics engine. |
237 | // Push the setting of the values to the viewer. | 266 | // Push the setting of the values to the viewer. |
238 | // Called at taint time! | 267 | // Called at taint time! |
239 | public override void ZeroMotion() | 268 | public void ZeroMotion() |
240 | { | 269 | { |
241 | _velocity = OMV.Vector3.Zero; | 270 | _velocity = OMV.Vector3.Zero; |
242 | _acceleration = OMV.Vector3.Zero; | 271 | _acceleration = OMV.Vector3.Zero; |
243 | _rotationalVelocity = OMV.Vector3.Zero; | 272 | _rotationalVelocity = OMV.Vector3.Zero; |
244 | 273 | ||
245 | // Zero some other properties in the physics engine | 274 | // Zero some other properties directly into the physics engine |
246 | BulletSimAPI.ClearAllForces2(PhysBody.ptr); | 275 | BulletSimAPI.SetVelocity2(Body.Ptr, OMV.Vector3.Zero); |
276 | BulletSimAPI.SetAngularVelocity2(Body.Ptr, OMV.Vector3.Zero); | ||
277 | BulletSimAPI.SetInterpolation2(Body.Ptr, OMV.Vector3.Zero, OMV.Vector3.Zero); | ||
278 | BulletSimAPI.ClearForces2(Body.Ptr); | ||
247 | } | 279 | } |
248 | 280 | ||
249 | public override void LockAngularMotion(OMV.Vector3 axis) | 281 | public override void LockAngularMotion(OMV.Vector3 axis) |
250 | { | 282 | { |
251 | DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis); | 283 | // DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis); |
252 | return; | 284 | return; |
253 | } | 285 | } |
254 | 286 | ||
255 | public override OMV.Vector3 RawPosition | 287 | public override OMV.Vector3 Position { |
256 | { | 288 | get { |
257 | get { return _position; } | 289 | if (!_linkset.IsRoot(this)) |
258 | set { _position = value; } | 290 | // child prims move around based on their parent. Need to get the latest location |
259 | } | 291 | _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); |
260 | public override OMV.Vector3 Position { | ||
261 | get { | ||
262 | // child prims move around based on their parent. Need to get the latest location | ||
263 | if (!Linkset.IsRoot(this)) | ||
264 | _position = Linkset.Position(this); | ||
265 | 292 | ||
266 | // don't do the GetObjectPosition for root elements because this function is called a zillion times | 293 | // don't do the GetObjectPosition for root elements because this function is called a zillion times |
267 | // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); | 294 | // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); |
268 | return _position; | 295 | return _position; |
269 | } | 296 | } |
270 | set { | 297 | set { |
271 | // If you must push the position into the physics engine, use ForcePosition. | ||
272 | if (_position == value) | ||
273 | { | ||
274 | return; | ||
275 | } | ||
276 | _position = value; | 298 | _position = value; |
277 | // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? | 299 | // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? |
278 | PositionSanityCheck(); | 300 | _scene.TaintedObject("BSPrim.setPosition", delegate() |
279 | PhysicsScene.TaintedObject("BSPrim.setPosition", delegate() | ||
280 | { | 301 | { |
281 | // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); | 302 | // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); |
282 | BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); | 303 | BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); |
283 | ActivateIfPhysical(false); | ||
284 | }); | ||
285 | } | ||
286 | } | ||
287 | public override OMV.Vector3 ForcePosition { | ||
288 | get { | ||
289 | _position = BulletSimAPI.GetPosition2(PhysBody.ptr); | ||
290 | return _position; | ||
291 | } | ||
292 | set { | ||
293 | _position = value; | ||
294 | PositionSanityCheck(); | ||
295 | BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); | ||
296 | ActivateIfPhysical(false); | ||
297 | } | ||
298 | } | ||
299 | |||
300 | // Check that the current position is sane and, if not, modify the position to make it so. | ||
301 | // Check for being below terrain and being out of bounds. | ||
302 | // Returns 'true' of the position was made sane by some action. | ||
303 | private bool PositionSanityCheck() | ||
304 | { | ||
305 | bool ret = false; | ||
306 | |||
307 | // If totally below the ground, move the prim up | ||
308 | // TODO: figure out the right solution for this... only for dynamic objects? | ||
309 | /* | ||
310 | float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); | ||
311 | if (Position.Z < terrainHeight) | ||
312 | { | ||
313 | DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); | ||
314 | _position.Z = terrainHeight + 2.0f; | ||
315 | ret = true; | ||
316 | } | ||
317 | */ | ||
318 | if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) | ||
319 | { | ||
320 | float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position); | ||
321 | // TODO: a floating motor so object will bob in the water | ||
322 | if (Position.Z < waterHeight) | ||
323 | { | ||
324 | _position.Z = waterHeight; | ||
325 | ret = true; | ||
326 | } | ||
327 | } | ||
328 | |||
329 | // TODO: check for out of bounds | ||
330 | return ret; | ||
331 | } | ||
332 | |||
333 | // A version of the sanity check that also makes sure a new position value is | ||
334 | // pushed to the physics engine. This routine would be used by anyone | ||
335 | // who is not already pushing the value. | ||
336 | private bool PositionSanityCheck(bool inTaintTime) | ||
337 | { | ||
338 | bool ret = false; | ||
339 | if (PositionSanityCheck()) | ||
340 | { | ||
341 | // The new position value must be pushed into the physics engine but we can't | ||
342 | // just assign to "Position" because of potential call loops. | ||
343 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.PositionSanityCheck", delegate() | ||
344 | { | ||
345 | DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); | ||
346 | ForcePosition = _position; | ||
347 | }); | 304 | }); |
348 | ret = true; | 305 | } |
349 | } | ||
350 | return ret; | ||
351 | } | 306 | } |
352 | 307 | ||
353 | // Return the effective mass of the object. | 308 | // Return the effective mass of the object. |
354 | // If there are multiple items in the linkset, add them together for the root | 309 | // If there are multiple items in the linkset, add them together for the root |
355 | public override float Mass | 310 | public override float Mass |
356 | { | 311 | { |
357 | get | 312 | get |
358 | { | 313 | { |
359 | return Linkset.LinksetMass; | 314 | return _linkset.LinksetMass; |
360 | // return _mass; | ||
361 | } | 315 | } |
362 | } | 316 | } |
363 | 317 | ||
364 | // used when we only want this prim's mass and not the linkset thing | 318 | // used when we only want this prim's mass and not the linkset thing |
365 | public override float RawMass { | 319 | public float MassRaw { get { return _mass; } } |
366 | get { return _mass; } | ||
367 | } | ||
368 | // Set the physical mass to the passed mass. | ||
369 | // Note that this does not change _mass! | ||
370 | public override void UpdatePhysicalMassProperties(float physMass) | ||
371 | { | ||
372 | if (IsStatic) | ||
373 | { | ||
374 | BulletSimAPI.SetMassProps2(PhysBody.ptr, 0f, OMV.Vector3.Zero); | ||
375 | BulletSimAPI.UpdateInertiaTensor2(PhysBody.ptr); | ||
376 | } | ||
377 | else | ||
378 | { | ||
379 | OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(PhysShape.ptr, physMass); | ||
380 | BulletSimAPI.SetMassProps2(PhysBody.ptr, physMass, localInertia); | ||
381 | // center of mass is at the zero of the object | ||
382 | BulletSimAPI.SetCenterOfMassByPosRot2(PhysBody.ptr, ForcePosition, ForceOrientation); | ||
383 | // BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr); | ||
384 | DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2}", LocalID, physMass, localInertia); | ||
385 | } | ||
386 | } | ||
387 | 320 | ||
388 | // Is this used? | 321 | // Is this used? |
389 | public override OMV.Vector3 CenterOfMass | 322 | public override OMV.Vector3 CenterOfMass |
390 | { | 323 | { |
391 | get { return Linkset.CenterOfMass; } | 324 | get { return _linkset.CenterOfMass; } |
392 | } | 325 | } |
393 | 326 | ||
394 | // Is this used? | 327 | // Is this used? |
395 | public override OMV.Vector3 GeometricCenter | 328 | public override OMV.Vector3 GeometricCenter |
396 | { | 329 | { |
397 | get { return Linkset.GeometricCenter; } | 330 | get { return _linkset.GeometricCenter; } |
398 | } | 331 | } |
399 | 332 | ||
400 | public override OMV.Vector3 Force { | 333 | public override OMV.Vector3 Force { |
401 | get { return _force; } | 334 | get { return _force; } |
402 | set { | 335 | set { |
403 | _force = value; | 336 | _force = value; |
404 | PhysicsScene.TaintedObject("BSPrim.setForce", delegate() | 337 | _scene.TaintedObject("BSPrim.setForce", delegate() |
405 | { | 338 | { |
406 | // DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force); | 339 | // DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force); |
407 | BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force); | 340 | // BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); |
341 | BulletSimAPI.SetObjectForce2(Body.Ptr, _force); | ||
408 | }); | 342 | }); |
409 | } | 343 | } |
410 | } | 344 | } |
411 | 345 | ||
412 | public override int VehicleType { | 346 | public override int VehicleType { |
413 | get { | 347 | get { |
414 | return (int)_vehicle.Type; // if we are a vehicle, return that type | 348 | return (int)_vehicle.Type; // if we are a vehicle, return that type |
415 | } | 349 | } |
416 | set { | 350 | set { |
417 | Vehicle type = (Vehicle)value; | 351 | Vehicle type = (Vehicle)value; |
418 | 352 | BSPrim vehiclePrim = this; | |
419 | // Tell the scene about the vehicle so it will get processing each frame. | 353 | _scene.TaintedObject("setVehicleType", delegate() |
420 | PhysicsScene.VehicleInSceneTypeChanged(this, type); | ||
421 | |||
422 | PhysicsScene.TaintedObject("setVehicleType", delegate() | ||
423 | { | 354 | { |
424 | // Done at taint time so we're sure the physics engine is not using the variables | 355 | // Done at taint time so we're sure the physics engine is not using the variables |
425 | // Vehicle code changes the parameters for this vehicle type. | 356 | // Vehicle code changes the parameters for this vehicle type. |
426 | _vehicle.ProcessTypeChange(type); | 357 | _vehicle.ProcessTypeChange(type); |
427 | ActivateIfPhysical(false); | 358 | // Tell the scene about the vehicle so it will get processing each frame. |
359 | _scene.VehicleInSceneTypeChanged(this, type); | ||
428 | }); | 360 | }); |
429 | } | 361 | } |
430 | } | 362 | } |
431 | public override void VehicleFloatParam(int param, float value) | 363 | public override void VehicleFloatParam(int param, float value) |
432 | { | 364 | { |
433 | PhysicsScene.TaintedObject("BSPrim.VehicleFloatParam", delegate() | 365 | _scene.TaintedObject("BSPrim.VehicleFloatParam", delegate() |
434 | { | 366 | { |
435 | _vehicle.ProcessFloatVehicleParam((Vehicle)param, value); | 367 | _vehicle.ProcessFloatVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep); |
436 | ActivateIfPhysical(false); | ||
437 | }); | 368 | }); |
438 | } | 369 | } |
439 | public override void VehicleVectorParam(int param, OMV.Vector3 value) | 370 | public override void VehicleVectorParam(int param, OMV.Vector3 value) |
440 | { | 371 | { |
441 | PhysicsScene.TaintedObject("BSPrim.VehicleVectorParam", delegate() | 372 | _scene.TaintedObject("BSPrim.VehicleVectorParam", delegate() |
442 | { | 373 | { |
443 | _vehicle.ProcessVectorVehicleParam((Vehicle)param, value); | 374 | _vehicle.ProcessVectorVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep); |
444 | ActivateIfPhysical(false); | ||
445 | }); | 375 | }); |
446 | } | 376 | } |
447 | public override void VehicleRotationParam(int param, OMV.Quaternion rotation) | 377 | public override void VehicleRotationParam(int param, OMV.Quaternion rotation) |
448 | { | 378 | { |
449 | PhysicsScene.TaintedObject("BSPrim.VehicleRotationParam", delegate() | 379 | _scene.TaintedObject("BSPrim.VehicleRotationParam", delegate() |
450 | { | 380 | { |
451 | _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation); | 381 | _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation); |
452 | ActivateIfPhysical(false); | ||
453 | }); | 382 | }); |
454 | } | 383 | } |
455 | public override void VehicleFlags(int param, bool remove) | 384 | public override void VehicleFlags(int param, bool remove) |
456 | { | 385 | { |
457 | PhysicsScene.TaintedObject("BSPrim.VehicleFlags", delegate() | 386 | _scene.TaintedObject("BSPrim.VehicleFlags", delegate() |
458 | { | 387 | { |
459 | _vehicle.ProcessVehicleFlags(param, remove); | 388 | _vehicle.ProcessVehicleFlags(param, remove); |
460 | }); | 389 | }); |
@@ -462,355 +391,143 @@ public sealed class BSPrim : BSPhysObject | |||
462 | 391 | ||
463 | // Called each simulation step to advance vehicle characteristics. | 392 | // Called each simulation step to advance vehicle characteristics. |
464 | // Called from Scene when doing simulation step so we're in taint processing time. | 393 | // Called from Scene when doing simulation step so we're in taint processing time. |
465 | public override void StepVehicle(float timeStep) | 394 | public void StepVehicle(float timeStep) |
466 | { | 395 | { |
467 | if (IsPhysical && _vehicle.IsActive) | 396 | if (IsPhysical) |
468 | { | ||
469 | _vehicle.Step(timeStep); | 397 | _vehicle.Step(timeStep); |
470 | /* // TEST TEST DEBUG DEBUG -- trying to reduce the extra action of Bullet simulation step | ||
471 | PhysicsScene.PostTaintObject("BSPrim.StepVehicles", LocalID, delegate() | ||
472 | { | ||
473 | // This resets the interpolation values and recomputes the tensor variables | ||
474 | BulletSimAPI.SetCenterOfMassByPosRot2(BSBody.ptr, ForcePosition, ForceOrientation); | ||
475 | }); | ||
476 | */ | ||
477 | } | ||
478 | } | 398 | } |
479 | 399 | ||
480 | // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more | 400 | // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more |
481 | public override void SetVolumeDetect(int param) { | 401 | public override void SetVolumeDetect(int param) { |
482 | bool newValue = (param != 0); | 402 | bool newValue = (param != 0); |
483 | if (_isVolumeDetect != newValue) | 403 | _isVolumeDetect = newValue; |
404 | _scene.TaintedObject("BSPrim.SetVolumeDetect", delegate() | ||
484 | { | 405 | { |
485 | _isVolumeDetect = newValue; | 406 | SetObjectDynamic(); |
486 | PhysicsScene.TaintedObject("BSPrim.SetVolumeDetect", delegate() | 407 | }); |
487 | { | 408 | return; |
488 | // DetailLog("{0},setVolumeDetect,taint,volDetect={1}", LocalID, _isVolumeDetect); | ||
489 | SetObjectDynamic(true); | ||
490 | }); | ||
491 | } | ||
492 | return; | ||
493 | } | 409 | } |
494 | public override OMV.Vector3 Velocity { | 410 | |
495 | get { return _velocity; } | 411 | public override OMV.Vector3 Velocity { |
412 | get { return _velocity; } | ||
496 | set { | 413 | set { |
497 | _velocity = value; | 414 | _velocity = value; |
498 | PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate() | 415 | _scene.TaintedObject("BSPrim.setVelocity", delegate() |
499 | { | 416 | { |
500 | // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); | 417 | // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); |
501 | BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity); | 418 | BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity); |
502 | }); | 419 | }); |
503 | } | 420 | } |
504 | } | ||
505 | public override OMV.Vector3 ForceVelocity { | ||
506 | get { return _velocity; } | ||
507 | set { | ||
508 | _velocity = value; | ||
509 | BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity); | ||
510 | } | ||
511 | } | 421 | } |
512 | public override OMV.Vector3 Torque { | 422 | public override OMV.Vector3 Torque { |
513 | get { return _torque; } | 423 | get { return _torque; } |
514 | set { | 424 | set { _torque = value; |
515 | _torque = value; | ||
516 | AddAngularForce(_torque, false, false); | ||
517 | // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque); | 425 | // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque); |
518 | } | 426 | } |
519 | } | 427 | } |
520 | public override float CollisionScore { | 428 | public override float CollisionScore { |
521 | get { return _collisionScore; } | 429 | get { return _collisionScore; } |
522 | set { _collisionScore = value; | 430 | set { _collisionScore = value; |
523 | } | 431 | } |
524 | } | 432 | } |
525 | public override OMV.Vector3 Acceleration { | 433 | public override OMV.Vector3 Acceleration { |
526 | get { return _acceleration; } | 434 | get { return _acceleration; } |
527 | set { _acceleration = value; } | 435 | set { _acceleration = value; } |
528 | } | 436 | } |
529 | public override OMV.Quaternion RawOrientation | 437 | public override OMV.Quaternion Orientation { |
530 | { | ||
531 | get { return _orientation; } | ||
532 | set { _orientation = value; } | ||
533 | } | ||
534 | public override OMV.Quaternion Orientation { | ||
535 | get { | 438 | get { |
536 | // Children move around because tied to parent. Get a fresh value. | 439 | if (!_linkset.IsRoot(this)) |
537 | if (!Linkset.IsRoot(this)) | ||
538 | { | 440 | { |
539 | _orientation = Linkset.Orientation(this); | 441 | // Children move around because tied to parent. Get a fresh value. |
442 | _orientation = BulletSimAPI.GetObjectOrientation(_scene.WorldID, LocalID); | ||
540 | } | 443 | } |
541 | return _orientation; | 444 | return _orientation; |
542 | } | 445 | } |
543 | set { | 446 | set { |
544 | if (_orientation == value) | ||
545 | return; | ||
546 | _orientation = value; | 447 | _orientation = value; |
547 | // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint? | 448 | // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint? |
548 | PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate() | 449 | _scene.TaintedObject("BSPrim.setOrientation", delegate() |
549 | { | 450 | { |
550 | // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); | 451 | // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); |
551 | // DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); | 452 | // DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); |
552 | BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); | 453 | BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); |
553 | }); | 454 | }); |
554 | } | 455 | } |
555 | } | 456 | } |
556 | // Go directly to Bullet to get/set the value. | 457 | public override int PhysicsActorType { |
557 | public override OMV.Quaternion ForceOrientation | 458 | get { return _physicsActorType; } |
558 | { | 459 | set { _physicsActorType = value; |
559 | get | 460 | } |
560 | { | ||
561 | _orientation = BulletSimAPI.GetOrientation2(PhysBody.ptr); | ||
562 | return _orientation; | ||
563 | } | ||
564 | set | ||
565 | { | ||
566 | _orientation = value; | ||
567 | BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); | ||
568 | } | ||
569 | } | 461 | } |
570 | public override int PhysicsActorType { | 462 | public override bool IsPhysical { |
571 | get { return _physicsActorType; } | 463 | get { return _isPhysical; } |
572 | set { _physicsActorType = value; } | ||
573 | } | ||
574 | public override bool IsPhysical { | ||
575 | get { return _isPhysical; } | ||
576 | set { | 464 | set { |
577 | if (_isPhysical != value) | 465 | _isPhysical = value; |
466 | _scene.TaintedObject("BSPrim.setIsPhysical", delegate() | ||
578 | { | 467 | { |
579 | _isPhysical = value; | 468 | SetObjectDynamic(); |
580 | PhysicsScene.TaintedObject("BSPrim.setIsPhysical", delegate() | 469 | }); |
581 | { | 470 | } |
582 | // DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical); | ||
583 | SetObjectDynamic(true); | ||
584 | // whether phys-to-static or static-to-phys, the object is not moving. | ||
585 | ZeroMotion(); | ||
586 | }); | ||
587 | } | ||
588 | } | ||
589 | } | 471 | } |
590 | 472 | ||
591 | // An object is static (does not move) if selected or not physical | 473 | // An object is static (does not move) if selected or not physical |
592 | public override bool IsStatic | 474 | private bool IsStatic |
593 | { | 475 | { |
594 | get { return _isSelected || !IsPhysical; } | 476 | get { return _isSelected || !IsPhysical; } |
595 | } | 477 | } |
596 | 478 | ||
597 | // An object is solid if it's not phantom and if it's not doing VolumeDetect | 479 | // An object is solid if it's not phantom and if it's not doing VolumeDetect |
598 | public override bool IsSolid | 480 | private bool IsSolid |
599 | { | 481 | { |
600 | get { return !IsPhantom && !_isVolumeDetect; } | 482 | get { return !IsPhantom && !_isVolumeDetect; } |
601 | } | 483 | } |
602 | 484 | ||
603 | // Make gravity work if the object is physical and not selected | 485 | // Make gravity work if the object is physical and not selected |
604 | // Called at taint-time!! | 486 | // No locking here because only called when it is safe |
605 | private void SetObjectDynamic(bool forceRebuild) | 487 | private void SetObjectDynamic() |
606 | { | ||
607 | // Recreate the physical object if necessary | ||
608 | CreateGeomAndObject(forceRebuild); | ||
609 | } | ||
610 | |||
611 | // Convert the simulator's physical properties into settings on BulletSim objects. | ||
612 | // There are four flags we're interested in: | ||
613 | // IsStatic: Object does not move, otherwise the object has mass and moves | ||
614 | // isSolid: other objects bounce off of this object | ||
615 | // isVolumeDetect: other objects pass through but can generate collisions | ||
616 | // collisionEvents: whether this object returns collision events | ||
617 | private void UpdatePhysicalParameters() | ||
618 | { | ||
619 | // DetailLog("{0},BSPrim.UpdatePhysicalParameters,entry,body={1},shape={2}", LocalID, BSBody, BSShape); | ||
620 | |||
621 | // Mangling all the physical properties requires the object not be in the physical world. | ||
622 | // This is a NOOP if the object is not in the world (BulletSim and Bullet ignore objects not found). | ||
623 | BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, PhysBody.ptr); | ||
624 | |||
625 | // Set up the object physicalness (does gravity and collisions move this object) | ||
626 | MakeDynamic(IsStatic); | ||
627 | |||
628 | // Update vehicle specific parameters (after MakeDynamic() so can change physical parameters) | ||
629 | _vehicle.Refresh(); | ||
630 | |||
631 | // Arrange for collision events if the simulator wants them | ||
632 | EnableCollisions(SubscribedEvents()); | ||
633 | |||
634 | // Make solid or not (do things bounce off or pass through this object). | ||
635 | MakeSolid(IsSolid); | ||
636 | |||
637 | BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, PhysBody.ptr); | ||
638 | |||
639 | // Rebuild its shape | ||
640 | BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr); | ||
641 | |||
642 | // Collision filter can be set only when the object is in the world | ||
643 | if (PhysBody.collisionFilter != 0 || PhysBody.collisionMask != 0) | ||
644 | { | ||
645 | BulletSimAPI.SetCollisionFilterMask2(PhysBody.ptr, (uint)PhysBody.collisionFilter, (uint)PhysBody.collisionMask); | ||
646 | } | ||
647 | |||
648 | // Recompute any linkset parameters. | ||
649 | // When going from non-physical to physical, this re-enables the constraints that | ||
650 | // had been automatically disabled when the mass was set to zero. | ||
651 | Linkset.Refresh(this); | ||
652 | |||
653 | DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},body={6},shape={7}", | ||
654 | LocalID, IsStatic, IsSolid, _mass, SubscribedEvents(), CurrentCollisionFlags, PhysBody, PhysShape); | ||
655 | } | ||
656 | |||
657 | // "Making dynamic" means changing to and from static. | ||
658 | // When static, gravity does not effect the object and it is fixed in space. | ||
659 | // When dynamic, the object can fall and be pushed by others. | ||
660 | // This is independent of its 'solidness' which controls what passes through | ||
661 | // this object and what interacts with it. | ||
662 | private void MakeDynamic(bool makeStatic) | ||
663 | { | 488 | { |
664 | if (makeStatic) | 489 | // RA: remove this for the moment. |
665 | { | 490 | // The problem is that dynamic objects are hulls so if we are becoming physical |
666 | // Become a Bullet 'static' object type | 491 | // the shape has to be checked and possibly built. |
667 | CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_STATIC_OBJECT); | 492 | // Maybe a VerifyCorrectPhysicalShape() routine? |
668 | // Stop all movement | 493 | // RecreateGeomAndObject(); |
669 | ZeroMotion(); | ||
670 | // Center of mass is at the center of the object | ||
671 | BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.PhysBody.ptr, _position, _orientation); | ||
672 | // Mass is zero which disables a bunch of physics stuff in Bullet | ||
673 | UpdatePhysicalMassProperties(0f); | ||
674 | // Set collision detection parameters | ||
675 | if (PhysicsScene.Params.ccdMotionThreshold > 0f) | ||
676 | { | ||
677 | BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, PhysicsScene.Params.ccdMotionThreshold); | ||
678 | BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); | ||
679 | } | ||
680 | // There can be special things needed for implementing linksets | ||
681 | Linkset.MakeStatic(this); | ||
682 | // The activation state is 'disabled' so Bullet will not try to act on it. | ||
683 | BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.DISABLE_SIMULATION); | ||
684 | // Start it out sleeping and physical actions could wake it up. | ||
685 | // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING); | ||
686 | |||
687 | PhysBody.collisionFilter = CollisionFilterGroups.StaticObjectFilter; | ||
688 | PhysBody.collisionMask = CollisionFilterGroups.StaticObjectMask; | ||
689 | } | ||
690 | else | ||
691 | { | ||
692 | // Not a Bullet static object | ||
693 | CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_STATIC_OBJECT); | ||
694 | |||
695 | // Set various physical properties so internal dynamic properties will get computed correctly as they are set | ||
696 | BulletSimAPI.SetFriction2(PhysBody.ptr, PhysicsScene.Params.defaultFriction); | ||
697 | BulletSimAPI.SetRestitution2(PhysBody.ptr, PhysicsScene.Params.defaultRestitution); | ||
698 | |||
699 | // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382 | ||
700 | // Since this can be called multiple times, only zero forces when becoming physical | ||
701 | // BulletSimAPI.ClearAllForces2(BSBody.ptr); | ||
702 | 494 | ||
703 | // For good measure, make sure the transform is set through to the motion state | 495 | // Bullet wants static objects to have a mass of zero |
704 | BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); | 496 | float mass = IsStatic ? 0f : _mass; |
705 | 497 | ||
706 | // Center of mass is at the center of the object | 498 | BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass); |
707 | BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.PhysBody.ptr, _position, _orientation); | ||
708 | |||
709 | // A dynamic object has mass | ||
710 | UpdatePhysicalMassProperties(RawMass); | ||
711 | |||
712 | // Set collision detection parameters | ||
713 | if (PhysicsScene.Params.ccdMotionThreshold > 0f) | ||
714 | { | ||
715 | BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, PhysicsScene.Params.ccdMotionThreshold); | ||
716 | BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); | ||
717 | } | ||
718 | |||
719 | // Various values for simulation limits | ||
720 | BulletSimAPI.SetDamping2(PhysBody.ptr, PhysicsScene.Params.linearDamping, PhysicsScene.Params.angularDamping); | ||
721 | BulletSimAPI.SetDeactivationTime2(PhysBody.ptr, PhysicsScene.Params.deactivationTime); | ||
722 | BulletSimAPI.SetSleepingThresholds2(PhysBody.ptr, PhysicsScene.Params.linearSleepingThreshold, PhysicsScene.Params.angularSleepingThreshold); | ||
723 | BulletSimAPI.SetContactProcessingThreshold2(PhysBody.ptr, PhysicsScene.Params.contactProcessingThreshold); | ||
724 | |||
725 | // There might be special things needed for implementing linksets. | ||
726 | Linkset.MakeDynamic(this); | ||
727 | |||
728 | // Force activation of the object so Bullet will act on it. | ||
729 | // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects. | ||
730 | BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.ACTIVE_TAG); | ||
731 | // BulletSimAPI.Activate2(BSBody.ptr, true); | ||
732 | |||
733 | PhysBody.collisionFilter = CollisionFilterGroups.ObjectFilter; | ||
734 | PhysBody.collisionMask = CollisionFilterGroups.ObjectMask; | ||
735 | } | ||
736 | } | ||
737 | |||
738 | // "Making solid" means that other object will not pass through this object. | ||
739 | // To make transparent, we create a Bullet ghost object. | ||
740 | // Note: This expects to be called from the UpdatePhysicalParameters() routine as | ||
741 | // the functions after this one set up the state of a possibly newly created collision body. | ||
742 | private void MakeSolid(bool makeSolid) | ||
743 | { | ||
744 | CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(PhysBody.ptr); | ||
745 | if (makeSolid) | ||
746 | { | ||
747 | // Verify the previous code created the correct shape for this type of thing. | ||
748 | if ((bodyType & CollisionObjectTypes.CO_RIGID_BODY) == 0) | ||
749 | { | ||
750 | m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for solidity. id={1}, type={2}", LogHeader, LocalID, bodyType); | ||
751 | } | ||
752 | CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); | ||
753 | } | ||
754 | else | ||
755 | { | ||
756 | if ((bodyType & CollisionObjectTypes.CO_GHOST_OBJECT) == 0) | ||
757 | { | ||
758 | m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType); | ||
759 | } | ||
760 | CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); | ||
761 | PhysBody.collisionFilter = CollisionFilterGroups.VolumeDetectFilter; | ||
762 | PhysBody.collisionMask = CollisionFilterGroups.VolumeDetectMask; | ||
763 | } | ||
764 | } | ||
765 | 499 | ||
766 | // Enable physical actions. Bullet will keep sleeping non-moving physical objects so | 500 | // recompute any linkset parameters |
767 | // they need waking up when parameters are changed. | 501 | _linkset.Refresh(this); |
768 | // Called in taint-time!! | ||
769 | private void ActivateIfPhysical(bool forceIt) | ||
770 | { | ||
771 | if (IsPhysical) | ||
772 | BulletSimAPI.Activate2(PhysBody.ptr, forceIt); | ||
773 | } | ||
774 | 502 | ||
775 | // Turn on or off the flag controlling whether collision events are returned to the simulator. | 503 | CollisionFlags cf = BulletSimAPI.GetCollisionFlags2(Body.Ptr); |
776 | private void EnableCollisions(bool wantsCollisionEvents) | 504 | // DetailLog("{0},BSPrim.SetObjectDynamic,taint,static={1},solid={2},mass={3}, cf={4}", LocalID, IsStatic, IsSolid, mass, cf); |
777 | { | ||
778 | if (wantsCollisionEvents) | ||
779 | { | ||
780 | CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); | ||
781 | } | ||
782 | else | ||
783 | { | ||
784 | CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); | ||
785 | } | ||
786 | } | 505 | } |
787 | 506 | ||
788 | // prims don't fly | 507 | // prims don't fly |
789 | public override bool Flying { | 508 | public override bool Flying { |
790 | get { return _flying; } | 509 | get { return _flying; } |
791 | set { | 510 | set { _flying = value; } |
792 | _flying = value; | ||
793 | } | ||
794 | } | 511 | } |
795 | public override bool SetAlwaysRun { | 512 | public override bool SetAlwaysRun { |
796 | get { return _setAlwaysRun; } | 513 | get { return _setAlwaysRun; } |
797 | set { _setAlwaysRun = value; } | 514 | set { _setAlwaysRun = value; } |
798 | } | 515 | } |
799 | public override bool ThrottleUpdates { | 516 | public override bool ThrottleUpdates { |
800 | get { return _throttleUpdates; } | 517 | get { return _throttleUpdates; } |
801 | set { _throttleUpdates = value; } | 518 | set { _throttleUpdates = value; } |
802 | } | 519 | } |
803 | public override bool IsColliding { | 520 | public override bool IsColliding { |
804 | get { return (CollidingStep == PhysicsScene.SimulationStep); } | 521 | get { return (_collidingStep == _scene.SimulationStep); } |
805 | set { _isColliding = value; } | 522 | set { _isColliding = value; } |
806 | } | 523 | } |
807 | public override bool CollidingGround { | 524 | public override bool CollidingGround { |
808 | get { return (CollidingGroundStep == PhysicsScene.SimulationStep); } | 525 | get { return (_collidingGroundStep == _scene.SimulationStep); } |
809 | set { _collidingGround = value; } | 526 | set { _collidingGround = value; } |
810 | } | 527 | } |
811 | public override bool CollidingObj { | 528 | public override bool CollidingObj { |
812 | get { return _collidingObj; } | 529 | get { return _collidingObj; } |
813 | set { _collidingObj = value; } | 530 | set { _collidingObj = value; } |
814 | } | 531 | } |
815 | public bool IsPhantom { | 532 | public bool IsPhantom { |
816 | get { | 533 | get { |
@@ -820,19 +537,10 @@ public sealed class BSPrim : BSPhysObject | |||
820 | return false; | 537 | return false; |
821 | } | 538 | } |
822 | } | 539 | } |
823 | public override bool FloatOnWater { | 540 | public override bool FloatOnWater { |
824 | set { | 541 | set { _floatOnWater = value; } |
825 | _floatOnWater = value; | ||
826 | PhysicsScene.TaintedObject("BSPrim.setFloatOnWater", delegate() | ||
827 | { | ||
828 | if (_floatOnWater) | ||
829 | CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); | ||
830 | else | ||
831 | CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); | ||
832 | }); | ||
833 | } | ||
834 | } | 542 | } |
835 | public override OMV.Vector3 RotationalVelocity { | 543 | public override OMV.Vector3 RotationalVelocity { |
836 | get { | 544 | get { |
837 | /* | 545 | /* |
838 | OMV.Vector3 pv = OMV.Vector3.Zero; | 546 | OMV.Vector3 pv = OMV.Vector3.Zero; |
@@ -844,76 +552,58 @@ public sealed class BSPrim : BSPhysObject | |||
844 | */ | 552 | */ |
845 | 553 | ||
846 | return _rotationalVelocity; | 554 | return _rotationalVelocity; |
847 | } | 555 | } |
848 | set { | 556 | set { |
849 | _rotationalVelocity = value; | 557 | _rotationalVelocity = value; |
850 | // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); | 558 | // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); |
851 | PhysicsScene.TaintedObject("BSPrim.setRotationalVelocity", delegate() | 559 | _scene.TaintedObject("BSPrim.setRotationalVelocity", delegate() |
852 | { | 560 | { |
853 | DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); | 561 | // DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); |
854 | BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, _rotationalVelocity); | 562 | BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity); |
855 | }); | 563 | }); |
856 | } | 564 | } |
857 | } | ||
858 | public override OMV.Vector3 ForceRotationalVelocity { | ||
859 | get { | ||
860 | return _rotationalVelocity; | ||
861 | } | ||
862 | set { | ||
863 | _rotationalVelocity = value; | ||
864 | BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, _rotationalVelocity); | ||
865 | } | ||
866 | } | 565 | } |
867 | public override bool Kinematic { | 566 | public override bool Kinematic { |
868 | get { return _kinematic; } | 567 | get { return _kinematic; } |
869 | set { _kinematic = value; | 568 | set { _kinematic = value; |
870 | // m_log.DebugFormat("{0}: Kinematic={1}", LogHeader, _kinematic); | 569 | // m_log.DebugFormat("{0}: Kinematic={1}", LogHeader, _kinematic); |
871 | } | 570 | } |
872 | } | 571 | } |
873 | public override float Buoyancy { | 572 | public override float Buoyancy { |
874 | get { return _buoyancy; } | 573 | get { return _buoyancy; } |
875 | set { | 574 | set { |
876 | _buoyancy = value; | 575 | _buoyancy = value; |
877 | PhysicsScene.TaintedObject("BSPrim.setBuoyancy", delegate() | 576 | _scene.TaintedObject("BSPrim.setBuoyancy", delegate() |
878 | { | 577 | { |
879 | ForceBuoyancy = _buoyancy; | 578 | // DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy); |
579 | BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy); | ||
880 | }); | 580 | }); |
881 | } | 581 | } |
882 | } | ||
883 | public override float ForceBuoyancy { | ||
884 | get { return _buoyancy; } | ||
885 | set { | ||
886 | _buoyancy = value; | ||
887 | // DetailLog("{0},BSPrim.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); | ||
888 | // Buoyancy is faked by changing the gravity applied to the object | ||
889 | float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); | ||
890 | BulletSimAPI.SetGravity2(PhysBody.ptr, new OMV.Vector3(0f, 0f, grav)); | ||
891 | } | ||
892 | } | 582 | } |
893 | 583 | ||
894 | // Used for MoveTo | 584 | // Used for MoveTo |
895 | public override OMV.Vector3 PIDTarget { | 585 | public override OMV.Vector3 PIDTarget { |
896 | set { _PIDTarget = value; } | 586 | set { _PIDTarget = value; } |
897 | } | 587 | } |
898 | public override bool PIDActive { | 588 | public override bool PIDActive { |
899 | set { _usePID = value; } | 589 | set { _usePID = value; } |
900 | } | 590 | } |
901 | public override float PIDTau { | 591 | public override float PIDTau { |
902 | set { _PIDTau = value; } | 592 | set { _PIDTau = value; } |
903 | } | 593 | } |
904 | 594 | ||
905 | // Used for llSetHoverHeight and maybe vehicle height | 595 | // Used for llSetHoverHeight and maybe vehicle height |
906 | // Hover Height will override MoveTo target's Z | 596 | // Hover Height will override MoveTo target's Z |
907 | public override bool PIDHoverActive { | 597 | public override bool PIDHoverActive { |
908 | set { _useHoverPID = value; } | 598 | set { _useHoverPID = value; } |
909 | } | 599 | } |
910 | public override float PIDHoverHeight { | 600 | public override float PIDHoverHeight { |
911 | set { _PIDHoverHeight = value; } | 601 | set { _PIDHoverHeight = value; } |
912 | } | 602 | } |
913 | public override PIDHoverType PIDHoverType { | 603 | public override PIDHoverType PIDHoverType { |
914 | set { _PIDHoverType = value; } | 604 | set { _PIDHoverType = value; } |
915 | } | 605 | } |
916 | public override float PIDHoverTau { | 606 | public override float PIDHoverTau { |
917 | set { _PIDHoverTao = value; } | 607 | set { _PIDHoverTao = value; } |
918 | } | 608 | } |
919 | 609 | ||
@@ -925,9 +615,6 @@ public sealed class BSPrim : BSPhysObject | |||
925 | 615 | ||
926 | private List<OMV.Vector3> m_accumulatedForces = new List<OMV.Vector3>(); | 616 | private List<OMV.Vector3> m_accumulatedForces = new List<OMV.Vector3>(); |
927 | public override void AddForce(OMV.Vector3 force, bool pushforce) { | 617 | public override void AddForce(OMV.Vector3 force, bool pushforce) { |
928 | AddForce(force, pushforce, false); | ||
929 | } | ||
930 | public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { | ||
931 | // for an object, doesn't matter if force is a pushforce or not | 618 | // for an object, doesn't matter if force is a pushforce or not |
932 | if (force.IsFinite()) | 619 | if (force.IsFinite()) |
933 | { | 620 | { |
@@ -937,78 +624,56 @@ public sealed class BSPrim : BSPhysObject | |||
937 | } | 624 | } |
938 | else | 625 | else |
939 | { | 626 | { |
940 | m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); | 627 | m_log.WarnFormat("{0}: Got a NaN force applied to a Character", LogHeader); |
941 | return; | 628 | return; |
942 | } | 629 | } |
943 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate() | 630 | _scene.TaintedObject("BSPrim.AddForce", delegate() |
944 | { | 631 | { |
945 | OMV.Vector3 fSum = OMV.Vector3.Zero; | 632 | OMV.Vector3 fSum = OMV.Vector3.Zero; |
946 | lock (m_accumulatedForces) | 633 | lock (m_accumulatedForces) |
947 | { | 634 | { |
948 | // Sum the accumulated additional forces for one big force to apply once. | ||
949 | foreach (OMV.Vector3 v in m_accumulatedForces) | 635 | foreach (OMV.Vector3 v in m_accumulatedForces) |
950 | { | 636 | { |
951 | fSum += v; | 637 | fSum += v; |
952 | } | 638 | } |
953 | m_accumulatedForces.Clear(); | 639 | m_accumulatedForces.Clear(); |
954 | } | 640 | } |
955 | DetailLog("{0},BSPrim.AddForce,taint,force={1}", LocalID, fSum); | 641 | // DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, _force); |
956 | if (fSum != OMV.Vector3.Zero) | 642 | BulletSimAPI.AddObjectForce2(Body.Ptr, fSum); |
957 | BulletSimAPI.ApplyCentralForce2(PhysBody.ptr, fSum); | ||
958 | }); | 643 | }); |
959 | } | 644 | } |
960 | 645 | ||
961 | private List<OMV.Vector3> m_accumulatedAngularForces = new List<OMV.Vector3>(); | 646 | public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { |
962 | public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { | 647 | // DetailLog("{0},BSPrim.AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce); |
963 | AddAngularForce(force, pushforce, false); | 648 | // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce); |
964 | } | 649 | } |
965 | public void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) | 650 | public override void SetMomentum(OMV.Vector3 momentum) { |
966 | { | 651 | // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum); |
967 | if (force.IsFinite()) | 652 | } |
968 | { | 653 | public override void SubscribeEvents(int ms) { |
969 | // _force += force; | 654 | _subscribedEventsMs = ms; |
970 | lock (m_accumulatedAngularForces) | 655 | if (ms > 0) |
971 | m_accumulatedAngularForces.Add(new OMV.Vector3(force)); | ||
972 | } | ||
973 | else | ||
974 | { | ||
975 | m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); | ||
976 | return; | ||
977 | } | ||
978 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddAngularForce", delegate() | ||
979 | { | 656 | { |
980 | OMV.Vector3 fSum = OMV.Vector3.Zero; | 657 | // make sure first collision happens |
981 | lock (m_accumulatedAngularForces) | 658 | _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs; |
982 | { | 659 | |
983 | // Sum the accumulated additional forces for one big force to apply once. | 660 | Scene.TaintedObject("BSPrim.SubscribeEvents", delegate() |
984 | foreach (OMV.Vector3 v in m_accumulatedAngularForces) | ||
985 | { | ||
986 | fSum += v; | ||
987 | } | ||
988 | m_accumulatedAngularForces.Clear(); | ||
989 | } | ||
990 | DetailLog("{0},BSPrim.AddAngularForce,taint,aForce={1}", LocalID, fSum); | ||
991 | if (fSum != OMV.Vector3.Zero) | ||
992 | { | 661 | { |
993 | BulletSimAPI.ApplyTorque2(PhysBody.ptr, fSum); | 662 | BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); |
994 | _torque = fSum; | 663 | }); |
995 | } | 664 | } |
996 | }); | ||
997 | } | 665 | } |
998 | // A torque impulse. | 666 | public override void UnSubscribeEvents() { |
999 | public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime) | 667 | _subscribedEventsMs = 0; |
1000 | { | 668 | Scene.TaintedObject("BSPrim.UnSubscribeEvents", delegate() |
1001 | OMV.Vector3 applyImpulse = impulse; | ||
1002 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyTorqueImpulse", delegate() | ||
1003 | { | 669 | { |
1004 | DetailLog("{0},BSPrim.ApplyTorqueImpulse,taint,tImpulse={1}", LocalID, applyImpulse); | 670 | BulletSimAPI.RemoveFromCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); |
1005 | BulletSimAPI.ApplyTorqueImpulse2(PhysBody.ptr, applyImpulse); | ||
1006 | }); | 671 | }); |
1007 | } | 672 | } |
1008 | 673 | public override bool SubscribedEvents() { | |
1009 | public override void SetMomentum(OMV.Vector3 momentum) { | 674 | return (_subscribedEventsMs > 0); |
1010 | // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum); | ||
1011 | } | 675 | } |
676 | |||
1012 | #region Mass Calculation | 677 | #region Mass Calculation |
1013 | 678 | ||
1014 | private float CalculateMass() | 679 | private float CalculateMass() |
@@ -1017,19 +682,19 @@ public sealed class BSPrim : BSPhysObject | |||
1017 | float tmp; | 682 | float tmp; |
1018 | 683 | ||
1019 | float returnMass = 0; | 684 | float returnMass = 0; |
1020 | float hollowAmount = (float)BaseShape.ProfileHollow * 2.0e-5f; | 685 | float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f; |
1021 | float hollowVolume = hollowAmount * hollowAmount; | 686 | float hollowVolume = hollowAmount * hollowAmount; |
1022 | 687 | ||
1023 | switch (BaseShape.ProfileShape) | 688 | switch (_pbs.ProfileShape) |
1024 | { | 689 | { |
1025 | case ProfileShape.Square: | 690 | case ProfileShape.Square: |
1026 | // default box | 691 | // default box |
1027 | 692 | ||
1028 | if (BaseShape.PathCurve == (byte)Extrusion.Straight) | 693 | if (_pbs.PathCurve == (byte)Extrusion.Straight) |
1029 | { | 694 | { |
1030 | if (hollowAmount > 0.0) | 695 | if (hollowAmount > 0.0) |
1031 | { | 696 | { |
1032 | switch (BaseShape.HollowShape) | 697 | switch (_pbs.HollowShape) |
1033 | { | 698 | { |
1034 | case HollowShape.Square: | 699 | case HollowShape.Square: |
1035 | case HollowShape.Same: | 700 | case HollowShape.Same: |
@@ -1053,19 +718,19 @@ public sealed class BSPrim : BSPhysObject | |||
1053 | } | 718 | } |
1054 | } | 719 | } |
1055 | 720 | ||
1056 | else if (BaseShape.PathCurve == (byte)Extrusion.Curve1) | 721 | else if (_pbs.PathCurve == (byte)Extrusion.Curve1) |
1057 | { | 722 | { |
1058 | //a tube | 723 | //a tube |
1059 | 724 | ||
1060 | volume *= 0.78539816339e-2f * (float)(200 - BaseShape.PathScaleX); | 725 | volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX); |
1061 | tmp= 1.0f -2.0e-2f * (float)(200 - BaseShape.PathScaleY); | 726 | tmp= 1.0f -2.0e-2f * (float)(200 - _pbs.PathScaleY); |
1062 | volume -= volume*tmp*tmp; | 727 | volume -= volume*tmp*tmp; |
1063 | 728 | ||
1064 | if (hollowAmount > 0.0) | 729 | if (hollowAmount > 0.0) |
1065 | { | 730 | { |
1066 | hollowVolume *= hollowAmount; | 731 | hollowVolume *= hollowAmount; |
1067 | 732 | ||
1068 | switch (BaseShape.HollowShape) | 733 | switch (_pbs.HollowShape) |
1069 | { | 734 | { |
1070 | case HollowShape.Square: | 735 | case HollowShape.Square: |
1071 | case HollowShape.Same: | 736 | case HollowShape.Same: |
@@ -1090,13 +755,13 @@ public sealed class BSPrim : BSPhysObject | |||
1090 | 755 | ||
1091 | case ProfileShape.Circle: | 756 | case ProfileShape.Circle: |
1092 | 757 | ||
1093 | if (BaseShape.PathCurve == (byte)Extrusion.Straight) | 758 | if (_pbs.PathCurve == (byte)Extrusion.Straight) |
1094 | { | 759 | { |
1095 | volume *= 0.78539816339f; // elipse base | 760 | volume *= 0.78539816339f; // elipse base |
1096 | 761 | ||
1097 | if (hollowAmount > 0.0) | 762 | if (hollowAmount > 0.0) |
1098 | { | 763 | { |
1099 | switch (BaseShape.HollowShape) | 764 | switch (_pbs.HollowShape) |
1100 | { | 765 | { |
1101 | case HollowShape.Same: | 766 | case HollowShape.Same: |
1102 | case HollowShape.Circle: | 767 | case HollowShape.Circle: |
@@ -1118,19 +783,19 @@ public sealed class BSPrim : BSPhysObject | |||
1118 | } | 783 | } |
1119 | } | 784 | } |
1120 | 785 | ||
1121 | else if (BaseShape.PathCurve == (byte)Extrusion.Curve1) | 786 | else if (_pbs.PathCurve == (byte)Extrusion.Curve1) |
1122 | { | 787 | { |
1123 | volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - BaseShape.PathScaleX); | 788 | volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX); |
1124 | tmp = 1.0f - .02f * (float)(200 - BaseShape.PathScaleY); | 789 | tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY); |
1125 | volume *= (1.0f - tmp * tmp); | 790 | volume *= (1.0f - tmp * tmp); |
1126 | 791 | ||
1127 | if (hollowAmount > 0.0) | 792 | if (hollowAmount > 0.0) |
1128 | { | 793 | { |
1129 | 794 | ||
1130 | // calculate the hollow volume by it's shape compared to the prim shape | 795 | // calculate the hollow volume by it's shape compared to the prim shape |
1131 | hollowVolume *= hollowAmount; | 796 | hollowVolume *= hollowAmount; |
1132 | 797 | ||
1133 | switch (BaseShape.HollowShape) | 798 | switch (_pbs.HollowShape) |
1134 | { | 799 | { |
1135 | case HollowShape.Same: | 800 | case HollowShape.Same: |
1136 | case HollowShape.Circle: | 801 | case HollowShape.Circle: |
@@ -1154,7 +819,7 @@ public sealed class BSPrim : BSPhysObject | |||
1154 | break; | 819 | break; |
1155 | 820 | ||
1156 | case ProfileShape.HalfCircle: | 821 | case ProfileShape.HalfCircle: |
1157 | if (BaseShape.PathCurve == (byte)Extrusion.Curve1) | 822 | if (_pbs.PathCurve == (byte)Extrusion.Curve1) |
1158 | { | 823 | { |
1159 | volume *= 0.52359877559829887307710723054658f; | 824 | volume *= 0.52359877559829887307710723054658f; |
1160 | } | 825 | } |
@@ -1162,7 +827,7 @@ public sealed class BSPrim : BSPhysObject | |||
1162 | 827 | ||
1163 | case ProfileShape.EquilateralTriangle: | 828 | case ProfileShape.EquilateralTriangle: |
1164 | 829 | ||
1165 | if (BaseShape.PathCurve == (byte)Extrusion.Straight) | 830 | if (_pbs.PathCurve == (byte)Extrusion.Straight) |
1166 | { | 831 | { |
1167 | volume *= 0.32475953f; | 832 | volume *= 0.32475953f; |
1168 | 833 | ||
@@ -1170,7 +835,7 @@ public sealed class BSPrim : BSPhysObject | |||
1170 | { | 835 | { |
1171 | 836 | ||
1172 | // calculate the hollow volume by it's shape compared to the prim shape | 837 | // calculate the hollow volume by it's shape compared to the prim shape |
1173 | switch (BaseShape.HollowShape) | 838 | switch (_pbs.HollowShape) |
1174 | { | 839 | { |
1175 | case HollowShape.Same: | 840 | case HollowShape.Same: |
1176 | case HollowShape.Triangle: | 841 | case HollowShape.Triangle: |
@@ -1195,11 +860,11 @@ public sealed class BSPrim : BSPhysObject | |||
1195 | volume *= (1.0f - hollowVolume); | 860 | volume *= (1.0f - hollowVolume); |
1196 | } | 861 | } |
1197 | } | 862 | } |
1198 | else if (BaseShape.PathCurve == (byte)Extrusion.Curve1) | 863 | else if (_pbs.PathCurve == (byte)Extrusion.Curve1) |
1199 | { | 864 | { |
1200 | volume *= 0.32475953f; | 865 | volume *= 0.32475953f; |
1201 | volume *= 0.01f * (float)(200 - BaseShape.PathScaleX); | 866 | volume *= 0.01f * (float)(200 - _pbs.PathScaleX); |
1202 | tmp = 1.0f - .02f * (float)(200 - BaseShape.PathScaleY); | 867 | tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY); |
1203 | volume *= (1.0f - tmp * tmp); | 868 | volume *= (1.0f - tmp * tmp); |
1204 | 869 | ||
1205 | if (hollowAmount > 0.0) | 870 | if (hollowAmount > 0.0) |
@@ -1207,7 +872,7 @@ public sealed class BSPrim : BSPhysObject | |||
1207 | 872 | ||
1208 | hollowVolume *= hollowAmount; | 873 | hollowVolume *= hollowAmount; |
1209 | 874 | ||
1210 | switch (BaseShape.HollowShape) | 875 | switch (_pbs.HollowShape) |
1211 | { | 876 | { |
1212 | case HollowShape.Same: | 877 | case HollowShape.Same: |
1213 | case HollowShape.Triangle: | 878 | case HollowShape.Triangle: |
@@ -1247,26 +912,26 @@ public sealed class BSPrim : BSPhysObject | |||
1247 | float profileBegin; | 912 | float profileBegin; |
1248 | float profileEnd; | 913 | float profileEnd; |
1249 | 914 | ||
1250 | if (BaseShape.PathCurve == (byte)Extrusion.Straight || BaseShape.PathCurve == (byte)Extrusion.Flexible) | 915 | if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible) |
1251 | { | 916 | { |
1252 | taperX1 = BaseShape.PathScaleX * 0.01f; | 917 | taperX1 = _pbs.PathScaleX * 0.01f; |
1253 | if (taperX1 > 1.0f) | 918 | if (taperX1 > 1.0f) |
1254 | taperX1 = 2.0f - taperX1; | 919 | taperX1 = 2.0f - taperX1; |
1255 | taperX = 1.0f - taperX1; | 920 | taperX = 1.0f - taperX1; |
1256 | 921 | ||
1257 | taperY1 = BaseShape.PathScaleY * 0.01f; | 922 | taperY1 = _pbs.PathScaleY * 0.01f; |
1258 | if (taperY1 > 1.0f) | 923 | if (taperY1 > 1.0f) |
1259 | taperY1 = 2.0f - taperY1; | 924 | taperY1 = 2.0f - taperY1; |
1260 | taperY = 1.0f - taperY1; | 925 | taperY = 1.0f - taperY1; |
1261 | } | 926 | } |
1262 | else | 927 | else |
1263 | { | 928 | { |
1264 | taperX = BaseShape.PathTaperX * 0.01f; | 929 | taperX = _pbs.PathTaperX * 0.01f; |
1265 | if (taperX < 0.0f) | 930 | if (taperX < 0.0f) |
1266 | taperX = -taperX; | 931 | taperX = -taperX; |
1267 | taperX1 = 1.0f - taperX; | 932 | taperX1 = 1.0f - taperX; |
1268 | 933 | ||
1269 | taperY = BaseShape.PathTaperY * 0.01f; | 934 | taperY = _pbs.PathTaperY * 0.01f; |
1270 | if (taperY < 0.0f) | 935 | if (taperY < 0.0f) |
1271 | taperY = -taperY; | 936 | taperY = -taperY; |
1272 | taperY1 = 1.0f - taperY; | 937 | taperY1 = 1.0f - taperY; |
@@ -1276,18 +941,20 @@ public sealed class BSPrim : BSPhysObject | |||
1276 | 941 | ||
1277 | volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY); | 942 | volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY); |
1278 | 943 | ||
1279 | pathBegin = (float)BaseShape.PathBegin * 2.0e-5f; | 944 | pathBegin = (float)_pbs.PathBegin * 2.0e-5f; |
1280 | pathEnd = 1.0f - (float)BaseShape.PathEnd * 2.0e-5f; | 945 | pathEnd = 1.0f - (float)_pbs.PathEnd * 2.0e-5f; |
1281 | volume *= (pathEnd - pathBegin); | 946 | volume *= (pathEnd - pathBegin); |
1282 | 947 | ||
1283 | // this is crude aproximation | 948 | // this is crude aproximation |
1284 | profileBegin = (float)BaseShape.ProfileBegin * 2.0e-5f; | 949 | profileBegin = (float)_pbs.ProfileBegin * 2.0e-5f; |
1285 | profileEnd = 1.0f - (float)BaseShape.ProfileEnd * 2.0e-5f; | 950 | profileEnd = 1.0f - (float)_pbs.ProfileEnd * 2.0e-5f; |
1286 | volume *= (profileEnd - profileBegin); | 951 | volume *= (profileEnd - profileBegin); |
1287 | 952 | ||
1288 | returnMass = _density * volume; | 953 | returnMass = _density * volume; |
1289 | 954 | ||
1290 | /* Comment out code that computes the mass of the linkset. That is done in the Linkset class. | 955 | /* |
956 | * This change means each object keeps its own mass and the Mass property | ||
957 | * will return the sum if we're part of a linkset. | ||
1291 | if (IsRootOfLinkset) | 958 | if (IsRootOfLinkset) |
1292 | { | 959 | { |
1293 | foreach (BSPrim prim in _childrenPrims) | 960 | foreach (BSPrim prim in _childrenPrims) |
@@ -1300,42 +967,296 @@ public sealed class BSPrim : BSPhysObject | |||
1300 | if (returnMass <= 0) | 967 | if (returnMass <= 0) |
1301 | returnMass = 0.0001f; | 968 | returnMass = 0.0001f; |
1302 | 969 | ||
1303 | if (returnMass > PhysicsScene.MaximumObjectMass) | 970 | if (returnMass > _scene.MaximumObjectMass) |
1304 | returnMass = PhysicsScene.MaximumObjectMass; | 971 | returnMass = _scene.MaximumObjectMass; |
1305 | 972 | ||
1306 | return returnMass; | 973 | return returnMass; |
1307 | }// end CalculateMass | 974 | }// end CalculateMass |
1308 | #endregion Mass Calculation | 975 | #endregion Mass Calculation |
1309 | 976 | ||
1310 | // Rebuild the geometry and object. | 977 | // Create the geometry information in Bullet for later use |
1311 | // This is called when the shape changes so we need to recreate the mesh/hull. | 978 | // The objects needs a hull if it's physical otherwise a mesh is enough |
1312 | // Called at taint-time!!! | 979 | // No locking here because this is done when we know physics is not simulating |
1313 | private void CreateGeomAndObject(bool forceRebuild) | 980 | // if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used |
981 | // Returns 'true' if the geometry was rebuilt | ||
982 | private bool CreateGeom(bool forceRebuild) | ||
1314 | { | 983 | { |
1315 | // If this prim is part of a linkset, we must remove and restore the physical | 984 | // the mesher thought this was too simple to mesh. Use a native Bullet collision shape. |
1316 | // links if the body is rebuilt. | 985 | bool ret = false; |
1317 | bool needToRestoreLinkset = false; | 986 | if (!_scene.NeedsMeshing(_pbs)) |
1318 | |||
1319 | // Create the correct physical representation for this type of object. | ||
1320 | // Updates BSBody and BSShape with the new information. | ||
1321 | // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary. | ||
1322 | // Returns 'true' if either the body or the shape was changed. | ||
1323 | PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, null, delegate(BulletBody dBody) | ||
1324 | { | 987 | { |
1325 | // Called if the current prim body is about to be destroyed. | 988 | if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) |
1326 | // Remove all the physical dependencies on the old body. | 989 | { |
1327 | // (Maybe someday make the changing of BSShape an event handled by BSLinkset.) | 990 | // if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) |
1328 | needToRestoreLinkset = Linkset.RemoveBodyDependencies(this); | 991 | // { |
1329 | }); | 992 | // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size); |
993 | if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE)) | ||
994 | { | ||
995 | // DetailLog("{0},BSPrim.CreateGeom,sphere (force={1}", LocalID, forceRebuild); | ||
996 | _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE; | ||
997 | // Bullet native objects are scaled by the Bullet engine so pass the size in | ||
998 | _scale = _size; | ||
999 | // TODO: do we need to check for and destroy a mesh or hull that might have been left from before? | ||
1000 | ret = true; | ||
1001 | } | ||
1002 | // } | ||
1003 | } | ||
1004 | else | ||
1005 | { | ||
1006 | // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size); | ||
1007 | if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX)) | ||
1008 | { | ||
1009 | // DetailLog("{0},BSPrim.CreateGeom,box (force={1})", LocalID, forceRebuild); | ||
1010 | _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX; | ||
1011 | _scale = _size; | ||
1012 | // TODO: do we need to check for and destroy a mesh or hull that might have been left from before? | ||
1013 | ret = true; | ||
1014 | } | ||
1015 | } | ||
1016 | } | ||
1017 | else | ||
1018 | { | ||
1019 | if (IsPhysical) | ||
1020 | { | ||
1021 | if (forceRebuild || _hullKey == 0) | ||
1022 | { | ||
1023 | // physical objects require a hull for interaction. | ||
1024 | // This will create the mesh if it doesn't already exist | ||
1025 | CreateGeomHull(); | ||
1026 | ret = true; | ||
1027 | } | ||
1028 | } | ||
1029 | else | ||
1030 | { | ||
1031 | if (forceRebuild || _meshKey == 0) | ||
1032 | { | ||
1033 | // Static (non-physical) objects only need a mesh for bumping into | ||
1034 | CreateGeomMesh(); | ||
1035 | ret = true; | ||
1036 | } | ||
1037 | } | ||
1038 | } | ||
1039 | return ret; | ||
1040 | } | ||
1041 | |||
1042 | // No locking here because this is done when we know physics is not simulating | ||
1043 | private void CreateGeomMesh() | ||
1044 | { | ||
1045 | float lod = _pbs.SculptEntry ? _scene.SculptLOD : _scene.MeshLOD; | ||
1046 | ulong newMeshKey = (ulong)_pbs.GetMeshKey(_size, lod); | ||
1047 | // m_log.DebugFormat("{0}: CreateGeomMesh: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _meshKey, newMeshKey); | ||
1048 | |||
1049 | // if this new shape is the same as last time, don't recreate the mesh | ||
1050 | if (_meshKey == newMeshKey) return; | ||
1051 | |||
1052 | // DetailLog("{0},BSPrim.CreateGeomMesh,create,key={1}", LocalID, newMeshKey); | ||
1053 | // Since we're recreating new, get rid of any previously generated shape | ||
1054 | if (_meshKey != 0) | ||
1055 | { | ||
1056 | // m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey); | ||
1057 | // DetailLog("{0},BSPrim.CreateGeomMesh,deleteOld,key={1}", LocalID, _meshKey); | ||
1058 | BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey); | ||
1059 | _mesh = null; | ||
1060 | _meshKey = 0; | ||
1061 | } | ||
1062 | |||
1063 | _meshKey = newMeshKey; | ||
1064 | // always pass false for physicalness as this creates some sort of bounding box which we don't need | ||
1065 | _mesh = _scene.mesher.CreateMesh(_avName, _pbs, _size, lod, false); | ||
1066 | |||
1067 | int[] indices = _mesh.getIndexListAsInt(); | ||
1068 | List<OMV.Vector3> vertices = _mesh.getVertexList(); | ||
1069 | |||
1070 | float[] verticesAsFloats = new float[vertices.Count * 3]; | ||
1071 | int vi = 0; | ||
1072 | foreach (OMV.Vector3 vv in vertices) | ||
1073 | { | ||
1074 | verticesAsFloats[vi++] = vv.X; | ||
1075 | verticesAsFloats[vi++] = vv.Y; | ||
1076 | verticesAsFloats[vi++] = vv.Z; | ||
1077 | } | ||
1078 | |||
1079 | // m_log.DebugFormat("{0}: CreateGeomMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}", | ||
1080 | // LogHeader, _localID, _meshKey, indices.Length, vertices.Count); | ||
1081 | BulletSimAPI.CreateMesh(_scene.WorldID, _meshKey, indices.GetLength(0), indices, | ||
1082 | vertices.Count, verticesAsFloats); | ||
1083 | |||
1084 | _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH; | ||
1085 | // meshes are already scaled by the meshmerizer | ||
1086 | _scale = new OMV.Vector3(1f, 1f, 1f); | ||
1087 | // DetailLog("{0},BSPrim.CreateGeomMesh,done", LocalID); | ||
1088 | return; | ||
1089 | } | ||
1090 | |||
1091 | // No locking here because this is done when we know physics is not simulating | ||
1092 | private void CreateGeomHull() | ||
1093 | { | ||
1094 | float lod = _pbs.SculptEntry ? _scene.SculptLOD : _scene.MeshLOD; | ||
1095 | ulong newHullKey = (ulong)_pbs.GetMeshKey(_size, lod); | ||
1096 | // m_log.DebugFormat("{0}: CreateGeomHull: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _hullKey, newHullKey); | ||
1097 | |||
1098 | // if the hull hasn't changed, don't rebuild it | ||
1099 | if (newHullKey == _hullKey) return; | ||
1330 | 1100 | ||
1331 | if (needToRestoreLinkset) | 1101 | // DetailLog("{0},BSPrim.CreateGeomHull,create,oldKey={1},newKey={2}", LocalID, _hullKey, newHullKey); |
1102 | |||
1103 | // Since we're recreating new, get rid of any previously generated shape | ||
1104 | if (_hullKey != 0) | ||
1332 | { | 1105 | { |
1333 | // If physical body dependencies were removed, restore them | 1106 | // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey); |
1334 | Linkset.RestoreBodyDependencies(this); | 1107 | // DetailLog("{0},BSPrim.CreateGeomHull,deleteOldHull,key={1}", LocalID, _hullKey); |
1108 | BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey); | ||
1109 | _hullKey = 0; | ||
1110 | } | ||
1111 | |||
1112 | _hullKey = newHullKey; | ||
1113 | |||
1114 | // Make sure the underlying mesh exists and is correct | ||
1115 | CreateGeomMesh(); | ||
1116 | |||
1117 | int[] indices = _mesh.getIndexListAsInt(); | ||
1118 | List<OMV.Vector3> vertices = _mesh.getVertexList(); | ||
1119 | |||
1120 | //format conversion from IMesh format to DecompDesc format | ||
1121 | List<int> convIndices = new List<int>(); | ||
1122 | List<float3> convVertices = new List<float3>(); | ||
1123 | for (int ii = 0; ii < indices.GetLength(0); ii++) | ||
1124 | { | ||
1125 | convIndices.Add(indices[ii]); | ||
1126 | } | ||
1127 | foreach (OMV.Vector3 vv in vertices) | ||
1128 | { | ||
1129 | convVertices.Add(new float3(vv.X, vv.Y, vv.Z)); | ||
1130 | } | ||
1131 | |||
1132 | // setup and do convex hull conversion | ||
1133 | _hulls = new List<ConvexResult>(); | ||
1134 | DecompDesc dcomp = new DecompDesc(); | ||
1135 | dcomp.mIndices = convIndices; | ||
1136 | dcomp.mVertices = convVertices; | ||
1137 | ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn); | ||
1138 | // create the hull into the _hulls variable | ||
1139 | convexBuilder.process(dcomp); | ||
1140 | |||
1141 | // Convert the vertices and indices for passing to unmanaged. | ||
1142 | // The hull information is passed as a large floating point array. | ||
1143 | // The format is: | ||
1144 | // convHulls[0] = number of hulls | ||
1145 | // convHulls[1] = number of vertices in first hull | ||
1146 | // convHulls[2] = hull centroid X coordinate | ||
1147 | // convHulls[3] = hull centroid Y coordinate | ||
1148 | // convHulls[4] = hull centroid Z coordinate | ||
1149 | // convHulls[5] = first hull vertex X | ||
1150 | // convHulls[6] = first hull vertex Y | ||
1151 | // convHulls[7] = first hull vertex Z | ||
1152 | // convHulls[8] = second hull vertex X | ||
1153 | // ... | ||
1154 | // convHulls[n] = number of vertices in second hull | ||
1155 | // convHulls[n+1] = second hull centroid X coordinate | ||
1156 | // ... | ||
1157 | // | ||
1158 | // TODO: is is very inefficient. Someday change the convex hull generator to return | ||
1159 | // data structures that do not need to be converted in order to pass to Bullet. | ||
1160 | // And maybe put the values directly into pinned memory rather than marshaling. | ||
1161 | int hullCount = _hulls.Count; | ||
1162 | int totalVertices = 1; // include one for the count of the hulls | ||
1163 | foreach (ConvexResult cr in _hulls) | ||
1164 | { | ||
1165 | totalVertices += 4; // add four for the vertex count and centroid | ||
1166 | totalVertices += cr.HullIndices.Count * 3; // we pass just triangles | ||
1167 | } | ||
1168 | float[] convHulls = new float[totalVertices]; | ||
1169 | |||
1170 | convHulls[0] = (float)hullCount; | ||
1171 | int jj = 1; | ||
1172 | foreach (ConvexResult cr in _hulls) | ||
1173 | { | ||
1174 | // copy vertices for index access | ||
1175 | float3[] verts = new float3[cr.HullVertices.Count]; | ||
1176 | int kk = 0; | ||
1177 | foreach (float3 ff in cr.HullVertices) | ||
1178 | { | ||
1179 | verts[kk++] = ff; | ||
1180 | } | ||
1181 | |||
1182 | // add to the array one hull's worth of data | ||
1183 | convHulls[jj++] = cr.HullIndices.Count; | ||
1184 | convHulls[jj++] = 0f; // centroid x,y,z | ||
1185 | convHulls[jj++] = 0f; | ||
1186 | convHulls[jj++] = 0f; | ||
1187 | foreach (int ind in cr.HullIndices) | ||
1188 | { | ||
1189 | convHulls[jj++] = verts[ind].x; | ||
1190 | convHulls[jj++] = verts[ind].y; | ||
1191 | convHulls[jj++] = verts[ind].z; | ||
1192 | } | ||
1335 | } | 1193 | } |
1336 | 1194 | ||
1337 | // Make sure the properties are set on the new object | 1195 | // create the hull definition in Bullet |
1338 | UpdatePhysicalParameters(); | 1196 | // m_log.DebugFormat("{0}: CreateGeom: calling CreateHull. lid={1}, key={2}, hulls={3}", LogHeader, _localID, _hullKey, hullCount); |
1197 | BulletSimAPI.CreateHull(_scene.WorldID, _hullKey, hullCount, convHulls); | ||
1198 | _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL; | ||
1199 | // meshes are already scaled by the meshmerizer | ||
1200 | _scale = new OMV.Vector3(1f, 1f, 1f); | ||
1201 | // DetailLog("{0},BSPrim.CreateGeomHull,done", LocalID); | ||
1202 | return; | ||
1203 | } | ||
1204 | |||
1205 | // Callback from convex hull creater with a newly created hull. | ||
1206 | // Just add it to the collection of hulls for this shape. | ||
1207 | private void HullReturn(ConvexResult result) | ||
1208 | { | ||
1209 | _hulls.Add(result); | ||
1210 | return; | ||
1211 | } | ||
1212 | |||
1213 | // Create an object in Bullet if it has not already been created | ||
1214 | // No locking here because this is done when the physics engine is not simulating | ||
1215 | // Returns 'true' if an object was actually created. | ||
1216 | private bool CreateObject() | ||
1217 | { | ||
1218 | // this routine is called when objects are rebuilt. | ||
1219 | |||
1220 | // the mesh or hull must have already been created in Bullet | ||
1221 | ShapeData shape; | ||
1222 | FillShapeInfo(out shape); | ||
1223 | // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type); | ||
1224 | bool ret = BulletSimAPI.CreateObject(_scene.WorldID, shape); | ||
1225 | |||
1226 | // the CreateObject() may have recreated the rigid body. Make sure we have the latest. | ||
1227 | Body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); | ||
1228 | |||
1229 | return ret; | ||
1230 | } | ||
1231 | |||
1232 | // Copy prim's info into the BulletSim shape description structure | ||
1233 | public void FillShapeInfo(out ShapeData shape) | ||
1234 | { | ||
1235 | shape.ID = _localID; | ||
1236 | shape.Type = _shapeType; | ||
1237 | shape.Position = _position; | ||
1238 | shape.Rotation = _orientation; | ||
1239 | shape.Velocity = _velocity; | ||
1240 | shape.Scale = _scale; | ||
1241 | shape.Mass = _isPhysical ? _mass : 0f; | ||
1242 | shape.Buoyancy = _buoyancy; | ||
1243 | shape.HullKey = _hullKey; | ||
1244 | shape.MeshKey = _meshKey; | ||
1245 | shape.Friction = _friction; | ||
1246 | shape.Restitution = _restitution; | ||
1247 | shape.Collidable = (!IsPhantom) ? ShapeData.numericTrue : ShapeData.numericFalse; | ||
1248 | shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue; | ||
1249 | } | ||
1250 | |||
1251 | |||
1252 | // Rebuild the geometry and object. | ||
1253 | // This is called when the shape changes so we need to recreate the mesh/hull. | ||
1254 | // No locking here because this is done when the physics engine is not simulating | ||
1255 | private void RecreateGeomAndObject() | ||
1256 | { | ||
1257 | // m_log.DebugFormat("{0}: RecreateGeomAndObject. lID={1}", LogHeader, _localID); | ||
1258 | if (CreateGeom(true)) | ||
1259 | CreateObject(); | ||
1339 | return; | 1260 | return; |
1340 | } | 1261 | } |
1341 | 1262 | ||
@@ -1356,7 +1277,7 @@ public sealed class BSPrim : BSPhysObject | |||
1356 | const float ACCELERATION_TOLERANCE = 0.01f; | 1277 | const float ACCELERATION_TOLERANCE = 0.01f; |
1357 | const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f; | 1278 | const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f; |
1358 | 1279 | ||
1359 | public override void UpdateProperties(EntityProperties entprop) | 1280 | public void UpdateProperties(EntityProperties entprop) |
1360 | { | 1281 | { |
1361 | /* | 1282 | /* |
1362 | UpdatedProperties changed = 0; | 1283 | UpdatedProperties changed = 0; |
@@ -1404,7 +1325,7 @@ public sealed class BSPrim : BSPhysObject | |||
1404 | // Don't check for damping here -- it's done in BulletSim and SceneObjectPart. | 1325 | // Don't check for damping here -- it's done in BulletSim and SceneObjectPart. |
1405 | 1326 | ||
1406 | // Updates only for individual prims and for the root object of a linkset. | 1327 | // Updates only for individual prims and for the root object of a linkset. |
1407 | if (Linkset.IsRoot(this)) | 1328 | if (_linkset.IsRoot(this)) |
1408 | { | 1329 | { |
1409 | // Assign to the local variables so the normal set action does not happen | 1330 | // Assign to the local variables so the normal set action does not happen |
1410 | _position = entprop.Position; | 1331 | _position = entprop.Position; |
@@ -1413,32 +1334,69 @@ public sealed class BSPrim : BSPhysObject | |||
1413 | _acceleration = entprop.Acceleration; | 1334 | _acceleration = entprop.Acceleration; |
1414 | _rotationalVelocity = entprop.RotationalVelocity; | 1335 | _rotationalVelocity = entprop.RotationalVelocity; |
1415 | 1336 | ||
1416 | // remember the current and last set values | 1337 | // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}, vel={5}, acc={6}, rvel={7}", |
1417 | LastEntityProperties = CurrentEntityProperties; | 1338 | // LogHeader, LocalID, changed, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); |
1418 | CurrentEntityProperties = entprop; | 1339 | // DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", |
1419 | 1340 | // LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); | |
1420 | PositionSanityCheck(true); | ||
1421 | |||
1422 | OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation; | ||
1423 | DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},dir={3},vel={4},rotVel={5}", | ||
1424 | LocalID, _position, _orientation, direction, _velocity, _rotationalVelocity); | ||
1425 | |||
1426 | // BulletSimAPI.DumpRigidBody2(PhysicsScene.World.ptr, BSBody.ptr); // DEBUG DEBUG DEBUG | ||
1427 | 1341 | ||
1428 | base.RequestPhysicsterseUpdate(); | 1342 | base.RequestPhysicsterseUpdate(); |
1429 | } | 1343 | } |
1430 | /* | 1344 | /* |
1431 | else | 1345 | else |
1432 | { | 1346 | { |
1433 | // For debugging, report the movement of children | 1347 | // For debugging, we also report the movement of children |
1434 | DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}", | 1348 | DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}", |
1435 | LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, | 1349 | LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, |
1436 | entprop.Acceleration, entprop.RotationalVelocity); | 1350 | entprop.Acceleration, entprop.RotationalVelocity); |
1437 | } | 1351 | } |
1438 | */ | 1352 | */ |
1353 | } | ||
1354 | |||
1355 | // I've collided with something | ||
1356 | CollisionEventUpdate collisionCollection; | ||
1357 | public void Collide(uint collidingWith, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) | ||
1358 | { | ||
1359 | // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith); | ||
1360 | |||
1361 | // The following lines make IsColliding() and IsCollidingGround() work | ||
1362 | _collidingStep = _scene.SimulationStep; | ||
1363 | if (collidingWith == BSScene.TERRAIN_ID || collidingWith == BSScene.GROUNDPLANE_ID) | ||
1364 | { | ||
1365 | _collidingGroundStep = _scene.SimulationStep; | ||
1366 | } | ||
1367 | |||
1368 | // DetailLog("{0},BSPrim.Collison,call,with={1}", LocalID, collidingWith); | ||
1369 | |||
1370 | // if someone is subscribed to collision events.... | ||
1371 | if (_subscribedEventsMs != 0) { | ||
1372 | // throttle the collisions to the number of milliseconds specified in the subscription | ||
1373 | int nowTime = _scene.SimulationNowTime; | ||
1374 | if (nowTime >= _nextCollisionOkTime) { | ||
1375 | _nextCollisionOkTime = nowTime + _subscribedEventsMs; | ||
1439 | 1376 | ||
1440 | // The linkset implimentation might want to know about this. | 1377 | if (collisionCollection == null) |
1441 | Linkset.UpdateProperties(this); | 1378 | collisionCollection = new CollisionEventUpdate(); |
1379 | collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); | ||
1380 | } | ||
1381 | } | ||
1382 | } | ||
1383 | |||
1384 | // The scene is telling us it's time to pass our collected collisions into the simulator | ||
1385 | public void SendCollisions() | ||
1386 | { | ||
1387 | if (collisionCollection != null && collisionCollection.Count > 0) | ||
1388 | { | ||
1389 | base.SendCollisionUpdate(collisionCollection); | ||
1390 | // The collisionCollection structure is passed around in the simulator. | ||
1391 | // Make sure we don't have a handle to that one and that a new one is used next time. | ||
1392 | collisionCollection = null; | ||
1393 | } | ||
1394 | } | ||
1395 | |||
1396 | // Invoke the detailed logger and output something if it's enabled. | ||
1397 | private void DetailLog(string msg, params Object[] args) | ||
1398 | { | ||
1399 | Scene.PhysicsLogging.Write(msg, args); | ||
1442 | } | 1400 | } |
1443 | } | 1401 | } |
1444 | } | 1402 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 740f339..a31c578 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | |||
@@ -39,88 +39,96 @@ 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 | // Test sculpties (verified that they don't work) | 42 | // Debug linkset |
43 | // Test with multiple regions in one simulator | ||
44 | // Adjust character capsule size when height is adjusted (ScenePresence.SetHeight) | ||
45 | // Test sculpties | ||
43 | // Compute physics FPS reasonably | 46 | // Compute physics FPS reasonably |
44 | // Based on material, set density and friction | 47 | // Based on material, set density and friction |
45 | // Don't use constraints in linksets of non-physical objects. Means having to move children manually. | 48 | // More efficient memory usage when passing hull information from BSPrim to BulletSim |
49 | // Move all logic out of the C++ code and into the C# code for easier future modifications. | ||
46 | // Four states of prim: Physical, regular, phantom and selected. Are we modeling these correctly? | 50 | // Four states of prim: Physical, regular, phantom and selected. Are we modeling these correctly? |
47 | // In SL one can set both physical and phantom (gravity, does not effect others, makes collisions with ground) | 51 | // In SL one can set both physical and phantom (gravity, does not effect others, makes collisions with ground) |
48 | // At the moment, physical and phantom causes object to drop through the terrain | 52 | // At the moment, physical and phantom causes object to drop through the terrain |
49 | // Physical phantom objects and related typing (collision options ) | 53 | // Physical phantom objects and related typing (collision options ) |
54 | // Use collision masks for collision with terrain and phantom objects | ||
50 | // Check out llVolumeDetect. Must do something for that. | 55 | // Check out llVolumeDetect. Must do something for that. |
51 | // Use collision masks for collision with terrain and phantom objects | ||
52 | // More efficient memory usage when passing hull information from BSPrim to BulletSim | ||
53 | // Should prim.link() and prim.delink() membership checking happen at taint time? | 56 | // Should prim.link() and prim.delink() membership checking happen at taint time? |
54 | // Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once. | 57 | // changing the position and orientation of a linked prim must rebuild the constraint with the root. |
58 | // Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once | ||
55 | // Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect | 59 | // Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect |
60 | // Implement the genCollisions feature in BulletSim::SetObjectProperties (don't pass up unneeded collisions) | ||
56 | // Implement LockAngularMotion | 61 | // Implement LockAngularMotion |
57 | // Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation) | 62 | // Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation) |
63 | // Does NeedsMeshing() really need to exclude all the different shapes? | ||
58 | // Remove mesh and Hull stuff. Use mesh passed to bullet and use convexdecom from bullet. | 64 | // Remove mesh and Hull stuff. Use mesh passed to bullet and use convexdecom from bullet. |
59 | // Add PID movement operations. What does ScenePresence.MoveToTarget do? | 65 | // Add PID movement operations. What does ScenePresence.MoveToTarget do? |
60 | // Check terrain size. 128 or 127? | 66 | // Check terrain size. 128 or 127? |
61 | // Raycast | 67 | // Raycast |
62 | // | 68 | // |
63 | namespace OpenSim.Region.Physics.BulletSPlugin | 69 | namespace OpenSim.Region.Physics.BulletSPlugin |
64 | { | 70 | { |
65 | public sealed class BSScene : PhysicsScene, IPhysicsParameters | 71 | public class BSScene : PhysicsScene, IPhysicsParameters |
66 | { | 72 | { |
67 | private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | 73 | private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); |
68 | private static readonly string LogHeader = "[BULLETS SCENE]"; | 74 | private static readonly string LogHeader = "[BULLETS SCENE]"; |
69 | 75 | ||
70 | // The name of the region we're working for. | 76 | public void DebugLog(string mm, params Object[] xx) { if (ShouldDebugLog) m_log.DebugFormat(mm, xx); } |
71 | public string RegionName { get; private set; } | ||
72 | 77 | ||
73 | public string BulletSimVersion = "?"; | 78 | public string BulletSimVersion = "?"; |
74 | 79 | ||
75 | public Dictionary<uint, BSPhysObject> PhysObjects; | 80 | private Dictionary<uint, BSCharacter> m_avatars = new Dictionary<uint, BSCharacter>(); |
76 | public BSShapeCollection Shapes; | 81 | private Dictionary<uint, BSPrim> m_prims = new Dictionary<uint, BSPrim>(); |
77 | 82 | private HashSet<BSCharacter> m_avatarsWithCollisions = new HashSet<BSCharacter>(); | |
78 | // Keeping track of the objects with collisions so we can report begin and end of a collision | 83 | private HashSet<BSPrim> m_primsWithCollisions = new HashSet<BSPrim>(); |
79 | public HashSet<BSPhysObject> ObjectsWithCollisions = new HashSet<BSPhysObject>(); | 84 | private List<BSPrim> m_vehicles = new List<BSPrim>(); |
80 | public HashSet<BSPhysObject> ObjectsWithNoMoreCollisions = new HashSet<BSPhysObject>(); | 85 | private float[] m_heightMap; |
81 | // Keep track of all the avatars so we can send them a collision event | 86 | private float m_waterLevel; |
82 | // every tick so OpenSim will update its animation. | 87 | private uint m_worldID; |
83 | private HashSet<BSPhysObject> m_avatars = new HashSet<BSPhysObject>(); | 88 | public uint WorldID { get { return m_worldID; } } |
84 | |||
85 | // List of all the objects that have vehicle properties and should be called | ||
86 | // to update each physics step. | ||
87 | private List<BSPhysObject> m_vehicles = new List<BSPhysObject>(); | ||
88 | 89 | ||
89 | // let my minuions use my logger | 90 | // let my minuions use my logger |
90 | public ILog Logger { get { return m_log; } } | 91 | public ILog Logger { get { return m_log; } } |
91 | 92 | ||
92 | public IMesher mesher; | 93 | private bool m_initialized = false; |
93 | // Level of Detail values kept as float because that's what the Meshmerizer wants | ||
94 | public float MeshLOD { get; private set; } | ||
95 | public float MeshMegaPrimLOD { get; private set; } | ||
96 | public float MeshMegaPrimThreshold { get; private set; } | ||
97 | public float SculptLOD { get; private set; } | ||
98 | 94 | ||
99 | public uint WorldID { get; private set; } | 95 | private int m_detailedStatsStep = 0; |
100 | public BulletSim World { get; private set; } | 96 | |
97 | public IMesher mesher; | ||
98 | private float m_meshLOD; | ||
99 | public float MeshLOD | ||
100 | { | ||
101 | get { return m_meshLOD; } | ||
102 | } | ||
103 | private float m_sculptLOD; | ||
104 | public float SculptLOD | ||
105 | { | ||
106 | get { return m_sculptLOD; } | ||
107 | } | ||
101 | 108 | ||
102 | // All the constraints that have been allocated in this instance. | 109 | private BulletSim m_worldSim; |
103 | public BSConstraintCollection Constraints { get; private set; } | 110 | public BulletSim World |
111 | { | ||
112 | get { return m_worldSim; } | ||
113 | } | ||
114 | private BSConstraintCollection m_constraintCollection; | ||
115 | public BSConstraintCollection Constraints | ||
116 | { | ||
117 | get { return m_constraintCollection; } | ||
118 | } | ||
104 | 119 | ||
105 | // Simulation parameters | ||
106 | private int m_maxSubSteps; | 120 | private int m_maxSubSteps; |
107 | private float m_fixedTimeStep; | 121 | private float m_fixedTimeStep; |
108 | private long m_simulationStep = 0; | 122 | private long m_simulationStep = 0; |
109 | public long SimulationStep { get { return m_simulationStep; } } | 123 | public long SimulationStep { get { return m_simulationStep; } } |
110 | private int m_taintsToProcessPerStep; | 124 | |
125 | public float LastSimulatedTimestep { get; private set; } | ||
111 | 126 | ||
112 | // A value of the time now so all the collision and update routines do not have to get their own | 127 | // A value of the time now so all the collision and update routines do not have to get their own |
113 | // Set to 'now' just before all the prims and actors are called for collisions and updates | 128 | // Set to 'now' just before all the prims and actors are called for collisions and updates |
114 | public int SimulationNowTime { get; private set; } | 129 | private int m_simulationNowTime; |
115 | 130 | public int SimulationNowTime { get { return m_simulationNowTime; } } | |
116 | // True if initialized and ready to do simulation steps | ||
117 | private bool m_initialized = false; | ||
118 | |||
119 | // Flag which is true when processing taints. | ||
120 | // Not guaranteed to be correct all the time (don't depend on this) but good for debugging. | ||
121 | public bool InTaintTime { get; private set; } | ||
122 | 131 | ||
123 | // Pinned memory used to pass step information between managed and unmanaged | ||
124 | private int m_maxCollisionsPerFrame; | 132 | private int m_maxCollisionsPerFrame; |
125 | private CollisionDesc[] m_collisionArray; | 133 | private CollisionDesc[] m_collisionArray; |
126 | private GCHandle m_collisionArrayPinnedHandle; | 134 | private GCHandle m_collisionArrayPinnedHandle; |
@@ -129,19 +137,14 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
129 | private EntityProperties[] m_updateArray; | 137 | private EntityProperties[] m_updateArray; |
130 | private GCHandle m_updateArrayPinnedHandle; | 138 | private GCHandle m_updateArrayPinnedHandle; |
131 | 139 | ||
132 | public bool ShouldMeshSculptedPrim { get; private set; } // cause scuplted prims to get meshed | 140 | private bool _meshSculptedPrim = true; // cause scuplted prims to get meshed |
133 | public bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes | 141 | private bool _forceSimplePrimMeshing = false; // if a cube or sphere, let Bullet do internal shapes |
134 | public bool ShouldUseHullsForPhysicalObjects { get; private set; } // 'true' if should create hulls for physical objects | ||
135 | 142 | ||
136 | public float PID_D { get; private set; } // derivative | 143 | public float PID_D { get; private set; } // derivative |
137 | public float PID_P { get; private set; } // proportional | 144 | public float PID_P { get; private set; } // proportional |
138 | 145 | ||
139 | public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero | 146 | public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero |
140 | public const uint GROUNDPLANE_ID = 1; | 147 | public const uint GROUNDPLANE_ID = 1; |
141 | public const uint CHILDTERRAIN_ID = 2; // Terrain allocated based on our mega-prim childre start here | ||
142 | |||
143 | private float m_waterLevel; | ||
144 | public BSTerrainManager TerrainManager { get; private set; } | ||
145 | 148 | ||
146 | public ConfigurationParameters Params | 149 | public ConfigurationParameters Params |
147 | { | 150 | { |
@@ -151,18 +154,13 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
151 | { | 154 | { |
152 | get { return new Vector3(0f, 0f, Params.gravity); } | 155 | get { return new Vector3(0f, 0f, Params.gravity); } |
153 | } | 156 | } |
154 | // Just the Z value of the gravity | 157 | |
155 | public float DefaultGravityZ | 158 | private float m_maximumObjectMass; |
159 | public float MaximumObjectMass | ||
156 | { | 160 | { |
157 | get { return Params.gravity; } | 161 | get { return m_maximumObjectMass; } |
158 | } | 162 | } |
159 | 163 | ||
160 | public float MaximumObjectMass { get; private set; } | ||
161 | |||
162 | // When functions in the unmanaged code must be called, it is only | ||
163 | // done at a known time just before the simulation step. The taint | ||
164 | // system saves all these function calls and executes them in | ||
165 | // order before the simulation. | ||
166 | public delegate void TaintCallback(); | 164 | public delegate void TaintCallback(); |
167 | private struct TaintCallbackEntry | 165 | private struct TaintCallbackEntry |
168 | { | 166 | { |
@@ -174,19 +172,15 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
174 | callback = c; | 172 | callback = c; |
175 | } | 173 | } |
176 | } | 174 | } |
177 | private Object _taintLock = new Object(); // lock for using the next object | 175 | private List<TaintCallbackEntry> _taintedObjects; |
178 | private List<TaintCallbackEntry> _taintOperations; | 176 | private Object _taintLock = new Object(); |
179 | private Dictionary<string, TaintCallbackEntry> _postTaintOperations; | ||
180 | private List<TaintCallbackEntry> _postStepOperations; | ||
181 | 177 | ||
182 | // A pointer to an instance if this structure is passed to the C++ code | 178 | // A pointer to an instance if this structure is passed to the C++ code |
183 | // Used to pass basic configuration values to the unmanaged code. | ||
184 | ConfigurationParameters[] m_params; | 179 | ConfigurationParameters[] m_params; |
185 | GCHandle m_paramsHandle; | 180 | GCHandle m_paramsHandle; |
186 | 181 | ||
187 | // Handle to the callback used by the unmanaged code to call into the managed code. | 182 | public bool ShouldDebugLog { get; private set; } |
188 | // Used for debug logging. | 183 | |
189 | // Need to store the handle in a persistant variable so it won't be freed. | ||
190 | private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle; | 184 | private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle; |
191 | 185 | ||
192 | // Sometimes you just have to log everything. | 186 | // Sometimes you just have to log everything. |
@@ -195,26 +189,17 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
195 | private string m_physicsLoggingDir; | 189 | private string m_physicsLoggingDir; |
196 | private string m_physicsLoggingPrefix; | 190 | private string m_physicsLoggingPrefix; |
197 | private int m_physicsLoggingFileMinutes; | 191 | private int m_physicsLoggingFileMinutes; |
198 | // 'true' of the vehicle code is to log lots of details | ||
199 | public bool VehicleLoggingEnabled { get; private set; } | ||
200 | 192 | ||
201 | #region Construction and Initialization | 193 | private bool m_vehicleLoggingEnabled; |
194 | public bool VehicleLoggingEnabled { get { return m_vehicleLoggingEnabled; } } | ||
195 | |||
202 | public BSScene(string identifier) | 196 | public BSScene(string identifier) |
203 | { | 197 | { |
204 | m_initialized = false; | 198 | m_initialized = false; |
205 | // we are passed the name of the region we're working for. | ||
206 | RegionName = identifier; | ||
207 | } | 199 | } |
208 | 200 | ||
209 | public override void Initialise(IMesher meshmerizer, IConfigSource config) | 201 | public override void Initialise(IMesher meshmerizer, IConfigSource config) |
210 | { | 202 | { |
211 | mesher = meshmerizer; | ||
212 | _taintOperations = new List<TaintCallbackEntry>(); | ||
213 | _postTaintOperations = new Dictionary<string, TaintCallbackEntry>(); | ||
214 | _postStepOperations = new List<TaintCallbackEntry>(); | ||
215 | PhysObjects = new Dictionary<uint, BSPhysObject>(); | ||
216 | Shapes = new BSShapeCollection(this); | ||
217 | |||
218 | // Allocate pinned memory to pass parameters. | 203 | // Allocate pinned memory to pass parameters. |
219 | m_params = new ConfigurationParameters[1]; | 204 | m_params = new ConfigurationParameters[1]; |
220 | m_paramsHandle = GCHandle.Alloc(m_params, GCHandleType.Pinned); | 205 | m_paramsHandle = GCHandle.Alloc(m_params, GCHandleType.Pinned); |
@@ -230,7 +215,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
230 | 215 | ||
231 | // Enable very detailed logging. | 216 | // Enable very detailed logging. |
232 | // By creating an empty logger when not logging, the log message invocation code | 217 | // By creating an empty logger when not logging, the log message invocation code |
233 | // can be left in and every call doesn't have to check for null. | 218 | // can be left in and every call doesn't have to check for null. |
234 | if (m_physicsLoggingEnabled) | 219 | if (m_physicsLoggingEnabled) |
235 | { | 220 | { |
236 | PhysicsLogging = new Logging.LogWriter(m_physicsLoggingDir, m_physicsLoggingPrefix, m_physicsLoggingFileMinutes); | 221 | PhysicsLogging = new Logging.LogWriter(m_physicsLoggingDir, m_physicsLoggingPrefix, m_physicsLoggingFileMinutes); |
@@ -240,43 +225,39 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
240 | PhysicsLogging = new Logging.LogWriter(); | 225 | PhysicsLogging = new Logging.LogWriter(); |
241 | } | 226 | } |
242 | 227 | ||
243 | // If Debug logging level, enable logging from the unmanaged code | 228 | // Get the version of the DLL |
244 | m_DebugLogCallbackHandle = null; | 229 | // TODO: this doesn't work yet. Something wrong with marshaling the returned string. |
230 | // BulletSimVersion = BulletSimAPI.GetVersion(); | ||
231 | // m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion); | ||
232 | |||
233 | // if Debug, enable logging from the unmanaged code | ||
245 | if (m_log.IsDebugEnabled || PhysicsLogging.Enabled) | 234 | if (m_log.IsDebugEnabled || PhysicsLogging.Enabled) |
246 | { | 235 | { |
247 | m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader); | 236 | m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader); |
248 | if (PhysicsLogging.Enabled) | 237 | if (PhysicsLogging.Enabled) |
249 | // The handle is saved in a variable to make sure it doesn't get freed after this call | ||
250 | m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLoggerPhysLog); | 238 | m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLoggerPhysLog); |
251 | else | 239 | else |
252 | m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger); | 240 | m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger); |
241 | // the handle is saved in a variable to make sure it doesn't get freed after this call | ||
242 | BulletSimAPI.SetDebugLogCallback(m_DebugLogCallbackHandle); | ||
253 | } | 243 | } |
254 | 244 | ||
255 | // Get the version of the DLL | 245 | _taintedObjects = new List<TaintCallbackEntry>(); |
256 | // TODO: this doesn't work yet. Something wrong with marshaling the returned string. | ||
257 | // BulletSimVersion = BulletSimAPI.GetVersion(); | ||
258 | // m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion); | ||
259 | 246 | ||
260 | // The bounding box for the simulated world. The origin is 0,0,0 unless we're | 247 | mesher = meshmerizer; |
261 | // a child in a mega-region. | 248 | // The bounding box for the simulated world |
262 | // Bullet actually doesn't care about the extents of the simulated | 249 | Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, 8192f); |
263 | // area. It tracks active objects no matter where they are. | ||
264 | Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight); | ||
265 | 250 | ||
266 | // m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader); | 251 | // m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader); |
267 | World = new BulletSim(0, this, BulletSimAPI.Initialize2(worldExtent, m_paramsHandle.AddrOfPinnedObject(), | 252 | m_worldID = BulletSimAPI.Initialize(worldExtent, m_paramsHandle.AddrOfPinnedObject(), |
268 | m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(), | 253 | m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(), |
269 | m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject(), | 254 | m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject()); |
270 | m_DebugLogCallbackHandle)); | ||
271 | |||
272 | Constraints = new BSConstraintCollection(World); | ||
273 | 255 | ||
274 | TerrainManager = new BSTerrainManager(this); | 256 | // Initialization to support the transition to a new API which puts most of the logic |
275 | TerrainManager.CreateInitialGroundPlaneAndTerrain(); | 257 | // into the C# code so it is easier to modify and add to. |
258 | m_worldSim = new BulletSim(m_worldID, this, BulletSimAPI.GetSimHandle2(m_worldID)); | ||
259 | m_constraintCollection = new BSConstraintCollection(World); | ||
276 | 260 | ||
277 | m_log.WarnFormat("{0} Linksets implemented with {1}", LogHeader, (BSLinkset.LinksetImplementation)Params.linksetImplementation); | ||
278 | |||
279 | InTaintTime = false; | ||
280 | m_initialized = true; | 261 | m_initialized = true; |
281 | } | 262 | } |
282 | 263 | ||
@@ -300,13 +281,10 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
300 | // Very detailed logging for physics debugging | 281 | // Very detailed logging for physics debugging |
301 | m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false); | 282 | m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false); |
302 | m_physicsLoggingDir = pConfig.GetString("PhysicsLoggingDir", "."); | 283 | m_physicsLoggingDir = pConfig.GetString("PhysicsLoggingDir", "."); |
303 | m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-%REGIONNAME%-"); | 284 | m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-"); |
304 | m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5); | 285 | m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5); |
305 | // Very detailed logging for vehicle debugging | 286 | // Very detailed logging for vehicle debugging |
306 | VehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false); | 287 | m_vehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false); |
307 | |||
308 | // Do any replacements in the parameters | ||
309 | m_physicsLoggingPrefix = m_physicsLoggingPrefix.Replace("%REGIONNAME%", RegionName); | ||
310 | } | 288 | } |
311 | } | 289 | } |
312 | } | 290 | } |
@@ -331,50 +309,12 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
331 | { | 309 | { |
332 | m_log.Debug("[BULLETS UNMANAGED]:" + msg); | 310 | m_log.Debug("[BULLETS UNMANAGED]:" + msg); |
333 | } | 311 | } |
334 | 312 | ||
335 | // Called directly from unmanaged code so don't do much | 313 | // Called directly from unmanaged code so don't do much |
336 | private void BulletLoggerPhysLog(string msg) | 314 | private void BulletLoggerPhysLog(string msg) |
337 | { | 315 | { |
338 | DetailLog("[BULLETS UNMANAGED]:" + msg); | 316 | PhysicsLogging.Write("[BULLETS UNMANAGED]:" + msg); |
339 | } | ||
340 | |||
341 | public override void Dispose() | ||
342 | { | ||
343 | // m_log.DebugFormat("{0}: Dispose()", LogHeader); | ||
344 | |||
345 | // make sure no stepping happens while we're deleting stuff | ||
346 | m_initialized = false; | ||
347 | |||
348 | TerrainManager.ReleaseGroundPlaneAndTerrain(); | ||
349 | |||
350 | foreach (KeyValuePair<uint, BSPhysObject> kvp in PhysObjects) | ||
351 | { | ||
352 | kvp.Value.Destroy(); | ||
353 | } | ||
354 | PhysObjects.Clear(); | ||
355 | |||
356 | // Now that the prims are all cleaned up, there should be no constraints left | ||
357 | if (Constraints != null) | ||
358 | { | ||
359 | Constraints.Dispose(); | ||
360 | Constraints = null; | ||
361 | } | ||
362 | |||
363 | if (Shapes != null) | ||
364 | { | ||
365 | Shapes.Dispose(); | ||
366 | Shapes = null; | ||
367 | } | ||
368 | |||
369 | // Anything left in the unmanaged code should be cleaned out | ||
370 | BulletSimAPI.Shutdown2(World.ptr); | ||
371 | |||
372 | // Not logging any more | ||
373 | PhysicsLogging.Close(); | ||
374 | } | 317 | } |
375 | #endregion // Construction and Initialization | ||
376 | |||
377 | #region Prim and Avatar addition and removal | ||
378 | 318 | ||
379 | public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying) | 319 | public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying) |
380 | { | 320 | { |
@@ -389,13 +329,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
389 | if (!m_initialized) return null; | 329 | if (!m_initialized) return null; |
390 | 330 | ||
391 | BSCharacter actor = new BSCharacter(localID, avName, this, position, size, isFlying); | 331 | BSCharacter actor = new BSCharacter(localID, avName, this, position, size, isFlying); |
392 | lock (PhysObjects) PhysObjects.Add(localID, actor); | 332 | lock (m_avatars) m_avatars.Add(localID, actor); |
393 | |||
394 | // TODO: Remove kludge someday. | ||
395 | // We must generate a collision for avatars whether they collide or not. | ||
396 | // This is required by OpenSim to update avatar animations, etc. | ||
397 | lock (m_avatars) m_avatars.Add(actor); | ||
398 | |||
399 | return actor; | 333 | return actor; |
400 | } | 334 | } |
401 | 335 | ||
@@ -410,9 +344,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
410 | { | 344 | { |
411 | try | 345 | try |
412 | { | 346 | { |
413 | lock (PhysObjects) PhysObjects.Remove(actor.LocalID); | 347 | lock (m_avatars) m_avatars.Remove(actor.LocalID); |
414 | // Remove kludge someday | ||
415 | lock (m_avatars) m_avatars.Remove(bsactor); | ||
416 | } | 348 | } |
417 | catch (Exception e) | 349 | catch (Exception e) |
418 | { | 350 | { |
@@ -430,11 +362,11 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
430 | BSPrim bsprim = prim as BSPrim; | 362 | BSPrim bsprim = prim as BSPrim; |
431 | if (bsprim != null) | 363 | if (bsprim != null) |
432 | { | 364 | { |
433 | DetailLog("{0},RemovePrim,call", bsprim.LocalID); | 365 | // DetailLog("{0},RemovePrim,call", bsprim.LocalID); |
434 | // m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID); | 366 | // m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID); |
435 | try | 367 | try |
436 | { | 368 | { |
437 | lock (PhysObjects) PhysObjects.Remove(bsprim.LocalID); | 369 | lock (m_prims) m_prims.Remove(bsprim.LocalID); |
438 | } | 370 | } |
439 | catch (Exception e) | 371 | catch (Exception e) |
440 | { | 372 | { |
@@ -456,21 +388,18 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
456 | 388 | ||
457 | if (!m_initialized) return null; | 389 | if (!m_initialized) return null; |
458 | 390 | ||
459 | DetailLog("{0},AddPrimShape,call", localID); | 391 | // DetailLog("{0},AddPrimShape,call", localID); |
460 | 392 | ||
461 | BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical); | 393 | BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical); |
462 | lock (PhysObjects) PhysObjects.Add(localID, prim); | 394 | lock (m_prims) m_prims.Add(localID, prim); |
463 | return prim; | 395 | return prim; |
464 | } | 396 | } |
465 | 397 | ||
466 | // This is a call from the simulator saying that some physical property has been updated. | 398 | // This is a call from the simulator saying that some physical property has been updated. |
467 | // The BulletSim driver senses the changing of relevant properties so this taint | 399 | // The BulletSim driver senses the changing of relevant properties so this taint |
468 | // information call is not needed. | 400 | // information call is not needed. |
469 | public override void AddPhysicsActorTaint(PhysicsActor prim) { } | 401 | public override void AddPhysicsActorTaint(PhysicsActor prim) { } |
470 | 402 | ||
471 | #endregion // Prim and Avatar addition and removal | ||
472 | |||
473 | #region Simulation | ||
474 | // Simulate one timestep | 403 | // Simulate one timestep |
475 | public override float Simulate(float timeStep) | 404 | public override float Simulate(float timeStep) |
476 | { | 405 | { |
@@ -479,45 +408,34 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
479 | int collidersCount = 0; | 408 | int collidersCount = 0; |
480 | IntPtr collidersPtr; | 409 | IntPtr collidersPtr; |
481 | 410 | ||
482 | int beforeTime = 0; | 411 | LastSimulatedTimestep = timeStep; |
483 | int simTime = 0; | ||
484 | 412 | ||
485 | // prevent simulation until we've been initialized | 413 | // prevent simulation until we've been initialized |
486 | if (!m_initialized) return 5.0f; | 414 | if (!m_initialized) return 10.0f; |
415 | |||
416 | int simulateStartTime = Util.EnvironmentTickCount(); | ||
487 | 417 | ||
488 | // update the prim states while we know the physics engine is not busy | 418 | // update the prim states while we know the physics engine is not busy |
489 | int numTaints = _taintOperations.Count; | ||
490 | ProcessTaints(); | 419 | ProcessTaints(); |
491 | 420 | ||
492 | // Some of the prims operate with special vehicle properties | 421 | // Some of the prims operate with special vehicle properties |
493 | ProcessVehicles(timeStep); | 422 | ProcessVehicles(timeStep); |
494 | numTaints += _taintOperations.Count; | ||
495 | ProcessTaints(); // the vehicles might have added taints | 423 | ProcessTaints(); // the vehicles might have added taints |
496 | 424 | ||
497 | // step the physical world one interval | 425 | // step the physical world one interval |
498 | m_simulationStep++; | 426 | m_simulationStep++; |
499 | int numSubSteps = 0; | 427 | int numSubSteps = 0; |
500 | |||
501 | try | 428 | try |
502 | { | 429 | { |
503 | // DumpVehicles(); // DEBUG | 430 | numSubSteps = BulletSimAPI.PhysicsStep(m_worldID, timeStep, m_maxSubSteps, m_fixedTimeStep, |
504 | if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount(); | ||
505 | |||
506 | numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep, | ||
507 | out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr); | 431 | out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr); |
508 | 432 | // DetailLog("{0},Simulate,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount); | |
509 | if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime); | ||
510 | DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}", | ||
511 | DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount); | ||
512 | // DumpVehicles(); // DEBUG | ||
513 | } | 433 | } |
514 | catch (Exception e) | 434 | catch (Exception e) |
515 | { | 435 | { |
516 | m_log.WarnFormat("{0},PhysicsStep Exception: nTaints={1}, substeps={2}, updates={3}, colliders={4}, e={5}", | 436 | m_log.WarnFormat("{0},PhysicsStep Exception: substeps={1}, updates={2}, colliders={3}, e={4}", LogHeader, numSubSteps, updatedEntityCount, collidersCount, e); |
517 | LogHeader, numTaints, numSubSteps, updatedEntityCount, collidersCount, e); | 437 | // DetailLog("{0},PhysicsStepException,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount); |
518 | DetailLog("{0},PhysicsStepException,call, nTaints={1}, substeps={2}, updates={3}, colliders={4}", | 438 | // updatedEntityCount = 0; |
519 | DetailLogZero, numTaints, numSubSteps, updatedEntityCount, collidersCount); | ||
520 | updatedEntityCount = 0; | ||
521 | collidersCount = 0; | 439 | collidersCount = 0; |
522 | } | 440 | } |
523 | 441 | ||
@@ -525,7 +443,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
525 | // Don't have to use the pointers passed back since we know it is the same pinned memory we passed in | 443 | // Don't have to use the pointers passed back since we know it is the same pinned memory we passed in |
526 | 444 | ||
527 | // Get a value for 'now' so all the collision and update routines don't have to get their own | 445 | // Get a value for 'now' so all the collision and update routines don't have to get their own |
528 | SimulationNowTime = Util.EnvironmentTickCount(); | 446 | m_simulationNowTime = Util.EnvironmentTickCount(); |
529 | 447 | ||
530 | // If there were collisions, process them by sending the event to the prim. | 448 | // If there were collisions, process them by sending the event to the prim. |
531 | // Collisions must be processed before updates. | 449 | // Collisions must be processed before updates. |
@@ -544,32 +462,19 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
544 | 462 | ||
545 | // The above SendCollision's batch up the collisions on the objects. | 463 | // The above SendCollision's batch up the collisions on the objects. |
546 | // Now push the collisions into the simulator. | 464 | // Now push the collisions into the simulator. |
547 | if (ObjectsWithCollisions.Count > 0) | 465 | foreach (BSPrim bsp in m_primsWithCollisions) |
548 | { | 466 | bsp.SendCollisions(); |
549 | foreach (BSPhysObject bsp in ObjectsWithCollisions) | 467 | m_primsWithCollisions.Clear(); |
550 | if (!bsp.SendCollisions()) | 468 | |
551 | { | 469 | // This is a kludge to get avatar movement updated. |
552 | // If the object is done colliding, see that it's removed from the colliding list | 470 | // Don't send collisions only if there were collisions -- send everytime. |
553 | ObjectsWithNoMoreCollisions.Add(bsp); | 471 | // ODE sends collisions even if there are none and this is used to update |
554 | } | 472 | // avatar animations and stuff. |
555 | } | 473 | // foreach (BSCharacter bsc in m_avatarsWithCollisions) |
556 | 474 | // bsc.SendCollisions(); | |
557 | // This is a kludge to get avatar movement updates. | 475 | foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars) |
558 | // The simulator expects collisions for avatars even if there are have been no collisions. | 476 | kvp.Value.SendCollisions(); |
559 | // The event updates avatar animations and stuff. | 477 | m_avatarsWithCollisions.Clear(); |
560 | // If you fix avatar animation updates, remove this overhead and let normal collision processing happen. | ||
561 | foreach (BSPhysObject bsp in m_avatars) | ||
562 | if (!ObjectsWithCollisions.Contains(bsp)) // don't call avatars twice | ||
563 | bsp.SendCollisions(); | ||
564 | |||
565 | // Objects that are done colliding are removed from the ObjectsWithCollisions list. | ||
566 | // Not done above because it is inside an iteration of ObjectWithCollisions. | ||
567 | if (ObjectsWithNoMoreCollisions.Count > 0) | ||
568 | { | ||
569 | foreach (BSPhysObject po in ObjectsWithNoMoreCollisions) | ||
570 | ObjectsWithCollisions.Remove(po); | ||
571 | ObjectsWithNoMoreCollisions.Clear(); | ||
572 | } | ||
573 | 478 | ||
574 | // If any of the objects had updated properties, tell the object it has been changed by the physics engine | 479 | // If any of the objects had updated properties, tell the object it has been changed by the physics engine |
575 | if (updatedEntityCount > 0) | 480 | if (updatedEntityCount > 0) |
@@ -577,310 +482,320 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
577 | for (int ii = 0; ii < updatedEntityCount; ii++) | 482 | for (int ii = 0; ii < updatedEntityCount; ii++) |
578 | { | 483 | { |
579 | EntityProperties entprop = m_updateArray[ii]; | 484 | EntityProperties entprop = m_updateArray[ii]; |
580 | BSPhysObject pobj; | 485 | BSPrim prim; |
581 | if (PhysObjects.TryGetValue(entprop.ID, out pobj)) | 486 | if (m_prims.TryGetValue(entprop.ID, out prim)) |
487 | { | ||
488 | prim.UpdateProperties(entprop); | ||
489 | continue; | ||
490 | } | ||
491 | BSCharacter actor; | ||
492 | if (m_avatars.TryGetValue(entprop.ID, out actor)) | ||
582 | { | 493 | { |
583 | pobj.UpdateProperties(entprop); | 494 | actor.UpdateProperties(entprop); |
495 | continue; | ||
584 | } | 496 | } |
585 | } | 497 | } |
586 | } | 498 | } |
587 | 499 | ||
588 | ProcessPostStepTaints(); | 500 | // If enabled, call into the physics engine to dump statistics |
589 | 501 | if (m_detailedStatsStep > 0) | |
590 | // This causes the unmanaged code to output ALL the values found in ALL the objects in the world. | 502 | { |
591 | // Only enable this in a limited test world with few objects. | 503 | if ((m_simulationStep % m_detailedStatsStep) == 0) |
592 | // BulletSimAPI.DumpAllInfo2(World.ptr); // DEBUG DEBUG DEBUG | 504 | { |
505 | BulletSimAPI.DumpBulletStatistics(); | ||
506 | } | ||
507 | } | ||
593 | 508 | ||
594 | // The physics engine returns the number of milliseconds it simulated this call. | 509 | // this is a waste since the outside routine also calcuates the physics simulation |
595 | // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. | 510 | // period. TODO: There should be a way of computing physics frames from simulator computation. |
596 | // We multiply by 55 to give a recognizable running rate (55 or less). | 511 | // long simulateTotalTime = Util.EnvironmentTickCountSubtract(simulateStartTime); |
597 | return numSubSteps * m_fixedTimeStep * 1000 * 55; | 512 | // return (timeStep * (float)simulateTotalTime); |
598 | // return timeStep * 1000 * 55; | 513 | |
514 | // TODO: FIX THIS: fps calculation possibly wrong. | ||
515 | // This calculation says 1/timeStep is the ideal frame rate. Any time added to | ||
516 | // that by the physics simulation gives a slower frame rate. | ||
517 | long totalSimulationTime = Util.EnvironmentTickCountSubtract(simulateStartTime); | ||
518 | if (totalSimulationTime >= timeStep) | ||
519 | return 0; | ||
520 | return 1f / (timeStep + totalSimulationTime); | ||
599 | } | 521 | } |
600 | 522 | ||
601 | // Something has collided | 523 | // Something has collided |
602 | private void SendCollision(uint localID, uint collidingWith, Vector3 collidePoint, Vector3 collideNormal, float penetration) | 524 | private void SendCollision(uint localID, uint collidingWith, Vector3 collidePoint, Vector3 collideNormal, float penitration) |
603 | { | 525 | { |
604 | if (localID <= TerrainManager.HighestTerrainID) | 526 | if (localID == TERRAIN_ID || localID == GROUNDPLANE_ID) |
605 | { | 527 | { |
606 | return; // don't send collisions to the terrain | 528 | return; // don't send collisions to the terrain |
607 | } | 529 | } |
608 | 530 | ||
609 | BSPhysObject collider; | 531 | ActorTypes type = ActorTypes.Prim; |
610 | if (!PhysObjects.TryGetValue(localID, out collider)) | 532 | if (collidingWith == TERRAIN_ID || collidingWith == GROUNDPLANE_ID) |
611 | { | 533 | type = ActorTypes.Ground; |
612 | // If the object that is colliding cannot be found, just ignore the collision. | 534 | else if (m_avatars.ContainsKey(collidingWith)) |
613 | DetailLog("{0},BSScene.SendCollision,colliderNotInObjectList,id={1},with={2}", DetailLogZero, localID, collidingWith); | 535 | type = ActorTypes.Agent; |
536 | |||
537 | BSPrim prim; | ||
538 | if (m_prims.TryGetValue(localID, out prim)) { | ||
539 | prim.Collide(collidingWith, type, collidePoint, collideNormal, penitration); | ||
540 | m_primsWithCollisions.Add(prim); | ||
614 | return; | 541 | return; |
615 | } | 542 | } |
616 | 543 | BSCharacter actor; | |
617 | // The terrain is not in the physical object list so 'collidee' can be null when Collide() is called. | 544 | if (m_avatars.TryGetValue(localID, out actor)) { |
618 | BSPhysObject collidee = null; | 545 | actor.Collide(collidingWith, type, collidePoint, collideNormal, penitration); |
619 | PhysObjects.TryGetValue(collidingWith, out collidee); | 546 | m_avatarsWithCollisions.Add(actor); |
620 | 547 | return; | |
621 | // DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith); | ||
622 | |||
623 | if (collider.Collide(collidingWith, collidee, collidePoint, collideNormal, penetration)) | ||
624 | { | ||
625 | // If a collision was posted, remember to send it to the simulator | ||
626 | ObjectsWithCollisions.Add(collider); | ||
627 | } | 548 | } |
628 | |||
629 | return; | 549 | return; |
630 | } | 550 | } |
631 | 551 | ||
632 | #endregion // Simulation | ||
633 | |||
634 | public override void GetResults() { } | 552 | public override void GetResults() { } |
635 | 553 | ||
636 | #region Terrain | ||
637 | |||
638 | public override void SetTerrain(float[] heightMap) { | 554 | public override void SetTerrain(float[] heightMap) { |
639 | TerrainManager.SetTerrain(heightMap); | 555 | m_heightMap = heightMap; |
556 | this.TaintedObject("BSScene.SetTerrain", delegate() | ||
557 | { | ||
558 | BulletSimAPI.SetHeightmap(m_worldID, m_heightMap); | ||
559 | }); | ||
640 | } | 560 | } |
641 | 561 | ||
642 | public override void SetWaterLevel(float baseheight) | 562 | // Someday we will have complex terrain with caves and tunnels |
563 | // For the moment, it's flat and convex | ||
564 | public float GetTerrainHeightAtXYZ(Vector3 loc) | ||
643 | { | 565 | { |
644 | m_waterLevel = baseheight; | 566 | return GetTerrainHeightAtXY(loc.X, loc.Y); |
645 | } | ||
646 | // Someday.... | ||
647 | public float GetWaterLevelAtXYZ(Vector3 loc) | ||
648 | { | ||
649 | return m_waterLevel; | ||
650 | } | 567 | } |
651 | 568 | ||
652 | public override void DeleteTerrain() | 569 | public float GetTerrainHeightAtXY(float tX, float tY) |
653 | { | 570 | { |
654 | // m_log.DebugFormat("{0}: DeleteTerrain()", LogHeader); | 571 | if (tX < 0 || tX >= Constants.RegionSize || tY < 0 || tY >= Constants.RegionSize) |
572 | return 30; | ||
573 | return m_heightMap[((int)tX) * Constants.RegionSize + ((int)tY)]; | ||
655 | } | 574 | } |
656 | 575 | ||
657 | // Although no one seems to check this, I do support combining. | 576 | public override void SetWaterLevel(float baseheight) |
658 | public override bool SupportsCombining() | ||
659 | { | 577 | { |
660 | return TerrainManager.SupportsCombining(); | 578 | m_waterLevel = baseheight; |
579 | // TODO: pass to physics engine so things will float? | ||
661 | } | 580 | } |
662 | // This call says I am a child to region zero in a mega-region. 'pScene' is that | 581 | public float GetWaterLevel() |
663 | // of region zero, 'offset' is my offset from regions zero's origin, and | ||
664 | // 'extents' is the largest XY that is handled in my region. | ||
665 | public override void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents) | ||
666 | { | 582 | { |
667 | TerrainManager.Combine(pScene, offset, extents); | 583 | return m_waterLevel; |
668 | } | 584 | } |
669 | 585 | ||
670 | // Unhook all the combining that I know about. | 586 | public override void DeleteTerrain() |
671 | public override void UnCombine(PhysicsScene pScene) | ||
672 | { | 587 | { |
673 | TerrainManager.UnCombine(pScene); | 588 | // m_log.DebugFormat("{0}: DeleteTerrain()", LogHeader); |
674 | } | 589 | } |
675 | 590 | ||
676 | #endregion // Terrain | 591 | public override void Dispose() |
677 | |||
678 | public override Dictionary<uint, float> GetTopColliders() | ||
679 | { | 592 | { |
680 | return new Dictionary<uint, float>(); | 593 | // m_log.DebugFormat("{0}: Dispose()", LogHeader); |
681 | } | ||
682 | 594 | ||
683 | public override bool IsThreaded { get { return false; } } | 595 | // make sure no stepping happens while we're deleting stuff |
596 | m_initialized = false; | ||
684 | 597 | ||
685 | #region Taints | 598 | foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars) |
599 | { | ||
600 | kvp.Value.Destroy(); | ||
601 | } | ||
602 | m_avatars.Clear(); | ||
686 | 603 | ||
687 | // Calls to the PhysicsActors can't directly call into the physics engine | 604 | foreach (KeyValuePair<uint, BSPrim> kvp in m_prims) |
688 | // because it might be busy. We delay changes to a known time. | 605 | { |
689 | // We rely on C#'s closure to save and restore the context for the delegate. | 606 | kvp.Value.Destroy(); |
690 | public void TaintedObject(String ident, TaintCallback callback) | 607 | } |
691 | { | 608 | m_prims.Clear(); |
692 | if (!m_initialized) return; | ||
693 | 609 | ||
694 | lock (_taintLock) | 610 | // Now that the prims are all cleaned up, there should be no constraints left |
611 | if (m_constraintCollection != null) | ||
695 | { | 612 | { |
696 | _taintOperations.Add(new TaintCallbackEntry(ident, callback)); | 613 | m_constraintCollection.Dispose(); |
614 | m_constraintCollection = null; | ||
697 | } | 615 | } |
698 | 616 | ||
699 | return; | 617 | // Anything left in the unmanaged code should be cleaned out |
700 | } | 618 | BulletSimAPI.Shutdown(WorldID); |
701 | 619 | ||
702 | // Sometimes a potentially tainted operation can be used in and out of taint time. | 620 | // Not logging any more |
703 | // This routine executes the command immediately if in taint-time otherwise it is queued. | 621 | PhysicsLogging.Close(); |
704 | public void TaintedObject(bool inTaintTime, string ident, TaintCallback callback) | ||
705 | { | ||
706 | if (inTaintTime) | ||
707 | callback(); | ||
708 | else | ||
709 | TaintedObject(ident, callback); | ||
710 | } | 622 | } |
711 | 623 | ||
712 | // When someone tries to change a property on a BSPrim or BSCharacter, the object queues | 624 | public override Dictionary<uint, float> GetTopColliders() |
713 | // a callback into itself to do the actual property change. That callback is called | ||
714 | // here just before the physics engine is called to step the simulation. | ||
715 | public void ProcessTaints() | ||
716 | { | 625 | { |
717 | InTaintTime = true; | 626 | return new Dictionary<uint, float>(); |
718 | ProcessRegularTaints(); | ||
719 | ProcessPostTaintTaints(); | ||
720 | InTaintTime = false; | ||
721 | } | 627 | } |
722 | 628 | ||
723 | private void ProcessRegularTaints() | 629 | public override bool IsThreaded { get { return false; } } |
630 | |||
631 | /// <summary> | ||
632 | /// Routine to figure out if we need to mesh this prim with our mesher | ||
633 | /// </summary> | ||
634 | /// <param name="pbs"></param> | ||
635 | /// <returns>true if the prim needs meshing</returns> | ||
636 | public bool NeedsMeshing(PrimitiveBaseShape pbs) | ||
724 | { | 637 | { |
725 | if (_taintOperations.Count > 0) // save allocating new list if there is nothing to process | 638 | // most of this is redundant now as the mesher will return null if it cant mesh a prim |
639 | // but we still need to check for sculptie meshing being enabled so this is the most | ||
640 | // convenient place to do it for now... | ||
641 | |||
642 | // int iPropertiesNotSupportedDefault = 0; | ||
643 | |||
644 | if (pbs.SculptEntry && !_meshSculptedPrim) | ||
726 | { | 645 | { |
727 | int taintCount = m_taintsToProcessPerStep; | 646 | // Render sculpties as boxes |
728 | TaintCallbackEntry oneCallback = new TaintCallbackEntry(); | 647 | return false; |
729 | while (_taintOperations.Count > 0 && taintCount-- > 0) | 648 | } |
649 | |||
650 | // if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since Bullet | ||
651 | // can use an internal representation for the prim | ||
652 | if (!_forceSimplePrimMeshing) | ||
653 | { | ||
654 | if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) | ||
655 | || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 | ||
656 | && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z)) | ||
730 | { | 657 | { |
731 | bool gotOne = false; | 658 | |
732 | lock (_taintLock) | 659 | if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0 |
733 | { | 660 | && pbs.ProfileHollow == 0 |
734 | if (_taintOperations.Count > 0) | 661 | && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0 |
735 | { | 662 | && pbs.PathBegin == 0 && pbs.PathEnd == 0 |
736 | oneCallback = _taintOperations[0]; | 663 | && pbs.PathTaperX == 0 && pbs.PathTaperY == 0 |
737 | _taintOperations.RemoveAt(0); | 664 | && pbs.PathScaleX == 100 && pbs.PathScaleY == 100 |
738 | gotOne = true; | 665 | && pbs.PathShearX == 0 && pbs.PathShearY == 0) |
739 | } | ||
740 | } | ||
741 | if (gotOne) | ||
742 | { | 666 | { |
743 | try | 667 | return false; |
744 | { | ||
745 | DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", DetailLogZero, oneCallback.ident); | ||
746 | oneCallback.callback(); | ||
747 | } | ||
748 | catch (Exception e) | ||
749 | { | ||
750 | DetailLog("{0},BSScene.ProcessTaints,doTaintException,id={1}", DetailLogZero, oneCallback.ident); // DEBUG DEBUG DEBUG | ||
751 | m_log.ErrorFormat("{0}: ProcessTaints: {1}: Exception: {2}", LogHeader, oneCallback.ident, e); | ||
752 | } | ||
753 | } | 668 | } |
754 | } | 669 | } |
755 | /* | 670 | } |
756 | // swizzle a new list into the list location so we can process what's there | 671 | |
757 | List<TaintCallbackEntry> oldList; | 672 | /* TODO: verify that the mesher will now do all these shapes |
758 | lock (_taintLock) | 673 | if (pbs.ProfileHollow != 0) |
674 | iPropertiesNotSupportedDefault++; | ||
675 | |||
676 | if ((pbs.PathBegin != 0) || pbs.PathEnd != 0) | ||
677 | iPropertiesNotSupportedDefault++; | ||
678 | |||
679 | if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0)) | ||
680 | iPropertiesNotSupportedDefault++; | ||
681 | |||
682 | if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0) | ||
683 | iPropertiesNotSupportedDefault++; | ||
684 | |||
685 | if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100)) | ||
686 | iPropertiesNotSupportedDefault++; | ||
687 | |||
688 | if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0)) | ||
689 | iPropertiesNotSupportedDefault++; | ||
690 | |||
691 | if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight) | ||
692 | iPropertiesNotSupportedDefault++; | ||
693 | |||
694 | if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 && (pbs.Scale.X != pbs.Scale.Y || pbs.Scale.Y != pbs.Scale.Z || pbs.Scale.Z != pbs.Scale.X)) | ||
695 | iPropertiesNotSupportedDefault++; | ||
696 | |||
697 | if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte) Extrusion.Curve1) | ||
698 | iPropertiesNotSupportedDefault++; | ||
699 | |||
700 | // test for torus | ||
701 | if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Square) | ||
702 | { | ||
703 | if (pbs.PathCurve == (byte)Extrusion.Curve1) | ||
759 | { | 704 | { |
760 | oldList = _taintedObjects; | 705 | iPropertiesNotSupportedDefault++; |
761 | _taintedObjects = new List<TaintCallbackEntry>(); | ||
762 | } | 706 | } |
763 | 707 | } | |
764 | foreach (TaintCallbackEntry tcbe in oldList) | 708 | else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Circle) |
709 | { | ||
710 | if (pbs.PathCurve == (byte)Extrusion.Straight) | ||
765 | { | 711 | { |
766 | try | 712 | iPropertiesNotSupportedDefault++; |
767 | { | 713 | } |
768 | DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", DetailLogZero, tcbe.ident); // DEBUG DEBUG DEBUG | 714 | // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits |
769 | tcbe.callback(); | 715 | else if (pbs.PathCurve == (byte)Extrusion.Curve1) |
770 | } | 716 | { |
771 | catch (Exception e) | 717 | iPropertiesNotSupportedDefault++; |
772 | { | ||
773 | m_log.ErrorFormat("{0}: ProcessTaints: {1}: Exception: {2}", LogHeader, tcbe.ident, e); | ||
774 | } | ||
775 | } | 718 | } |
776 | oldList.Clear(); | ||
777 | */ | ||
778 | } | 719 | } |
779 | } | 720 | else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle) |
780 | |||
781 | // Schedule an update to happen after all the regular taints are processed. | ||
782 | // Note that new requests for the same operation ("ident") for the same object ("ID") | ||
783 | // will replace any previous operation by the same object. | ||
784 | public void PostTaintObject(String ident, uint ID, TaintCallback callback) | ||
785 | { | ||
786 | if (!m_initialized) return; | ||
787 | |||
788 | string uniqueIdent = ident + "-" + ID.ToString(); | ||
789 | lock (_taintLock) | ||
790 | { | 721 | { |
791 | _postTaintOperations[uniqueIdent] = new TaintCallbackEntry(uniqueIdent, callback); | 722 | if (pbs.PathCurve == (byte)Extrusion.Curve1 || pbs.PathCurve == (byte)Extrusion.Curve2) |
723 | { | ||
724 | iPropertiesNotSupportedDefault++; | ||
725 | } | ||
792 | } | 726 | } |
793 | 727 | else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle) | |
794 | return; | ||
795 | } | ||
796 | |||
797 | private void ProcessPostTaintTaints() | ||
798 | { | ||
799 | if (_postTaintOperations.Count > 0) | ||
800 | { | 728 | { |
801 | Dictionary<string, TaintCallbackEntry> oldList; | 729 | if (pbs.PathCurve == (byte)Extrusion.Straight) |
802 | lock (_taintLock) | ||
803 | { | 730 | { |
804 | oldList = _postTaintOperations; | 731 | iPropertiesNotSupportedDefault++; |
805 | _postTaintOperations = new Dictionary<string, TaintCallbackEntry>(); | ||
806 | } | 732 | } |
807 | 733 | else if (pbs.PathCurve == (byte)Extrusion.Curve1) | |
808 | foreach (KeyValuePair<string,TaintCallbackEntry> kvp in oldList) | ||
809 | { | 734 | { |
810 | try | 735 | iPropertiesNotSupportedDefault++; |
811 | { | ||
812 | DetailLog("{0},BSScene.ProcessPostTaintTaints,doTaint,id={1}", DetailLogZero, kvp.Key); // DEBUG DEBUG DEBUG | ||
813 | kvp.Value.callback(); | ||
814 | } | ||
815 | catch (Exception e) | ||
816 | { | ||
817 | m_log.ErrorFormat("{0}: ProcessPostTaintTaints: {1}: Exception: {2}", LogHeader, kvp.Key, e); | ||
818 | } | ||
819 | } | 736 | } |
820 | oldList.Clear(); | ||
821 | } | 737 | } |
738 | if (iPropertiesNotSupportedDefault == 0) | ||
739 | { | ||
740 | return false; | ||
741 | } | ||
742 | */ | ||
743 | return true; | ||
822 | } | 744 | } |
823 | 745 | ||
824 | public void PostStepTaintObject(String ident, TaintCallback callback) | 746 | // Calls to the PhysicsActors can't directly call into the physics engine |
747 | // because it might be busy. We delay changes to a known time. | ||
748 | // We rely on C#'s closure to save and restore the context for the delegate. | ||
749 | public void TaintedObject(String ident, TaintCallback callback) | ||
825 | { | 750 | { |
826 | if (!m_initialized) return; | 751 | if (!m_initialized) return; |
827 | 752 | ||
828 | lock (_taintLock) | 753 | lock (_taintLock) |
829 | { | 754 | _taintedObjects.Add(new TaintCallbackEntry(ident, callback)); |
830 | _postStepOperations.Add(new TaintCallbackEntry(ident, callback)); | ||
831 | } | ||
832 | |||
833 | return; | 755 | return; |
834 | } | 756 | } |
835 | 757 | ||
836 | private void ProcessPostStepTaints() | 758 | // When someone tries to change a property on a BSPrim or BSCharacter, the object queues |
759 | // a callback into itself to do the actual property change. That callback is called | ||
760 | // here just before the physics engine is called to step the simulation. | ||
761 | public void ProcessTaints() | ||
837 | { | 762 | { |
838 | if (_postStepOperations.Count > 0) | 763 | if (_taintedObjects.Count > 0) // save allocating new list if there is nothing to process |
839 | { | 764 | { |
765 | // swizzle a new list into the list location so we can process what's there | ||
840 | List<TaintCallbackEntry> oldList; | 766 | List<TaintCallbackEntry> oldList; |
841 | lock (_taintLock) | 767 | lock (_taintLock) |
842 | { | 768 | { |
843 | oldList = _postStepOperations; | 769 | oldList = _taintedObjects; |
844 | _postStepOperations = new List<TaintCallbackEntry>(); | 770 | _taintedObjects = new List<TaintCallbackEntry>(); |
845 | } | 771 | } |
846 | 772 | ||
847 | foreach (TaintCallbackEntry tcbe in oldList) | 773 | foreach (TaintCallbackEntry tcbe in oldList) |
848 | { | 774 | { |
849 | try | 775 | try |
850 | { | 776 | { |
851 | DetailLog("{0},BSScene.ProcessPostStepTaints,doTaint,id={1}", DetailLogZero, tcbe.ident); // DEBUG DEBUG DEBUG | ||
852 | tcbe.callback(); | 777 | tcbe.callback(); |
853 | } | 778 | } |
854 | catch (Exception e) | 779 | catch (Exception e) |
855 | { | 780 | { |
856 | m_log.ErrorFormat("{0}: ProcessPostStepTaints: {1}: Exception: {2}", LogHeader, tcbe.ident, e); | 781 | m_log.ErrorFormat("{0}: ProcessTaints: {1}: Exception: {2}", LogHeader, tcbe.ident, e); |
857 | } | 782 | } |
858 | } | 783 | } |
859 | oldList.Clear(); | 784 | oldList.Clear(); |
860 | } | 785 | } |
861 | } | 786 | } |
862 | 787 | ||
863 | public bool AssertInTaintTime(string whereFrom) | ||
864 | { | ||
865 | if (!InTaintTime) | ||
866 | { | ||
867 | DetailLog("{0},BSScene.AssertInTaintTime,NOT IN TAINT TIME,Region={1},Where={2}", DetailLogZero, RegionName, whereFrom); | ||
868 | m_log.ErrorFormat("{0} NOT IN TAINT TIME!! Region={1}, Where={2}", LogHeader, RegionName, whereFrom); | ||
869 | Util.PrintCallStack(); | ||
870 | } | ||
871 | return InTaintTime; | ||
872 | } | ||
873 | |||
874 | #endregion // Taints | ||
875 | |||
876 | #region Vehicles | 788 | #region Vehicles |
877 | 789 | ||
878 | public void VehicleInSceneTypeChanged(BSPrim vehic, Vehicle newType) | 790 | public void VehicleInSceneTypeChanged(BSPrim vehic, Vehicle newType) |
879 | { | 791 | { |
880 | RemoveVehiclePrim(vehic); | 792 | if (newType == Vehicle.TYPE_NONE) |
881 | if (newType != Vehicle.TYPE_NONE) | ||
882 | { | 793 | { |
883 | // make it so the scene will call us each tick to do vehicle things | 794 | RemoveVehiclePrim(vehic); |
795 | } | ||
796 | else | ||
797 | { | ||
798 | // make it so the scene will call us each tick to do vehicle things | ||
884 | AddVehiclePrim(vehic); | 799 | AddVehiclePrim(vehic); |
885 | } | 800 | } |
886 | } | 801 | } |
@@ -912,22 +827,21 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
912 | } | 827 | } |
913 | 828 | ||
914 | // Some prims have extra vehicle actions | 829 | // Some prims have extra vehicle actions |
915 | // Called at taint time! | 830 | // no locking because only called when physics engine is not busy |
916 | private void ProcessVehicles(float timeStep) | 831 | private void ProcessVehicles(float timeStep) |
917 | { | 832 | { |
918 | foreach (BSPhysObject pobj in m_vehicles) | 833 | foreach (BSPrim prim in m_vehicles) |
919 | { | 834 | { |
920 | pobj.StepVehicle(timeStep); | 835 | prim.StepVehicle(timeStep); |
921 | } | 836 | } |
922 | } | 837 | } |
923 | #endregion Vehicles | 838 | #endregion Vehicles |
924 | 839 | ||
925 | #region INI and command line parameter processing | 840 | #region Parameters |
926 | 841 | ||
927 | delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val); | 842 | delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val); |
928 | delegate float ParamGet(BSScene scene); | 843 | delegate float ParamGet(BSScene scene); |
929 | delegate void ParamSet(BSScene scene, string paramName, uint localID, float val); | 844 | delegate void ParamSet(BSScene scene, string paramName, uint localID, float val); |
930 | delegate void SetOnObject(BSScene scene, BSPhysObject obj, float val); | ||
931 | 845 | ||
932 | private struct ParameterDefn | 846 | private struct ParameterDefn |
933 | { | 847 | { |
@@ -937,7 +851,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
937 | public ParamUser userParam; // get the value from the configuration file | 851 | public ParamUser userParam; // get the value from the configuration file |
938 | public ParamGet getter; // return the current value stored for this parameter | 852 | public ParamGet getter; // return the current value stored for this parameter |
939 | public ParamSet setter; // set the current value for this parameter | 853 | public ParamSet setter; // set the current value for this parameter |
940 | public SetOnObject onObject; // set the value on an object in the physical domain | ||
941 | public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s) | 854 | public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s) |
942 | { | 855 | { |
943 | name = n; | 856 | name = n; |
@@ -946,17 +859,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
946 | userParam = u; | 859 | userParam = u; |
947 | getter = g; | 860 | getter = g; |
948 | setter = s; | 861 | setter = s; |
949 | onObject = null; | ||
950 | } | ||
951 | public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s, SetOnObject o) | ||
952 | { | ||
953 | name = n; | ||
954 | desc = d; | ||
955 | defaultValue = v; | ||
956 | userParam = u; | ||
957 | getter = g; | ||
958 | setter = s; | ||
959 | onObject = o; | ||
960 | } | 862 | } |
961 | } | 863 | } |
962 | 864 | ||
@@ -967,7 +869,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
967 | // getters and setters. | 869 | // getters and setters. |
968 | // It is easiest to find an existing definition and copy it. | 870 | // It is easiest to find an existing definition and copy it. |
969 | // Parameter values are floats. Booleans are converted to a floating value. | 871 | // Parameter values are floats. Booleans are converted to a floating value. |
970 | // | 872 | // |
971 | // A ParameterDefn() takes the following parameters: | 873 | // A ParameterDefn() takes the following parameters: |
972 | // -- the text name of the parameter. This is used for console input and ini file. | 874 | // -- the text name of the parameter. This is used for console input and ini file. |
973 | // -- a short text description of the parameter. This shows up in the console listing. | 875 | // -- a short text description of the parameter. This shows up in the console listing. |
@@ -978,7 +880,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
978 | // | 880 | // |
979 | // The single letter parameters for the delegates are: | 881 | // The single letter parameters for the delegates are: |
980 | // s = BSScene | 882 | // s = BSScene |
981 | // o = BSPhysObject | ||
982 | // p = string parameter name | 883 | // p = string parameter name |
983 | // l = localID of referenced object | 884 | // l = localID of referenced object |
984 | // v = float value | 885 | // v = float value |
@@ -987,40 +888,25 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
987 | { | 888 | { |
988 | new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties", | 889 | new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties", |
989 | ConfigurationParameters.numericTrue, | 890 | ConfigurationParameters.numericTrue, |
990 | (s,cf,p,v) => { s.ShouldMeshSculptedPrim = cf.GetBoolean(p, s.BoolNumeric(v)); }, | 891 | (s,cf,p,v) => { s._meshSculptedPrim = cf.GetBoolean(p, s.BoolNumeric(v)); }, |
991 | (s) => { return s.NumericBool(s.ShouldMeshSculptedPrim); }, | 892 | (s) => { return s.NumericBool(s._meshSculptedPrim); }, |
992 | (s,p,l,v) => { s.ShouldMeshSculptedPrim = s.BoolNumeric(v); } ), | 893 | (s,p,l,v) => { s._meshSculptedPrim = s.BoolNumeric(v); } ), |
993 | new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects", | 894 | new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects", |
994 | ConfigurationParameters.numericFalse, | 895 | ConfigurationParameters.numericFalse, |
995 | (s,cf,p,v) => { s.ShouldForceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); }, | 896 | (s,cf,p,v) => { s._forceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); }, |
996 | (s) => { return s.NumericBool(s.ShouldForceSimplePrimMeshing); }, | 897 | (s) => { return s.NumericBool(s._forceSimplePrimMeshing); }, |
997 | (s,p,l,v) => { s.ShouldForceSimplePrimMeshing = s.BoolNumeric(v); } ), | 898 | (s,p,l,v) => { s._forceSimplePrimMeshing = s.BoolNumeric(v); } ), |
998 | new ParameterDefn("UseHullsForPhysicalObjects", "If true, create hulls for physical objects", | ||
999 | ConfigurationParameters.numericTrue, | ||
1000 | (s,cf,p,v) => { s.ShouldUseHullsForPhysicalObjects = cf.GetBoolean(p, s.BoolNumeric(v)); }, | ||
1001 | (s) => { return s.NumericBool(s.ShouldUseHullsForPhysicalObjects); }, | ||
1002 | (s,p,l,v) => { s.ShouldUseHullsForPhysicalObjects = s.BoolNumeric(v); } ), | ||
1003 | 899 | ||
1004 | new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)", | 900 | new ParameterDefn("MeshLOD", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)", |
1005 | 8f, | 901 | 8f, |
1006 | (s,cf,p,v) => { s.MeshLOD = (float)cf.GetInt(p, (int)v); }, | 902 | (s,cf,p,v) => { s.m_meshLOD = cf.GetInt(p, (int)v); }, |
1007 | (s) => { return s.MeshLOD; }, | 903 | (s) => { return (float)s.m_meshLOD; }, |
1008 | (s,p,l,v) => { s.MeshLOD = v; } ), | 904 | (s,p,l,v) => { s.m_meshLOD = (int)v; } ), |
1009 | new ParameterDefn("MeshLevelOfDetailMegaPrim", "Level of detail to render meshes larger than threshold meters", | 905 | new ParameterDefn("SculptLOD", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)", |
1010 | 16f, | ||
1011 | (s,cf,p,v) => { s.MeshMegaPrimLOD = (float)cf.GetInt(p, (int)v); }, | ||
1012 | (s) => { return s.MeshMegaPrimLOD; }, | ||
1013 | (s,p,l,v) => { s.MeshMegaPrimLOD = v; } ), | ||
1014 | new ParameterDefn("MeshLevelOfDetailMegaPrimThreshold", "Size (in meters) of a mesh before using MeshMegaPrimLOD", | ||
1015 | 10f, | ||
1016 | (s,cf,p,v) => { s.MeshMegaPrimThreshold = (float)cf.GetInt(p, (int)v); }, | ||
1017 | (s) => { return s.MeshMegaPrimThreshold; }, | ||
1018 | (s,p,l,v) => { s.MeshMegaPrimThreshold = v; } ), | ||
1019 | new ParameterDefn("SculptLevelOfDetail", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)", | ||
1020 | 32f, | 906 | 32f, |
1021 | (s,cf,p,v) => { s.SculptLOD = (float)cf.GetInt(p, (int)v); }, | 907 | (s,cf,p,v) => { s.m_sculptLOD = cf.GetInt(p, (int)v); }, |
1022 | (s) => { return s.SculptLOD; }, | 908 | (s) => { return (float)s.m_sculptLOD; }, |
1023 | (s,p,l,v) => { s.SculptLOD = v; } ), | 909 | (s,p,l,v) => { s.m_sculptLOD = (int)v; } ), |
1024 | 910 | ||
1025 | new ParameterDefn("MaxSubStep", "In simulation step, maximum number of substeps", | 911 | new ParameterDefn("MaxSubStep", "In simulation step, maximum number of substeps", |
1026 | 10f, | 912 | 10f, |
@@ -1042,16 +928,11 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
1042 | (s,cf,p,v) => { s.m_maxUpdatesPerFrame = cf.GetInt(p, (int)v); }, | 928 | (s,cf,p,v) => { s.m_maxUpdatesPerFrame = cf.GetInt(p, (int)v); }, |
1043 | (s) => { return (float)s.m_maxUpdatesPerFrame; }, | 929 | (s) => { return (float)s.m_maxUpdatesPerFrame; }, |
1044 | (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ), | 930 | (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ), |
1045 | new ParameterDefn("MaxTaintsToProcessPerStep", "Number of update taints to process before each simulation step", | ||
1046 | 100f, | ||
1047 | (s,cf,p,v) => { s.m_taintsToProcessPerStep = cf.GetInt(p, (int)v); }, | ||
1048 | (s) => { return (float)s.m_taintsToProcessPerStep; }, | ||
1049 | (s,p,l,v) => { s.m_taintsToProcessPerStep = (int)v; } ), | ||
1050 | new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)", | 931 | new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)", |
1051 | 10000.01f, | 932 | 10000.01f, |
1052 | (s,cf,p,v) => { s.MaximumObjectMass = cf.GetFloat(p, v); }, | 933 | (s,cf,p,v) => { s.m_maximumObjectMass = cf.GetFloat(p, v); }, |
1053 | (s) => { return (float)s.MaximumObjectMass; }, | 934 | (s) => { return (float)s.m_maximumObjectMass; }, |
1054 | (s,p,l,v) => { s.MaximumObjectMass = v; } ), | 935 | (s,p,l,v) => { s.m_maximumObjectMass = v; } ), |
1055 | 936 | ||
1056 | new ParameterDefn("PID_D", "Derivitive factor for motion smoothing", | 937 | new ParameterDefn("PID_D", "Derivitive factor for motion smoothing", |
1057 | 2200f, | 938 | 2200f, |
@@ -1088,118 +969,104 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
1088 | -9.80665f, | 969 | -9.80665f, |
1089 | (s,cf,p,v) => { s.m_params[0].gravity = cf.GetFloat(p, v); }, | 970 | (s,cf,p,v) => { s.m_params[0].gravity = cf.GetFloat(p, v); }, |
1090 | (s) => { return s.m_params[0].gravity; }, | 971 | (s) => { return s.m_params[0].gravity; }, |
1091 | (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].gravity, p, PhysParameterEntry.APPLY_TO_NONE, v); }, | 972 | (s,p,l,v) => { s.m_params[0].gravity = v; s.TaintedUpdateParameter(p,l,v); } ), |
1092 | (s,o,v) => { BulletSimAPI.SetGravity2(s.World.ptr, new Vector3(0f,0f,v)); } ), | ||
1093 | 973 | ||
1094 | 974 | ||
1095 | new ParameterDefn("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)", | 975 | new ParameterDefn("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)", |
1096 | 0f, | 976 | 0f, |
1097 | (s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); }, | 977 | (s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); }, |
1098 | (s) => { return s.m_params[0].linearDamping; }, | 978 | (s) => { return s.m_params[0].linearDamping; }, |
1099 | (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearDamping, p, l, v); }, | 979 | (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].linearDamping, p, l, v); } ), |
1100 | (s,o,v) => { BulletSimAPI.SetDamping2(o.PhysBody.ptr, v, v); } ), | ||
1101 | new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)", | 980 | new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)", |
1102 | 0f, | 981 | 0f, |
1103 | (s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); }, | 982 | (s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); }, |
1104 | (s) => { return s.m_params[0].angularDamping; }, | 983 | (s) => { return s.m_params[0].angularDamping; }, |
1105 | (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularDamping, p, l, v); }, | 984 | (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].angularDamping, p, l, v); } ), |
1106 | (s,o,v) => { BulletSimAPI.SetDamping2(o.PhysBody.ptr, v, v); } ), | ||
1107 | new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static", | 985 | new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static", |
1108 | 0.2f, | 986 | 0.2f, |
1109 | (s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); }, | 987 | (s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); }, |
1110 | (s) => { return s.m_params[0].deactivationTime; }, | 988 | (s) => { return s.m_params[0].deactivationTime; }, |
1111 | (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].deactivationTime, p, l, v); }, | 989 | (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].deactivationTime, p, l, v); } ), |
1112 | (s,o,v) => { BulletSimAPI.SetDeactivationTime2(o.PhysBody.ptr, v); } ), | ||
1113 | new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static", | 990 | new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static", |
1114 | 0.8f, | 991 | 0.8f, |
1115 | (s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); }, | 992 | (s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); }, |
1116 | (s) => { return s.m_params[0].linearSleepingThreshold; }, | 993 | (s) => { return s.m_params[0].linearSleepingThreshold; }, |
1117 | (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearSleepingThreshold, p, l, v); }, | 994 | (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].linearSleepingThreshold, p, l, v); } ), |
1118 | (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.PhysBody.ptr, v, v); } ), | ||
1119 | new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static", | 995 | new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static", |
1120 | 1.0f, | 996 | 1.0f, |
1121 | (s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); }, | 997 | (s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); }, |
1122 | (s) => { return s.m_params[0].angularSleepingThreshold; }, | 998 | (s) => { return s.m_params[0].angularSleepingThreshold; }, |
1123 | (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularSleepingThreshold, p, l, v); }, | 999 | (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].angularSleepingThreshold, p, l, v); } ), |
1124 | (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.PhysBody.ptr, v, v); } ), | ||
1125 | new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" , | 1000 | new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" , |
1126 | 0f, // set to zero to disable | 1001 | 0f, // set to zero to disable |
1127 | (s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); }, | 1002 | (s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); }, |
1128 | (s) => { return s.m_params[0].ccdMotionThreshold; }, | 1003 | (s) => { return s.m_params[0].ccdMotionThreshold; }, |
1129 | (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdMotionThreshold, p, l, v); }, | 1004 | (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].ccdMotionThreshold, p, l, v); } ), |
1130 | (s,o,v) => { BulletSimAPI.SetCcdMotionThreshold2(o.PhysBody.ptr, v); } ), | ||
1131 | new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" , | 1005 | new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" , |
1132 | 0f, | 1006 | 0f, |
1133 | (s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); }, | 1007 | (s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); }, |
1134 | (s) => { return s.m_params[0].ccdSweptSphereRadius; }, | 1008 | (s) => { return s.m_params[0].ccdSweptSphereRadius; }, |
1135 | (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); }, | 1009 | (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); } ), |
1136 | (s,o,v) => { BulletSimAPI.SetCcdSweptSphereRadius2(o.PhysBody.ptr, v); } ), | ||
1137 | new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" , | 1010 | new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" , |
1138 | 0.1f, | 1011 | 0.1f, |
1139 | (s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); }, | 1012 | (s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); }, |
1140 | (s) => { return s.m_params[0].contactProcessingThreshold; }, | 1013 | (s) => { return s.m_params[0].contactProcessingThreshold; }, |
1141 | (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].contactProcessingThreshold, p, l, v); }, | 1014 | (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].contactProcessingThreshold, p, l, v); } ), |
1142 | (s,o,v) => { BulletSimAPI.SetContactProcessingThreshold2(o.PhysBody.ptr, v); } ), | ||
1143 | 1015 | ||
1144 | new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" , | 1016 | new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" , |
1145 | 0.5f, | 1017 | 0.5f, |
1146 | (s,cf,p,v) => { s.m_params[0].terrainFriction = cf.GetFloat(p, v); }, | 1018 | (s,cf,p,v) => { s.m_params[0].terrainFriction = cf.GetFloat(p, v); }, |
1147 | (s) => { return s.m_params[0].terrainFriction; }, | 1019 | (s) => { return s.m_params[0].terrainFriction; }, |
1148 | (s,p,l,v) => { s.m_params[0].terrainFriction = v; /* TODO: set on real terrain */} ), | 1020 | (s,p,l,v) => { s.m_params[0].terrainFriction = v; s.TaintedUpdateParameter(p,l,v); } ), |
1149 | new ParameterDefn("TerrainHitFraction", "Distance to measure hit collisions" , | 1021 | new ParameterDefn("TerrainHitFraction", "Distance to measure hit collisions" , |
1150 | 0.8f, | 1022 | 0.8f, |
1151 | (s,cf,p,v) => { s.m_params[0].terrainHitFraction = cf.GetFloat(p, v); }, | 1023 | (s,cf,p,v) => { s.m_params[0].terrainHitFraction = cf.GetFloat(p, v); }, |
1152 | (s) => { return s.m_params[0].terrainHitFraction; }, | 1024 | (s) => { return s.m_params[0].terrainHitFraction; }, |
1153 | (s,p,l,v) => { s.m_params[0].terrainHitFraction = v; /* TODO: set on real terrain */ } ), | 1025 | (s,p,l,v) => { s.m_params[0].terrainHitFraction = v; s.TaintedUpdateParameter(p,l,v); } ), |
1154 | new ParameterDefn("TerrainRestitution", "Bouncyness" , | 1026 | new ParameterDefn("TerrainRestitution", "Bouncyness" , |
1155 | 0f, | 1027 | 0f, |
1156 | (s,cf,p,v) => { s.m_params[0].terrainRestitution = cf.GetFloat(p, v); }, | 1028 | (s,cf,p,v) => { s.m_params[0].terrainRestitution = cf.GetFloat(p, v); }, |
1157 | (s) => { return s.m_params[0].terrainRestitution; }, | 1029 | (s) => { return s.m_params[0].terrainRestitution; }, |
1158 | (s,p,l,v) => { s.m_params[0].terrainRestitution = v; /* TODO: set on real terrain */ } ), | 1030 | (s,p,l,v) => { s.m_params[0].terrainRestitution = v; s.TaintedUpdateParameter(p,l,v); } ), |
1159 | new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.", | 1031 | new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.", |
1160 | 0.2f, | 1032 | 0.5f, |
1161 | (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); }, | 1033 | (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); }, |
1162 | (s) => { return s.m_params[0].avatarFriction; }, | 1034 | (s) => { return s.m_params[0].avatarFriction; }, |
1163 | (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarFriction, p, l, v); } ), | 1035 | (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarFriction, p, l, v); } ), |
1164 | new ParameterDefn("AvatarStandingFriction", "Avatar friction when standing. Changed on avatar recreation.", | ||
1165 | 10f, | ||
1166 | (s,cf,p,v) => { s.m_params[0].avatarStandingFriction = cf.GetFloat(p, v); }, | ||
1167 | (s) => { return s.m_params[0].avatarStandingFriction; }, | ||
1168 | (s,p,l,v) => { s.m_params[0].avatarStandingFriction = v; } ), | ||
1169 | new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.", | 1036 | new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.", |
1170 | 60f, | 1037 | 60f, |
1171 | (s,cf,p,v) => { s.m_params[0].avatarDensity = cf.GetFloat(p, v); }, | 1038 | (s,cf,p,v) => { s.m_params[0].avatarDensity = cf.GetFloat(p, v); }, |
1172 | (s) => { return s.m_params[0].avatarDensity; }, | 1039 | (s) => { return s.m_params[0].avatarDensity; }, |
1173 | (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarDensity, p, l, v); } ), | 1040 | (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarDensity, p, l, v); } ), |
1174 | new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.", | 1041 | new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.", |
1175 | 0f, | 1042 | 0f, |
1176 | (s,cf,p,v) => { s.m_params[0].avatarRestitution = cf.GetFloat(p, v); }, | 1043 | (s,cf,p,v) => { s.m_params[0].avatarRestitution = cf.GetFloat(p, v); }, |
1177 | (s) => { return s.m_params[0].avatarRestitution; }, | 1044 | (s) => { return s.m_params[0].avatarRestitution; }, |
1178 | (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarRestitution, p, l, v); } ), | 1045 | (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarRestitution, p, l, v); } ), |
1179 | new ParameterDefn("AvatarCapsuleRadius", "Radius of space around an avatar", | 1046 | new ParameterDefn("AvatarCapsuleRadius", "Radius of space around an avatar", |
1180 | 0.37f, | 1047 | 0.37f, |
1181 | (s,cf,p,v) => { s.m_params[0].avatarCapsuleRadius = cf.GetFloat(p, v); }, | 1048 | (s,cf,p,v) => { s.m_params[0].avatarCapsuleRadius = cf.GetFloat(p, v); }, |
1182 | (s) => { return s.m_params[0].avatarCapsuleRadius; }, | 1049 | (s) => { return s.m_params[0].avatarCapsuleRadius; }, |
1183 | (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleRadius, p, l, v); } ), | 1050 | (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarCapsuleRadius, p, l, v); } ), |
1184 | new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar", | 1051 | new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar", |
1185 | 1.5f, | 1052 | 1.5f, |
1186 | (s,cf,p,v) => { s.m_params[0].avatarCapsuleHeight = cf.GetFloat(p, v); }, | 1053 | (s,cf,p,v) => { s.m_params[0].avatarCapsuleHeight = cf.GetFloat(p, v); }, |
1187 | (s) => { return s.m_params[0].avatarCapsuleHeight; }, | 1054 | (s) => { return s.m_params[0].avatarCapsuleHeight; }, |
1188 | (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleHeight, p, l, v); } ), | 1055 | (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarCapsuleHeight, p, l, v); } ), |
1189 | new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions", | 1056 | new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions", |
1190 | 0.1f, | 1057 | 0.1f, |
1191 | (s,cf,p,v) => { s.m_params[0].avatarContactProcessingThreshold = cf.GetFloat(p, v); }, | 1058 | (s,cf,p,v) => { s.m_params[0].avatarContactProcessingThreshold = cf.GetFloat(p, v); }, |
1192 | (s) => { return s.m_params[0].avatarContactProcessingThreshold; }, | 1059 | (s) => { return s.m_params[0].avatarContactProcessingThreshold; }, |
1193 | (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ), | 1060 | (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ), |
1194 | 1061 | ||
1195 | 1062 | ||
1196 | new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)", | 1063 | new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)", |
1197 | 0f, | 1064 | 0f, // zero to disable |
1198 | (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); }, | 1065 | (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); }, |
1199 | (s) => { return s.m_params[0].maxPersistantManifoldPoolSize; }, | 1066 | (s) => { return s.m_params[0].maxPersistantManifoldPoolSize; }, |
1200 | (s,p,l,v) => { s.m_params[0].maxPersistantManifoldPoolSize = v; } ), | 1067 | (s,p,l,v) => { s.m_params[0].maxPersistantManifoldPoolSize = v; } ), |
1201 | new ParameterDefn("MaxCollisionAlgorithmPoolSize", "Number of collisions pooled (0 means default of 4096)", | 1068 | new ParameterDefn("MaxCollisionAlgorithmPoolSize", "Number of collisions pooled (0 means default of 4096)", |
1202 | 0f, | 1069 | 0f, // zero to disable |
1203 | (s,cf,p,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = cf.GetFloat(p, v); }, | 1070 | (s,cf,p,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = cf.GetFloat(p, v); }, |
1204 | (s) => { return s.m_params[0].maxCollisionAlgorithmPoolSize; }, | 1071 | (s) => { return s.m_params[0].maxCollisionAlgorithmPoolSize; }, |
1205 | (s,p,l,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = v; } ), | 1072 | (s,p,l,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = v; } ), |
@@ -1214,12 +1081,12 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
1214 | (s) => { return s.m_params[0].shouldForceUpdateAllAabbs; }, | 1081 | (s) => { return s.m_params[0].shouldForceUpdateAllAabbs; }, |
1215 | (s,p,l,v) => { s.m_params[0].shouldForceUpdateAllAabbs = v; } ), | 1082 | (s,p,l,v) => { s.m_params[0].shouldForceUpdateAllAabbs = v; } ), |
1216 | new ParameterDefn("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction", | 1083 | new ParameterDefn("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction", |
1217 | ConfigurationParameters.numericTrue, | 1084 | ConfigurationParameters.numericFalse, |
1218 | (s,cf,p,v) => { s.m_params[0].shouldRandomizeSolverOrder = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, | 1085 | (s,cf,p,v) => { s.m_params[0].shouldRandomizeSolverOrder = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, |
1219 | (s) => { return s.m_params[0].shouldRandomizeSolverOrder; }, | 1086 | (s) => { return s.m_params[0].shouldRandomizeSolverOrder; }, |
1220 | (s,p,l,v) => { s.m_params[0].shouldRandomizeSolverOrder = v; } ), | 1087 | (s,p,l,v) => { s.m_params[0].shouldRandomizeSolverOrder = v; } ), |
1221 | new ParameterDefn("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands", | 1088 | new ParameterDefn("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands", |
1222 | ConfigurationParameters.numericTrue, | 1089 | ConfigurationParameters.numericFalse, |
1223 | (s,cf,p,v) => { s.m_params[0].shouldSplitSimulationIslands = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, | 1090 | (s,cf,p,v) => { s.m_params[0].shouldSplitSimulationIslands = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, |
1224 | (s) => { return s.m_params[0].shouldSplitSimulationIslands; }, | 1091 | (s) => { return s.m_params[0].shouldSplitSimulationIslands; }, |
1225 | (s,p,l,v) => { s.m_params[0].shouldSplitSimulationIslands = v; } ), | 1092 | (s,p,l,v) => { s.m_params[0].shouldSplitSimulationIslands = v; } ), |
@@ -1234,11 +1101,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
1234 | (s) => { return s.m_params[0].numberOfSolverIterations; }, | 1101 | (s) => { return s.m_params[0].numberOfSolverIterations; }, |
1235 | (s,p,l,v) => { s.m_params[0].numberOfSolverIterations = v; } ), | 1102 | (s,p,l,v) => { s.m_params[0].numberOfSolverIterations = v; } ), |
1236 | 1103 | ||
1237 | new ParameterDefn("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)", | ||
1238 | (float)BSLinkset.LinksetImplementation.Compound, | ||
1239 | (s,cf,p,v) => { s.m_params[0].linksetImplementation = cf.GetFloat(p,v); }, | ||
1240 | (s) => { return s.m_params[0].linksetImplementation; }, | ||
1241 | (s,p,l,v) => { s.m_params[0].linksetImplementation = v; } ), | ||
1242 | new ParameterDefn("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.", | 1104 | new ParameterDefn("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.", |
1243 | ConfigurationParameters.numericFalse, | 1105 | ConfigurationParameters.numericFalse, |
1244 | (s,cf,p,v) => { s.m_params[0].linkConstraintUseFrameOffset = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, | 1106 | (s,cf,p,v) => { s.m_params[0].linkConstraintUseFrameOffset = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, |
@@ -1259,27 +1121,28 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
1259 | (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = cf.GetFloat(p, v); }, | 1121 | (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = cf.GetFloat(p, v); }, |
1260 | (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; }, | 1122 | (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; }, |
1261 | (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ), | 1123 | (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ), |
1262 | new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1", | 1124 | new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=none, 1=all. Default=0", |
1263 | 0.1f, | 1125 | 0.0f, |
1264 | (s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); }, | 1126 | (s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); }, |
1265 | (s) => { return s.m_params[0].linkConstraintCFM; }, | 1127 | (s) => { return s.m_params[0].linkConstraintCFM; }, |
1266 | (s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ), | 1128 | (s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ), |
1267 | new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2", | 1129 | new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2", |
1268 | 0.1f, | 1130 | 0.2f, |
1269 | (s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); }, | 1131 | (s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); }, |
1270 | (s) => { return s.m_params[0].linkConstraintERP; }, | 1132 | (s) => { return s.m_params[0].linkConstraintERP; }, |
1271 | (s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ), | 1133 | (s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ), |
1272 | new ParameterDefn("LinkConstraintSolverIterations", "Number of solver iterations when computing constraint. (0 = Bullet default)", | ||
1273 | 40, | ||
1274 | (s,cf,p,v) => { s.m_params[0].linkConstraintSolverIterations = cf.GetFloat(p, v); }, | ||
1275 | (s) => { return s.m_params[0].linkConstraintSolverIterations; }, | ||
1276 | (s,p,l,v) => { s.m_params[0].linkConstraintSolverIterations = v; } ), | ||
1277 | 1134 | ||
1278 | new ParameterDefn("LogPhysicsStatisticsFrames", "Frames between outputting detailed phys stats. (0 is off)", | 1135 | new ParameterDefn("DetailedStats", "Frames between outputting detailed phys stats. (0 is off)", |
1279 | 0f, | 1136 | 0f, |
1280 | (s,cf,p,v) => { s.m_params[0].physicsLoggingFrames = cf.GetInt(p, (int)v); }, | 1137 | (s,cf,p,v) => { s.m_detailedStatsStep = cf.GetInt(p, (int)v); }, |
1281 | (s) => { return (float)s.m_params[0].physicsLoggingFrames; }, | 1138 | (s) => { return (float)s.m_detailedStatsStep; }, |
1282 | (s,p,l,v) => { s.m_params[0].physicsLoggingFrames = (int)v; } ), | 1139 | (s,p,l,v) => { s.m_detailedStatsStep = (int)v; } ), |
1140 | new ParameterDefn("ShouldDebugLog", "Enables detailed DEBUG log statements", | ||
1141 | ConfigurationParameters.numericFalse, | ||
1142 | (s,cf,p,v) => { s.ShouldDebugLog = cf.GetBoolean(p, s.BoolNumeric(v)); }, | ||
1143 | (s) => { return s.NumericBool(s.ShouldDebugLog); }, | ||
1144 | (s,p,l,v) => { s.ShouldDebugLog = s.BoolNumeric(v); } ), | ||
1145 | |||
1283 | }; | 1146 | }; |
1284 | 1147 | ||
1285 | // Convert a boolean to our numeric true and false values | 1148 | // Convert a boolean to our numeric true and false values |
@@ -1337,12 +1200,11 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
1337 | 1200 | ||
1338 | private PhysParameterEntry[] SettableParameters = new PhysParameterEntry[1]; | 1201 | private PhysParameterEntry[] SettableParameters = new PhysParameterEntry[1]; |
1339 | 1202 | ||
1340 | // This creates an array in the correct format for returning the list of | ||
1341 | // parameters. This is used by the 'list' option of the 'physics' command. | ||
1342 | private void BuildParameterTable() | 1203 | private void BuildParameterTable() |
1343 | { | 1204 | { |
1344 | if (SettableParameters.Length < ParameterDefinitions.Length) | 1205 | if (SettableParameters.Length < ParameterDefinitions.Length) |
1345 | { | 1206 | { |
1207 | |||
1346 | List<PhysParameterEntry> entries = new List<PhysParameterEntry>(); | 1208 | List<PhysParameterEntry> entries = new List<PhysParameterEntry>(); |
1347 | for (int ii = 0; ii < ParameterDefinitions.Length; ii++) | 1209 | for (int ii = 0; ii < ParameterDefinitions.Length; ii++) |
1348 | { | 1210 | { |
@@ -1387,54 +1249,60 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
1387 | return ret; | 1249 | return ret; |
1388 | } | 1250 | } |
1389 | 1251 | ||
1252 | // check to see if we are updating a parameter for a particular or all of the prims | ||
1253 | protected void UpdateParameterPrims(ref float loc, string parm, uint localID, float val) | ||
1254 | { | ||
1255 | List<uint> operateOn; | ||
1256 | lock (m_prims) operateOn = new List<uint>(m_prims.Keys); | ||
1257 | UpdateParameterSet(operateOn, ref loc, parm, localID, val); | ||
1258 | } | ||
1259 | |||
1260 | // check to see if we are updating a parameter for a particular or all of the avatars | ||
1261 | protected void UpdateParameterAvatars(ref float loc, string parm, uint localID, float val) | ||
1262 | { | ||
1263 | List<uint> operateOn; | ||
1264 | lock (m_avatars) operateOn = new List<uint>(m_avatars.Keys); | ||
1265 | UpdateParameterSet(operateOn, ref loc, parm, localID, val); | ||
1266 | } | ||
1267 | |||
1390 | // update all the localIDs specified | 1268 | // update all the localIDs specified |
1391 | // If the local ID is APPLY_TO_NONE, just change the default value | 1269 | // If the local ID is APPLY_TO_NONE, just change the default value |
1392 | // If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs | 1270 | // If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs |
1393 | // If the localID is a specific object, apply the parameter change to only that object | 1271 | // If the localID is a specific object, apply the parameter change to only that object |
1394 | private void UpdateParameterObject(ref float defaultLoc, string parm, uint localID, float val) | 1272 | protected void UpdateParameterSet(List<uint> lIDs, ref float defaultLoc, string parm, uint localID, float val) |
1395 | { | 1273 | { |
1396 | List<uint> objectIDs = new List<uint>(); | ||
1397 | switch (localID) | 1274 | switch (localID) |
1398 | { | 1275 | { |
1399 | case PhysParameterEntry.APPLY_TO_NONE: | 1276 | case PhysParameterEntry.APPLY_TO_NONE: |
1400 | defaultLoc = val; // setting only the default value | 1277 | defaultLoc = val; // setting only the default value |
1401 | // This will cause a call into the physical world if some operation is specified (SetOnObject). | ||
1402 | objectIDs.Add(TERRAIN_ID); | ||
1403 | TaintedUpdateParameter(parm, objectIDs, val); | ||
1404 | break; | 1278 | break; |
1405 | case PhysParameterEntry.APPLY_TO_ALL: | 1279 | case PhysParameterEntry.APPLY_TO_ALL: |
1406 | defaultLoc = val; // setting ALL also sets the default value | 1280 | defaultLoc = val; // setting ALL also sets the default value |
1407 | lock (PhysObjects) objectIDs = new List<uint>(PhysObjects.Keys); | 1281 | List<uint> objectIDs = lIDs; |
1408 | TaintedUpdateParameter(parm, objectIDs, val); | 1282 | string xparm = parm.ToLower(); |
1283 | float xval = val; | ||
1284 | TaintedObject("BSScene.UpdateParameterSet", delegate() { | ||
1285 | foreach (uint lID in objectIDs) | ||
1286 | { | ||
1287 | BulletSimAPI.UpdateParameter(m_worldID, lID, xparm, xval); | ||
1288 | } | ||
1289 | }); | ||
1409 | break; | 1290 | break; |
1410 | default: | 1291 | default: |
1411 | // setting only one localID | 1292 | // setting only one localID |
1412 | objectIDs.Add(localID); | 1293 | TaintedUpdateParameter(parm, localID, val); |
1413 | TaintedUpdateParameter(parm, objectIDs, val); | ||
1414 | break; | 1294 | break; |
1415 | } | 1295 | } |
1416 | } | 1296 | } |
1417 | 1297 | ||
1418 | // schedule the actual updating of the paramter to when the phys engine is not busy | 1298 | // schedule the actual updating of the paramter to when the phys engine is not busy |
1419 | private void TaintedUpdateParameter(string parm, List<uint> lIDs, float val) | 1299 | protected void TaintedUpdateParameter(string parm, uint localID, float val) |
1420 | { | 1300 | { |
1301 | uint xlocalID = localID; | ||
1302 | string xparm = parm.ToLower(); | ||
1421 | float xval = val; | 1303 | float xval = val; |
1422 | List<uint> xlIDs = lIDs; | 1304 | TaintedObject("BSScene.TaintedUpdateParameter", delegate() { |
1423 | string xparm = parm; | 1305 | BulletSimAPI.UpdateParameter(m_worldID, xlocalID, xparm, xval); |
1424 | TaintedObject("BSScene.UpdateParameterSet", delegate() { | ||
1425 | ParameterDefn thisParam; | ||
1426 | if (TryGetParameter(xparm, out thisParam)) | ||
1427 | { | ||
1428 | if (thisParam.onObject != null) | ||
1429 | { | ||
1430 | foreach (uint lID in xlIDs) | ||
1431 | { | ||
1432 | BSPhysObject theObject = null; | ||
1433 | PhysObjects.TryGetValue(lID, out theObject); | ||
1434 | thisParam.onObject(this, theObject, xval); | ||
1435 | } | ||
1436 | } | ||
1437 | } | ||
1438 | }); | 1306 | }); |
1439 | } | 1307 | } |
1440 | 1308 | ||
@@ -1458,24 +1326,12 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
1458 | 1326 | ||
1459 | #endregion Runtime settable parameters | 1327 | #endregion Runtime settable parameters |
1460 | 1328 | ||
1461 | // Debugging routine for dumping detailed physical information for vehicle prims | ||
1462 | private void DumpVehicles() | ||
1463 | { | ||
1464 | foreach (BSPrim prim in m_vehicles) | ||
1465 | { | ||
1466 | BulletSimAPI.DumpRigidBody2(World.ptr, prim.PhysBody.ptr); | ||
1467 | BulletSimAPI.DumpCollisionShape2(World.ptr, prim.PhysShape.ptr); | ||
1468 | } | ||
1469 | } | ||
1470 | |||
1471 | // Invoke the detailed logger and output something if it's enabled. | 1329 | // Invoke the detailed logger and output something if it's enabled. |
1472 | public void DetailLog(string msg, params Object[] args) | 1330 | public void DetailLog(string msg, params Object[] args) |
1473 | { | 1331 | { |
1474 | PhysicsLogging.Write(msg, args); | 1332 | PhysicsLogging.Write(msg, args); |
1475 | // Add the Flush() if debugging crashes. Gets all the messages written out. | ||
1476 | PhysicsLogging.Flush(); | ||
1477 | } | 1333 | } |
1478 | // Used to fill in the LocalID when there isn't one. It's the correct number of characters. | 1334 | // used to fill in the LocalID when there isn't one |
1479 | public const string DetailLogZero = "0000000000"; | 1335 | public const string DetailLogZero = "0000000000"; |
1480 | 1336 | ||
1481 | } | 1337 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs deleted file mode 100755 index 29a23c0..0000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ /dev/null | |||
@@ -1,1000 +0,0 @@ | |||
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 copyrightD | ||
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 | using System; | ||
28 | using System.Collections.Generic; | ||
29 | using System.Text; | ||
30 | using OMV = OpenMetaverse; | ||
31 | using OpenSim.Framework; | ||
32 | using OpenSim.Region.Physics.Manager; | ||
33 | using OpenSim.Region.Physics.ConvexDecompositionDotNet; | ||
34 | |||
35 | namespace OpenSim.Region.Physics.BulletSPlugin | ||
36 | { | ||
37 | public sealed class BSShapeCollection : IDisposable | ||
38 | { | ||
39 | private static string LogHeader = "[BULLETSIM SHAPE COLLECTION]"; | ||
40 | |||
41 | private BSScene PhysicsScene { get; set; } | ||
42 | |||
43 | private Object m_collectionActivityLock = new Object(); | ||
44 | |||
45 | // Description of a Mesh | ||
46 | private struct MeshDesc | ||
47 | { | ||
48 | public IntPtr ptr; | ||
49 | public int referenceCount; | ||
50 | public DateTime lastReferenced; | ||
51 | public UInt64 shapeKey; | ||
52 | } | ||
53 | |||
54 | // Description of a hull. | ||
55 | // Meshes and hulls have the same shape hash key but we only need hulls for efficient collision calculations. | ||
56 | private struct HullDesc | ||
57 | { | ||
58 | public IntPtr ptr; | ||
59 | public int referenceCount; | ||
60 | public DateTime lastReferenced; | ||
61 | public UInt64 shapeKey; | ||
62 | } | ||
63 | |||
64 | // The sharable set of meshes and hulls. Indexed by their shape hash. | ||
65 | private Dictionary<System.UInt64, MeshDesc> Meshes = new Dictionary<System.UInt64, MeshDesc>(); | ||
66 | private Dictionary<System.UInt64, HullDesc> Hulls = new Dictionary<System.UInt64, HullDesc>(); | ||
67 | |||
68 | public BSShapeCollection(BSScene physScene) | ||
69 | { | ||
70 | PhysicsScene = physScene; | ||
71 | } | ||
72 | |||
73 | public void Dispose() | ||
74 | { | ||
75 | // TODO!!!!!!!!! | ||
76 | } | ||
77 | |||
78 | // Callbacks called just before either the body or shape is destroyed. | ||
79 | // Mostly used for changing bodies out from under Linksets. | ||
80 | // Useful for other cases where parameters need saving. | ||
81 | // Passing 'null' says no callback. | ||
82 | public delegate void ShapeDestructionCallback(BulletShape shape); | ||
83 | public delegate void BodyDestructionCallback(BulletBody body); | ||
84 | |||
85 | // Called to update/change the body and shape for an object. | ||
86 | // First checks the shape and updates that if necessary then makes | ||
87 | // sure the body is of the right type. | ||
88 | // Return 'true' if either the body or the shape changed. | ||
89 | // 'shapeCallback' and 'bodyCallback' are, if non-null, functions called just before | ||
90 | // the current shape or body is destroyed. This allows the caller to remove any | ||
91 | // higher level dependencies on the shape or body. Mostly used for LinkSets to | ||
92 | // remove the physical constraints before the body is destroyed. | ||
93 | // Called at taint-time!! | ||
94 | public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPhysObject prim, | ||
95 | ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback) | ||
96 | { | ||
97 | PhysicsScene.AssertInTaintTime("BSShapeCollection.GetBodyAndShape"); | ||
98 | |||
99 | bool ret = false; | ||
100 | |||
101 | // This lock could probably be pushed down lower but building shouldn't take long | ||
102 | lock (m_collectionActivityLock) | ||
103 | { | ||
104 | // Do we have the correct geometry for this type of object? | ||
105 | // Updates prim.BSShape with information/pointers to shape. | ||
106 | // Returns 'true' of BSShape is changed to a new shape. | ||
107 | bool newGeom = CreateGeom(forceRebuild, prim, shapeCallback); | ||
108 | // If we had to select a new shape geometry for the object, | ||
109 | // rebuild the body around it. | ||
110 | // Updates prim.BSBody with information/pointers to requested body | ||
111 | // Returns 'true' if BSBody was changed. | ||
112 | bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, | ||
113 | prim.PhysShape, bodyCallback); | ||
114 | ret = newGeom || newBody; | ||
115 | } | ||
116 | DetailLog("{0},BSShapeCollection.GetBodyAndShape,taintExit,force={1},ret={2},body={3},shape={4}", | ||
117 | prim.LocalID, forceRebuild, ret, prim.PhysBody, prim.PhysShape); | ||
118 | |||
119 | return ret; | ||
120 | } | ||
121 | |||
122 | // Track another user of a body. | ||
123 | // We presume the caller has allocated the body. | ||
124 | // Bodies only have one user so the body is just put into the world if not already there. | ||
125 | public void ReferenceBody(BulletBody body, bool inTaintTime) | ||
126 | { | ||
127 | lock (m_collectionActivityLock) | ||
128 | { | ||
129 | DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,body={1}", body.ID, body); | ||
130 | PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.ReferenceBody", delegate() | ||
131 | { | ||
132 | if (!BulletSimAPI.IsInWorld2(body.ptr)) | ||
133 | { | ||
134 | BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, body.ptr); | ||
135 | DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body); | ||
136 | } | ||
137 | }); | ||
138 | } | ||
139 | } | ||
140 | |||
141 | // Release the usage of a body. | ||
142 | // Called when releasing use of a BSBody. BSShape is handled separately. | ||
143 | public void DereferenceBody(BulletBody body, bool inTaintTime, BodyDestructionCallback bodyCallback ) | ||
144 | { | ||
145 | if (body.ptr == IntPtr.Zero) | ||
146 | return; | ||
147 | |||
148 | lock (m_collectionActivityLock) | ||
149 | { | ||
150 | PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceBody", delegate() | ||
151 | { | ||
152 | DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1},inTaintTime={2}", | ||
153 | body.ID, body, inTaintTime); | ||
154 | // If the caller needs to know the old body is going away, pass the event up. | ||
155 | if (bodyCallback != null) bodyCallback(body); | ||
156 | |||
157 | if (BulletSimAPI.IsInWorld2(body.ptr)) | ||
158 | { | ||
159 | BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr); | ||
160 | DetailLog("{0},BSShapeCollection.DereferenceBody,removingFromWorld. Body={1}", body.ID, body); | ||
161 | } | ||
162 | |||
163 | // Zero any reference to the shape so it is not freed when the body is deleted. | ||
164 | BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, IntPtr.Zero); | ||
165 | BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, body.ptr); | ||
166 | }); | ||
167 | } | ||
168 | } | ||
169 | |||
170 | // Track the datastructures and use count for a shape. | ||
171 | // When creating a hull, this is called first to reference the mesh | ||
172 | // and then again to reference the hull. | ||
173 | // Meshes and hulls for the same shape have the same hash key. | ||
174 | // NOTE that native shapes are not added to the mesh list or removed. | ||
175 | // Returns 'true' if this is the initial reference to the shape. Otherwise reused. | ||
176 | public bool ReferenceShape(BulletShape shape) | ||
177 | { | ||
178 | bool ret = false; | ||
179 | switch (shape.type) | ||
180 | { | ||
181 | case ShapeData.PhysicsShapeType.SHAPE_MESH: | ||
182 | MeshDesc meshDesc; | ||
183 | if (Meshes.TryGetValue(shape.shapeKey, out meshDesc)) | ||
184 | { | ||
185 | // There is an existing instance of this mesh. | ||
186 | meshDesc.referenceCount++; | ||
187 | DetailLog("{0},BSShapeCollection.ReferenceShape,existingMesh,key={1},cnt={2}", | ||
188 | BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount); | ||
189 | } | ||
190 | else | ||
191 | { | ||
192 | // This is a new reference to a mesh | ||
193 | meshDesc.ptr = shape.ptr; | ||
194 | meshDesc.shapeKey = shape.shapeKey; | ||
195 | // We keep a reference to the underlying IMesh data so a hull can be built | ||
196 | meshDesc.referenceCount = 1; | ||
197 | DetailLog("{0},BSShapeCollection.ReferenceShape,newMesh,key={1},cnt={2}", | ||
198 | BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount); | ||
199 | ret = true; | ||
200 | } | ||
201 | meshDesc.lastReferenced = System.DateTime.Now; | ||
202 | Meshes[shape.shapeKey] = meshDesc; | ||
203 | break; | ||
204 | case ShapeData.PhysicsShapeType.SHAPE_HULL: | ||
205 | HullDesc hullDesc; | ||
206 | if (Hulls.TryGetValue(shape.shapeKey, out hullDesc)) | ||
207 | { | ||
208 | // There is an existing instance of this hull. | ||
209 | hullDesc.referenceCount++; | ||
210 | DetailLog("{0},BSShapeCollection.ReferenceShape,existingHull,key={1},cnt={2}", | ||
211 | BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); | ||
212 | } | ||
213 | else | ||
214 | { | ||
215 | // This is a new reference to a hull | ||
216 | hullDesc.ptr = shape.ptr; | ||
217 | hullDesc.shapeKey = shape.shapeKey; | ||
218 | hullDesc.referenceCount = 1; | ||
219 | DetailLog("{0},BSShapeCollection.ReferenceShape,newHull,key={1},cnt={2}", | ||
220 | BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); | ||
221 | ret = true; | ||
222 | |||
223 | } | ||
224 | hullDesc.lastReferenced = System.DateTime.Now; | ||
225 | Hulls[shape.shapeKey] = hullDesc; | ||
226 | break; | ||
227 | case ShapeData.PhysicsShapeType.SHAPE_UNKNOWN: | ||
228 | break; | ||
229 | default: | ||
230 | // Native shapes are not tracked and they don't go into any list | ||
231 | break; | ||
232 | } | ||
233 | return ret; | ||
234 | } | ||
235 | |||
236 | // Release the usage of a shape. | ||
237 | public void DereferenceShape(BulletShape shape, bool inTaintTime, ShapeDestructionCallback shapeCallback) | ||
238 | { | ||
239 | if (shape.ptr == IntPtr.Zero) | ||
240 | return; | ||
241 | |||
242 | PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceShape", delegate() | ||
243 | { | ||
244 | if (shape.ptr != IntPtr.Zero) | ||
245 | { | ||
246 | if (shape.isNativeShape) | ||
247 | { | ||
248 | // Native shapes are not tracked and are released immediately | ||
249 | DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}", | ||
250 | BSScene.DetailLogZero, shape.ptr.ToString("X"), inTaintTime); | ||
251 | if (shapeCallback != null) shapeCallback(shape); | ||
252 | BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr); | ||
253 | } | ||
254 | else | ||
255 | { | ||
256 | switch (shape.type) | ||
257 | { | ||
258 | case ShapeData.PhysicsShapeType.SHAPE_HULL: | ||
259 | DereferenceHull(shape, shapeCallback); | ||
260 | break; | ||
261 | case ShapeData.PhysicsShapeType.SHAPE_MESH: | ||
262 | DereferenceMesh(shape, shapeCallback); | ||
263 | break; | ||
264 | case ShapeData.PhysicsShapeType.SHAPE_COMPOUND: | ||
265 | DereferenceCompound(shape, shapeCallback); | ||
266 | break; | ||
267 | case ShapeData.PhysicsShapeType.SHAPE_UNKNOWN: | ||
268 | break; | ||
269 | default: | ||
270 | break; | ||
271 | } | ||
272 | } | ||
273 | } | ||
274 | }); | ||
275 | } | ||
276 | |||
277 | // Count down the reference count for a mesh shape | ||
278 | // Called at taint-time. | ||
279 | private void DereferenceMesh(BulletShape shape, ShapeDestructionCallback shapeCallback) | ||
280 | { | ||
281 | MeshDesc meshDesc; | ||
282 | if (Meshes.TryGetValue(shape.shapeKey, out meshDesc)) | ||
283 | { | ||
284 | meshDesc.referenceCount--; | ||
285 | // TODO: release the Bullet storage | ||
286 | if (shapeCallback != null) shapeCallback(shape); | ||
287 | meshDesc.lastReferenced = System.DateTime.Now; | ||
288 | Meshes[shape.shapeKey] = meshDesc; | ||
289 | DetailLog("{0},BSShapeCollection.DereferenceMesh,shape={1},refCnt={2}", | ||
290 | BSScene.DetailLogZero, shape, meshDesc.referenceCount); | ||
291 | |||
292 | } | ||
293 | } | ||
294 | |||
295 | // Count down the reference count for a hull shape | ||
296 | // Called at taint-time. | ||
297 | private void DereferenceHull(BulletShape shape, ShapeDestructionCallback shapeCallback) | ||
298 | { | ||
299 | HullDesc hullDesc; | ||
300 | if (Hulls.TryGetValue(shape.shapeKey, out hullDesc)) | ||
301 | { | ||
302 | hullDesc.referenceCount--; | ||
303 | // TODO: release the Bullet storage (aging old entries?) | ||
304 | |||
305 | // Tell upper layers that, if they have dependencies on this shape, this link is going away | ||
306 | if (shapeCallback != null) shapeCallback(shape); | ||
307 | |||
308 | hullDesc.lastReferenced = System.DateTime.Now; | ||
309 | Hulls[shape.shapeKey] = hullDesc; | ||
310 | DetailLog("{0},BSShapeCollection.DereferenceHull,shape={1},refCnt={2}", | ||
311 | BSScene.DetailLogZero, shape, hullDesc.referenceCount); | ||
312 | } | ||
313 | } | ||
314 | |||
315 | // Remove a reference to a compound shape. | ||
316 | // Taking a compound shape apart is a little tricky because if you just delete the | ||
317 | // physical shape, it will free all the underlying children. We can't do that because | ||
318 | // they could be shared. So, this removes each of the children from the compound and | ||
319 | // dereferences them separately before destroying the compound collision object itself. | ||
320 | // Called at taint-time. | ||
321 | private void DereferenceCompound(BulletShape shape, ShapeDestructionCallback shapeCallback) | ||
322 | { | ||
323 | if (!BulletSimAPI.IsCompound2(shape.ptr)) | ||
324 | { | ||
325 | // Failed the sanity check!! | ||
326 | PhysicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}", | ||
327 | LogHeader, shape.type, shape.ptr.ToString("X")); | ||
328 | DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}", | ||
329 | BSScene.DetailLogZero, shape.type, shape.ptr.ToString("X")); | ||
330 | return; | ||
331 | } | ||
332 | |||
333 | int numChildren = BulletSimAPI.GetNumberOfCompoundChildren2(shape.ptr); | ||
334 | DetailLog("{0},BSShapeCollection.DereferenceCompound,shape={1},children={2}", BSScene.DetailLogZero, shape, numChildren); | ||
335 | |||
336 | for (int ii = numChildren - 1; ii >= 0; ii--) | ||
337 | { | ||
338 | IntPtr childShape = BulletSimAPI.RemoveChildShapeFromCompoundShapeIndex2(shape.ptr, ii); | ||
339 | DereferenceAnonCollisionShape(childShape); | ||
340 | } | ||
341 | BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr); | ||
342 | } | ||
343 | |||
344 | // Sometimes we have a pointer to a collision shape but don't know what type it is. | ||
345 | // Figure out type and call the correct dereference routine. | ||
346 | // Called at taint-time. | ||
347 | private void DereferenceAnonCollisionShape(IntPtr cShape) | ||
348 | { | ||
349 | MeshDesc meshDesc; | ||
350 | HullDesc hullDesc; | ||
351 | |||
352 | BulletShape shapeInfo = new BulletShape(cShape); | ||
353 | if (TryGetMeshByPtr(cShape, out meshDesc)) | ||
354 | { | ||
355 | shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_MESH; | ||
356 | shapeInfo.shapeKey = meshDesc.shapeKey; | ||
357 | } | ||
358 | else | ||
359 | { | ||
360 | if (TryGetHullByPtr(cShape, out hullDesc)) | ||
361 | { | ||
362 | shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_HULL; | ||
363 | shapeInfo.shapeKey = hullDesc.shapeKey; | ||
364 | } | ||
365 | else | ||
366 | { | ||
367 | if (BulletSimAPI.IsCompound2(cShape)) | ||
368 | { | ||
369 | shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_COMPOUND; | ||
370 | } | ||
371 | else | ||
372 | { | ||
373 | if (BulletSimAPI.IsNativeShape2(cShape)) | ||
374 | { | ||
375 | shapeInfo.isNativeShape = true; | ||
376 | shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_BOX; // (technically, type doesn't matter) | ||
377 | } | ||
378 | } | ||
379 | } | ||
380 | } | ||
381 | |||
382 | DetailLog("{0},BSShapeCollection.DereferenceAnonCollisionShape,shape={1}", BSScene.DetailLogZero, shapeInfo); | ||
383 | |||
384 | if (shapeInfo.type != ShapeData.PhysicsShapeType.SHAPE_UNKNOWN) | ||
385 | { | ||
386 | DereferenceShape(shapeInfo, true, null); | ||
387 | } | ||
388 | else | ||
389 | { | ||
390 | PhysicsScene.Logger.ErrorFormat("{0} Could not decypher shape type. Region={1}, addr={2}", | ||
391 | LogHeader, PhysicsScene.RegionName, cShape.ToString("X")); | ||
392 | } | ||
393 | } | ||
394 | |||
395 | // Create the geometry information in Bullet for later use. | ||
396 | // The objects needs a hull if it's physical otherwise a mesh is enough. | ||
397 | // if 'forceRebuild' is true, the geometry is unconditionally rebuilt. For meshes and hulls, | ||
398 | // shared geometries will be used. If the parameters of the existing shape are the same | ||
399 | // as this request, the shape is not rebuilt. | ||
400 | // Info in prim.BSShape is updated to the new shape. | ||
401 | // Returns 'true' if the geometry was rebuilt. | ||
402 | // Called at taint-time! | ||
403 | private bool CreateGeom(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback) | ||
404 | { | ||
405 | bool ret = false; | ||
406 | bool haveShape = false; | ||
407 | |||
408 | if (!haveShape && prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_AVATAR) | ||
409 | { | ||
410 | // an avatar capsule is close to a native shape (it is not shared) | ||
411 | ret = GetReferenceToNativeShape(prim, ShapeData.PhysicsShapeType.SHAPE_AVATAR, | ||
412 | ShapeData.FixedShapeKey.KEY_CAPSULE, shapeCallback); | ||
413 | DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.PhysShape); | ||
414 | ret = true; | ||
415 | haveShape = true; | ||
416 | } | ||
417 | |||
418 | // Compound shapes are handled special as they are rebuilt from scratch. | ||
419 | // This isn't too great a hardship since most of the child shapes will already been created. | ||
420 | if (!haveShape && prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_COMPOUND) | ||
421 | { | ||
422 | ret = GetReferenceToCompoundShape(prim, shapeCallback); | ||
423 | DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, prim.PhysShape); | ||
424 | haveShape = true; | ||
425 | } | ||
426 | |||
427 | if (!haveShape) | ||
428 | { | ||
429 | ret = CreateGeomNonSpecial(forceRebuild, prim, shapeCallback); | ||
430 | } | ||
431 | |||
432 | return ret; | ||
433 | } | ||
434 | |||
435 | // Create a mesh/hull shape or a native shape if 'nativeShapePossible' is 'true'. | ||
436 | private bool CreateGeomNonSpecial(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback) | ||
437 | { | ||
438 | bool ret = false; | ||
439 | bool haveShape = false; | ||
440 | bool nativeShapePossible = true; | ||
441 | PrimitiveBaseShape pbs = prim.BaseShape; | ||
442 | |||
443 | // If the prim attributes are simple, this could be a simple Bullet native shape | ||
444 | if (!haveShape | ||
445 | && pbs != null | ||
446 | && nativeShapePossible | ||
447 | && ((pbs.SculptEntry && !PhysicsScene.ShouldMeshSculptedPrim) | ||
448 | || (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0 | ||
449 | && pbs.ProfileHollow == 0 | ||
450 | && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0 | ||
451 | && pbs.PathBegin == 0 && pbs.PathEnd == 0 | ||
452 | && pbs.PathTaperX == 0 && pbs.PathTaperY == 0 | ||
453 | && pbs.PathScaleX == 100 && pbs.PathScaleY == 100 | ||
454 | && pbs.PathShearX == 0 && pbs.PathShearY == 0) ) ) | ||
455 | { | ||
456 | // It doesn't look like Bullet scales spheres so make sure the scales are all equal | ||
457 | if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1) | ||
458 | && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z) | ||
459 | { | ||
460 | haveShape = true; | ||
461 | if (forceRebuild | ||
462 | || prim.Scale != prim.Size | ||
463 | || prim.PhysShape.type != ShapeData.PhysicsShapeType.SHAPE_SPHERE | ||
464 | ) | ||
465 | { | ||
466 | ret = GetReferenceToNativeShape(prim, ShapeData.PhysicsShapeType.SHAPE_SPHERE, | ||
467 | ShapeData.FixedShapeKey.KEY_SPHERE, shapeCallback); | ||
468 | DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}", | ||
469 | prim.LocalID, forceRebuild, prim.PhysShape); | ||
470 | } | ||
471 | } | ||
472 | if (!haveShape && pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) | ||
473 | { | ||
474 | haveShape = true; | ||
475 | if (forceRebuild | ||
476 | || prim.Scale != prim.Size | ||
477 | || prim.PhysShape.type != ShapeData.PhysicsShapeType.SHAPE_BOX | ||
478 | ) | ||
479 | { | ||
480 | ret = GetReferenceToNativeShape( prim, ShapeData.PhysicsShapeType.SHAPE_BOX, | ||
481 | ShapeData.FixedShapeKey.KEY_BOX, shapeCallback); | ||
482 | DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}", | ||
483 | prim.LocalID, forceRebuild, prim.PhysShape); | ||
484 | } | ||
485 | } | ||
486 | } | ||
487 | |||
488 | // If a simple shape is not happening, create a mesh and possibly a hull. | ||
489 | if (!haveShape && pbs != null) | ||
490 | { | ||
491 | ret = CreateGeomMeshOrHull(prim, shapeCallback); | ||
492 | } | ||
493 | |||
494 | return ret; | ||
495 | } | ||
496 | |||
497 | public bool CreateGeomMeshOrHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback) | ||
498 | { | ||
499 | |||
500 | bool ret = false; | ||
501 | // Note that if it's a native shape, the check for physical/non-physical is not | ||
502 | // made. Native shapes work in either case. | ||
503 | if (prim.IsPhysical && PhysicsScene.ShouldUseHullsForPhysicalObjects) | ||
504 | { | ||
505 | // Update prim.BSShape to reference a hull of this shape. | ||
506 | ret = GetReferenceToHull(prim,shapeCallback); | ||
507 | DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}", | ||
508 | prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); | ||
509 | } | ||
510 | else | ||
511 | { | ||
512 | ret = GetReferenceToMesh(prim, shapeCallback); | ||
513 | DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}", | ||
514 | prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); | ||
515 | } | ||
516 | return ret; | ||
517 | } | ||
518 | |||
519 | // Creates a native shape and assignes it to prim.BSShape. | ||
520 | // "Native" shapes are never shared. they are created here and destroyed in DereferenceShape(). | ||
521 | private bool GetReferenceToNativeShape(BSPhysObject prim, | ||
522 | ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey, | ||
523 | ShapeDestructionCallback shapeCallback) | ||
524 | { | ||
525 | // release any previous shape | ||
526 | DereferenceShape(prim.PhysShape, true, shapeCallback); | ||
527 | |||
528 | // Bullet native objects are scaled by the Bullet engine so pass the size in | ||
529 | prim.Scale = prim.Size; | ||
530 | |||
531 | BulletShape newShape = BuildPhysicalNativeShape(prim, shapeType, shapeKey); | ||
532 | |||
533 | // Don't need to do a 'ReferenceShape()' here because native shapes are not shared. | ||
534 | DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}", | ||
535 | prim.LocalID, newShape, prim.Scale); | ||
536 | |||
537 | prim.PhysShape = newShape; | ||
538 | return true; | ||
539 | } | ||
540 | |||
541 | private BulletShape BuildPhysicalNativeShape(BSPhysObject prim, ShapeData.PhysicsShapeType shapeType, | ||
542 | ShapeData.FixedShapeKey shapeKey) | ||
543 | { | ||
544 | BulletShape newShape; | ||
545 | // Need to make sure the passed shape information is for the native type. | ||
546 | ShapeData nativeShapeData = new ShapeData(); | ||
547 | nativeShapeData.Type = shapeType; | ||
548 | nativeShapeData.ID = prim.LocalID; | ||
549 | nativeShapeData.Scale = prim.Scale; | ||
550 | nativeShapeData.Size = prim.Scale; | ||
551 | nativeShapeData.MeshKey = (ulong)shapeKey; | ||
552 | nativeShapeData.HullKey = (ulong)shapeKey; | ||
553 | |||
554 | if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR) | ||
555 | { | ||
556 | newShape = new BulletShape( | ||
557 | BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1f, 1f, prim.Scale) | ||
558 | , shapeType); | ||
559 | DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale); | ||
560 | } | ||
561 | else | ||
562 | { | ||
563 | newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, nativeShapeData), shapeType); | ||
564 | } | ||
565 | if (newShape.ptr == IntPtr.Zero) | ||
566 | { | ||
567 | PhysicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}", | ||
568 | LogHeader, prim.LocalID, shapeType); | ||
569 | } | ||
570 | newShape.shapeKey = (System.UInt64)shapeKey; | ||
571 | newShape.isNativeShape = true; | ||
572 | |||
573 | return newShape; | ||
574 | } | ||
575 | |||
576 | // Builds a mesh shape in the physical world and updates prim.BSShape. | ||
577 | // Dereferences previous shape in BSShape and adds a reference for this new shape. | ||
578 | // Returns 'true' of a mesh was actually built. Otherwise . | ||
579 | // Called at taint-time! | ||
580 | private bool GetReferenceToMesh(BSPhysObject prim, ShapeDestructionCallback shapeCallback) | ||
581 | { | ||
582 | BulletShape newShape = new BulletShape(IntPtr.Zero); | ||
583 | |||
584 | float lod; | ||
585 | System.UInt64 newMeshKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod); | ||
586 | |||
587 | // if this new shape is the same as last time, don't recreate the mesh | ||
588 | if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == ShapeData.PhysicsShapeType.SHAPE_MESH) | ||
589 | return false; | ||
590 | |||
591 | DetailLog("{0},BSShapeCollection.GetReferenceToMesh,create,oldKey={1},newKey={2}", | ||
592 | prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X")); | ||
593 | |||
594 | // Since we're recreating new, get rid of the reference to the previous shape | ||
595 | DereferenceShape(prim.PhysShape, true, shapeCallback); | ||
596 | |||
597 | newShape = CreatePhysicalMesh(prim.PhysObjectName, newMeshKey, prim.BaseShape, prim.Size, lod); | ||
598 | // Take evasive action if the mesh was not constructed. | ||
599 | newShape = VerifyMeshCreated(newShape, prim); | ||
600 | |||
601 | ReferenceShape(newShape); | ||
602 | |||
603 | // meshes are already scaled by the meshmerizer | ||
604 | prim.Scale = new OMV.Vector3(1f, 1f, 1f); | ||
605 | prim.PhysShape = newShape; | ||
606 | |||
607 | return true; // 'true' means a new shape has been added to this prim | ||
608 | } | ||
609 | |||
610 | private BulletShape CreatePhysicalMesh(string objName, System.UInt64 newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) | ||
611 | { | ||
612 | IMesh meshData = null; | ||
613 | IntPtr meshPtr = IntPtr.Zero; | ||
614 | MeshDesc meshDesc; | ||
615 | if (Meshes.TryGetValue(newMeshKey, out meshDesc)) | ||
616 | { | ||
617 | // If the mesh has already been built just use it. | ||
618 | meshPtr = meshDesc.ptr; | ||
619 | } | ||
620 | else | ||
621 | { | ||
622 | // Pass false for physicalness as this creates some sort of bounding box which we don't need | ||
623 | meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false); | ||
624 | |||
625 | if (meshData != null) | ||
626 | { | ||
627 | int[] indices = meshData.getIndexListAsInt(); | ||
628 | List<OMV.Vector3> vertices = meshData.getVertexList(); | ||
629 | |||
630 | float[] verticesAsFloats = new float[vertices.Count * 3]; | ||
631 | int vi = 0; | ||
632 | foreach (OMV.Vector3 vv in vertices) | ||
633 | { | ||
634 | verticesAsFloats[vi++] = vv.X; | ||
635 | verticesAsFloats[vi++] = vv.Y; | ||
636 | verticesAsFloats[vi++] = vv.Z; | ||
637 | } | ||
638 | |||
639 | // m_log.DebugFormat("{0}: BSShapeCollection.CreatePhysicalMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}", | ||
640 | // LogHeader, prim.LocalID, newMeshKey, indices.Length, vertices.Count); | ||
641 | |||
642 | meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr, | ||
643 | indices.GetLength(0), indices, vertices.Count, verticesAsFloats); | ||
644 | } | ||
645 | } | ||
646 | BulletShape newShape = new BulletShape(meshPtr, ShapeData.PhysicsShapeType.SHAPE_MESH); | ||
647 | newShape.shapeKey = newMeshKey; | ||
648 | |||
649 | return newShape; | ||
650 | } | ||
651 | |||
652 | // See that hull shape exists in the physical world and update prim.BSShape. | ||
653 | // We could be creating the hull because scale changed or whatever. | ||
654 | private bool GetReferenceToHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback) | ||
655 | { | ||
656 | BulletShape newShape; | ||
657 | |||
658 | float lod; | ||
659 | System.UInt64 newHullKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod); | ||
660 | |||
661 | // if the hull hasn't changed, don't rebuild it | ||
662 | if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == ShapeData.PhysicsShapeType.SHAPE_HULL) | ||
663 | return false; | ||
664 | |||
665 | DetailLog("{0},BSShapeCollection.GetReferenceToHull,create,oldKey={1},newKey={2}", | ||
666 | prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X")); | ||
667 | |||
668 | // Remove usage of the previous shape. | ||
669 | DereferenceShape(prim.PhysShape, true, shapeCallback); | ||
670 | |||
671 | newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, prim.BaseShape, prim.Size, lod); | ||
672 | newShape = VerifyMeshCreated(newShape, prim); | ||
673 | |||
674 | ReferenceShape(newShape); | ||
675 | |||
676 | // hulls are already scaled by the meshmerizer | ||
677 | prim.Scale = new OMV.Vector3(1f, 1f, 1f); | ||
678 | prim.PhysShape = newShape; | ||
679 | return true; // 'true' means a new shape has been added to this prim | ||
680 | } | ||
681 | |||
682 | List<ConvexResult> m_hulls; | ||
683 | private BulletShape CreatePhysicalHull(string objName, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) | ||
684 | { | ||
685 | |||
686 | IntPtr hullPtr = IntPtr.Zero; | ||
687 | HullDesc hullDesc; | ||
688 | if (Hulls.TryGetValue(newHullKey, out hullDesc)) | ||
689 | { | ||
690 | // If the hull shape already is created, just use it. | ||
691 | hullPtr = hullDesc.ptr; | ||
692 | } | ||
693 | else | ||
694 | { | ||
695 | // Build a new hull in the physical world | ||
696 | // Pass false for physicalness as this creates some sort of bounding box which we don't need | ||
697 | IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false); | ||
698 | if (meshData != null) | ||
699 | { | ||
700 | |||
701 | int[] indices = meshData.getIndexListAsInt(); | ||
702 | List<OMV.Vector3> vertices = meshData.getVertexList(); | ||
703 | |||
704 | //format conversion from IMesh format to DecompDesc format | ||
705 | List<int> convIndices = new List<int>(); | ||
706 | List<float3> convVertices = new List<float3>(); | ||
707 | for (int ii = 0; ii < indices.GetLength(0); ii++) | ||
708 | { | ||
709 | convIndices.Add(indices[ii]); | ||
710 | } | ||
711 | foreach (OMV.Vector3 vv in vertices) | ||
712 | { | ||
713 | convVertices.Add(new float3(vv.X, vv.Y, vv.Z)); | ||
714 | } | ||
715 | |||
716 | // setup and do convex hull conversion | ||
717 | m_hulls = new List<ConvexResult>(); | ||
718 | DecompDesc dcomp = new DecompDesc(); | ||
719 | dcomp.mIndices = convIndices; | ||
720 | dcomp.mVertices = convVertices; | ||
721 | ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn); | ||
722 | // create the hull into the _hulls variable | ||
723 | convexBuilder.process(dcomp); | ||
724 | |||
725 | // Convert the vertices and indices for passing to unmanaged. | ||
726 | // The hull information is passed as a large floating point array. | ||
727 | // The format is: | ||
728 | // convHulls[0] = number of hulls | ||
729 | // convHulls[1] = number of vertices in first hull | ||
730 | // convHulls[2] = hull centroid X coordinate | ||
731 | // convHulls[3] = hull centroid Y coordinate | ||
732 | // convHulls[4] = hull centroid Z coordinate | ||
733 | // convHulls[5] = first hull vertex X | ||
734 | // convHulls[6] = first hull vertex Y | ||
735 | // convHulls[7] = first hull vertex Z | ||
736 | // convHulls[8] = second hull vertex X | ||
737 | // ... | ||
738 | // convHulls[n] = number of vertices in second hull | ||
739 | // convHulls[n+1] = second hull centroid X coordinate | ||
740 | // ... | ||
741 | // | ||
742 | // TODO: is is very inefficient. Someday change the convex hull generator to return | ||
743 | // data structures that do not need to be converted in order to pass to Bullet. | ||
744 | // And maybe put the values directly into pinned memory rather than marshaling. | ||
745 | int hullCount = m_hulls.Count; | ||
746 | int totalVertices = 1; // include one for the count of the hulls | ||
747 | foreach (ConvexResult cr in m_hulls) | ||
748 | { | ||
749 | totalVertices += 4; // add four for the vertex count and centroid | ||
750 | totalVertices += cr.HullIndices.Count * 3; // we pass just triangles | ||
751 | } | ||
752 | float[] convHulls = new float[totalVertices]; | ||
753 | |||
754 | convHulls[0] = (float)hullCount; | ||
755 | int jj = 1; | ||
756 | foreach (ConvexResult cr in m_hulls) | ||
757 | { | ||
758 | // copy vertices for index access | ||
759 | float3[] verts = new float3[cr.HullVertices.Count]; | ||
760 | int kk = 0; | ||
761 | foreach (float3 ff in cr.HullVertices) | ||
762 | { | ||
763 | verts[kk++] = ff; | ||
764 | } | ||
765 | |||
766 | // add to the array one hull's worth of data | ||
767 | convHulls[jj++] = cr.HullIndices.Count; | ||
768 | convHulls[jj++] = 0f; // centroid x,y,z | ||
769 | convHulls[jj++] = 0f; | ||
770 | convHulls[jj++] = 0f; | ||
771 | foreach (int ind in cr.HullIndices) | ||
772 | { | ||
773 | convHulls[jj++] = verts[ind].x; | ||
774 | convHulls[jj++] = verts[ind].y; | ||
775 | convHulls[jj++] = verts[ind].z; | ||
776 | } | ||
777 | } | ||
778 | // create the hull data structure in Bullet | ||
779 | hullPtr = BulletSimAPI.CreateHullShape2(PhysicsScene.World.ptr, hullCount, convHulls); | ||
780 | } | ||
781 | } | ||
782 | |||
783 | BulletShape newShape = new BulletShape(hullPtr, ShapeData.PhysicsShapeType.SHAPE_HULL); | ||
784 | newShape.shapeKey = newHullKey; | ||
785 | |||
786 | return newShape; // 'true' means a new shape has been added to this prim | ||
787 | } | ||
788 | |||
789 | // Callback from convex hull creater with a newly created hull. | ||
790 | // Just add it to our collection of hulls for this shape. | ||
791 | private void HullReturn(ConvexResult result) | ||
792 | { | ||
793 | m_hulls.Add(result); | ||
794 | return; | ||
795 | } | ||
796 | |||
797 | // Compound shapes are always built from scratch. | ||
798 | // This shouldn't be to bad since most of the parts will be meshes that had been built previously. | ||
799 | private bool GetReferenceToCompoundShape(BSPhysObject prim, ShapeDestructionCallback shapeCallback) | ||
800 | { | ||
801 | // Remove reference to the old shape | ||
802 | // Don't need to do this as the shape is freed when the new root shape is created below. | ||
803 | // DereferenceShape(prim.PhysShape, true, shapeCallback); | ||
804 | |||
805 | BulletShape cShape = new BulletShape( | ||
806 | BulletSimAPI.CreateCompoundShape2(PhysicsScene.World.ptr, false), ShapeData.PhysicsShapeType.SHAPE_COMPOUND); | ||
807 | |||
808 | // Create the shape for the root prim and add it to the compound shape. Cannot be a native shape. | ||
809 | CreateGeomMeshOrHull(prim, shapeCallback); | ||
810 | BulletSimAPI.AddChildShapeToCompoundShape2(cShape.ptr, prim.PhysShape.ptr, OMV.Vector3.Zero, OMV.Quaternion.Identity); | ||
811 | DetailLog("{0},BSShapeCollection.GetReferenceToCompoundShape,addRootPrim,compShape={1},rootShape={2}", | ||
812 | prim.LocalID, cShape, prim.PhysShape); | ||
813 | |||
814 | prim.PhysShape = cShape; | ||
815 | |||
816 | return true; | ||
817 | } | ||
818 | |||
819 | // Create a hash of all the shape parameters to be used as a key | ||
820 | // for this particular shape. | ||
821 | private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod) | ||
822 | { | ||
823 | // level of detail based on size and type of the object | ||
824 | float lod = PhysicsScene.MeshLOD; | ||
825 | if (pbs.SculptEntry) | ||
826 | lod = PhysicsScene.SculptLOD; | ||
827 | |||
828 | // Mega prims usually get more detail because one can interact with shape approximations at this size. | ||
829 | float maxAxis = Math.Max(size.X, Math.Max(size.Y, size.Z)); | ||
830 | if (maxAxis > PhysicsScene.MeshMegaPrimThreshold) | ||
831 | lod = PhysicsScene.MeshMegaPrimLOD; | ||
832 | |||
833 | retLod = lod; | ||
834 | return pbs.GetMeshKey(size, lod); | ||
835 | } | ||
836 | // For those who don't want the LOD | ||
837 | private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs) | ||
838 | { | ||
839 | float lod; | ||
840 | return ComputeShapeKey(size, pbs, out lod); | ||
841 | } | ||
842 | |||
843 | // The creation of a mesh or hull can fail if an underlying asset is not available. | ||
844 | // There are two cases: 1) the asset is not in the cache and it needs to be fetched; | ||
845 | // and 2) the asset cannot be converted (like failed decompression of JPEG2000s). | ||
846 | // The first case causes the asset to be fetched. The second case requires | ||
847 | // us to not loop forever. | ||
848 | // Called after creating a physical mesh or hull. If the physical shape was created, | ||
849 | // just return. | ||
850 | private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim) | ||
851 | { | ||
852 | // If the shape was successfully created, nothing more to do | ||
853 | if (newShape.ptr != IntPtr.Zero) | ||
854 | return newShape; | ||
855 | |||
856 | // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset | ||
857 | if (prim.BaseShape.SculptEntry && !prim.LastAssetBuildFailed && prim.BaseShape.SculptTexture != OMV.UUID.Zero) | ||
858 | { | ||
859 | prim.LastAssetBuildFailed = true; | ||
860 | BSPhysObject xprim = prim; | ||
861 | DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset,lID={1},lastFailed={2}", | ||
862 | LogHeader, prim.LocalID, prim.LastAssetBuildFailed); | ||
863 | Util.FireAndForget(delegate | ||
864 | { | ||
865 | RequestAssetDelegate assetProvider = PhysicsScene.RequestAssetMethod; | ||
866 | if (assetProvider != null) | ||
867 | { | ||
868 | BSPhysObject yprim = xprim; // probably not necessary, but, just in case. | ||
869 | assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset) | ||
870 | { | ||
871 | if (!yprim.BaseShape.SculptEntry) | ||
872 | return; | ||
873 | if (yprim.BaseShape.SculptTexture.ToString() != asset.ID) | ||
874 | return; | ||
875 | |||
876 | yprim.BaseShape.SculptData = asset.Data; | ||
877 | // This will cause the prim to see that the filler shape is not the right | ||
878 | // one and try again to build the object. | ||
879 | // No race condition with the normal shape setting since the rebuild is at taint time. | ||
880 | yprim.ForceBodyShapeRebuild(false); | ||
881 | |||
882 | }); | ||
883 | } | ||
884 | }); | ||
885 | } | ||
886 | else | ||
887 | { | ||
888 | if (prim.LastAssetBuildFailed) | ||
889 | { | ||
890 | PhysicsScene.Logger.ErrorFormat("{0} Mesh failed to fetch asset. lID={1}, texture={2}", | ||
891 | LogHeader, prim.LocalID, prim.BaseShape.SculptTexture); | ||
892 | } | ||
893 | } | ||
894 | |||
895 | // While we figure out the real problem, stick a simple native shape on the object. | ||
896 | BulletShape fillinShape = | ||
897 | BuildPhysicalNativeShape(prim, ShapeData.PhysicsShapeType.SHAPE_BOX, ShapeData.FixedShapeKey.KEY_BOX); | ||
898 | |||
899 | return fillinShape; | ||
900 | } | ||
901 | |||
902 | // Create a body object in Bullet. | ||
903 | // Updates prim.BSBody with the information about the new body if one is created. | ||
904 | // Returns 'true' if an object was actually created. | ||
905 | // Called at taint-time. | ||
906 | private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletSim sim, BulletShape shape, | ||
907 | BodyDestructionCallback bodyCallback) | ||
908 | { | ||
909 | bool ret = false; | ||
910 | |||
911 | // the mesh, hull or native shape must have already been created in Bullet | ||
912 | bool mustRebuild = (prim.PhysBody.ptr == IntPtr.Zero); | ||
913 | |||
914 | // If there is an existing body, verify it's of an acceptable type. | ||
915 | // If not a solid object, body is a GhostObject. Otherwise a RigidBody. | ||
916 | if (!mustRebuild) | ||
917 | { | ||
918 | CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(prim.PhysBody.ptr); | ||
919 | if (prim.IsSolid && bodyType != CollisionObjectTypes.CO_RIGID_BODY | ||
920 | || !prim.IsSolid && bodyType != CollisionObjectTypes.CO_GHOST_OBJECT) | ||
921 | { | ||
922 | // If the collisionObject is not the correct type for solidness, rebuild what's there | ||
923 | mustRebuild = true; | ||
924 | } | ||
925 | } | ||
926 | |||
927 | if (mustRebuild || forceRebuild) | ||
928 | { | ||
929 | // Free any old body | ||
930 | DereferenceBody(prim.PhysBody, true, bodyCallback); | ||
931 | |||
932 | BulletBody aBody; | ||
933 | IntPtr bodyPtr = IntPtr.Zero; | ||
934 | if (prim.IsSolid) | ||
935 | { | ||
936 | bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr, | ||
937 | prim.LocalID, prim.RawPosition, prim.RawOrientation); | ||
938 | DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); | ||
939 | } | ||
940 | else | ||
941 | { | ||
942 | bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr, | ||
943 | prim.LocalID, prim.ForcePosition, prim.ForceOrientation); | ||
944 | DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); | ||
945 | } | ||
946 | aBody = new BulletBody(prim.LocalID, bodyPtr); | ||
947 | |||
948 | ReferenceBody(aBody, true); | ||
949 | |||
950 | prim.PhysBody = aBody; | ||
951 | |||
952 | ret = true; | ||
953 | } | ||
954 | |||
955 | return ret; | ||
956 | } | ||
957 | |||
958 | private bool TryGetMeshByPtr(IntPtr addr, out MeshDesc outDesc) | ||
959 | { | ||
960 | bool ret = false; | ||
961 | MeshDesc foundDesc = new MeshDesc(); | ||
962 | foreach (MeshDesc md in Meshes.Values) | ||
963 | { | ||
964 | if (md.ptr == addr) | ||
965 | { | ||
966 | foundDesc = md; | ||
967 | ret = true; | ||
968 | break; | ||
969 | } | ||
970 | |||
971 | } | ||
972 | outDesc = foundDesc; | ||
973 | return ret; | ||
974 | } | ||
975 | |||
976 | private bool TryGetHullByPtr(IntPtr addr, out HullDesc outDesc) | ||
977 | { | ||
978 | bool ret = false; | ||
979 | HullDesc foundDesc = new HullDesc(); | ||
980 | foreach (HullDesc hd in Hulls.Values) | ||
981 | { | ||
982 | if (hd.ptr == addr) | ||
983 | { | ||
984 | foundDesc = hd; | ||
985 | ret = true; | ||
986 | break; | ||
987 | } | ||
988 | |||
989 | } | ||
990 | outDesc = foundDesc; | ||
991 | return ret; | ||
992 | } | ||
993 | |||
994 | private void DetailLog(string msg, params Object[] args) | ||
995 | { | ||
996 | if (PhysicsScene.PhysicsLogging.Enabled) | ||
997 | PhysicsScene.DetailLog(msg, args); | ||
998 | } | ||
999 | } | ||
1000 | } | ||
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs deleted file mode 100755 index 7c34af2..0000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ /dev/null | |||
@@ -1,479 +0,0 @@ | |||
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 copyrightD | ||
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 | using System; | ||
28 | using System.Collections.Generic; | ||
29 | using System.Text; | ||
30 | |||
31 | using OpenSim.Framework; | ||
32 | using OpenSim.Region.Framework; | ||
33 | using OpenSim.Region.CoreModules; | ||
34 | using OpenSim.Region.Physics.Manager; | ||
35 | |||
36 | using Nini.Config; | ||
37 | using log4net; | ||
38 | |||
39 | using OpenMetaverse; | ||
40 | |||
41 | namespace OpenSim.Region.Physics.BulletSPlugin | ||
42 | { | ||
43 | public sealed class BSTerrainManager | ||
44 | { | ||
45 | static string LogHeader = "[BULLETSIM TERRAIN MANAGER]"; | ||
46 | |||
47 | // These height values are fractional so the odd values will be | ||
48 | // noticable when debugging. | ||
49 | public const float HEIGHT_INITIALIZATION = 24.987f; | ||
50 | public const float HEIGHT_INITIAL_LASTHEIGHT = 24.876f; | ||
51 | public const float HEIGHT_GETHEIGHT_RET = 24.765f; | ||
52 | |||
53 | // If the min and max height are equal, we reduce the min by this | ||
54 | // amount to make sure that a bounding box is built for the terrain. | ||
55 | public const float HEIGHT_EQUAL_FUDGE = 0.2f; | ||
56 | |||
57 | public const float TERRAIN_COLLISION_MARGIN = 0.0f; | ||
58 | |||
59 | // Until the whole simulator is changed to pass us the region size, we rely on constants. | ||
60 | public Vector3 DefaultRegionSize = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight); | ||
61 | |||
62 | // The scene that I am part of | ||
63 | private BSScene PhysicsScene { get; set; } | ||
64 | |||
65 | // The ground plane created to keep thing from falling to infinity. | ||
66 | private BulletBody m_groundPlane; | ||
67 | |||
68 | // If doing mega-regions, if we're region zero we will be managing multiple | ||
69 | // region terrains since region zero does the physics for the whole mega-region. | ||
70 | private Dictionary<Vector2, BulletHeightMapInfo> m_heightMaps; | ||
71 | |||
72 | // True of the terrain has been modified. | ||
73 | // Used to force recalculation of terrain height after terrain has been modified | ||
74 | private bool m_terrainModified; | ||
75 | |||
76 | // If we are doing mega-regions, terrains are added from TERRAIN_ID to m_terrainCount. | ||
77 | // This is incremented before assigning to new region so it is the last ID allocated. | ||
78 | private uint m_terrainCount = BSScene.CHILDTERRAIN_ID - 1; | ||
79 | public uint HighestTerrainID { get {return m_terrainCount; } } | ||
80 | |||
81 | // If doing mega-regions, this holds our offset from region zero of | ||
82 | // the mega-regions. "parentScene" points to the PhysicsScene of region zero. | ||
83 | private Vector3 m_worldOffset; | ||
84 | // If the parent region (region 0), this is the extent of the combined regions | ||
85 | // relative to the origin of region zero | ||
86 | private Vector3 m_worldMax; | ||
87 | private PhysicsScene MegaRegionParentPhysicsScene { get; set; } | ||
88 | |||
89 | public BSTerrainManager(BSScene physicsScene) | ||
90 | { | ||
91 | PhysicsScene = physicsScene; | ||
92 | m_heightMaps = new Dictionary<Vector2,BulletHeightMapInfo>(); | ||
93 | m_terrainModified = false; | ||
94 | |||
95 | // Assume one region of default size | ||
96 | m_worldOffset = Vector3.Zero; | ||
97 | m_worldMax = new Vector3(DefaultRegionSize); | ||
98 | MegaRegionParentPhysicsScene = null; | ||
99 | } | ||
100 | |||
101 | // Create the initial instance of terrain and the underlying ground plane. | ||
102 | // The objects are allocated in the unmanaged space and the pointers are tracked | ||
103 | // by the managed code. | ||
104 | // The terrains and the groundPlane are not added to the list of PhysObjects. | ||
105 | // This is called from the initialization routine so we presume it is | ||
106 | // safe to call Bullet in real time. We hope no one is moving prims around yet. | ||
107 | public void CreateInitialGroundPlaneAndTerrain() | ||
108 | { | ||
109 | // The ground plane is here to catch things that are trying to drop to negative infinity | ||
110 | BulletShape groundPlaneShape = new BulletShape( | ||
111 | BulletSimAPI.CreateGroundPlaneShape2(BSScene.GROUNDPLANE_ID, 1f, TERRAIN_COLLISION_MARGIN), | ||
112 | ShapeData.PhysicsShapeType.SHAPE_GROUNDPLANE); | ||
113 | m_groundPlane = new BulletBody(BSScene.GROUNDPLANE_ID, | ||
114 | BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.ptr, BSScene.GROUNDPLANE_ID, | ||
115 | Vector3.Zero, Quaternion.Identity)); | ||
116 | BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr); | ||
117 | BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_groundPlane.ptr); | ||
118 | // Ground plane does not move | ||
119 | BulletSimAPI.ForceActivationState2(m_groundPlane.ptr, ActivationState.DISABLE_SIMULATION); | ||
120 | // Everything collides with the ground plane. | ||
121 | BulletSimAPI.SetCollisionFilterMask2(m_groundPlane.ptr, | ||
122 | (uint)CollisionFilterGroups.GroundPlaneFilter, (uint)CollisionFilterGroups.GroundPlaneMask); | ||
123 | |||
124 | Vector3 minTerrainCoords = new Vector3(0f, 0f, HEIGHT_INITIALIZATION - HEIGHT_EQUAL_FUDGE); | ||
125 | Vector3 maxTerrainCoords = new Vector3(DefaultRegionSize.X, DefaultRegionSize.Y, HEIGHT_INITIALIZATION); | ||
126 | int totalHeights = (int)maxTerrainCoords.X * (int)maxTerrainCoords.Y; | ||
127 | float[] initialMap = new float[totalHeights]; | ||
128 | for (int ii = 0; ii < totalHeights; ii++) | ||
129 | { | ||
130 | initialMap[ii] = HEIGHT_INITIALIZATION; | ||
131 | } | ||
132 | UpdateOrCreateTerrain(BSScene.TERRAIN_ID, initialMap, minTerrainCoords, maxTerrainCoords, true); | ||
133 | } | ||
134 | |||
135 | // Release all the terrain structures we might have allocated | ||
136 | public void ReleaseGroundPlaneAndTerrain() | ||
137 | { | ||
138 | if (m_groundPlane.ptr != IntPtr.Zero) | ||
139 | { | ||
140 | if (BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr)) | ||
141 | { | ||
142 | BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, m_groundPlane.ptr); | ||
143 | } | ||
144 | m_groundPlane.ptr = IntPtr.Zero; | ||
145 | } | ||
146 | |||
147 | ReleaseTerrain(); | ||
148 | } | ||
149 | |||
150 | // Release all the terrain we have allocated | ||
151 | public void ReleaseTerrain() | ||
152 | { | ||
153 | foreach (KeyValuePair<Vector2, BulletHeightMapInfo> kvp in m_heightMaps) | ||
154 | { | ||
155 | if (BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, kvp.Value.terrainBody.ptr)) | ||
156 | { | ||
157 | BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, kvp.Value.terrainBody.ptr); | ||
158 | BulletSimAPI.ReleaseHeightMapInfo2(kvp.Value.Ptr); | ||
159 | } | ||
160 | } | ||
161 | m_heightMaps.Clear(); | ||
162 | } | ||
163 | |||
164 | // The simulator wants to set a new heightmap for the terrain. | ||
165 | public void SetTerrain(float[] heightMap) { | ||
166 | float[] localHeightMap = heightMap; | ||
167 | PhysicsScene.TaintedObject("TerrainManager.SetTerrain", delegate() | ||
168 | { | ||
169 | if (m_worldOffset != Vector3.Zero && MegaRegionParentPhysicsScene != null) | ||
170 | { | ||
171 | // If a child of a mega-region, we shouldn't have any terrain allocated for us | ||
172 | ReleaseGroundPlaneAndTerrain(); | ||
173 | // If doing the mega-prim stuff and we are the child of the zero region, | ||
174 | // the terrain is added to our parent | ||
175 | if (MegaRegionParentPhysicsScene is BSScene) | ||
176 | { | ||
177 | DetailLog("{0},SetTerrain.ToParent,offset={1},worldMax={2}", | ||
178 | BSScene.DetailLogZero, m_worldOffset, m_worldMax); | ||
179 | ((BSScene)MegaRegionParentPhysicsScene).TerrainManager.UpdateOrCreateTerrain(BSScene.CHILDTERRAIN_ID, | ||
180 | localHeightMap, m_worldOffset, m_worldOffset + DefaultRegionSize, true); | ||
181 | } | ||
182 | } | ||
183 | else | ||
184 | { | ||
185 | // If not doing the mega-prim thing, just change the terrain | ||
186 | DetailLog("{0},SetTerrain.Existing", BSScene.DetailLogZero); | ||
187 | |||
188 | UpdateOrCreateTerrain(BSScene.TERRAIN_ID, localHeightMap, | ||
189 | m_worldOffset, m_worldOffset + DefaultRegionSize, true); | ||
190 | } | ||
191 | }); | ||
192 | } | ||
193 | |||
194 | // If called with no mapInfo for the terrain, this will create a new mapInfo and terrain | ||
195 | // based on the passed information. The 'id' should be either the terrain id or | ||
196 | // BSScene.CHILDTERRAIN_ID. If the latter, a new child terrain ID will be allocated and used. | ||
197 | // The latter feature is for creating child terrains for mega-regions. | ||
198 | // If called with a mapInfo in m_heightMaps but the terrain has no body yet (mapInfo.terrainBody.Ptr == 0) | ||
199 | // then a new body and shape is created and the mapInfo is filled. | ||
200 | // This call is used for doing the initial terrain creation. | ||
201 | // If called with a mapInfo in m_heightMaps and there is an existing terrain body, a new | ||
202 | // terrain shape is created and added to the body. | ||
203 | // This call is most often used to update the heightMap and parameters of the terrain. | ||
204 | // (The above does suggest that some simplification/refactoring is in order.) | ||
205 | private void UpdateOrCreateTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords, bool inTaintTime) | ||
206 | { | ||
207 | DetailLog("{0},BSTerrainManager.UpdateOrCreateTerrain,call,minC={1},maxC={2},inTaintTime={3}", | ||
208 | BSScene.DetailLogZero, minCoords, maxCoords, inTaintTime); | ||
209 | |||
210 | float minZ = float.MaxValue; | ||
211 | float maxZ = float.MinValue; | ||
212 | Vector2 terrainRegionBase = new Vector2(minCoords.X, minCoords.Y); | ||
213 | |||
214 | int heightMapSize = heightMap.Length; | ||
215 | for (int ii = 0; ii < heightMapSize; ii++) | ||
216 | { | ||
217 | float height = heightMap[ii]; | ||
218 | if (height < minZ) minZ = height; | ||
219 | if (height > maxZ) maxZ = height; | ||
220 | } | ||
221 | |||
222 | // The shape of the terrain is from its base to its extents. | ||
223 | minCoords.Z = minZ; | ||
224 | maxCoords.Z = maxZ; | ||
225 | |||
226 | BulletHeightMapInfo mapInfo; | ||
227 | if (m_heightMaps.TryGetValue(terrainRegionBase, out mapInfo)) | ||
228 | { | ||
229 | // If this is terrain we know about, it's easy to update | ||
230 | |||
231 | mapInfo.heightMap = heightMap; | ||
232 | mapInfo.minCoords = minCoords; | ||
233 | mapInfo.maxCoords = maxCoords; | ||
234 | mapInfo.minZ = minZ; | ||
235 | mapInfo.maxZ = maxZ; | ||
236 | mapInfo.sizeX = maxCoords.X - minCoords.X; | ||
237 | mapInfo.sizeY = maxCoords.Y - minCoords.Y; | ||
238 | DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,call,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}", | ||
239 | BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY); | ||
240 | |||
241 | PhysicsScene.TaintedObject(inTaintTime, "BSScene.UpdateOrCreateTerrain:UpdateExisting", delegate() | ||
242 | { | ||
243 | if (MegaRegionParentPhysicsScene != null) | ||
244 | { | ||
245 | // It's possible that Combine() was called after this code was queued. | ||
246 | // If we are a child of combined regions, we don't create any terrain for us. | ||
247 | DetailLog("{0},UpdateOrCreateTerrain:AmACombineChild,taint", BSScene.DetailLogZero); | ||
248 | |||
249 | // Get rid of any terrain that may have been allocated for us. | ||
250 | ReleaseGroundPlaneAndTerrain(); | ||
251 | |||
252 | // I hate doing this, but just bail | ||
253 | return; | ||
254 | } | ||
255 | |||
256 | if (mapInfo.terrainBody.ptr != IntPtr.Zero) | ||
257 | { | ||
258 | // Updating an existing terrain. | ||
259 | DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,taint,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}", | ||
260 | BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY); | ||
261 | |||
262 | // Remove from the dynamics world because we're going to mangle this object | ||
263 | BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr); | ||
264 | |||
265 | // Get rid of the old terrain | ||
266 | BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr); | ||
267 | BulletSimAPI.ReleaseHeightMapInfo2(mapInfo.Ptr); | ||
268 | mapInfo.Ptr = IntPtr.Zero; | ||
269 | |||
270 | /* | ||
271 | // NOTE: This routine is half here because I can't get the terrain shape replacement | ||
272 | // to work. In the short term, the above three lines completely delete the old | ||
273 | // terrain and the code below recreates one from scratch. | ||
274 | // Hopefully the Bullet community will help me out on this one. | ||
275 | |||
276 | // First, release the old collision shape (there is only one terrain) | ||
277 | BulletSimAPI.DeleteCollisionShape2(m_physicsScene.World.Ptr, mapInfo.terrainShape.Ptr); | ||
278 | |||
279 | // Fill the existing height map info with the new location and size information | ||
280 | BulletSimAPI.FillHeightMapInfo2(m_physicsScene.World.Ptr, mapInfo.Ptr, mapInfo.ID, | ||
281 | mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN); | ||
282 | |||
283 | // Create a terrain shape based on the new info | ||
284 | mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr)); | ||
285 | |||
286 | // Stuff the shape into the existing terrain body | ||
287 | BulletSimAPI.SetBodyShape2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr, mapInfo.terrainShape.Ptr); | ||
288 | */ | ||
289 | } | ||
290 | // else | ||
291 | { | ||
292 | // Creating a new terrain. | ||
293 | DetailLog("{0},UpdateOrCreateTerrain:CreateNewTerrain,taint,baseX={1},baseY={2},minZ={3},maxZ={4}", | ||
294 | BSScene.DetailLogZero, mapInfo.minCoords.X, mapInfo.minCoords.Y, minZ, maxZ); | ||
295 | |||
296 | mapInfo.ID = id; | ||
297 | mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, mapInfo.ID, | ||
298 | mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN); | ||
299 | |||
300 | // Create the terrain shape from the mapInfo | ||
301 | mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr), | ||
302 | ShapeData.PhysicsShapeType.SHAPE_TERRAIN); | ||
303 | |||
304 | // The terrain object initial position is at the center of the object | ||
305 | Vector3 centerPos; | ||
306 | centerPos.X = minCoords.X + (mapInfo.sizeX / 2f); | ||
307 | centerPos.Y = minCoords.Y + (mapInfo.sizeY / 2f); | ||
308 | centerPos.Z = minZ + ((maxZ - minZ) / 2f); | ||
309 | |||
310 | mapInfo.terrainBody = new BulletBody(mapInfo.ID, | ||
311 | BulletSimAPI.CreateBodyWithDefaultMotionState2(mapInfo.terrainShape.ptr, | ||
312 | id, centerPos, Quaternion.Identity)); | ||
313 | } | ||
314 | |||
315 | // Make sure the entry is in the heightmap table | ||
316 | m_heightMaps[terrainRegionBase] = mapInfo; | ||
317 | |||
318 | // Set current terrain attributes | ||
319 | BulletSimAPI.SetFriction2(mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainFriction); | ||
320 | BulletSimAPI.SetHitFraction2(mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainHitFraction); | ||
321 | BulletSimAPI.SetRestitution2(mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainRestitution); | ||
322 | BulletSimAPI.SetCollisionFlags2(mapInfo.terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT); | ||
323 | |||
324 | // Return the new terrain to the world of physical objects | ||
325 | BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr); | ||
326 | |||
327 | // redo its bounding box now that it is in the world | ||
328 | BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr); | ||
329 | |||
330 | BulletSimAPI.SetCollisionFilterMask2(mapInfo.terrainBody.ptr, | ||
331 | (uint)CollisionFilterGroups.TerrainFilter, | ||
332 | (uint)CollisionFilterGroups.TerrainMask); | ||
333 | |||
334 | // Make sure the new shape is processed. | ||
335 | // BulletSimAPI.Activate2(mapInfo.terrainBody.ptr, true); | ||
336 | // BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.ISLAND_SLEEPING); | ||
337 | BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION); | ||
338 | |||
339 | m_terrainModified = true; | ||
340 | }); | ||
341 | } | ||
342 | else | ||
343 | { | ||
344 | // We don't know about this terrain so either we are creating a new terrain or | ||
345 | // our mega-prim child is giving us a new terrain to add to the phys world | ||
346 | |||
347 | // if this is a child terrain, calculate a unique terrain id | ||
348 | uint newTerrainID = id; | ||
349 | if (newTerrainID >= BSScene.CHILDTERRAIN_ID) | ||
350 | newTerrainID = ++m_terrainCount; | ||
351 | |||
352 | float[] heightMapX = heightMap; | ||
353 | Vector3 minCoordsX = minCoords; | ||
354 | Vector3 maxCoordsX = maxCoords; | ||
355 | |||
356 | DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,call,id={1}, minC={2}, maxC={3}", | ||
357 | BSScene.DetailLogZero, newTerrainID, minCoords, minCoords); | ||
358 | |||
359 | // Code that must happen at taint-time | ||
360 | PhysicsScene.TaintedObject(inTaintTime, "BSScene.UpdateOrCreateTerrain:NewTerrain", delegate() | ||
361 | { | ||
362 | DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,taint,baseX={1},baseY={2}", BSScene.DetailLogZero, minCoords.X, minCoords.Y); | ||
363 | // Create a new mapInfo that will be filled with the new info | ||
364 | mapInfo = new BulletHeightMapInfo(id, heightMapX, | ||
365 | BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, newTerrainID, | ||
366 | minCoordsX, maxCoordsX, heightMapX, TERRAIN_COLLISION_MARGIN)); | ||
367 | // Put the unfilled heightmap info into the collection of same | ||
368 | m_heightMaps.Add(terrainRegionBase, mapInfo); | ||
369 | // Build the terrain | ||
370 | UpdateOrCreateTerrain(newTerrainID, heightMap, minCoords, maxCoords, true); | ||
371 | |||
372 | m_terrainModified = true; | ||
373 | }); | ||
374 | } | ||
375 | } | ||
376 | |||
377 | // Someday we will have complex terrain with caves and tunnels | ||
378 | public float GetTerrainHeightAtXYZ(Vector3 loc) | ||
379 | { | ||
380 | // For the moment, it's flat and convex | ||
381 | return GetTerrainHeightAtXY(loc.X, loc.Y); | ||
382 | } | ||
383 | |||
384 | // Given an X and Y, find the height of the terrain. | ||
385 | // Since we could be handling multiple terrains for a mega-region, | ||
386 | // the base of the region is calcuated assuming all regions are | ||
387 | // the same size and that is the default. | ||
388 | // Once the heightMapInfo is found, we have all the information to | ||
389 | // compute the offset into the array. | ||
390 | private float lastHeightTX = 999999f; | ||
391 | private float lastHeightTY = 999999f; | ||
392 | private float lastHeight = HEIGHT_INITIAL_LASTHEIGHT; | ||
393 | private float GetTerrainHeightAtXY(float tX, float tY) | ||
394 | { | ||
395 | // You'd be surprized at the number of times this routine is called | ||
396 | // with the same parameters as last time. | ||
397 | if (!m_terrainModified && lastHeightTX == tX && lastHeightTY == tY) | ||
398 | return lastHeight; | ||
399 | |||
400 | lastHeightTX = tX; | ||
401 | lastHeightTY = tY; | ||
402 | float ret = HEIGHT_GETHEIGHT_RET; | ||
403 | |||
404 | int offsetX = ((int)(tX / (int)DefaultRegionSize.X)) * (int)DefaultRegionSize.X; | ||
405 | int offsetY = ((int)(tY / (int)DefaultRegionSize.Y)) * (int)DefaultRegionSize.Y; | ||
406 | Vector2 terrainBaseXY = new Vector2(offsetX, offsetY); | ||
407 | |||
408 | BulletHeightMapInfo mapInfo; | ||
409 | if (m_heightMaps.TryGetValue(terrainBaseXY, out mapInfo)) | ||
410 | { | ||
411 | float regionX = tX - offsetX; | ||
412 | float regionY = tY - offsetY; | ||
413 | int mapIndex = (int)regionY * (int)mapInfo.sizeY + (int)regionX; | ||
414 | try | ||
415 | { | ||
416 | ret = mapInfo.heightMap[mapIndex]; | ||
417 | } | ||
418 | catch | ||
419 | { | ||
420 | // Sometimes they give us wonky values of X and Y. Give a warning and return something. | ||
421 | PhysicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, x={2}, y={3}", | ||
422 | LogHeader, terrainBaseXY, regionX, regionY); | ||
423 | ret = HEIGHT_GETHEIGHT_RET; | ||
424 | } | ||
425 | // DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXY,bX={1},baseY={2},szX={3},szY={4},regX={5},regY={6},index={7},ht={8}", | ||
426 | // BSScene.DetailLogZero, offsetX, offsetY, mapInfo.sizeX, mapInfo.sizeY, regionX, regionY, mapIndex, ret); | ||
427 | } | ||
428 | else | ||
429 | { | ||
430 | PhysicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}", | ||
431 | LogHeader, PhysicsScene.RegionName, tX, tY); | ||
432 | } | ||
433 | m_terrainModified = false; | ||
434 | lastHeight = ret; | ||
435 | return ret; | ||
436 | } | ||
437 | |||
438 | // Although no one seems to check this, I do support combining. | ||
439 | public bool SupportsCombining() | ||
440 | { | ||
441 | return true; | ||
442 | } | ||
443 | |||
444 | // This routine is called two ways: | ||
445 | // One with 'offset' and 'pScene' zero and null but 'extents' giving the maximum | ||
446 | // extent of the combined regions. This is to inform the parent of the size | ||
447 | // of the combined regions. | ||
448 | // and one with 'offset' as the offset of the child region to the base region, | ||
449 | // 'pScene' pointing to the parent and 'extents' of zero. This informs the | ||
450 | // child of its relative base and new parent. | ||
451 | public void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents) | ||
452 | { | ||
453 | m_worldOffset = offset; | ||
454 | m_worldMax = extents; | ||
455 | MegaRegionParentPhysicsScene = pScene; | ||
456 | if (pScene != null) | ||
457 | { | ||
458 | // We are a child. | ||
459 | // We want m_worldMax to be the highest coordinate of our piece of terrain. | ||
460 | m_worldMax = offset + DefaultRegionSize; | ||
461 | } | ||
462 | DetailLog("{0},BSTerrainManager.Combine,offset={1},extents={2},wOffset={3},wMax={4}", | ||
463 | BSScene.DetailLogZero, offset, extents, m_worldOffset, m_worldMax); | ||
464 | } | ||
465 | |||
466 | // Unhook all the combining that I know about. | ||
467 | public void UnCombine(PhysicsScene pScene) | ||
468 | { | ||
469 | // Just like ODE, for the moment a NOP | ||
470 | DetailLog("{0},BSTerrainManager.UnCombine", BSScene.DetailLogZero); | ||
471 | } | ||
472 | |||
473 | |||
474 | private void DetailLog(string msg, params Object[] args) | ||
475 | { | ||
476 | PhysicsScene.PhysicsLogging.Write(msg, args); | ||
477 | } | ||
478 | } | ||
479 | } | ||
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 702bd77..504bd3c 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs | |||
@@ -33,153 +33,38 @@ using OpenMetaverse; | |||
33 | namespace OpenSim.Region.Physics.BulletSPlugin { | 33 | namespace OpenSim.Region.Physics.BulletSPlugin { |
34 | 34 | ||
35 | // Classes to allow some type checking for the API | 35 | // Classes to allow some type checking for the API |
36 | // These hold pointers to allocated objects in the unmanaged space. | ||
37 | |||
38 | // The physics engine controller class created at initialization | ||
39 | public struct BulletSim | 36 | public struct BulletSim |
40 | { | 37 | { |
41 | public BulletSim(uint worldId, BSScene bss, IntPtr xx) | 38 | public BulletSim(uint id, BSScene bss, IntPtr xx) { ID = id; scene = bss; Ptr = xx; } |
42 | { | 39 | public uint ID; |
43 | ptr = xx; | ||
44 | worldID = worldId; | ||
45 | physicsScene = bss; | ||
46 | } | ||
47 | public IntPtr ptr; | ||
48 | public uint worldID; | ||
49 | // The scene is only in here so very low level routines have a handle to print debug/error messages | 40 | // The scene is only in here so very low level routines have a handle to print debug/error messages |
50 | public BSScene physicsScene; | 41 | public BSScene scene; |
42 | public IntPtr Ptr; | ||
51 | } | 43 | } |
52 | 44 | ||
53 | // An allocated Bullet btRigidBody | ||
54 | public struct BulletBody | 45 | public struct BulletBody |
55 | { | 46 | { |
56 | public BulletBody(uint id, IntPtr xx) | 47 | public BulletBody(uint id, IntPtr xx) { ID = id; Ptr = xx; } |
57 | { | 48 | public IntPtr Ptr; |
58 | ID = id; | ||
59 | ptr = xx; | ||
60 | collisionFilter = 0; | ||
61 | collisionMask = 0; | ||
62 | } | ||
63 | public IntPtr ptr; | ||
64 | public uint ID; | 49 | public uint ID; |
65 | public CollisionFilterGroups collisionFilter; | ||
66 | public CollisionFilterGroups collisionMask; | ||
67 | public override string ToString() | ||
68 | { | ||
69 | StringBuilder buff = new StringBuilder(); | ||
70 | buff.Append("<id="); | ||
71 | buff.Append(ID.ToString()); | ||
72 | buff.Append(",p="); | ||
73 | buff.Append(ptr.ToString("X")); | ||
74 | if (collisionFilter != 0 || collisionMask != 0) | ||
75 | { | ||
76 | buff.Append(",f="); | ||
77 | buff.Append(collisionFilter.ToString("X")); | ||
78 | buff.Append(",m="); | ||
79 | buff.Append(collisionMask.ToString("X")); | ||
80 | } | ||
81 | buff.Append(">"); | ||
82 | return buff.ToString(); | ||
83 | } | ||
84 | } | ||
85 | |||
86 | public struct BulletShape | ||
87 | { | ||
88 | public BulletShape(IntPtr xx) | ||
89 | { | ||
90 | ptr = xx; | ||
91 | type=ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; | ||
92 | shapeKey = 0; | ||
93 | isNativeShape = false; | ||
94 | } | ||
95 | public BulletShape(IntPtr xx, ShapeData.PhysicsShapeType typ) | ||
96 | { | ||
97 | ptr = xx; | ||
98 | type = typ; | ||
99 | shapeKey = 0; | ||
100 | isNativeShape = false; | ||
101 | } | ||
102 | public IntPtr ptr; | ||
103 | public ShapeData.PhysicsShapeType type; | ||
104 | public System.UInt64 shapeKey; | ||
105 | public bool isNativeShape; | ||
106 | public override string ToString() | ||
107 | { | ||
108 | StringBuilder buff = new StringBuilder(); | ||
109 | buff.Append("<p="); | ||
110 | buff.Append(ptr.ToString("X")); | ||
111 | buff.Append(",s="); | ||
112 | buff.Append(type.ToString()); | ||
113 | buff.Append(",k="); | ||
114 | buff.Append(shapeKey.ToString("X")); | ||
115 | buff.Append(",n="); | ||
116 | buff.Append(isNativeShape.ToString()); | ||
117 | buff.Append(">"); | ||
118 | return buff.ToString(); | ||
119 | } | ||
120 | } | 50 | } |
121 | 51 | ||
122 | // Constraint type values as defined by Bullet | ||
123 | public enum ConstraintType : int | ||
124 | { | ||
125 | POINT2POINT_CONSTRAINT_TYPE = 3, | ||
126 | HINGE_CONSTRAINT_TYPE, | ||
127 | CONETWIST_CONSTRAINT_TYPE, | ||
128 | D6_CONSTRAINT_TYPE, | ||
129 | SLIDER_CONSTRAINT_TYPE, | ||
130 | CONTACT_CONSTRAINT_TYPE, | ||
131 | D6_SPRING_CONSTRAINT_TYPE, | ||
132 | MAX_CONSTRAINT_TYPE | ||
133 | } | ||
134 | |||
135 | // An allocated Bullet btConstraint | ||
136 | public struct BulletConstraint | 52 | public struct BulletConstraint |
137 | { | 53 | { |
138 | public BulletConstraint(IntPtr xx) | 54 | public BulletConstraint(IntPtr xx) { Ptr = xx; } |
139 | { | ||
140 | ptr = xx; | ||
141 | } | ||
142 | public IntPtr ptr; | ||
143 | } | ||
144 | |||
145 | // An allocated HeightMapThing which holds various heightmap info. | ||
146 | // Made a class rather than a struct so there would be only one | ||
147 | // instance of this and C# will pass around pointers rather | ||
148 | // than making copies. | ||
149 | public class BulletHeightMapInfo | ||
150 | { | ||
151 | public BulletHeightMapInfo(uint id, float[] hm, IntPtr xx) { | ||
152 | ID = id; | ||
153 | Ptr = xx; | ||
154 | heightMap = hm; | ||
155 | terrainRegionBase = new Vector2(0f, 0f); | ||
156 | minCoords = new Vector3(100f, 100f, 25f); | ||
157 | maxCoords = new Vector3(101f, 101f, 26f); | ||
158 | minZ = maxZ = 0f; | ||
159 | sizeX = sizeY = 256f; | ||
160 | } | ||
161 | public uint ID; | ||
162 | public IntPtr Ptr; | 55 | public IntPtr Ptr; |
163 | public float[] heightMap; | ||
164 | public Vector2 terrainRegionBase; | ||
165 | public Vector3 minCoords; | ||
166 | public Vector3 maxCoords; | ||
167 | public float sizeX, sizeY; | ||
168 | public float minZ, maxZ; | ||
169 | public BulletShape terrainShape; | ||
170 | public BulletBody terrainBody; | ||
171 | } | 56 | } |
172 | 57 | ||
173 | // =============================================================================== | 58 | // =============================================================================== |
174 | [StructLayout(LayoutKind.Sequential)] | 59 | [StructLayout(LayoutKind.Sequential)] |
175 | public struct ConvexHull | 60 | public struct ConvexHull |
176 | { | 61 | { |
177 | Vector3 Offset; | 62 | Vector3 Offset; |
178 | int VertexCount; | 63 | int VertexCount; |
179 | Vector3[] Vertices; | 64 | Vector3[] Vertices; |
180 | } | 65 | } |
181 | [StructLayout(LayoutKind.Sequential)] | 66 | [StructLayout(LayoutKind.Sequential)] |
182 | public struct ShapeData | 67 | public struct ShapeData |
183 | { | 68 | { |
184 | public enum PhysicsShapeType | 69 | public enum PhysicsShapeType |
185 | { | 70 | { |
@@ -190,11 +75,7 @@ public struct ShapeData | |||
190 | SHAPE_CYLINDER = 4, | 75 | SHAPE_CYLINDER = 4, |
191 | SHAPE_SPHERE = 5, | 76 | SHAPE_SPHERE = 5, |
192 | SHAPE_MESH = 6, | 77 | SHAPE_MESH = 6, |
193 | SHAPE_HULL = 7, | 78 | SHAPE_HULL = 7 |
194 | // following defined by BulletSim | ||
195 | SHAPE_GROUNDPLANE = 20, | ||
196 | SHAPE_TERRAIN = 21, | ||
197 | SHAPE_COMPOUND = 22, | ||
198 | }; | 79 | }; |
199 | public uint ID; | 80 | public uint ID; |
200 | public PhysicsShapeType Type; | 81 | public PhysicsShapeType Type; |
@@ -210,25 +91,13 @@ public struct ShapeData | |||
210 | public float Restitution; | 91 | public float Restitution; |
211 | public float Collidable; // true of things bump into this | 92 | public float Collidable; // true of things bump into this |
212 | public float Static; // true if a static object. Otherwise gravity, etc. | 93 | public float Static; // true if a static object. Otherwise gravity, etc. |
213 | public float Solid; // true if object cannot be passed through | ||
214 | public Vector3 Size; | ||
215 | 94 | ||
216 | // note that bools are passed as floats since bool size changes by language and architecture | 95 | // note that bools are passed as floats since bool size changes by language and architecture |
217 | public const float numericTrue = 1f; | 96 | public const float numericTrue = 1f; |
218 | public const float numericFalse = 0f; | 97 | public const float numericFalse = 0f; |
219 | |||
220 | // The native shapes have predefined shape hash keys | ||
221 | public enum FixedShapeKey : ulong | ||
222 | { | ||
223 | KEY_BOX = 1, | ||
224 | KEY_SPHERE = 2, | ||
225 | KEY_CONE = 3, | ||
226 | KEY_CYLINDER = 4, | ||
227 | KEY_CAPSULE = 5, | ||
228 | } | ||
229 | } | 98 | } |
230 | [StructLayout(LayoutKind.Sequential)] | 99 | [StructLayout(LayoutKind.Sequential)] |
231 | public struct SweepHit | 100 | public struct SweepHit |
232 | { | 101 | { |
233 | public uint ID; | 102 | public uint ID; |
234 | public float Fraction; | 103 | public float Fraction; |
@@ -284,7 +153,6 @@ public struct ConfigurationParameters | |||
284 | public float terrainHitFraction; | 153 | public float terrainHitFraction; |
285 | public float terrainRestitution; | 154 | public float terrainRestitution; |
286 | public float avatarFriction; | 155 | public float avatarFriction; |
287 | public float avatarStandingFriction; | ||
288 | public float avatarDensity; | 156 | public float avatarDensity; |
289 | public float avatarRestitution; | 157 | public float avatarRestitution; |
290 | public float avatarCapsuleRadius; | 158 | public float avatarCapsuleRadius; |
@@ -300,45 +168,18 @@ public struct ConfigurationParameters | |||
300 | public float shouldEnableFrictionCaching; | 168 | public float shouldEnableFrictionCaching; |
301 | public float numberOfSolverIterations; | 169 | public float numberOfSolverIterations; |
302 | 170 | ||
303 | public float linksetImplementation; | ||
304 | public float linkConstraintUseFrameOffset; | 171 | public float linkConstraintUseFrameOffset; |
305 | public float linkConstraintEnableTransMotor; | 172 | public float linkConstraintEnableTransMotor; |
306 | public float linkConstraintTransMotorMaxVel; | 173 | public float linkConstraintTransMotorMaxVel; |
307 | public float linkConstraintTransMotorMaxForce; | 174 | public float linkConstraintTransMotorMaxForce; |
308 | public float linkConstraintERP; | 175 | public float linkConstraintERP; |
309 | public float linkConstraintCFM; | 176 | public float linkConstraintCFM; |
310 | public float linkConstraintSolverIterations; | ||
311 | |||
312 | public float physicsLoggingFrames; | ||
313 | 177 | ||
314 | public const float numericTrue = 1f; | 178 | public const float numericTrue = 1f; |
315 | public const float numericFalse = 0f; | 179 | public const float numericFalse = 0f; |
316 | } | 180 | } |
317 | 181 | ||
318 | 182 | // Values used by Bullet and BulletSim to control collisions | |
319 | // The states a bullet collision object can have | ||
320 | public enum ActivationState : uint | ||
321 | { | ||
322 | ACTIVE_TAG = 1, | ||
323 | ISLAND_SLEEPING, | ||
324 | WANTS_DEACTIVATION, | ||
325 | DISABLE_DEACTIVATION, | ||
326 | DISABLE_SIMULATION, | ||
327 | } | ||
328 | |||
329 | public enum CollisionObjectTypes : int | ||
330 | { | ||
331 | CO_COLLISION_OBJECT = 1 << 0, | ||
332 | CO_RIGID_BODY = 1 << 1, | ||
333 | CO_GHOST_OBJECT = 1 << 2, | ||
334 | CO_SOFT_BODY = 1 << 3, | ||
335 | CO_HF_FLUID = 1 << 4, | ||
336 | CO_USER_TYPE = 1 << 5, | ||
337 | } | ||
338 | |||
339 | // Values used by Bullet and BulletSim to control object properties. | ||
340 | // Bullet's "CollisionFlags" has more to do with operations on the | ||
341 | // object (if collisions happen, if gravity effects it, ...). | ||
342 | public enum CollisionFlags : uint | 183 | public enum CollisionFlags : uint |
343 | { | 184 | { |
344 | CF_STATIC_OBJECT = 1 << 0, | 185 | CF_STATIC_OBJECT = 1 << 0, |
@@ -350,54 +191,9 @@ public enum CollisionFlags : uint | |||
350 | CF_DISABLE_SPU_COLLISION_PROCESS = 1 << 6, | 191 | CF_DISABLE_SPU_COLLISION_PROCESS = 1 << 6, |
351 | // Following used by BulletSim to control collisions | 192 | // Following used by BulletSim to control collisions |
352 | BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10, | 193 | BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10, |
353 | BS_FLOATS_ON_WATER = 1 << 11, | 194 | BS_VOLUME_DETECT_OBJECT = 1 << 11, |
354 | BS_NONE = 0, | 195 | BS_PHANTOM_OBJECT = 1 << 12, |
355 | BS_ALL = 0xFFFFFFFF, | 196 | BS_PHYSICAL_OBJECT = 1 << 13, |
356 | |||
357 | // These are the collision flags switched depending on physical state. | ||
358 | // The other flags are used for other things and should not be fooled with. | ||
359 | BS_ACTIVE = CF_STATIC_OBJECT | ||
360 | | CF_KINEMATIC_OBJECT | ||
361 | | CF_NO_CONTACT_RESPONSE | ||
362 | }; | ||
363 | |||
364 | // Values for collisions groups and masks | ||
365 | public enum CollisionFilterGroups : uint | ||
366 | { | ||
367 | // Don't use the bit definitions!! Define the use in a | ||
368 | // filter/mask definition below. This way collision interactions | ||
369 | // are more easily debugged. | ||
370 | BNoneFilter = 0, | ||
371 | BDefaultFilter = 1 << 0, | ||
372 | BStaticFilter = 1 << 1, | ||
373 | BKinematicFilter = 1 << 2, | ||
374 | BDebrisFilter = 1 << 3, | ||
375 | BSensorTrigger = 1 << 4, | ||
376 | BCharacterFilter = 1 << 5, | ||
377 | BAllFilter = 0xFFFFFFFF, | ||
378 | // Filter groups defined by BulletSim | ||
379 | BGroundPlaneFilter = 1 << 10, | ||
380 | BTerrainFilter = 1 << 11, | ||
381 | BRaycastFilter = 1 << 12, | ||
382 | BSolidFilter = 1 << 13, | ||
383 | BLinksetFilter = 1 << 14, | ||
384 | |||
385 | // The collsion filters and masked are defined in one place -- don't want them scattered | ||
386 | AvatarFilter = BCharacterFilter, | ||
387 | AvatarMask = BAllFilter, | ||
388 | ObjectFilter = BSolidFilter, | ||
389 | ObjectMask = BAllFilter, | ||
390 | StaticObjectFilter = BStaticFilter, | ||
391 | StaticObjectMask = BAllFilter, | ||
392 | LinksetFilter = BLinksetFilter, | ||
393 | LinksetMask = BAllFilter & ~BLinksetFilter, | ||
394 | VolumeDetectFilter = BSensorTrigger, | ||
395 | VolumeDetectMask = ~BSensorTrigger, | ||
396 | TerrainFilter = BTerrainFilter, | ||
397 | TerrainMask = BAllFilter & ~BStaticFilter, | ||
398 | GroundPlaneFilter = BGroundPlaneFilter, | ||
399 | GroundPlaneMask = BAllFilter | ||
400 | |||
401 | }; | 197 | }; |
402 | 198 | ||
403 | // CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0 | 199 | // CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0 |
@@ -425,23 +221,14 @@ public enum ConstraintParamAxis : int | |||
425 | // =============================================================================== | 221 | // =============================================================================== |
426 | static class BulletSimAPI { | 222 | static class BulletSimAPI { |
427 | 223 | ||
428 | // Link back to the managed code for outputting log messages | ||
429 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] | ||
430 | public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg); | ||
431 | |||
432 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 224 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
433 | [return: MarshalAs(UnmanagedType.LPStr)] | 225 | [return: MarshalAs(UnmanagedType.LPStr)] |
434 | public static extern string GetVersion(); | 226 | public static extern string GetVersion(); |
435 | 227 | ||
436 | /* Remove the linkage to the old api methods | ||
437 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 228 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
438 | public static extern uint Initialize(Vector3 maxPosition, IntPtr parms, | 229 | public static extern uint Initialize(Vector3 maxPosition, IntPtr parms, |
439 | int maxCollisions, IntPtr collisionArray, | 230 | int maxCollisions, IntPtr collisionArray, |
440 | int maxUpdates, IntPtr updateArray, | 231 | int maxUpdates, IntPtr updateArray); |
441 | DebugLogCallback logRoutine); | ||
442 | |||
443 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
444 | public static extern void CreateInitialGroundPlaneAndTerrain(uint worldID); | ||
445 | 232 | ||
446 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 233 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
447 | public static extern void SetHeightmap(uint worldID, [MarshalAs(UnmanagedType.LPArray)] float[] heightMap); | 234 | public static extern void SetHeightmap(uint worldID, [MarshalAs(UnmanagedType.LPArray)] float[] heightMap); |
@@ -455,19 +242,19 @@ public static extern bool UpdateParameter(uint worldID, uint localID, | |||
455 | 242 | ||
456 | // =============================================================================== | 243 | // =============================================================================== |
457 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 244 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
458 | public static extern int PhysicsStep(uint worldID, float timeStep, int maxSubSteps, float fixedTimeStep, | 245 | public static extern int PhysicsStep(uint worldID, float timeStep, int maxSubSteps, float fixedTimeStep, |
459 | out int updatedEntityCount, | 246 | out int updatedEntityCount, |
460 | out IntPtr updatedEntitiesPtr, | 247 | out IntPtr updatedEntitiesPtr, |
461 | out int collidersCount, | 248 | out int collidersCount, |
462 | out IntPtr collidersPtr); | 249 | out IntPtr collidersPtr); |
463 | 250 | ||
464 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 251 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
465 | public static extern bool CreateHull(uint worldID, System.UInt64 meshKey, | 252 | public static extern bool CreateHull(uint worldID, System.UInt64 meshKey, |
466 | int hullCount, [MarshalAs(UnmanagedType.LPArray)] float[] hulls | 253 | int hullCount, [MarshalAs(UnmanagedType.LPArray)] float[] hulls |
467 | ); | 254 | ); |
468 | 255 | ||
469 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 256 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
470 | public static extern bool CreateMesh(uint worldID, System.UInt64 meshKey, | 257 | public static extern bool CreateMesh(uint worldID, System.UInt64 meshKey, |
471 | int indexCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices, | 258 | int indexCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices, |
472 | int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices | 259 | int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices |
473 | ); | 260 | ); |
@@ -481,6 +268,23 @@ public static extern bool DestroyMesh(uint worldID, System.UInt64 meshKey); | |||
481 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 268 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
482 | public static extern bool CreateObject(uint worldID, ShapeData shapeData); | 269 | public static extern bool CreateObject(uint worldID, ShapeData shapeData); |
483 | 270 | ||
271 | /* Remove old functionality | ||
272 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
273 | public static extern void CreateLinkset(uint worldID, int objectCount, ShapeData[] shapeDatas); | ||
274 | |||
275 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
276 | public static extern void AddConstraint(uint worldID, uint id1, uint id2, | ||
277 | Vector3 frame1, Quaternion frame1rot, | ||
278 | Vector3 frame2, Quaternion frame2rot, | ||
279 | Vector3 lowLinear, Vector3 hiLinear, Vector3 lowAngular, Vector3 hiAngular); | ||
280 | |||
281 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
282 | public static extern bool RemoveConstraintByID(uint worldID, uint id1); | ||
283 | |||
284 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
285 | public static extern bool RemoveConstraint(uint worldID, uint id1, uint id2); | ||
286 | */ | ||
287 | |||
484 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 288 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
485 | public static extern Vector3 GetObjectPosition(uint WorldID, uint id); | 289 | public static extern Vector3 GetObjectPosition(uint WorldID, uint id); |
486 | 290 | ||
@@ -496,7 +300,6 @@ public static extern bool SetObjectVelocity(uint worldID, uint id, Vector3 veloc | |||
496 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 300 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
497 | public static extern bool SetObjectAngularVelocity(uint worldID, uint id, Vector3 angularVelocity); | 301 | public static extern bool SetObjectAngularVelocity(uint worldID, uint id, Vector3 angularVelocity); |
498 | 302 | ||
499 | // Set the current force acting on the object | ||
500 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 303 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
501 | public static extern bool SetObjectForce(uint worldID, uint id, Vector3 force); | 304 | public static extern bool SetObjectForce(uint worldID, uint id, Vector3 force); |
502 | 305 | ||
@@ -537,8 +340,10 @@ public static extern Vector3 RecoverFromPenetration(uint worldID, uint id); | |||
537 | // =============================================================================== | 340 | // =============================================================================== |
538 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 341 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
539 | public static extern void DumpBulletStatistics(); | 342 | public static extern void DumpBulletStatistics(); |
540 | */ | 343 | |
541 | // Log a debug message | 344 | // Log a debug message |
345 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] | ||
346 | public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg); | ||
542 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 347 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
543 | public static extern void SetDebugLogCallback(DebugLogCallback callback); | 348 | public static extern void SetDebugLogCallback(DebugLogCallback callback); |
544 | 349 | ||
@@ -553,7 +358,6 @@ public static extern void SetDebugLogCallback(DebugLogCallback callback); | |||
553 | // The names have a "2" tacked on. This will be removed as the C# code gets rebuilt | 358 | // The names have a "2" tacked on. This will be removed as the C# code gets rebuilt |
554 | // and the old code is removed. | 359 | // and the old code is removed. |
555 | 360 | ||
556 | // Functions use while converting from API1 to API2. Can be removed when totally converted. | ||
557 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 361 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
558 | public static extern IntPtr GetSimHandle2(uint worldID); | 362 | public static extern IntPtr GetSimHandle2(uint worldID); |
559 | 363 | ||
@@ -564,25 +368,23 @@ public static extern IntPtr GetBodyHandleWorldID2(uint worldID, uint id); | |||
564 | public static extern IntPtr GetBodyHandle2(IntPtr world, uint id); | 368 | public static extern IntPtr GetBodyHandle2(IntPtr world, uint id); |
565 | 369 | ||
566 | // =============================================================================== | 370 | // =============================================================================== |
567 | // Initialization and simulation | ||
568 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 371 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
569 | public static extern IntPtr Initialize2(Vector3 maxPosition, IntPtr parms, | 372 | public static extern IntPtr Initialize2(Vector3 maxPosition, IntPtr parms, |
570 | int maxCollisions, IntPtr collisionArray, | 373 | int maxCollisions, IntPtr collisionArray, |
571 | int maxUpdates, IntPtr updateArray, | 374 | int maxUpdates, IntPtr updateArray); |
572 | DebugLogCallback logRoutine); | ||
573 | 375 | ||
574 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 376 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
575 | public static extern bool UpdateParameter2(IntPtr world, uint localID, String parm, float value); | 377 | public static extern bool UpdateParameter2(IntPtr world, uint localID, String parm, float value); |
576 | 378 | ||
577 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 379 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
578 | public static extern void SetHeightMap2(IntPtr world, float[] heightmap); | 380 | public static extern void SetHeightmap2(IntPtr world, float[] heightmap); |
579 | 381 | ||
580 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 382 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
581 | public static extern void Shutdown2(IntPtr sim); | 383 | public static extern void Shutdown2(IntPtr sim); |
582 | 384 | ||
583 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 385 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
584 | public static extern int PhysicsStep2(IntPtr world, float timeStep, int maxSubSteps, float fixedTimeStep, | 386 | public static extern int PhysicsStep2(IntPtr world, float timeStep, int maxSubSteps, float fixedTimeStep, |
585 | out int updatedEntityCount, | 387 | out int updatedEntityCount, |
586 | out IntPtr updatedEntitiesPtr, | 388 | out IntPtr updatedEntitiesPtr, |
587 | out int collidersCount, | 389 | out int collidersCount, |
588 | out IntPtr collidersPtr); | 390 | out IntPtr collidersPtr); |
@@ -590,98 +392,23 @@ public static extern int PhysicsStep2(IntPtr world, float timeStep, int maxSubSt | |||
590 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 392 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
591 | public static extern bool PushUpdate2(IntPtr obj); | 393 | public static extern bool PushUpdate2(IntPtr obj); |
592 | 394 | ||
593 | // ===================================================================================== | 395 | /* |
594 | // Mesh, hull, shape and body creation helper routines | ||
595 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
596 | public static extern IntPtr CreateMeshShape2(IntPtr world, | ||
597 | int indicesCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices, | ||
598 | int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices ); | ||
599 | |||
600 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
601 | public static extern IntPtr CreateHullShape2(IntPtr world, | ||
602 | int hullCount, [MarshalAs(UnmanagedType.LPArray)] float[] hulls); | ||
603 | |||
604 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
605 | public static extern IntPtr BuildHullShapeFromMesh2(IntPtr world, IntPtr meshShape); | ||
606 | |||
607 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
608 | public static extern IntPtr BuildNativeShape2(IntPtr world, ShapeData shapeData); | ||
609 | |||
610 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
611 | public static extern bool IsNativeShape2(IntPtr shape); | ||
612 | |||
613 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
614 | public static extern IntPtr BuildCapsuleShape2(IntPtr world, float radius, float height, Vector3 scale); | ||
615 | |||
616 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
617 | public static extern IntPtr CreateCompoundShape2(IntPtr sim, bool enableDynamicAabbTree); | ||
618 | |||
619 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
620 | public static extern int GetNumberOfCompoundChildren2(IntPtr cShape); | ||
621 | |||
622 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
623 | public static extern void AddChildShapeToCompoundShape2(IntPtr cShape, IntPtr addShape, Vector3 pos, Quaternion rot); | ||
624 | |||
625 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
626 | public static extern IntPtr GetChildShapeFromCompoundShapeIndex2(IntPtr cShape, int indx); | ||
627 | |||
628 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
629 | public static extern IntPtr RemoveChildShapeFromCompoundShapeIndex2(IntPtr cShape, int indx); | ||
630 | |||
631 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
632 | public static extern void RemoveChildShapeFromCompoundShape2(IntPtr cShape, IntPtr removeShape); | ||
633 | |||
634 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
635 | public static extern IntPtr DuplicateCollisionShape2(IntPtr sim, IntPtr srcShape, uint id); | ||
636 | |||
637 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
638 | public static extern IntPtr CreateBodyFromShapeAndInfo2(IntPtr sim, IntPtr shape, uint id, IntPtr constructionInfo); | ||
639 | |||
640 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
641 | public static extern bool DeleteCollisionShape2(IntPtr world, IntPtr shape); | ||
642 | |||
643 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
644 | public static extern int GetBodyType2(IntPtr obj); | ||
645 | |||
646 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
647 | public static extern IntPtr CreateBodyFromShape2(IntPtr sim, IntPtr shape, uint id, Vector3 pos, Quaternion rot); | ||
648 | |||
649 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
650 | public static extern IntPtr CreateBodyWithDefaultMotionState2(IntPtr shape, uint id, Vector3 pos, Quaternion rot); | ||
651 | |||
652 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
653 | public static extern IntPtr CreateGhostFromShape2(IntPtr sim, IntPtr shape, uint id, Vector3 pos, Quaternion rot); | ||
654 | |||
655 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
656 | public static extern IntPtr AllocateBodyInfo2(IntPtr obj); | ||
657 | |||
658 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
659 | public static extern void ReleaseBodyInfo2(IntPtr obj); | ||
660 | |||
661 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
662 | public static extern void DestroyObject2(IntPtr sim, IntPtr obj); | ||
663 | |||
664 | // ===================================================================================== | ||
665 | // Terrain creation and helper routines | ||
666 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 396 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
667 | public static extern IntPtr CreateHeightMapInfo2(IntPtr sim, uint id, Vector3 minCoords, Vector3 maxCoords, | 397 | public static extern IntPtr CreateMesh2(IntPtr world, int indicesCount, int* indices, int verticesCount, float* vertices ); |
668 | [MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin); | ||
669 | 398 | ||
670 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 399 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
671 | public static extern IntPtr FillHeightMapInfo2(IntPtr sim, IntPtr mapInfo, uint id, Vector3 minCoords, Vector3 maxCoords, | 400 | public static extern bool BuildHull2(IntPtr world, IntPtr mesh); |
672 | [MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin); | ||
673 | 401 | ||
674 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 402 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
675 | public static extern bool ReleaseHeightMapInfo2(IntPtr heightMapInfo); | 403 | public static extern bool ReleaseHull2(IntPtr world, IntPtr mesh); |
676 | 404 | ||
677 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 405 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
678 | public static extern IntPtr CreateGroundPlaneShape2(uint id, float height, float collisionMargin); | 406 | public static extern bool DestroyMesh2(IntPtr world, IntPtr mesh); |
679 | 407 | ||
680 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 408 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
681 | public static extern IntPtr CreateTerrainShape2(IntPtr mapInfo); | 409 | public static extern IntPtr CreateObject2(IntPtr world, ShapeData shapeData); |
410 | */ | ||
682 | 411 | ||
683 | // ===================================================================================== | ||
684 | // Constraint creation and helper routines | ||
685 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 412 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
686 | public static extern IntPtr Create6DofConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2, | 413 | public static extern IntPtr Create6DofConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2, |
687 | Vector3 frame1loc, Quaternion frame1rot, | 414 | Vector3 frame1loc, Quaternion frame1rot, |
@@ -706,7 +433,7 @@ public static extern void SetConstraintEnable2(IntPtr constrain, float numericTr | |||
706 | public static extern void SetConstraintNumSolverIterations2(IntPtr constrain, float iterations); | 433 | public static extern void SetConstraintNumSolverIterations2(IntPtr constrain, float iterations); |
707 | 434 | ||
708 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 435 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
709 | public static extern bool SetFrames2(IntPtr constrain, | 436 | public static extern bool SetFrames2(IntPtr constrain, |
710 | Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot); | 437 | Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot); |
711 | 438 | ||
712 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 439 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
@@ -733,108 +460,11 @@ public static extern bool SetConstraintParam2(IntPtr constrain, ConstraintParams | |||
733 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 460 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
734 | public static extern bool DestroyConstraint2(IntPtr world, IntPtr constrain); | 461 | public static extern bool DestroyConstraint2(IntPtr world, IntPtr constrain); |
735 | 462 | ||
736 | // ===================================================================================== | ||
737 | // btCollisionWorld entries | ||
738 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 463 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
739 | public static extern void UpdateSingleAabb2(IntPtr world, IntPtr obj); | 464 | public static extern Vector3 AddObjectToWorld2(IntPtr world, IntPtr obj); |
740 | 465 | ||
741 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 466 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
742 | public static extern void UpdateAabbs2(IntPtr world); | 467 | public static extern Vector3 RemoveObjectFromWorld2(IntPtr world, IntPtr obj); |
743 | |||
744 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
745 | public static extern bool GetForceUpdateAllAabbs2(IntPtr world); | ||
746 | |||
747 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
748 | public static extern void SetForceUpdateAllAabbs2(IntPtr world, bool force); | ||
749 | |||
750 | // ===================================================================================== | ||
751 | // btDynamicsWorld entries | ||
752 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
753 | public static extern bool AddObjectToWorld2(IntPtr world, IntPtr obj); | ||
754 | |||
755 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
756 | public static extern bool RemoveObjectFromWorld2(IntPtr world, IntPtr obj); | ||
757 | |||
758 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
759 | public static extern bool AddConstraintToWorld2(IntPtr world, IntPtr constrain, bool disableCollisionsBetweenLinkedObjects); | ||
760 | |||
761 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
762 | public static extern bool RemoveConstraintFromWorld2(IntPtr world, IntPtr constrain); | ||
763 | // ===================================================================================== | ||
764 | // btCollisionObject entries | ||
765 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
766 | public static extern Vector3 GetAnisotripicFriction2(IntPtr constrain); | ||
767 | |||
768 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
769 | public static extern Vector3 SetAnisotripicFriction2(IntPtr constrain, Vector3 frict); | ||
770 | |||
771 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
772 | public static extern bool HasAnisotripicFriction2(IntPtr constrain); | ||
773 | |||
774 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
775 | public static extern void SetContactProcessingThreshold2(IntPtr obj, float val); | ||
776 | |||
777 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
778 | public static extern float GetContactProcessingThreshold2(IntPtr obj); | ||
779 | |||
780 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
781 | public static extern bool IsStaticObject2(IntPtr obj); | ||
782 | |||
783 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
784 | public static extern bool IsKinematicObject2(IntPtr obj); | ||
785 | |||
786 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
787 | public static extern bool IsStaticOrKinematicObject2(IntPtr obj); | ||
788 | |||
789 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
790 | public static extern bool HasContactResponse2(IntPtr obj); | ||
791 | |||
792 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
793 | public static extern void SetCollisionShape2(IntPtr sim, IntPtr obj, IntPtr shape); | ||
794 | |||
795 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
796 | public static extern IntPtr GetCollisionShape2(IntPtr obj); | ||
797 | |||
798 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
799 | public static extern int GetActivationState2(IntPtr obj); | ||
800 | |||
801 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
802 | public static extern void SetActivationState2(IntPtr obj, int state); | ||
803 | |||
804 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
805 | public static extern void SetDeactivationTime2(IntPtr obj, float dtime); | ||
806 | |||
807 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
808 | public static extern float GetDeactivationTime2(IntPtr obj); | ||
809 | |||
810 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
811 | public static extern void ForceActivationState2(IntPtr obj, ActivationState state); | ||
812 | |||
813 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
814 | public static extern void Activate2(IntPtr obj, bool forceActivation); | ||
815 | |||
816 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
817 | public static extern bool IsActive2(IntPtr obj); | ||
818 | |||
819 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
820 | public static extern void SetRestitution2(IntPtr obj, float val); | ||
821 | |||
822 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
823 | public static extern float GetRestitution2(IntPtr obj); | ||
824 | |||
825 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
826 | public static extern void SetFriction2(IntPtr obj, float val); | ||
827 | |||
828 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
829 | public static extern float GetFriction2(IntPtr obj); | ||
830 | |||
831 | /* Haven't defined the type 'Transform' | ||
832 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
833 | public static extern Transform GetWorldTransform2(IntPtr obj); | ||
834 | |||
835 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
836 | public static extern void setWorldTransform2(IntPtr obj, Transform trans); | ||
837 | */ | ||
838 | 468 | ||
839 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 469 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
840 | public static extern Vector3 GetPosition2(IntPtr obj); | 470 | public static extern Vector3 GetPosition2(IntPtr obj); |
@@ -843,290 +473,85 @@ public static extern Vector3 GetPosition2(IntPtr obj); | |||
843 | public static extern Quaternion GetOrientation2(IntPtr obj); | 473 | public static extern Quaternion GetOrientation2(IntPtr obj); |
844 | 474 | ||
845 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 475 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
846 | public static extern void SetTranslation2(IntPtr obj, Vector3 position, Quaternion rotation); | 476 | public static extern bool SetTranslation2(IntPtr obj, Vector3 position, Quaternion rotation); |
847 | |||
848 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
849 | public static extern IntPtr GetBroadphaseHandle2(IntPtr obj); | ||
850 | |||
851 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
852 | public static extern void SetBroadphaseHandle2(IntPtr obj, IntPtr handle); | ||
853 | |||
854 | /* | ||
855 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
856 | public static extern Transform GetInterpolationWorldTransform2(IntPtr obj); | ||
857 | |||
858 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
859 | public static extern void SetInterpolationWorldTransform2(IntPtr obj, Transform trans); | ||
860 | */ | ||
861 | |||
862 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
863 | public static extern void SetInterpolationLinearVelocity2(IntPtr obj, Vector3 vel); | ||
864 | |||
865 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
866 | public static extern void SetInterpolationAngularVelocity2(IntPtr obj, Vector3 vel); | ||
867 | |||
868 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
869 | public static extern void SetInterpolationVelocity2(IntPtr obj, Vector3 linearVel, Vector3 angularVel); | ||
870 | |||
871 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
872 | public static extern float GetHitFraction2(IntPtr obj); | ||
873 | |||
874 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
875 | public static extern void SetHitFraction2(IntPtr obj, float val); | ||
876 | |||
877 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
878 | public static extern CollisionFlags GetCollisionFlags2(IntPtr obj); | ||
879 | |||
880 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
881 | public static extern CollisionFlags SetCollisionFlags2(IntPtr obj, CollisionFlags flags); | ||
882 | |||
883 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
884 | public static extern CollisionFlags AddToCollisionFlags2(IntPtr obj, CollisionFlags flags); | ||
885 | |||
886 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
887 | public static extern CollisionFlags RemoveFromCollisionFlags2(IntPtr obj, CollisionFlags flags); | ||
888 | |||
889 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
890 | public static extern float GetCcdMotionThreshold2(IntPtr obj); | ||
891 | |||
892 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
893 | public static extern void SetCcdMotionThreshold2(IntPtr obj, float val); | ||
894 | |||
895 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
896 | public static extern float GetCcdSweptSphereRadius2(IntPtr obj); | ||
897 | |||
898 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
899 | public static extern void SetCcdSweptSphereRadius2(IntPtr obj, float val); | ||
900 | |||
901 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
902 | public static extern IntPtr GetUserPointer2(IntPtr obj); | ||
903 | |||
904 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
905 | public static extern void SetUserPointer2(IntPtr obj, IntPtr val); | ||
906 | |||
907 | // ===================================================================================== | ||
908 | // btRigidBody entries | ||
909 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
910 | public static extern void ApplyGravity2(IntPtr obj); | ||
911 | |||
912 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
913 | public static extern void SetGravity2(IntPtr obj, Vector3 val); | ||
914 | |||
915 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
916 | public static extern Vector3 GetGravity2(IntPtr obj); | ||
917 | |||
918 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
919 | public static extern void SetDamping2(IntPtr obj, float lin_damping, float ang_damping); | ||
920 | |||
921 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
922 | public static extern float GetLinearDamping2(IntPtr obj); | ||
923 | |||
924 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
925 | public static extern float GetAngularDamping2(IntPtr obj); | ||
926 | |||
927 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
928 | public static extern float GetLinearSleepingThreshold2(IntPtr obj); | ||
929 | |||
930 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
931 | public static extern float GetAngularSleepingThreshold2(IntPtr obj); | ||
932 | |||
933 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
934 | public static extern void ApplyDamping2(IntPtr obj, float timeStep); | ||
935 | |||
936 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
937 | public static extern void SetMassProps2(IntPtr obj, float mass, Vector3 inertia); | ||
938 | |||
939 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
940 | public static extern Vector3 GetLinearFactor2(IntPtr obj); | ||
941 | |||
942 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
943 | public static extern void SetLinearFactor2(IntPtr obj, Vector3 factor); | ||
944 | |||
945 | /* | ||
946 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
947 | public static extern void SetCenterOfMassTransform2(IntPtr obj, Transform trans); | ||
948 | */ | ||
949 | |||
950 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
951 | public static extern void SetCenterOfMassByPosRot2(IntPtr obj, Vector3 pos, Quaternion rot); | ||
952 | |||
953 | // Add a force to the object as if its mass is one. | ||
954 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
955 | public static extern void ApplyCentralForce2(IntPtr obj, Vector3 force); | ||
956 | |||
957 | // Set the force being applied to the object as if its mass is one. | ||
958 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
959 | public static extern void SetObjectForce2(IntPtr obj, Vector3 force); | ||
960 | |||
961 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
962 | public static extern Vector3 GetTotalForce2(IntPtr obj); | ||
963 | |||
964 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
965 | public static extern Vector3 GetTotalTorque2(IntPtr obj); | ||
966 | |||
967 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
968 | public static extern Vector3 GetInvInertiaDiagLocal2(IntPtr obj); | ||
969 | |||
970 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
971 | public static extern void SetInvInertiaDiagLocal2(IntPtr obj, Vector3 inert); | ||
972 | |||
973 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
974 | public static extern void SetSleepingThresholds2(IntPtr obj, float lin_threshold, float ang_threshold); | ||
975 | |||
976 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
977 | public static extern void ApplyTorque2(IntPtr obj, Vector3 torque); | ||
978 | 477 | ||
979 | // Apply force at the given point. Will add torque to the object. | ||
980 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 478 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
981 | public static extern void ApplyForce2(IntPtr obj, Vector3 force, Vector3 pos); | 479 | public static extern bool SetVelocity2(IntPtr obj, Vector3 velocity); |
982 | 480 | ||
983 | // Apply impulse to the object. Same as "ApplycentralForce" but force scaled by object's mass. | ||
984 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 481 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
985 | public static extern void ApplyCentralImpulse2(IntPtr obj, Vector3 imp); | 482 | public static extern bool SetAngularVelocity2(IntPtr obj, Vector3 angularVelocity); |
986 | 483 | ||
987 | // Apply impulse to the object's torque. Force is scaled by object's mass. | ||
988 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 484 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
989 | public static extern void ApplyTorqueImpulse2(IntPtr obj, Vector3 imp); | 485 | public static extern bool SetObjectForce2(IntPtr obj, Vector3 force); |
990 | 486 | ||
991 | // Apply impulse at the point given. For is scaled by object's mass and effects both linear and angular forces. | ||
992 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 487 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
993 | public static extern void ApplyImpulse2(IntPtr obj, Vector3 imp, Vector3 pos); | 488 | public static extern bool AddObjectForce2(IntPtr obj, Vector3 force); |
994 | 489 | ||
995 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 490 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
996 | public static extern void ClearForces2(IntPtr obj); | 491 | public static extern bool SetCcdMotionThreshold2(IntPtr obj, float val); |
997 | 492 | ||
998 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 493 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
999 | public static extern void ClearAllForces2(IntPtr obj); | 494 | public static extern bool SetCcdSweepSphereRadius2(IntPtr obj, float val); |
1000 | 495 | ||
1001 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 496 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
1002 | public static extern void UpdateInertiaTensor2(IntPtr obj); | 497 | public static extern bool SetDamping2(IntPtr obj, float lin_damping, float ang_damping); |
1003 | 498 | ||
1004 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 499 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
1005 | public static extern Vector3 GetCenterOfMassPosition2(IntPtr obj); | 500 | public static extern bool SetDeactivationTime2(IntPtr obj, float val); |
1006 | 501 | ||
1007 | /* | ||
1008 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 502 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
1009 | public static extern Transform GetCenterOfMassTransform2(IntPtr obj); | 503 | public static extern bool SetSleepingThresholds2(IntPtr obj, float lin_threshold, float ang_threshold); |
1010 | */ | ||
1011 | 504 | ||
1012 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 505 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
1013 | public static extern Vector3 GetLinearVelocity2(IntPtr obj); | 506 | public static extern bool SetContactProcessingThreshold2(IntPtr obj, float val); |
1014 | 507 | ||
1015 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 508 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
1016 | public static extern Vector3 GetAngularVelocity2(IntPtr obj); | 509 | public static extern bool SetFriction2(IntPtr obj, float val); |
1017 | 510 | ||
1018 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 511 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
1019 | public static extern void SetLinearVelocity2(IntPtr obj, Vector3 val); | 512 | public static extern bool SetRestitution2(IntPtr obj, float val); |
1020 | 513 | ||
1021 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 514 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
1022 | public static extern void SetAngularVelocity2(IntPtr obj, Vector3 angularVelocity); | 515 | public static extern bool SetLinearVelocity2(IntPtr obj, Vector3 val); |
1023 | 516 | ||
1024 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 517 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
1025 | public static extern Vector3 GetVelocityInLocalPoint2(IntPtr obj, Vector3 pos); | 518 | public static extern bool SetInterpolation2(IntPtr obj, Vector3 lin, Vector3 ang); |
1026 | 519 | ||
1027 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 520 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
1028 | public static extern void Translate2(IntPtr obj, Vector3 trans); | 521 | public static extern CollisionFlags GetCollisionFlags2(IntPtr obj); |
1029 | |||
1030 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
1031 | public static extern void UpdateDeactivation2(IntPtr obj, float timeStep); | ||
1032 | |||
1033 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
1034 | public static extern bool WantsSleeping2(IntPtr obj); | ||
1035 | |||
1036 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
1037 | public static extern void SetAngularFactor2(IntPtr obj, float factor); | ||
1038 | |||
1039 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
1040 | public static extern void SetAngularFactorV2(IntPtr obj, Vector3 factor); | ||
1041 | |||
1042 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
1043 | public static extern Vector3 GetAngularFactor2(IntPtr obj); | ||
1044 | |||
1045 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
1046 | public static extern bool IsInWorld2(IntPtr obj); | ||
1047 | |||
1048 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
1049 | public static extern void AddConstraintRef2(IntPtr obj, IntPtr constrain); | ||
1050 | |||
1051 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
1052 | public static extern void RemoveConstraintRef2(IntPtr obj, IntPtr constrain); | ||
1053 | |||
1054 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
1055 | public static extern IntPtr GetConstraintRef2(IntPtr obj, int index); | ||
1056 | |||
1057 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
1058 | public static extern int GetNumConstraintRefs2(IntPtr obj); | ||
1059 | |||
1060 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
1061 | public static extern void SetCollisionFilterMask2(IntPtr body, uint filter, uint mask); | ||
1062 | |||
1063 | // ===================================================================================== | ||
1064 | // btCollisionShape entries | ||
1065 | |||
1066 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
1067 | public static extern float GetAngularMotionDisc2(IntPtr shape); | ||
1068 | |||
1069 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
1070 | public static extern float GetContactBreakingThreshold2(IntPtr shape, float defaultFactor); | ||
1071 | |||
1072 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
1073 | public static extern bool IsPolyhedral2(IntPtr shape); | ||
1074 | |||
1075 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
1076 | public static extern bool IsConvex2d2(IntPtr shape); | ||
1077 | |||
1078 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
1079 | public static extern bool IsConvex2(IntPtr shape); | ||
1080 | |||
1081 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
1082 | public static extern bool IsNonMoving2(IntPtr shape); | ||
1083 | |||
1084 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
1085 | public static extern bool IsConcave2(IntPtr shape); | ||
1086 | |||
1087 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
1088 | public static extern bool IsCompound2(IntPtr shape); | ||
1089 | |||
1090 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
1091 | public static extern bool IsSoftBody2(IntPtr shape); | ||
1092 | |||
1093 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
1094 | public static extern bool IsInfinite2(IntPtr shape); | ||
1095 | 522 | ||
1096 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 523 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
1097 | public static extern void SetLocalScaling2(IntPtr shape, Vector3 scale); | 524 | public static extern IntPtr SetCollisionFlags2(IntPtr obj, CollisionFlags flags); |
1098 | 525 | ||
1099 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 526 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
1100 | public static extern Vector3 GetLocalScaling2(IntPtr shape); | 527 | public static extern IntPtr AddToCollisionFlags2(IntPtr obj, CollisionFlags flags); |
1101 | 528 | ||
1102 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 529 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
1103 | public static extern Vector3 CalculateLocalInertia2(IntPtr shape, float mass); | 530 | public static extern IntPtr RemoveFromCollisionFlags2(IntPtr obj, CollisionFlags flags); |
1104 | 531 | ||
1105 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 532 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
1106 | public static extern int GetShapeType2(IntPtr shape); | 533 | public static extern bool SetMassProps2(IntPtr obj, float mass, Vector3 inertia); |
1107 | 534 | ||
1108 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 535 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
1109 | public static extern void SetMargin2(IntPtr shape, float val); | 536 | public static extern bool UpdateInertiaTensor2(IntPtr obj); |
1110 | 537 | ||
1111 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 538 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
1112 | public static extern float GetMargin2(IntPtr shape); | 539 | public static extern bool SetGravity2(IntPtr obj, Vector3 val); |
1113 | 540 | ||
1114 | // ===================================================================================== | ||
1115 | // Debugging | ||
1116 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 541 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
1117 | public static extern void DumpRigidBody2(IntPtr sim, IntPtr collisionObject); | 542 | public static extern IntPtr ClearForces2(IntPtr obj); |
1118 | 543 | ||
1119 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 544 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
1120 | public static extern void DumpCollisionShape2(IntPtr sim, IntPtr collisionShape); | 545 | public static extern IntPtr ClearAllForces2(IntPtr obj); |
1121 | 546 | ||
1122 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 547 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
1123 | public static extern void DumpConstraint2(IntPtr sim, IntPtr constrain); | 548 | public static extern bool SetMargin2(IntPtr obj, float val); |
1124 | 549 | ||
1125 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 550 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
1126 | public static extern void DumpAllInfo2(IntPtr sim); | 551 | public static extern bool UpdateSingleAabb2(IntPtr world, IntPtr obj); |
1127 | 552 | ||
1128 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 553 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
1129 | public static extern void DumpMapInfo2(IntPtr sim, IntPtr manInfo); | 554 | public static extern bool DestroyObject2(IntPtr world, uint id); |
1130 | 555 | ||
1131 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 556 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
1132 | public static extern void DumpPhysicsStatistics2(IntPtr sim); | 557 | public static extern void DumpPhysicsStatistics2(IntPtr sim); |
diff --git a/OpenSim/Region/Physics/Manager/PhysicsActor.cs b/OpenSim/Region/Physics/Manager/PhysicsActor.cs index 5af6373..14f65b8 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsActor.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsActor.cs | |||
@@ -340,12 +340,6 @@ namespace OpenSim.Region.Physics.Manager | |||
340 | /// Getting this returns the velocity calculated by physics scene updates, using factors such as target velocity, | 340 | /// Getting this returns the velocity calculated by physics scene updates, using factors such as target velocity, |
341 | /// time to accelerate and collisions. | 341 | /// time to accelerate and collisions. |
342 | /// </remarks> | 342 | /// </remarks> |
343 | public virtual Vector3 TargetVelocity | ||
344 | { | ||
345 | get { return Velocity; } | ||
346 | set { Velocity = value; } | ||
347 | } | ||
348 | |||
349 | public abstract Vector3 Velocity { get; set; } | 343 | public abstract Vector3 Velocity { get; set; } |
350 | 344 | ||
351 | public abstract Vector3 Torque { get; set; } | 345 | public abstract Vector3 Torque { get; set; } |
diff --git a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs index c736557..f3b0630 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 | internal bool m_avatarplanted = false; | 103 | |
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 && !m_avatarplanted) | 416 | if (value) |
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/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index a59f63f..2e78de5 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | |||
@@ -67,14 +67,6 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
67 | private int m_expectedCollisionContacts = 0; | 67 | private int m_expectedCollisionContacts = 0; |
68 | 68 | ||
69 | /// <summary> | 69 | /// <summary> |
70 | /// Gets collide bits so that we can still perform land collisions if a mesh fails to load. | ||
71 | /// </summary> | ||
72 | private int BadMeshAssetCollideBits | ||
73 | { | ||
74 | get { return m_isphysical ? (int)CollisionCategories.Land : 0; } | ||
75 | } | ||
76 | |||
77 | /// <summary> | ||
78 | /// Is this prim subject to physics? Even if not, it's still solid for collision purposes. | 70 | /// Is this prim subject to physics? Even if not, it's still solid for collision purposes. |
79 | /// </summary> | 71 | /// </summary> |
80 | public override bool IsPhysical | 72 | public override bool IsPhysical |
@@ -164,7 +156,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
164 | 156 | ||
165 | private PrimitiveBaseShape _pbs; | 157 | private PrimitiveBaseShape _pbs; |
166 | private OdeScene _parent_scene; | 158 | private OdeScene _parent_scene; |
167 | 159 | ||
168 | /// <summary> | 160 | /// <summary> |
169 | /// The physics space which contains prim geometries | 161 | /// The physics space which contains prim geometries |
170 | /// </summary> | 162 | /// </summary> |
@@ -3341,6 +3333,7 @@ Console.WriteLine(" JointCreateFixed"); | |||
3341 | m_material = pMaterial; | 3333 | m_material = pMaterial; |
3342 | } | 3334 | } |
3343 | 3335 | ||
3336 | |||
3344 | private void CheckMeshAsset() | 3337 | private void CheckMeshAsset() |
3345 | { | 3338 | { |
3346 | if (_pbs.SculptEntry && !m_assetFailed && _pbs.SculptTexture != UUID.Zero) | 3339 | if (_pbs.SculptEntry && !m_assetFailed && _pbs.SculptTexture != UUID.Zero) |
@@ -3350,14 +3343,14 @@ Console.WriteLine(" JointCreateFixed"); | |||
3350 | { | 3343 | { |
3351 | RequestAssetDelegate assetProvider = _parent_scene.RequestAssetMethod; | 3344 | RequestAssetDelegate assetProvider = _parent_scene.RequestAssetMethod; |
3352 | if (assetProvider != null) | 3345 | if (assetProvider != null) |
3353 | assetProvider(_pbs.SculptTexture, MeshAssetReceived); | 3346 | assetProvider(_pbs.SculptTexture, MeshAssetReveived); |
3354 | }); | 3347 | }); |
3355 | } | 3348 | } |
3356 | } | 3349 | } |
3357 | 3350 | ||
3358 | private void MeshAssetReceived(AssetBase asset) | 3351 | void MeshAssetReveived(AssetBase asset) |
3359 | { | 3352 | { |
3360 | if (asset != null && asset.Data != null && asset.Data.Length > 0) | 3353 | if (asset.Data != null && asset.Data.Length > 0) |
3361 | { | 3354 | { |
3362 | if (!_pbs.SculptEntry) | 3355 | if (!_pbs.SculptEntry) |
3363 | return; | 3356 | return; |
@@ -3370,12 +3363,6 @@ Console.WriteLine(" JointCreateFixed"); | |||
3370 | m_taintshape = true; | 3363 | m_taintshape = true; |
3371 | _parent_scene.AddPhysicsActorTaint(this); | 3364 | _parent_scene.AddPhysicsActorTaint(this); |
3372 | } | 3365 | } |
3373 | else | ||
3374 | { | ||
3375 | m_log.WarnFormat( | ||
3376 | "[ODE PRIM]: Could not get mesh/sculpt asset {0} for {1} at {2} in {3}", | ||
3377 | _pbs.SculptTexture, Name, _position, _parent_scene.Name); | ||
3378 | } | ||
3379 | } | 3366 | } |
3380 | } | 3367 | } |
3381 | } | 3368 | } \ No newline at end of file |
diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs index d53bd90..7a50c4c 100644 --- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs +++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs | |||
@@ -501,8 +501,6 @@ 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; | ||
506 | 504 | ||
507 | public d.Vector3 xyz = new d.Vector3(128.1640f, 128.3079f, 25.7600f); | 505 | public d.Vector3 xyz = new d.Vector3(128.1640f, 128.3079f, 25.7600f); |
508 | public d.Vector3 hpr = new d.Vector3(125.5000f, -17.0000f, 0.0000f); | 506 | public d.Vector3 hpr = new d.Vector3(125.5000f, -17.0000f, 0.0000f); |
@@ -646,9 +644,6 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
646 | avMovementDivisorWalk = physicsconfig.GetFloat("av_movement_divisor_walk", 1.3f); | 644 | avMovementDivisorWalk = physicsconfig.GetFloat("av_movement_divisor_walk", 1.3f); |
647 | avMovementDivisorRun = physicsconfig.GetFloat("av_movement_divisor_run", 0.8f); | 645 | avMovementDivisorRun = physicsconfig.GetFloat("av_movement_divisor_run", 0.8f); |
648 | avCapRadius = physicsconfig.GetFloat("av_capsule_radius", 0.37f); | 646 | 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 | |||
652 | IsAvCapsuleTilted = physicsconfig.GetBoolean("av_capsule_tilted", false); | 647 | IsAvCapsuleTilted = physicsconfig.GetBoolean("av_capsule_tilted", false); |
653 | 648 | ||
654 | contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", 80); | 649 | contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", 80); |
@@ -668,8 +663,6 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
668 | meshSculptLOD = physicsconfig.GetFloat("mesh_lod", 32f); | 663 | meshSculptLOD = physicsconfig.GetFloat("mesh_lod", 32f); |
669 | MeshSculptphysicalLOD = physicsconfig.GetFloat("mesh_physical_lod", 16f); | 664 | MeshSculptphysicalLOD = physicsconfig.GetFloat("mesh_physical_lod", 16f); |
670 | m_filterCollisions = physicsconfig.GetBoolean("filter_collisions", false); | 665 | m_filterCollisions = physicsconfig.GetBoolean("filter_collisions", false); |
671 | |||
672 | |||
673 | 666 | ||
674 | if (Environment.OSVersion.Platform == PlatformID.Unix) | 667 | if (Environment.OSVersion.Platform == PlatformID.Unix) |
675 | { | 668 | { |
@@ -1316,10 +1309,6 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1316 | if ((p1 is OdePrim) && (((OdePrim)p1).m_isVolumeDetect)) | 1309 | if ((p1 is OdePrim) && (((OdePrim)p1).m_isVolumeDetect)) |
1317 | skipThisContact = true; // No collision on volume detect prims | 1310 | skipThisContact = true; // No collision on volume detect prims |
1318 | 1311 | ||
1319 | if (av_av_collisions_off) | ||
1320 | if ((p1 is OdeCharacter) && (p2 is OdeCharacter)) | ||
1321 | skipThisContact = true; | ||
1322 | |||
1323 | if (!skipThisContact && (p2 is OdePrim) && (((OdePrim)p2).m_isVolumeDetect)) | 1312 | if (!skipThisContact && (p2 is OdePrim) && (((OdePrim)p2).m_isVolumeDetect)) |
1324 | skipThisContact = true; // No collision on volume detect prims | 1313 | skipThisContact = true; // No collision on volume detect prims |
1325 | 1314 | ||
@@ -1983,8 +1972,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1983 | 1972 | ||
1984 | newAv.Flying = isFlying; | 1973 | newAv.Flying = isFlying; |
1985 | newAv.MinimumGroundFlightOffset = minimumGroundFlightOffset; | 1974 | newAv.MinimumGroundFlightOffset = minimumGroundFlightOffset; |
1986 | newAv.m_avatarplanted = avplanted; | 1975 | |
1987 | |||
1988 | return newAv; | 1976 | return newAv; |
1989 | } | 1977 | } |
1990 | 1978 | ||
@@ -1999,7 +1987,6 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1999 | 1987 | ||
2000 | internal void AddCharacter(OdeCharacter chr) | 1988 | internal void AddCharacter(OdeCharacter chr) |
2001 | { | 1989 | { |
2002 | chr.m_avatarplanted = avplanted; | ||
2003 | if (!_characters.Contains(chr)) | 1990 | if (!_characters.Contains(chr)) |
2004 | { | 1991 | { |
2005 | _characters.Add(chr); | 1992 | _characters.Add(chr); |
@@ -4320,4 +4307,4 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
4320 | m_stats[ODEPrimUpdateFrameMsStatName] = 0; | 4307 | m_stats[ODEPrimUpdateFrameMsStatName] = 0; |
4321 | } | 4308 | } |
4322 | } | 4309 | } |
4323 | } | 4310 | } \ No newline at end of file |
diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs index 905540d..3144d76 100644 --- a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs +++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs | |||
@@ -39,8 +39,11 @@ using OpenSim.Framework.Console; | |||
39 | using OpenSim.Region.Physics.Manager; | 39 | using OpenSim.Region.Physics.Manager; |
40 | using Mono.Addins; | 40 | using Mono.Addins; |
41 | 41 | ||
42 | [assembly: Addin("RegionCombinerModule", "0.1")] | ||
43 | [assembly: AddinDependency("OpenSim", "0.5")] | ||
42 | namespace OpenSim.Region.RegionCombinerModule | 44 | namespace OpenSim.Region.RegionCombinerModule |
43 | { | 45 | { |
46 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] | ||
44 | public class RegionCombinerModule : ISharedRegionModule, IRegionCombinerModule | 47 | public class RegionCombinerModule : ISharedRegionModule, IRegionCombinerModule |
45 | { | 48 | { |
46 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 49 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
@@ -719,21 +722,21 @@ namespace OpenSim.Region.RegionCombinerModule | |||
719 | rootConn.ClientEventForwarder = new RegionCombinerClientEventForwarder(rootConn); | 722 | rootConn.ClientEventForwarder = new RegionCombinerClientEventForwarder(rootConn); |
720 | 723 | ||
721 | // Sets up the CoarseLocationUpdate forwarder for this root region | 724 | // Sets up the CoarseLocationUpdate forwarder for this root region |
722 | scene.EventManager.OnNewPresence += SetCoarseLocationDelegate; | 725 | scene.EventManager.OnNewPresence += SetCourseLocationDelegate; |
723 | 726 | ||
724 | // Adds this root region to a dictionary of regions that are connectable | 727 | // Adds this root region to a dictionary of regions that are connectable |
725 | m_regions.Add(scene.RegionInfo.originRegionID, rootConn); | 728 | m_regions.Add(scene.RegionInfo.originRegionID, rootConn); |
726 | } | 729 | } |
727 | } | 730 | } |
728 | 731 | ||
729 | private void SetCoarseLocationDelegate(ScenePresence presence) | 732 | private void SetCourseLocationDelegate(ScenePresence presence) |
730 | { | 733 | { |
731 | presence.SetSendCoarseLocationMethod(SendCoarseLocationUpdates); | 734 | presence.SetSendCourseLocationMethod(SendCourseLocationUpdates); |
732 | } | 735 | } |
733 | 736 | ||
734 | // This delegate was refactored for non-combined regions. | 737 | // This delegate was refactored for non-combined regions. |
735 | // This combined region version will not use the pre-compiled lists of locations and ids | 738 | // This combined region version will not use the pre-compiled lists of locations and ids |
736 | private void SendCoarseLocationUpdates(UUID sceneId, ScenePresence presence, List<Vector3> coarseLocations, List<UUID> avatarUUIDs) | 739 | private void SendCourseLocationUpdates(UUID sceneId, ScenePresence presence, List<Vector3> coarseLocations, List<UUID> avatarUUIDs) |
737 | { | 740 | { |
738 | RegionConnections connectiondata = null; | 741 | RegionConnections connectiondata = null; |
739 | lock (m_regions) | 742 | lock (m_regions) |
@@ -756,18 +759,18 @@ namespace OpenSim.Region.RegionCombinerModule | |||
756 | } | 759 | } |
757 | }); | 760 | }); |
758 | 761 | ||
759 | DistributeCoarseLocationUpdates(CoarseLocations, AvatarUUIDs, connectiondata, presence); | 762 | DistributeCourseLocationUpdates(CoarseLocations, AvatarUUIDs, connectiondata, presence); |
760 | } | 763 | } |
761 | 764 | ||
762 | private void DistributeCoarseLocationUpdates(List<Vector3> locations, List<UUID> uuids, | 765 | private void DistributeCourseLocationUpdates(List<Vector3> locations, List<UUID> uuids, |
763 | RegionConnections connectiondata, ScenePresence rootPresence) | 766 | RegionConnections connectiondata, ScenePresence rootPresence) |
764 | { | 767 | { |
765 | RegionData[] rdata = connectiondata.ConnectedRegions.ToArray(); | 768 | RegionData[] rdata = connectiondata.ConnectedRegions.ToArray(); |
766 | //List<IClientAPI> clients = new List<IClientAPI>(); | 769 | //List<IClientAPI> clients = new List<IClientAPI>(); |
767 | Dictionary<Vector2, RegionCoarseLocationStruct> updates = new Dictionary<Vector2, RegionCoarseLocationStruct>(); | 770 | Dictionary<Vector2, RegionCourseLocationStruct> updates = new Dictionary<Vector2, RegionCourseLocationStruct>(); |
768 | 771 | ||
769 | // Root Region entry | 772 | // Root Region entry |
770 | RegionCoarseLocationStruct rootupdatedata = new RegionCoarseLocationStruct(); | 773 | RegionCourseLocationStruct rootupdatedata = new RegionCourseLocationStruct(); |
771 | rootupdatedata.Locations = new List<Vector3>(); | 774 | rootupdatedata.Locations = new List<Vector3>(); |
772 | rootupdatedata.Uuids = new List<UUID>(); | 775 | rootupdatedata.Uuids = new List<UUID>(); |
773 | rootupdatedata.Offset = Vector2.Zero; | 776 | rootupdatedata.Offset = Vector2.Zero; |
@@ -781,7 +784,7 @@ namespace OpenSim.Region.RegionCombinerModule | |||
781 | foreach (RegionData regiondata in rdata) | 784 | foreach (RegionData regiondata in rdata) |
782 | { | 785 | { |
783 | Vector2 offset = new Vector2(regiondata.Offset.X, regiondata.Offset.Y); | 786 | Vector2 offset = new Vector2(regiondata.Offset.X, regiondata.Offset.Y); |
784 | RegionCoarseLocationStruct updatedata = new RegionCoarseLocationStruct(); | 787 | RegionCourseLocationStruct updatedata = new RegionCourseLocationStruct(); |
785 | updatedata.Locations = new List<Vector3>(); | 788 | updatedata.Locations = new List<Vector3>(); |
786 | updatedata.Uuids = new List<UUID>(); | 789 | updatedata.Uuids = new List<UUID>(); |
787 | updatedata.Offset = offset; | 790 | updatedata.Offset = offset; |
@@ -807,7 +810,7 @@ namespace OpenSim.Region.RegionCombinerModule | |||
807 | if (!updates.ContainsKey(offset)) | 810 | if (!updates.ContainsKey(offset)) |
808 | { | 811 | { |
809 | // This shouldn't happen | 812 | // This shouldn't happen |
810 | RegionCoarseLocationStruct updatedata = new RegionCoarseLocationStruct(); | 813 | RegionCourseLocationStruct updatedata = new RegionCourseLocationStruct(); |
811 | updatedata.Locations = new List<Vector3>(); | 814 | updatedata.Locations = new List<Vector3>(); |
812 | updatedata.Uuids = new List<UUID>(); | 815 | updatedata.Uuids = new List<UUID>(); |
813 | updatedata.Offset = offset; | 816 | updatedata.Offset = offset; |
diff --git a/OpenSim/Region/RegionCombinerModule/RegionCourseLocation.cs b/OpenSim/Region/RegionCombinerModule/RegionCourseLocation.cs index 224ac99..53a678f 100644 --- a/OpenSim/Region/RegionCombinerModule/RegionCourseLocation.cs +++ b/OpenSim/Region/RegionCombinerModule/RegionCourseLocation.cs | |||
@@ -33,7 +33,7 @@ using OpenSim.Framework; | |||
33 | namespace OpenSim.Region.RegionCombinerModule | 33 | namespace OpenSim.Region.RegionCombinerModule |
34 | { | 34 | { |
35 | 35 | ||
36 | struct RegionCoarseLocationStruct | 36 | struct RegionCourseLocationStruct |
37 | { | 37 | { |
38 | public List<Vector3> Locations; | 38 | public List<Vector3> Locations; |
39 | public List<UUID> Uuids; | 39 | public List<UUID> Uuids; |
diff --git a/OpenSim/Region/RegionCombinerModule/Resources/RegionCombinerModule.addin.xml b/OpenSim/Region/RegionCombinerModule/Resources/RegionCombinerModule.addin.xml deleted file mode 100644 index 13cb8b6..0000000 --- a/OpenSim/Region/RegionCombinerModule/Resources/RegionCombinerModule.addin.xml +++ /dev/null | |||
@@ -1,14 +0,0 @@ | |||
1 | <Addin id="OpenSim.RegionModules.RegionCombinerModule" version="0.3"> | ||
2 | <Runtime> | ||
3 | <Import assembly="OpenSim.Region.RegionCombinerModule.dll"/> | ||
4 | </Runtime> | ||
5 | |||
6 | <Dependencies> | ||
7 | <Addin id="OpenSim" version="0.5" /> | ||
8 | </Dependencies> | ||
9 | |||
10 | <Extension path = "/OpenSim/RegionModules"> | ||
11 | <RegionModule id="RegionCombinerModule" type="OpenSim.Region.RegionCombinerModule.RegionCombinerModule" /> | ||
12 | </Extension> | ||
13 | |||
14 | </Addin> | ||
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 3bbdbe8..82de06f 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | |||
@@ -59,7 +59,6 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion; | |||
59 | using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; | 59 | using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; |
60 | using PrimType = OpenSim.Region.Framework.Scenes.PrimType; | 60 | using PrimType = OpenSim.Region.Framework.Scenes.PrimType; |
61 | using AssetLandmark = OpenSim.Framework.AssetLandmark; | 61 | using AssetLandmark = OpenSim.Framework.AssetLandmark; |
62 | using RegionFlags = OpenSim.Framework.RegionFlags; | ||
63 | 62 | ||
64 | using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; | 63 | using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; |
65 | using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; | 64 | using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; |
@@ -113,7 +112,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
113 | protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache = | 112 | protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache = |
114 | new Dictionary<UUID, UserInfoCacheEntry>(); | 113 | new Dictionary<UUID, UserInfoCacheEntry>(); |
115 | protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp. | 114 | protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp. |
116 | protected ISoundModule m_SoundModule = null; | ||
117 | 115 | ||
118 | // protected Timer m_ShoutSayTimer; | 116 | // protected Timer m_ShoutSayTimer; |
119 | protected int m_SayShoutCount = 0; | 117 | protected int m_SayShoutCount = 0; |
@@ -161,7 +159,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
161 | m_TransferModule = | 159 | m_TransferModule = |
162 | m_ScriptEngine.World.RequestModuleInterface<IMessageTransferModule>(); | 160 | m_ScriptEngine.World.RequestModuleInterface<IMessageTransferModule>(); |
163 | m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>(); | 161 | m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>(); |
164 | m_SoundModule = m_ScriptEngine.World.RequestModuleInterface<ISoundModule>(); | ||
165 | 162 | ||
166 | AsyncCommands = new AsyncCommandManager(ScriptEngine); | 163 | AsyncCommands = new AsyncCommandManager(ScriptEngine); |
167 | } | 164 | } |
@@ -344,7 +341,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
344 | return GetLinkParts(m_host, linkType); | 341 | return GetLinkParts(m_host, linkType); |
345 | } | 342 | } |
346 | 343 | ||
347 | public static List<SceneObjectPart> GetLinkParts(SceneObjectPart part, int linkType) | 344 | private List<SceneObjectPart> GetLinkParts(SceneObjectPart part, int linkType) |
348 | { | 345 | { |
349 | List<SceneObjectPart> ret = new List<SceneObjectPart>(); | 346 | List<SceneObjectPart> ret = new List<SceneObjectPart>(); |
350 | if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) | 347 | if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) |
@@ -429,40 +426,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
429 | return key; | 426 | return key; |
430 | } | 427 | } |
431 | 428 | ||
432 | /// <summary> | 429 | // convert a LSL_Rotation to a Quaternion |
433 | /// Return the UUID of the asset matching the specified key or name | 430 | public static Quaternion Rot2Quaternion(LSL_Rotation r) |
434 | /// and asset type. | ||
435 | /// </summary> | ||
436 | /// <param name="k"></param> | ||
437 | /// <param name="type"></param> | ||
438 | /// <returns></returns> | ||
439 | protected UUID KeyOrName(string k, AssetType type) | ||
440 | { | 431 | { |
441 | UUID key; | 432 | Quaternion q = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s); |
442 | 433 | q.Normalize(); | |
443 | if (!UUID.TryParse(k, out key)) | 434 | return q; |
444 | { | ||
445 | TaskInventoryItem item = m_host.Inventory.GetInventoryItem(k); | ||
446 | if (item != null && item.Type == (int)type) | ||
447 | key = item.AssetID; | ||
448 | } | ||
449 | else | ||
450 | { | ||
451 | lock (m_host.TaskInventory) | ||
452 | { | ||
453 | foreach (KeyValuePair<UUID, TaskInventoryItem> item in m_host.TaskInventory) | ||
454 | { | ||
455 | if (item.Value.Type == (int)type && item.Value.Name == k) | ||
456 | { | ||
457 | key = item.Value.ItemID; | ||
458 | break; | ||
459 | } | ||
460 | } | ||
461 | } | ||
462 | } | ||
463 | |||
464 | |||
465 | return key; | ||
466 | } | 435 | } |
467 | 436 | ||
468 | //These are the implementations of the various ll-functions used by the LSL scripts. | 437 | //These are the implementations of the various ll-functions used by the LSL scripts. |
@@ -1271,7 +1240,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
1271 | public LSL_Float llGround(LSL_Vector offset) | 1240 | public LSL_Float llGround(LSL_Vector offset) |
1272 | { | 1241 | { |
1273 | m_host.AddScriptLPS(1); | 1242 | m_host.AddScriptLPS(1); |
1274 | Vector3 pos = m_host.GetWorldPosition() + (Vector3)offset; | 1243 | Vector3 pos = m_host.GetWorldPosition() + new Vector3((float)offset.x, |
1244 | (float)offset.y, | ||
1245 | (float)offset.z); | ||
1275 | 1246 | ||
1276 | //Get the slope normal. This gives us the equation of the plane tangent to the slope. | 1247 | //Get the slope normal. This gives us the equation of the plane tangent to the slope. |
1277 | LSL_Vector vsn = llGroundNormal(offset); | 1248 | LSL_Vector vsn = llGroundNormal(offset); |
@@ -1521,22 +1492,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
1521 | if (part == null || part.ParentGroup.IsDeleted) | 1492 | if (part == null || part.ParentGroup.IsDeleted) |
1522 | return; | 1493 | return; |
1523 | 1494 | ||
1524 | // First we need to check whether or not we need to clamp the size of a physics-enabled prim | 1495 | if (scale.x < 0.01) |
1496 | scale.x = 0.01; | ||
1497 | if (scale.y < 0.01) | ||
1498 | scale.y = 0.01; | ||
1499 | if (scale.z < 0.01) | ||
1500 | scale.z = 0.01; | ||
1501 | |||
1525 | PhysicsActor pa = part.ParentGroup.RootPart.PhysActor; | 1502 | PhysicsActor pa = part.ParentGroup.RootPart.PhysActor; |
1503 | |||
1526 | if (pa != null && pa.IsPhysical) | 1504 | if (pa != null && pa.IsPhysical) |
1527 | { | 1505 | { |
1528 | scale.x = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.x)); | 1506 | if (scale.x > World.m_maxPhys) |
1529 | scale.y = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.y)); | 1507 | scale.x = World.m_maxPhys; |
1530 | scale.z = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.z)); | 1508 | if (scale.y > World.m_maxPhys) |
1531 | } | 1509 | scale.y = World.m_maxPhys; |
1532 | else | 1510 | if (scale.z > World.m_maxPhys) |
1533 | { | 1511 | scale.z = World.m_maxPhys; |
1534 | // If not physical, then we clamp the scale to the non-physical min/max | ||
1535 | scale.x = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.x)); | ||
1536 | scale.y = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.y)); | ||
1537 | scale.z = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.z)); | ||
1538 | } | 1512 | } |
1539 | 1513 | ||
1514 | if (scale.x > World.m_maxNonphys) | ||
1515 | scale.x = World.m_maxNonphys; | ||
1516 | if (scale.y > World.m_maxNonphys) | ||
1517 | scale.y = World.m_maxNonphys; | ||
1518 | if (scale.z > World.m_maxNonphys) | ||
1519 | scale.z = World.m_maxNonphys; | ||
1520 | |||
1540 | Vector3 tmp = part.Scale; | 1521 | Vector3 tmp = part.Scale; |
1541 | tmp.X = (float)scale.x; | 1522 | tmp.X = (float)scale.x; |
1542 | tmp.Y = (float)scale.y; | 1523 | tmp.Y = (float)scale.y; |
@@ -1609,7 +1590,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
1609 | if (face == ScriptBaseClass.ALL_SIDES) | 1590 | if (face == ScriptBaseClass.ALL_SIDES) |
1610 | face = SceneObjectPart.ALL_SIDES; | 1591 | face = SceneObjectPart.ALL_SIDES; |
1611 | 1592 | ||
1612 | m_host.SetFaceColorAlpha(face, color, null); | 1593 | m_host.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); |
1613 | } | 1594 | } |
1614 | 1595 | ||
1615 | public void SetTexGen(SceneObjectPart part, int face,int style) | 1596 | public void SetTexGen(SceneObjectPart part, int face,int style) |
@@ -2221,7 +2202,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2221 | pos.x > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a east-adjacent region. | 2202 | pos.x > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a east-adjacent region. |
2222 | pos.y < -10.0 || // return FALSE if more than 10 meters into a south-adjacent region. | 2203 | pos.y < -10.0 || // return FALSE if more than 10 meters into a south-adjacent region. |
2223 | pos.y > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a north-adjacent region. | 2204 | pos.y > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a north-adjacent region. |
2224 | pos.z > Constants.RegionHeight // return FALSE if altitude than 4096m | 2205 | pos.z > 4096 // return FALSE if altitude than 4096m |
2225 | ) | 2206 | ) |
2226 | ) | 2207 | ) |
2227 | { | 2208 | { |
@@ -2232,15 +2213,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2232 | // this could possibly be done in the above else-if block, but we're doing the check here to keep the code easier to read. | 2213 | // this could possibly be done in the above else-if block, but we're doing the check here to keep the code easier to read. |
2233 | 2214 | ||
2234 | Vector3 objectPos = m_host.ParentGroup.RootPart.AbsolutePosition; | 2215 | Vector3 objectPos = m_host.ParentGroup.RootPart.AbsolutePosition; |
2235 | LandData here = World.GetLandData(objectPos); | 2216 | LandData here = World.GetLandData((float)objectPos.X, (float)objectPos.Y); |
2236 | LandData there = World.GetLandData(pos); | 2217 | LandData there = World.GetLandData((float)pos.x, (float)pos.y); |
2237 | 2218 | ||
2238 | // we're only checking prim limits if it's moving to a different parcel under the assumption that if the object got onto the parcel without exceeding the prim limits. | 2219 | // we're only checking prim limits if it's moving to a different parcel under the assumption that if the object got onto the parcel without exceeding the prim limits. |
2239 | 2220 | ||
2240 | bool sameParcel = here.GlobalID == there.GlobalID; | 2221 | bool sameParcel = here.GlobalID == there.GlobalID; |
2241 | 2222 | ||
2242 | if (!sameParcel && !World.Permissions.CanRezObject( | 2223 | if (!sameParcel && !World.Permissions.CanObjectEntry(m_host.UUID, false, new Vector3((float)pos.x, (float)pos.y, (float)pos.z))) |
2243 | m_host.ParentGroup.PrimCount, m_host.ParentGroup.OwnerID, pos)) | ||
2244 | { | 2224 | { |
2245 | return 0; | 2225 | return 0; |
2246 | } | 2226 | } |
@@ -2299,15 +2279,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2299 | if (part.ParentGroup.RootPart == part) | 2279 | if (part.ParentGroup.RootPart == part) |
2300 | { | 2280 | { |
2301 | SceneObjectGroup parent = part.ParentGroup; | 2281 | SceneObjectGroup parent = part.ParentGroup; |
2302 | if (!World.Permissions.CanObjectEntry(parent.UUID, false, (Vector3)toPos)) | 2282 | Vector3 dest = new Vector3((float)toPos.x, (float)toPos.y, (float)toPos.z); |
2283 | if (!World.Permissions.CanObjectEntry(parent.UUID, false, dest)) | ||
2303 | return; | 2284 | return; |
2304 | Util.FireAndForget(delegate(object x) { | 2285 | Util.FireAndForget(delegate(object x) { |
2305 | parent.UpdateGroupPosition((Vector3)toPos); | 2286 | parent.UpdateGroupPosition(dest); |
2306 | }); | 2287 | }); |
2307 | } | 2288 | } |
2308 | else | 2289 | else |
2309 | { | 2290 | { |
2310 | part.OffsetPosition = (Vector3)toPos; | 2291 | part.OffsetPosition = new Vector3((float)toPos.x, (float)toPos.y, (float)toPos.z); |
2311 | SceneObjectGroup parent = part.ParentGroup; | 2292 | SceneObjectGroup parent = part.ParentGroup; |
2312 | parent.HasGroupChanged = true; | 2293 | parent.HasGroupChanged = true; |
2313 | parent.ScheduleGroupForTerseUpdate(); | 2294 | parent.ScheduleGroupForTerseUpdate(); |
@@ -2317,7 +2298,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2317 | public LSL_Vector llGetPos() | 2298 | public LSL_Vector llGetPos() |
2318 | { | 2299 | { |
2319 | m_host.AddScriptLPS(1); | 2300 | m_host.AddScriptLPS(1); |
2320 | return m_host.GetWorldPosition(); | 2301 | Vector3 pos = m_host.GetWorldPosition(); |
2302 | return new LSL_Vector(pos.X, pos.Y, pos.Z); | ||
2321 | } | 2303 | } |
2322 | 2304 | ||
2323 | public LSL_Vector llGetLocalPos() | 2305 | public LSL_Vector llGetLocalPos() |
@@ -2344,9 +2326,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2344 | pos = part.AbsolutePosition; | 2326 | pos = part.AbsolutePosition; |
2345 | } | 2327 | } |
2346 | 2328 | ||
2347 | // m_log.DebugFormat("[LSL API]: Returning {0} in GetPartLocalPos()", pos); | 2329 | return new LSL_Vector(pos.X, pos.Y, pos.Z); |
2348 | |||
2349 | return new LSL_Vector(pos); | ||
2350 | } | 2330 | } |
2351 | 2331 | ||
2352 | public void llSetRot(LSL_Rotation rot) | 2332 | public void llSetRot(LSL_Rotation rot) |
@@ -2354,18 +2334,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2354 | m_host.AddScriptLPS(1); | 2334 | m_host.AddScriptLPS(1); |
2355 | 2335 | ||
2356 | // try to let this work as in SL... | 2336 | // try to let this work as in SL... |
2357 | if (m_host.ParentID == 0) | 2337 | if (m_host.LinkNum < 2) |
2358 | { | 2338 | { |
2359 | // special case: If we are root, rotate complete SOG to new rotation | 2339 | // Special case: If we are root, rotate complete SOG to new |
2360 | SetRot(m_host, rot); | 2340 | // rotation. |
2341 | // We are root if the link number is 0 (single prim) or 1 | ||
2342 | // (root prim). ParentID may be nonzero in attachments and | ||
2343 | // using it would cause attachments and HUDs to rotate | ||
2344 | // to the wrong positions. | ||
2345 | |||
2346 | SetRot(m_host, Rot2Quaternion(rot)); | ||
2361 | } | 2347 | } |
2362 | else | 2348 | else |
2363 | { | 2349 | { |
2364 | // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask. | 2350 | // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask. |
2365 | SceneObjectPart rootPart = m_host.ParentGroup.RootPart; | 2351 | SceneObjectPart rootPart; |
2366 | if (rootPart != null) // better safe than sorry | 2352 | if (m_host.ParentGroup != null) // better safe than sorry |
2367 | { | 2353 | { |
2368 | SetRot(m_host, rootPart.RotationOffset * (Quaternion)rot); | 2354 | rootPart = m_host.ParentGroup.RootPart; |
2355 | if (rootPart != null) | ||
2356 | SetRot(m_host, rootPart.RotationOffset * Rot2Quaternion(rot)); | ||
2369 | } | 2357 | } |
2370 | } | 2358 | } |
2371 | 2359 | ||
@@ -2375,7 +2363,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2375 | public void llSetLocalRot(LSL_Rotation rot) | 2363 | public void llSetLocalRot(LSL_Rotation rot) |
2376 | { | 2364 | { |
2377 | m_host.AddScriptLPS(1); | 2365 | m_host.AddScriptLPS(1); |
2378 | SetRot(m_host, rot); | 2366 | |
2367 | SetRot(m_host, Rot2Quaternion(rot)); | ||
2379 | ScriptSleep(200); | 2368 | ScriptSleep(200); |
2380 | } | 2369 | } |
2381 | 2370 | ||
@@ -2487,7 +2476,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2487 | if (local != 0) | 2476 | if (local != 0) |
2488 | force *= llGetRot(); | 2477 | force *= llGetRot(); |
2489 | 2478 | ||
2490 | m_host.ParentGroup.RootPart.SetForce(force); | 2479 | m_host.ParentGroup.RootPart.SetForce(new Vector3((float)force.x, (float)force.y, (float)force.z)); |
2491 | } | 2480 | } |
2492 | } | 2481 | } |
2493 | 2482 | ||
@@ -2499,7 +2488,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2499 | 2488 | ||
2500 | if (!m_host.ParentGroup.IsDeleted) | 2489 | if (!m_host.ParentGroup.IsDeleted) |
2501 | { | 2490 | { |
2502 | force = m_host.ParentGroup.RootPart.GetForce(); | 2491 | Vector3 tmpForce = m_host.ParentGroup.RootPart.GetForce(); |
2492 | force.x = tmpForce.X; | ||
2493 | force.y = tmpForce.Y; | ||
2494 | force.z = tmpForce.Z; | ||
2503 | } | 2495 | } |
2504 | 2496 | ||
2505 | return force; | 2497 | return force; |
@@ -2508,8 +2500,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2508 | public LSL_Integer llTarget(LSL_Vector position, double range) | 2500 | public LSL_Integer llTarget(LSL_Vector position, double range) |
2509 | { | 2501 | { |
2510 | m_host.AddScriptLPS(1); | 2502 | m_host.AddScriptLPS(1); |
2511 | return m_host.ParentGroup.registerTargetWaypoint(position, | 2503 | return m_host.ParentGroup.registerTargetWaypoint( |
2512 | (float)range); | 2504 | new Vector3((float)position.x, (float)position.y, (float)position.z), (float)range); |
2513 | } | 2505 | } |
2514 | 2506 | ||
2515 | public void llTargetRemove(int number) | 2507 | public void llTargetRemove(int number) |
@@ -2521,7 +2513,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2521 | public LSL_Integer llRotTarget(LSL_Rotation rot, double error) | 2513 | public LSL_Integer llRotTarget(LSL_Rotation rot, double error) |
2522 | { | 2514 | { |
2523 | m_host.AddScriptLPS(1); | 2515 | m_host.AddScriptLPS(1); |
2524 | return m_host.ParentGroup.registerRotTargetWaypoint(rot, (float)error); | 2516 | return m_host.ParentGroup.registerRotTargetWaypoint( |
2517 | new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s), (float)error); | ||
2525 | } | 2518 | } |
2526 | 2519 | ||
2527 | public void llRotTargetRemove(int number) | 2520 | public void llRotTargetRemove(int number) |
@@ -2533,7 +2526,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2533 | public void llMoveToTarget(LSL_Vector target, double tau) | 2526 | public void llMoveToTarget(LSL_Vector target, double tau) |
2534 | { | 2527 | { |
2535 | m_host.AddScriptLPS(1); | 2528 | m_host.AddScriptLPS(1); |
2536 | m_host.MoveToTarget(target, (float)tau); | 2529 | m_host.MoveToTarget(new Vector3((float)target.x, (float)target.y, (float)target.z), (float)tau); |
2537 | } | 2530 | } |
2538 | 2531 | ||
2539 | public void llStopMoveToTarget() | 2532 | public void llStopMoveToTarget() |
@@ -2546,7 +2539,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2546 | { | 2539 | { |
2547 | m_host.AddScriptLPS(1); | 2540 | m_host.AddScriptLPS(1); |
2548 | //No energy force yet | 2541 | //No energy force yet |
2549 | Vector3 v = force; | 2542 | Vector3 v = new Vector3((float)force.x, (float)force.y, (float)force.z); |
2550 | if (v.Length() > 20000.0f) | 2543 | if (v.Length() > 20000.0f) |
2551 | { | 2544 | { |
2552 | v.Normalize(); | 2545 | v.Normalize(); |
@@ -2559,13 +2552,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2559 | public void llApplyRotationalImpulse(LSL_Vector force, int local) | 2552 | public void llApplyRotationalImpulse(LSL_Vector force, int local) |
2560 | { | 2553 | { |
2561 | m_host.AddScriptLPS(1); | 2554 | m_host.AddScriptLPS(1); |
2562 | m_host.ParentGroup.RootPart.ApplyAngularImpulse(force, local != 0); | 2555 | m_host.ParentGroup.RootPart.ApplyAngularImpulse(new Vector3((float)force.x, (float)force.y, (float)force.z), local != 0); |
2563 | } | 2556 | } |
2564 | 2557 | ||
2565 | public void llSetTorque(LSL_Vector torque, int local) | 2558 | public void llSetTorque(LSL_Vector torque, int local) |
2566 | { | 2559 | { |
2567 | m_host.AddScriptLPS(1); | 2560 | m_host.AddScriptLPS(1); |
2568 | m_host.ParentGroup.RootPart.SetAngularImpulse(torque, local != 0); | 2561 | m_host.ParentGroup.RootPart.SetAngularImpulse(new Vector3((float)torque.x, (float)torque.y, (float)torque.z), local != 0); |
2569 | } | 2562 | } |
2570 | 2563 | ||
2571 | public LSL_Vector llGetTorque() | 2564 | public LSL_Vector llGetTorque() |
@@ -2675,32 +2668,63 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2675 | m_host.AddScriptLPS(1); | 2668 | m_host.AddScriptLPS(1); |
2676 | 2669 | ||
2677 | // send the sound, once, to all clients in range | 2670 | // send the sound, once, to all clients in range |
2678 | if (m_SoundModule != null) | 2671 | m_host.SendSound(KeyOrName(sound).ToString(), volume, false, 0, 0, false, false); |
2679 | { | ||
2680 | m_SoundModule.SendSound(m_host.UUID, | ||
2681 | KeyOrName(sound, AssetType.Sound), volume, false, 0, | ||
2682 | 0, false, false); | ||
2683 | } | ||
2684 | } | 2672 | } |
2685 | 2673 | ||
2674 | // Xantor 20080528 we should do this differently. | ||
2675 | // 1) apply the sound to the object | ||
2676 | // 2) schedule full update | ||
2677 | // just sending the sound out once doesn't work so well when other avatars come in view later on | ||
2678 | // or when the prim gets moved, changed, sat on, whatever | ||
2679 | // see large number of mantises (mantes?) | ||
2680 | // 20080530 Updated to remove code duplication | ||
2681 | // 20080530 Stop sound if there is one, otherwise volume only changes don't work | ||
2686 | public void llLoopSound(string sound, double volume) | 2682 | public void llLoopSound(string sound, double volume) |
2687 | { | 2683 | { |
2688 | m_host.AddScriptLPS(1); | 2684 | m_host.AddScriptLPS(1); |
2689 | if (m_SoundModule != null) | 2685 | |
2690 | { | 2686 | if (m_host.Sound != UUID.Zero) |
2691 | m_SoundModule.LoopSound(m_host.UUID, KeyOrName(sound), | 2687 | llStopSound(); |
2692 | volume, 20, false); | 2688 | |
2693 | } | 2689 | m_host.Sound = KeyOrName(sound); |
2690 | m_host.SoundGain = volume; | ||
2691 | m_host.SoundFlags = 1; // looping | ||
2692 | m_host.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable? | ||
2693 | |||
2694 | m_host.ScheduleFullUpdate(); | ||
2695 | m_host.SendFullUpdateToAllClients(); | ||
2694 | } | 2696 | } |
2695 | 2697 | ||
2696 | public void llLoopSoundMaster(string sound, double volume) | 2698 | public void llLoopSoundMaster(string sound, double volume) |
2697 | { | 2699 | { |
2698 | m_host.AddScriptLPS(1); | 2700 | m_host.AddScriptLPS(1); |
2699 | if (m_SoundModule != null) | 2701 | m_host.ParentGroup.LoopSoundMasterPrim = m_host; |
2702 | lock (m_host.ParentGroup.LoopSoundSlavePrims) | ||
2700 | { | 2703 | { |
2701 | m_SoundModule.LoopSound(m_host.UUID, KeyOrName(sound), | 2704 | foreach (SceneObjectPart prim in m_host.ParentGroup.LoopSoundSlavePrims) |
2702 | volume, 20, true); | 2705 | { |
2706 | if (prim.Sound != UUID.Zero) | ||
2707 | llStopSound(); | ||
2708 | |||
2709 | prim.Sound = KeyOrName(sound); | ||
2710 | prim.SoundGain = volume; | ||
2711 | prim.SoundFlags = 1; // looping | ||
2712 | prim.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable? | ||
2713 | |||
2714 | prim.ScheduleFullUpdate(); | ||
2715 | prim.SendFullUpdateToAllClients(); | ||
2716 | } | ||
2703 | } | 2717 | } |
2718 | if (m_host.Sound != UUID.Zero) | ||
2719 | llStopSound(); | ||
2720 | |||
2721 | m_host.Sound = KeyOrName(sound); | ||
2722 | m_host.SoundGain = volume; | ||
2723 | m_host.SoundFlags = 1; // looping | ||
2724 | m_host.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable? | ||
2725 | |||
2726 | m_host.ScheduleFullUpdate(); | ||
2727 | m_host.SendFullUpdateToAllClients(); | ||
2704 | } | 2728 | } |
2705 | 2729 | ||
2706 | public void llLoopSoundSlave(string sound, double volume) | 2730 | public void llLoopSoundSlave(string sound, double volume) |
@@ -2717,39 +2741,61 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2717 | m_host.AddScriptLPS(1); | 2741 | m_host.AddScriptLPS(1); |
2718 | 2742 | ||
2719 | // send the sound, once, to all clients in range | 2743 | // send the sound, once, to all clients in range |
2720 | if (m_SoundModule != null) | 2744 | m_host.SendSound(KeyOrName(sound).ToString(), volume, false, 0, 0, true, false); |
2721 | { | ||
2722 | m_SoundModule.SendSound(m_host.UUID, | ||
2723 | KeyOrName(sound, AssetType.Sound), volume, false, 0, | ||
2724 | 0, true, false); | ||
2725 | } | ||
2726 | } | 2745 | } |
2727 | 2746 | ||
2728 | public void llTriggerSound(string sound, double volume) | 2747 | public void llTriggerSound(string sound, double volume) |
2729 | { | 2748 | { |
2730 | m_host.AddScriptLPS(1); | 2749 | m_host.AddScriptLPS(1); |
2731 | // send the sound, once, to all clients in rangeTrigger or play an attached sound in this part's inventory. | 2750 | // send the sound, once, to all clients in range |
2732 | if (m_SoundModule != null) | 2751 | m_host.SendSound(KeyOrName(sound).ToString(), volume, true, 0, 0, false, false); |
2733 | { | ||
2734 | m_SoundModule.SendSound(m_host.UUID, | ||
2735 | KeyOrName(sound, AssetType.Sound), volume, true, 0, 0, | ||
2736 | false, false); | ||
2737 | } | ||
2738 | } | 2752 | } |
2739 | 2753 | ||
2754 | // Xantor 20080528: Clear prim data of sound instead | ||
2740 | public void llStopSound() | 2755 | public void llStopSound() |
2741 | { | 2756 | { |
2742 | m_host.AddScriptLPS(1); | 2757 | m_host.AddScriptLPS(1); |
2743 | 2758 | if (m_host.ParentGroup.LoopSoundSlavePrims.Contains(m_host)) | |
2744 | if (m_SoundModule != null) | 2759 | { |
2745 | m_SoundModule.StopSound(m_host.UUID); | 2760 | if (m_host.ParentGroup.LoopSoundMasterPrim == m_host) |
2761 | { | ||
2762 | foreach (SceneObjectPart part in m_host.ParentGroup.LoopSoundSlavePrims) | ||
2763 | { | ||
2764 | part.Sound = UUID.Zero; | ||
2765 | part.SoundGain = 0; | ||
2766 | part.SoundFlags = 0; | ||
2767 | part.SoundRadius = 0; | ||
2768 | part.ScheduleFullUpdate(); | ||
2769 | part.SendFullUpdateToAllClients(); | ||
2770 | } | ||
2771 | m_host.ParentGroup.LoopSoundMasterPrim = null; | ||
2772 | m_host.ParentGroup.LoopSoundSlavePrims.Clear(); | ||
2773 | } | ||
2774 | else | ||
2775 | { | ||
2776 | m_host.Sound = UUID.Zero; | ||
2777 | m_host.SoundGain = 0; | ||
2778 | m_host.SoundFlags = 0; | ||
2779 | m_host.SoundRadius = 0; | ||
2780 | m_host.ScheduleFullUpdate(); | ||
2781 | m_host.SendFullUpdateToAllClients(); | ||
2782 | } | ||
2783 | } | ||
2784 | else | ||
2785 | { | ||
2786 | m_host.Sound = UUID.Zero; | ||
2787 | m_host.SoundGain = 0; | ||
2788 | m_host.SoundFlags = 0; | ||
2789 | m_host.SoundRadius = 0; | ||
2790 | m_host.ScheduleFullUpdate(); | ||
2791 | m_host.SendFullUpdateToAllClients(); | ||
2792 | } | ||
2746 | } | 2793 | } |
2747 | 2794 | ||
2748 | public void llPreloadSound(string sound) | 2795 | public void llPreloadSound(string sound) |
2749 | { | 2796 | { |
2750 | m_host.AddScriptLPS(1); | 2797 | m_host.AddScriptLPS(1); |
2751 | if (m_SoundModule != null) | 2798 | m_host.PreloadSound(sound); |
2752 | m_SoundModule.PreloadSound(m_host.UUID, KeyOrName(sound), 0); | ||
2753 | ScriptSleep(1000); | 2799 | ScriptSleep(1000); |
2754 | } | 2800 | } |
2755 | 2801 | ||
@@ -3077,10 +3123,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3077 | return; | 3123 | return; |
3078 | } | 3124 | } |
3079 | 3125 | ||
3126 | Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z); | ||
3127 | Vector3 llvel = new Vector3((float)vel.x, (float)vel.y, (float)vel.z); | ||
3128 | |||
3080 | // need the magnitude later | 3129 | // need the magnitude later |
3081 | // float velmag = (float)Util.GetMagnitude(llvel); | 3130 | // float velmag = (float)Util.GetMagnitude(llvel); |
3082 | 3131 | ||
3083 | SceneObjectGroup new_group = World.RezObject(m_host, item, pos, rot, vel, param); | 3132 | SceneObjectGroup new_group = World.RezObject(m_host, item, llpos, Rot2Quaternion(rot), llvel, param); |
3084 | 3133 | ||
3085 | // If either of these are null, then there was an unknown error. | 3134 | // If either of these are null, then there was an unknown error. |
3086 | if (new_group == null) | 3135 | if (new_group == null) |
@@ -3107,11 +3156,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3107 | 3156 | ||
3108 | PhysicsActor pa = new_group.RootPart.PhysActor; | 3157 | PhysicsActor pa = new_group.RootPart.PhysActor; |
3109 | 3158 | ||
3110 | if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero) | 3159 | if (pa != null && pa.IsPhysical && llvel != Vector3.Zero) |
3111 | { | 3160 | { |
3112 | float groupmass = new_group.GetMass(); | 3161 | float groupmass = new_group.GetMass(); |
3113 | vel *= -groupmass; | 3162 | llvel *= -groupmass; |
3114 | llApplyImpulse(vel, 0); | 3163 | llApplyImpulse(new LSL_Vector(llvel.X, llvel.Y,llvel.Z), 0); |
3115 | } | 3164 | } |
3116 | // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay) | 3165 | // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay) |
3117 | return; | 3166 | return; |
@@ -3162,7 +3211,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3162 | return; | 3211 | return; |
3163 | } | 3212 | } |
3164 | 3213 | ||
3165 | m_host.StartLookAt((Quaternion)(r3 * r2 * r1), (float)strength, (float)damping); | 3214 | m_host.StartLookAt(Rot2Quaternion(r3 * r2 * r1), (float)strength, (float)damping); |
3166 | } | 3215 | } |
3167 | } | 3216 | } |
3168 | 3217 | ||
@@ -3588,7 +3637,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3588 | } | 3637 | } |
3589 | else | 3638 | else |
3590 | { | 3639 | { |
3591 | m_host.RotLookAt(target, (float)strength, (float)damping); | 3640 | m_host.RotLookAt(Rot2Quaternion(target), (float)strength, (float)damping); |
3592 | } | 3641 | } |
3593 | } | 3642 | } |
3594 | 3643 | ||
@@ -3669,7 +3718,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3669 | 3718 | ||
3670 | protected void TargetOmega(SceneObjectPart part, LSL_Vector axis, double spinrate, double gain) | 3719 | protected void TargetOmega(SceneObjectPart part, LSL_Vector axis, double spinrate, double gain) |
3671 | { | 3720 | { |
3672 | part.UpdateAngularVelocity(axis * spinrate); | 3721 | part.UpdateAngularVelocity(new Vector3((float)(axis.x * spinrate), (float)(axis.y * spinrate), (float)(axis.z * spinrate))); |
3673 | } | 3722 | } |
3674 | 3723 | ||
3675 | public LSL_Integer llGetStartParameter() | 3724 | public LSL_Integer llGetStartParameter() |
@@ -3883,7 +3932,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3883 | try | 3932 | try |
3884 | { | 3933 | { |
3885 | foreach (SceneObjectPart part in parts) | 3934 | foreach (SceneObjectPart part in parts) |
3886 | part.SetFaceColorAlpha(face, color, null); | 3935 | part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); |
3887 | } | 3936 | } |
3888 | finally | 3937 | finally |
3889 | { | 3938 | { |
@@ -4109,16 +4158,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4109 | } | 4158 | } |
4110 | 4159 | ||
4111 | /// <summary> | 4160 | /// <summary> |
4112 | /// Returns the name of the child prim or seated avatar matching the | ||
4113 | /// specified link number. | ||
4114 | /// </summary> | ||
4115 | /// <param name="linknum"> | ||
4116 | /// The number of a link in the linkset or a link-related constant. | ||
4117 | /// </param> | ||
4118 | /// <returns> | ||
4119 | /// The name determined to match the specified link number. | ||
4120 | /// </returns> | ||
4121 | /// <remarks> | ||
4122 | /// The rules governing the returned name are not simple. The only | 4161 | /// The rules governing the returned name are not simple. The only |
4123 | /// time a blank name is returned is if the target prim has a blank | 4162 | /// time a blank name is returned is if the target prim has a blank |
4124 | /// name. If no prim with the given link number can be found then | 4163 | /// name. If no prim with the given link number can be found then |
@@ -4146,14 +4185,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4146 | /// Mentions NULL_KEY being returned | 4185 | /// Mentions NULL_KEY being returned |
4147 | /// http://wiki.secondlife.com/wiki/LlGetLinkName | 4186 | /// http://wiki.secondlife.com/wiki/LlGetLinkName |
4148 | /// Mentions using the LINK_* constants, some of which are negative | 4187 | /// Mentions using the LINK_* constants, some of which are negative |
4149 | /// </remarks> | 4188 | /// </summary> |
4150 | public LSL_String llGetLinkName(int linknum) | 4189 | public LSL_String llGetLinkName(int linknum) |
4151 | { | 4190 | { |
4152 | m_host.AddScriptLPS(1); | 4191 | m_host.AddScriptLPS(1); |
4153 | // simplest case, this prims link number | ||
4154 | if (linknum == m_host.LinkNum || linknum == ScriptBaseClass.LINK_THIS) | ||
4155 | return m_host.Name; | ||
4156 | |||
4157 | // parse for sitting avatare-names | 4192 | // parse for sitting avatare-names |
4158 | List<String> nametable = new List<String>(); | 4193 | List<String> nametable = new List<String>(); |
4159 | World.ForEachRootScenePresence(delegate(ScenePresence presence) | 4194 | World.ForEachRootScenePresence(delegate(ScenePresence presence) |
@@ -4177,6 +4212,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4177 | return nametable[totalprims - linknum]; | 4212 | return nametable[totalprims - linknum]; |
4178 | } | 4213 | } |
4179 | 4214 | ||
4215 | // simplest case, this prims link number | ||
4216 | if (m_host.LinkNum == linknum) | ||
4217 | return m_host.Name; | ||
4218 | |||
4180 | // Single prim | 4219 | // Single prim |
4181 | if (m_host.LinkNum == 0) | 4220 | if (m_host.LinkNum == 0) |
4182 | { | 4221 | { |
@@ -4325,7 +4364,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4325 | World.RegionInfo.RegionName+" "+ | 4364 | World.RegionInfo.RegionName+" "+ |
4326 | m_host.AbsolutePosition.ToString(), | 4365 | m_host.AbsolutePosition.ToString(), |
4327 | agentItem.ID, true, m_host.AbsolutePosition, | 4366 | agentItem.ID, true, m_host.AbsolutePosition, |
4328 | bucket, true); | 4367 | bucket); |
4329 | 4368 | ||
4330 | ScenePresence sp; | 4369 | ScenePresence sp; |
4331 | 4370 | ||
@@ -4363,7 +4402,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4363 | public void llSetText(string text, LSL_Vector color, double alpha) | 4402 | public void llSetText(string text, LSL_Vector color, double alpha) |
4364 | { | 4403 | { |
4365 | m_host.AddScriptLPS(1); | 4404 | m_host.AddScriptLPS(1); |
4366 | Vector3 av3 = Util.Clip(color, 0.0f, 1.0f); | 4405 | Vector3 av3 = new Vector3(Util.Clip((float)color.x, 0.0f, 1.0f), |
4406 | Util.Clip((float)color.y, 0.0f, 1.0f), | ||
4407 | Util.Clip((float)color.z, 0.0f, 1.0f)); | ||
4367 | if (text.Length > 254) | 4408 | if (text.Length > 254) |
4368 | text = text.Remove(254); | 4409 | text = text.Remove(254); |
4369 | 4410 | ||
@@ -4590,11 +4631,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4590 | ScriptSleep(5000); | 4631 | ScriptSleep(5000); |
4591 | } | 4632 | } |
4592 | 4633 | ||
4593 | public void llTeleportAgent(string agent, string destination, LSL_Vector targetPos, LSL_Vector targetLookAt) | 4634 | public void llTeleportAgent(string agent, string destination, LSL_Vector pos, LSL_Vector lookAt) |
4594 | { | 4635 | { |
4595 | m_host.AddScriptLPS(1); | 4636 | m_host.AddScriptLPS(1); |
4596 | UUID agentId = new UUID(); | 4637 | UUID agentId = new UUID(); |
4597 | 4638 | ||
4639 | Vector3 targetPos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z); | ||
4640 | Vector3 targetLookAt = new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z); | ||
4641 | |||
4598 | if (UUID.TryParse(agent, out agentId)) | 4642 | if (UUID.TryParse(agent, out agentId)) |
4599 | { | 4643 | { |
4600 | ScenePresence presence = World.GetScenePresence(agentId); | 4644 | ScenePresence presence = World.GetScenePresence(agentId); |
@@ -4623,13 +4667,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4623 | } | 4667 | } |
4624 | } | 4668 | } |
4625 | 4669 | ||
4626 | public void llTeleportAgentGlobalCoords(string agent, LSL_Vector global_coords, LSL_Vector targetPos, LSL_Vector targetLookAt) | 4670 | public void llTeleportAgentGlobalCoords(string agent, LSL_Vector global_coords, LSL_Vector pos, LSL_Vector lookAt) |
4627 | { | 4671 | { |
4628 | m_host.AddScriptLPS(1); | 4672 | m_host.AddScriptLPS(1); |
4629 | UUID agentId = new UUID(); | 4673 | UUID agentId = new UUID(); |
4630 | 4674 | ||
4631 | ulong regionHandle = Utils.UIntsToLong((uint)global_coords.x, (uint)global_coords.y); | 4675 | ulong regionHandle = Utils.UIntsToLong((uint)global_coords.x, (uint)global_coords.y); |
4632 | 4676 | ||
4677 | Vector3 targetPos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z); | ||
4678 | Vector3 targetLookAt = new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z); | ||
4633 | if (UUID.TryParse(agent, out agentId)) | 4679 | if (UUID.TryParse(agent, out agentId)) |
4634 | { | 4680 | { |
4635 | ScenePresence presence = World.GetScenePresence(agentId); | 4681 | ScenePresence presence = World.GetScenePresence(agentId); |
@@ -4731,7 +4777,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4731 | return; | 4777 | return; |
4732 | } | 4778 | } |
4733 | // TODO: Parameter check logic required. | 4779 | // TODO: Parameter check logic required. |
4734 | m_host.CollisionSound = KeyOrName(impact_sound, AssetType.Sound); | 4780 | UUID soundId = UUID.Zero; |
4781 | if (!UUID.TryParse(impact_sound, out soundId)) | ||
4782 | { | ||
4783 | TaskInventoryItem item = m_host.Inventory.GetInventoryItem(impact_sound); | ||
4784 | |||
4785 | if (item != null && item.Type == (int)AssetType.Sound) | ||
4786 | soundId = item.AssetID; | ||
4787 | } | ||
4788 | |||
4789 | m_host.CollisionSound = soundId; | ||
4735 | m_host.CollisionSoundVolume = (float)impact_volume; | 4790 | m_host.CollisionSoundVolume = (float)impact_volume; |
4736 | m_host.CollisionSoundType = 1; | 4791 | m_host.CollisionSoundType = 1; |
4737 | } | 4792 | } |
@@ -4917,7 +4972,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4917 | distance_attenuation = 1f / normalized_units; | 4972 | distance_attenuation = 1f / normalized_units; |
4918 | } | 4973 | } |
4919 | 4974 | ||
4920 | Vector3 applied_linear_impulse = impulse; | 4975 | Vector3 applied_linear_impulse = new Vector3((float)impulse.x, (float)impulse.y, (float)impulse.z); |
4921 | { | 4976 | { |
4922 | float impulse_length = applied_linear_impulse.Length(); | 4977 | float impulse_length = applied_linear_impulse.Length(); |
4923 | 4978 | ||
@@ -5565,15 +5620,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
5565 | /// separated list. There is a space after | 5620 | /// separated list. There is a space after |
5566 | /// each comma. | 5621 | /// each comma. |
5567 | /// </summary> | 5622 | /// </summary> |
5623 | |||
5568 | public LSL_String llList2CSV(LSL_List src) | 5624 | public LSL_String llList2CSV(LSL_List src) |
5569 | { | 5625 | { |
5626 | |||
5627 | string ret = String.Empty; | ||
5628 | int x = 0; | ||
5629 | |||
5570 | m_host.AddScriptLPS(1); | 5630 | m_host.AddScriptLPS(1); |
5571 | 5631 | ||
5572 | return string.Join(", ", | 5632 | if (src.Data.Length > 0) |
5573 | (new List<object>(src.Data)).ConvertAll<string>(o => | 5633 | { |
5574 | { | 5634 | ret = src.Data[x++].ToString(); |
5575 | return o.ToString(); | 5635 | for (; x < src.Data.Length; x++) |
5576 | }).ToArray()); | 5636 | { |
5637 | ret += ", "+src.Data[x].ToString(); | ||
5638 | } | ||
5639 | } | ||
5640 | |||
5641 | return ret; | ||
5577 | } | 5642 | } |
5578 | 5643 | ||
5579 | /// <summary> | 5644 | /// <summary> |
@@ -5872,36 +5937,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
5872 | /// Returns the index of the first occurrence of test | 5937 | /// Returns the index of the first occurrence of test |
5873 | /// in src. | 5938 | /// in src. |
5874 | /// </summary> | 5939 | /// </summary> |
5875 | /// <param name="src">Source list</param> | 5940 | |
5876 | /// <param name="test">List to search for</param> | ||
5877 | /// <returns> | ||
5878 | /// The index number of the point in src where test was found if it was found. | ||
5879 | /// Otherwise returns -1 | ||
5880 | /// </returns> | ||
5881 | public LSL_Integer llListFindList(LSL_List src, LSL_List test) | 5941 | public LSL_Integer llListFindList(LSL_List src, LSL_List test) |
5882 | { | 5942 | { |
5943 | |||
5883 | int index = -1; | 5944 | int index = -1; |
5884 | int length = src.Length - test.Length + 1; | 5945 | int length = src.Length - test.Length + 1; |
5885 | 5946 | ||
5886 | m_host.AddScriptLPS(1); | 5947 | m_host.AddScriptLPS(1); |
5887 | 5948 | ||
5888 | // If either list is empty, do not match | 5949 | // If either list is empty, do not match |
5950 | |||
5889 | if (src.Length != 0 && test.Length != 0) | 5951 | if (src.Length != 0 && test.Length != 0) |
5890 | { | 5952 | { |
5891 | for (int i = 0; i < length; i++) | 5953 | for (int i = 0; i < length; i++) |
5892 | { | 5954 | { |
5893 | // Why this piece of insanity? This is because most script constants are C# value types (e.g. int) | 5955 | if (src.Data[i].Equals(test.Data[0])) |
5894 | // rather than wrapped LSL types. Such a script constant does not have int.Equal(LSL_Integer) code | ||
5895 | // and so the comparison fails even if the LSL_Integer conceptually has the same value. | ||
5896 | // Therefore, here we test Equals on both the source and destination objects. | ||
5897 | // However, a future better approach may be use LSL struct script constants (e.g. LSL_Integer(1)). | ||
5898 | if (src.Data[i].Equals(test.Data[0]) || test.Data[0].Equals(src.Data[i])) | ||
5899 | { | 5956 | { |
5900 | int j; | 5957 | int j; |
5901 | for (j = 1; j < test.Length; j++) | 5958 | for (j = 1; j < test.Length; j++) |
5902 | if (!(src.Data[i+j].Equals(test.Data[j]) || test.Data[j].Equals(src.Data[i+j]))) | 5959 | if (!src.Data[i+j].Equals(test.Data[j])) |
5903 | break; | 5960 | break; |
5904 | |||
5905 | if (j == test.Length) | 5961 | if (j == test.Length) |
5906 | { | 5962 | { |
5907 | index = i; | 5963 | index = i; |
@@ -5912,18 +5968,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
5912 | } | 5968 | } |
5913 | 5969 | ||
5914 | return index; | 5970 | return index; |
5971 | |||
5915 | } | 5972 | } |
5916 | 5973 | ||
5917 | public LSL_String llGetObjectName() | 5974 | public LSL_String llGetObjectName() |
5918 | { | 5975 | { |
5919 | m_host.AddScriptLPS(1); | 5976 | m_host.AddScriptLPS(1); |
5920 | return m_host.Name !=null ? m_host.Name : String.Empty; | 5977 | return m_host.Name!=null?m_host.Name:String.Empty; |
5921 | } | 5978 | } |
5922 | 5979 | ||
5923 | public void llSetObjectName(string name) | 5980 | public void llSetObjectName(string name) |
5924 | { | 5981 | { |
5925 | m_host.AddScriptLPS(1); | 5982 | m_host.AddScriptLPS(1); |
5926 | m_host.Name = name != null ? name : String.Empty; | 5983 | m_host.Name = name!=null?name:String.Empty; |
5927 | } | 5984 | } |
5928 | 5985 | ||
5929 | public LSL_String llGetDate() | 5986 | public LSL_String llGetDate() |
@@ -6097,7 +6154,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6097 | flags |= ScriptBaseClass.AGENT_SITTING; | 6154 | flags |= ScriptBaseClass.AGENT_SITTING; |
6098 | } | 6155 | } |
6099 | 6156 | ||
6100 | if (agent.Animator.Animations.ImplicitDefaultAnimation.AnimID | 6157 | if (agent.Animator.Animations.DefaultAnimation.AnimID |
6101 | == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) | 6158 | == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) |
6102 | { | 6159 | { |
6103 | flags |= ScriptBaseClass.AGENT_SITTING; | 6160 | flags |= ScriptBaseClass.AGENT_SITTING; |
@@ -6254,17 +6311,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6254 | m_host.AddScriptLPS(1); | 6311 | m_host.AddScriptLPS(1); |
6255 | 6312 | ||
6256 | List<SceneObjectPart> parts = GetLinkParts(linknumber); | 6313 | List<SceneObjectPart> parts = GetLinkParts(linknumber); |
6257 | 6314 | if (parts.Count > 0) | |
6258 | try | ||
6259 | { | 6315 | { |
6260 | foreach (SceneObjectPart part in parts) | 6316 | try |
6317 | { | ||
6318 | foreach (var part in parts) | ||
6319 | { | ||
6320 | SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate); | ||
6321 | } | ||
6322 | } | ||
6323 | finally | ||
6261 | { | 6324 | { |
6262 | SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate); | ||
6263 | } | 6325 | } |
6264 | } | 6326 | } |
6265 | finally | ||
6266 | { | ||
6267 | } | ||
6268 | } | 6327 | } |
6269 | 6328 | ||
6270 | private void SetTextureAnim(SceneObjectPart part, int mode, int face, int sizex, int sizey, double start, double length, double rate) | 6329 | private void SetTextureAnim(SceneObjectPart part, int mode, int face, int sizex, int sizey, double start, double length, double rate) |
@@ -6293,12 +6352,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6293 | LSL_Vector bottom_south_west) | 6352 | LSL_Vector bottom_south_west) |
6294 | { | 6353 | { |
6295 | m_host.AddScriptLPS(1); | 6354 | m_host.AddScriptLPS(1); |
6296 | if (m_SoundModule != null) | 6355 | float radius1 = (float)llVecDist(llGetPos(), top_north_east); |
6297 | { | 6356 | float radius2 = (float)llVecDist(llGetPos(), bottom_south_west); |
6298 | m_SoundModule.TriggerSoundLimited(m_host.UUID, | 6357 | float radius = Math.Abs(radius1 - radius2); |
6299 | KeyOrName(sound, AssetType.Sound), volume, | 6358 | m_host.SendSound(KeyOrName(sound).ToString(), volume, true, 0, radius, false, false); |
6300 | bottom_south_west, top_north_east); | ||
6301 | } | ||
6302 | } | 6359 | } |
6303 | 6360 | ||
6304 | public void llEjectFromLand(string pest) | 6361 | public void llEjectFromLand(string pest) |
@@ -6484,7 +6541,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6484 | 6541 | ||
6485 | //Plug the x,y coordinates of the slope normal into the equation of the plane to get | 6542 | //Plug the x,y coordinates of the slope normal into the equation of the plane to get |
6486 | //the height of that point on the plane. The resulting vector gives the slope. | 6543 | //the height of that point on the plane. The resulting vector gives the slope. |
6487 | Vector3 vsl = vsn; | 6544 | Vector3 vsl = new Vector3(); |
6545 | vsl.X = (float)vsn.x; | ||
6546 | vsl.Y = (float)vsn.y; | ||
6488 | vsl.Z = (float)(((vsn.x * vsn.x) + (vsn.y * vsn.y)) / (-1 * vsn.z)); | 6547 | vsl.Z = (float)(((vsn.x * vsn.x) + (vsn.y * vsn.y)) / (-1 * vsn.z)); |
6489 | vsl.Normalize(); | 6548 | vsl.Normalize(); |
6490 | //Normalization might be overkill here | 6549 | //Normalization might be overkill here |
@@ -6495,7 +6554,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6495 | public LSL_Vector llGroundNormal(LSL_Vector offset) | 6554 | public LSL_Vector llGroundNormal(LSL_Vector offset) |
6496 | { | 6555 | { |
6497 | m_host.AddScriptLPS(1); | 6556 | m_host.AddScriptLPS(1); |
6498 | Vector3 pos = m_host.GetWorldPosition() + (Vector3)offset; | 6557 | Vector3 pos = m_host.GetWorldPosition() + new Vector3((float)offset.x, |
6558 | (float)offset.y, | ||
6559 | (float)offset.z); | ||
6499 | // Clamp to valid position | 6560 | // Clamp to valid position |
6500 | if (pos.X < 0) | 6561 | if (pos.X < 0) |
6501 | pos.X = 0; | 6562 | pos.X = 0; |
@@ -6660,7 +6721,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6660 | 6721 | ||
6661 | List<SceneObjectPart> parts = GetLinkParts(linknumber); | 6722 | List<SceneObjectPart> parts = GetLinkParts(linknumber); |
6662 | 6723 | ||
6663 | foreach (SceneObjectPart part in parts) | 6724 | foreach (var part in parts) |
6664 | { | 6725 | { |
6665 | SetParticleSystem(part, rules); | 6726 | SetParticleSystem(part, rules); |
6666 | } | 6727 | } |
@@ -6904,17 +6965,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6904 | if (m_TransferModule != null) | 6965 | if (m_TransferModule != null) |
6905 | { | 6966 | { |
6906 | byte[] bucket = new byte[] { (byte)AssetType.Folder }; | 6967 | byte[] bucket = new byte[] { (byte)AssetType.Folder }; |
6907 | 6968 | ||
6908 | Vector3 pos = m_host.AbsolutePosition; | ||
6909 | |||
6910 | GridInstantMessage msg = new GridInstantMessage(World, | 6969 | GridInstantMessage msg = new GridInstantMessage(World, |
6911 | m_host.OwnerID, m_host.Name, destID, | 6970 | m_host.UUID, m_host.Name + ", an object owned by " + |
6971 | resolveName(m_host.OwnerID) + ",", destID, | ||
6912 | (byte)InstantMessageDialog.TaskInventoryOffered, | 6972 | (byte)InstantMessageDialog.TaskInventoryOffered, |
6913 | false, string.Format("'{0}'", category), | 6973 | false, category + "\n" + m_host.Name + " is located at " + |
6914 | // We won't go so far as to add a SLURL, but this is the format used by LL as of 2012-10-06 | 6974 | World.RegionInfo.RegionName + " " + |
6915 | // false, string.Format("'{0}' ( http://slurl.com/secondlife/{1}/{2}/{3}/{4} )", category, World.Name, (int)pos.X, (int)pos.Y, (int)pos.Z), | 6975 | m_host.AbsolutePosition.ToString(), |
6916 | folderID, false, pos, | 6976 | folderID, true, m_host.AbsolutePosition, |
6917 | bucket, false); | 6977 | bucket); |
6918 | 6978 | ||
6919 | m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); | 6979 | m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); |
6920 | } | 6980 | } |
@@ -6950,7 +7010,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6950 | 7010 | ||
6951 | if (!m_host.ParentGroup.IsDeleted) | 7011 | if (!m_host.ParentGroup.IsDeleted) |
6952 | { | 7012 | { |
6953 | m_host.ParentGroup.RootPart.SetVehicleVectorParam(param, vec); | 7013 | m_host.ParentGroup.RootPart.SetVehicleVectorParam(param, |
7014 | new Vector3((float)vec.x, (float)vec.y, (float)vec.z)); | ||
6954 | } | 7015 | } |
6955 | } | 7016 | } |
6956 | 7017 | ||
@@ -6962,7 +7023,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6962 | 7023 | ||
6963 | if (!m_host.ParentGroup.IsDeleted) | 7024 | if (!m_host.ParentGroup.IsDeleted) |
6964 | { | 7025 | { |
6965 | m_host.ParentGroup.RootPart.SetVehicleRotationParam(param, rot); | 7026 | m_host.ParentGroup.RootPart.SetVehicleRotationParam(param, Rot2Quaternion(rot)); |
6966 | } | 7027 | } |
6967 | } | 7028 | } |
6968 | 7029 | ||
@@ -6992,8 +7053,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6992 | if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0) | 7053 | if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0) |
6993 | rot.s = 1; // ZERO_ROTATION = 0,0,0,1 | 7054 | rot.s = 1; // ZERO_ROTATION = 0,0,0,1 |
6994 | 7055 | ||
6995 | part.SitTargetPosition = offset; | 7056 | part.SitTargetPosition = new Vector3((float)offset.x, (float)offset.y, (float)offset.z); |
6996 | part.SitTargetOrientation = rot; | 7057 | part.SitTargetOrientation = Rot2Quaternion(rot); |
6997 | part.ParentGroup.HasGroupChanged = true; | 7058 | part.ParentGroup.HasGroupChanged = true; |
6998 | } | 7059 | } |
6999 | 7060 | ||
@@ -7096,13 +7157,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
7096 | public void llSetCameraEyeOffset(LSL_Vector offset) | 7157 | public void llSetCameraEyeOffset(LSL_Vector offset) |
7097 | { | 7158 | { |
7098 | m_host.AddScriptLPS(1); | 7159 | m_host.AddScriptLPS(1); |
7099 | m_host.SetCameraEyeOffset(offset); | 7160 | m_host.SetCameraEyeOffset(new Vector3((float)offset.x, (float)offset.y, (float)offset.z)); |
7100 | } | 7161 | } |
7101 | 7162 | ||
7102 | public void llSetCameraAtOffset(LSL_Vector offset) | 7163 | public void llSetCameraAtOffset(LSL_Vector offset) |
7103 | { | 7164 | { |
7104 | m_host.AddScriptLPS(1); | 7165 | m_host.AddScriptLPS(1); |
7105 | m_host.SetCameraAtOffset(offset); | 7166 | m_host.SetCameraAtOffset(new Vector3((float)offset.x, (float)offset.y, (float)offset.z)); |
7106 | } | 7167 | } |
7107 | 7168 | ||
7108 | public LSL_String llDumpList2String(LSL_List src, string seperator) | 7169 | public LSL_String llDumpList2String(LSL_List src, string seperator) |
@@ -7124,7 +7185,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
7124 | public LSL_Integer llScriptDanger(LSL_Vector pos) | 7185 | public LSL_Integer llScriptDanger(LSL_Vector pos) |
7125 | { | 7186 | { |
7126 | m_host.AddScriptLPS(1); | 7187 | m_host.AddScriptLPS(1); |
7127 | bool result = World.ScriptDanger(m_host.LocalId, pos); | 7188 | bool result = World.ScriptDanger(m_host.LocalId, new Vector3((float)pos.x, (float)pos.y, (float)pos.z)); |
7128 | if (result) | 7189 | if (result) |
7129 | { | 7190 | { |
7130 | return 1; | 7191 | return 1; |
@@ -7706,7 +7767,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
7706 | { | 7767 | { |
7707 | m_host.AddScriptLPS(1); | 7768 | m_host.AddScriptLPS(1); |
7708 | 7769 | ||
7709 | setLinkPrimParams(ScriptBaseClass.LINK_THIS, rules, "llSetPrimitiveParams"); | 7770 | setLinkPrimParams(ScriptBaseClass.LINK_THIS, rules); |
7710 | 7771 | ||
7711 | ScriptSleep(200); | 7772 | ScriptSleep(200); |
7712 | } | 7773 | } |
@@ -7715,12 +7776,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
7715 | { | 7776 | { |
7716 | m_host.AddScriptLPS(1); | 7777 | m_host.AddScriptLPS(1); |
7717 | 7778 | ||
7718 | setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParamsFast"); | 7779 | setLinkPrimParams(linknumber, rules); |
7719 | |||
7720 | ScriptSleep(200); | ||
7721 | } | 7780 | } |
7722 | 7781 | ||
7723 | private void setLinkPrimParams(int linknumber, LSL_List rules, string originFunc) | 7782 | private void setLinkPrimParams(int linknumber, LSL_List rules) |
7724 | { | 7783 | { |
7725 | List<object> parts = new List<object>(); | 7784 | List<object> parts = new List<object>(); |
7726 | List<SceneObjectPart> prims = GetLinkParts(linknumber); | 7785 | List<SceneObjectPart> prims = GetLinkParts(linknumber); |
@@ -7731,16 +7790,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
7731 | parts.Add(p); | 7790 | parts.Add(p); |
7732 | 7791 | ||
7733 | LSL_List remaining = null; | 7792 | LSL_List remaining = null; |
7734 | uint rulesParsed = 0; | ||
7735 | 7793 | ||
7736 | if (parts.Count > 0) | 7794 | if (parts.Count > 0) |
7737 | { | 7795 | { |
7738 | foreach (object part in parts) | 7796 | foreach (object part in parts) |
7739 | { | 7797 | { |
7740 | if (part is SceneObjectPart) | 7798 | if (part is SceneObjectPart) |
7741 | remaining = SetPrimParams((SceneObjectPart)part, rules, originFunc, ref rulesParsed); | 7799 | remaining = SetPrimParams((SceneObjectPart)part, rules); |
7742 | else | 7800 | else |
7743 | remaining = SetPrimParams((ScenePresence)part, rules, originFunc, ref rulesParsed); | 7801 | remaining = SetPrimParams((ScenePresence)part, rules); |
7744 | } | 7802 | } |
7745 | 7803 | ||
7746 | while ((object)remaining != null && remaining.Length > 2) | 7804 | while ((object)remaining != null && remaining.Length > 2) |
@@ -7759,9 +7817,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
7759 | foreach (object part in parts) | 7817 | foreach (object part in parts) |
7760 | { | 7818 | { |
7761 | if (part is SceneObjectPart) | 7819 | if (part is SceneObjectPart) |
7762 | remaining = SetPrimParams((SceneObjectPart)part, rules, originFunc, ref rulesParsed); | 7820 | remaining = SetPrimParams((SceneObjectPart)part, rules); |
7763 | else | 7821 | else |
7764 | remaining = SetPrimParams((ScenePresence)part, rules, originFunc, ref rulesParsed); | 7822 | remaining = SetPrimParams((ScenePresence)part, rules); |
7765 | } | 7823 | } |
7766 | } | 7824 | } |
7767 | } | 7825 | } |
@@ -7799,7 +7857,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
7799 | 7857 | ||
7800 | public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) | 7858 | public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) |
7801 | { | 7859 | { |
7802 | setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParams"); | ||
7803 | llSetLinkPrimitiveParamsFast(linknumber, rules); | 7860 | llSetLinkPrimitiveParamsFast(linknumber, rules); |
7804 | ScriptSleep(200); | 7861 | ScriptSleep(200); |
7805 | } | 7862 | } |
@@ -7827,13 +7884,195 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
7827 | return new Vector3((float)x, (float)y, (float)z); | 7884 | return new Vector3((float)x, (float)y, (float)z); |
7828 | } | 7885 | } |
7829 | 7886 | ||
7830 | protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules, string originFunc, ref uint rulesParsed) | 7887 | protected LSL_List SetPrimParams(ScenePresence av, LSL_List rules) |
7888 | { | ||
7889 | //This is a special version of SetPrimParams to deal with avatars which are sat on the linkset. | ||
7890 | |||
7891 | int idx = 0; | ||
7892 | |||
7893 | bool positionChanged = false; | ||
7894 | Vector3 finalPos = Vector3.Zero; | ||
7895 | |||
7896 | try | ||
7897 | { | ||
7898 | while (idx < rules.Length) | ||
7899 | { | ||
7900 | int code = rules.GetLSLIntegerItem(idx++); | ||
7901 | |||
7902 | int remain = rules.Length - idx; | ||
7903 | |||
7904 | switch (code) | ||
7905 | { | ||
7906 | case (int)ScriptBaseClass.PRIM_POSITION: | ||
7907 | case (int)ScriptBaseClass.PRIM_POS_LOCAL: | ||
7908 | { | ||
7909 | if (remain < 1) | ||
7910 | return null; | ||
7911 | |||
7912 | LSL_Vector v; | ||
7913 | v = rules.GetVector3Item(idx++); | ||
7914 | |||
7915 | SceneObjectPart part = World.GetSceneObjectPart(av.ParentID); | ||
7916 | if (part == null) | ||
7917 | break; | ||
7918 | |||
7919 | LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION; | ||
7920 | LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR; | ||
7921 | if (part.LinkNum > 1) | ||
7922 | { | ||
7923 | localRot = GetPartLocalRot(part); | ||
7924 | localPos = GetPartLocalPos(part); | ||
7925 | } | ||
7926 | |||
7927 | v -= localPos; | ||
7928 | v /= localRot; | ||
7929 | |||
7930 | LSL_Vector sitOffset = (llRot2Up(new LSL_Rotation(av.Rotation.X, av.Rotation.Y, av.Rotation.Z, av.Rotation.W)) * av.Appearance.AvatarHeight * 0.02638f); | ||
7931 | |||
7932 | v = v + 2 * sitOffset; | ||
7933 | |||
7934 | av.OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z); | ||
7935 | av.SendAvatarDataToAllAgents(); | ||
7936 | |||
7937 | } | ||
7938 | break; | ||
7939 | |||
7940 | case (int)ScriptBaseClass.PRIM_ROT_LOCAL: | ||
7941 | case (int)ScriptBaseClass.PRIM_ROTATION: | ||
7942 | { | ||
7943 | if (remain < 1) | ||
7944 | return null; | ||
7945 | |||
7946 | LSL_Rotation r; | ||
7947 | r = rules.GetQuaternionItem(idx++); | ||
7948 | |||
7949 | SceneObjectPart part = World.GetSceneObjectPart(av.ParentID); | ||
7950 | if (part == null) | ||
7951 | break; | ||
7952 | |||
7953 | LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION; | ||
7954 | LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR; | ||
7955 | |||
7956 | if (part.LinkNum > 1) | ||
7957 | localRot = GetPartLocalRot(part); | ||
7958 | |||
7959 | r = r * llGetRootRotation() / localRot; | ||
7960 | av.Rotation = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s); | ||
7961 | av.SendAvatarDataToAllAgents(); | ||
7962 | } | ||
7963 | break; | ||
7964 | |||
7965 | // parse rest doing nothing but number of parameters error check | ||
7966 | case (int)ScriptBaseClass.PRIM_SIZE: | ||
7967 | case (int)ScriptBaseClass.PRIM_MATERIAL: | ||
7968 | case (int)ScriptBaseClass.PRIM_PHANTOM: | ||
7969 | case (int)ScriptBaseClass.PRIM_PHYSICS: | ||
7970 | case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE: | ||
7971 | case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: | ||
7972 | case (int)ScriptBaseClass.PRIM_NAME: | ||
7973 | case (int)ScriptBaseClass.PRIM_DESC: | ||
7974 | if (remain < 1) | ||
7975 | return null; | ||
7976 | idx++; | ||
7977 | break; | ||
7978 | |||
7979 | case (int)ScriptBaseClass.PRIM_GLOW: | ||
7980 | case (int)ScriptBaseClass.PRIM_FULLBRIGHT: | ||
7981 | case (int)ScriptBaseClass.PRIM_TEXGEN: | ||
7982 | if (remain < 2) | ||
7983 | return null; | ||
7984 | idx += 2; | ||
7985 | break; | ||
7986 | |||
7987 | case (int)ScriptBaseClass.PRIM_TYPE: | ||
7988 | if (remain < 3) | ||
7989 | return null; | ||
7990 | code = (int)rules.GetLSLIntegerItem(idx++); | ||
7991 | remain = rules.Length - idx; | ||
7992 | switch (code) | ||
7993 | { | ||
7994 | case (int)ScriptBaseClass.PRIM_TYPE_BOX: | ||
7995 | case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER: | ||
7996 | case (int)ScriptBaseClass.PRIM_TYPE_PRISM: | ||
7997 | if (remain < 6) | ||
7998 | return null; | ||
7999 | idx += 6; | ||
8000 | break; | ||
8001 | |||
8002 | case (int)ScriptBaseClass.PRIM_TYPE_SPHERE: | ||
8003 | if (remain < 5) | ||
8004 | return null; | ||
8005 | idx += 5; | ||
8006 | break; | ||
8007 | |||
8008 | case (int)ScriptBaseClass.PRIM_TYPE_TORUS: | ||
8009 | case (int)ScriptBaseClass.PRIM_TYPE_TUBE: | ||
8010 | case (int)ScriptBaseClass.PRIM_TYPE_RING: | ||
8011 | if (remain < 11) | ||
8012 | return null; | ||
8013 | idx += 11; | ||
8014 | break; | ||
8015 | |||
8016 | case (int)ScriptBaseClass.PRIM_TYPE_SCULPT: | ||
8017 | if (remain < 2) | ||
8018 | return null; | ||
8019 | idx += 2; | ||
8020 | break; | ||
8021 | } | ||
8022 | break; | ||
8023 | |||
8024 | case (int)ScriptBaseClass.PRIM_COLOR: | ||
8025 | case (int)ScriptBaseClass.PRIM_TEXT: | ||
8026 | case (int)ScriptBaseClass.PRIM_BUMP_SHINY: | ||
8027 | case (int)ScriptBaseClass.PRIM_OMEGA: | ||
8028 | if (remain < 3) | ||
8029 | return null; | ||
8030 | idx += 3; | ||
8031 | break; | ||
8032 | |||
8033 | case (int)ScriptBaseClass.PRIM_TEXTURE: | ||
8034 | case (int)ScriptBaseClass.PRIM_POINT_LIGHT: | ||
8035 | case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL: | ||
8036 | if (remain < 5) | ||
8037 | return null; | ||
8038 | idx += 5; | ||
8039 | break; | ||
8040 | |||
8041 | case (int)ScriptBaseClass.PRIM_FLEXIBLE: | ||
8042 | if (remain < 7) | ||
8043 | return null; | ||
8044 | |||
8045 | idx += 7; | ||
8046 | break; | ||
8047 | |||
8048 | case (int)ScriptBaseClass.PRIM_LINK_TARGET: | ||
8049 | if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. | ||
8050 | return null; | ||
8051 | |||
8052 | return rules.GetSublist(idx, -1); | ||
8053 | } | ||
8054 | } | ||
8055 | } | ||
8056 | |||
8057 | finally | ||
8058 | { | ||
8059 | if (positionChanged) | ||
8060 | { | ||
8061 | av.OffsetPosition = finalPos; | ||
8062 | // av.SendAvatarDataToAllAgents(); | ||
8063 | av.SendTerseUpdateToAllClients(); | ||
8064 | positionChanged = false; | ||
8065 | } | ||
8066 | } | ||
8067 | return null; | ||
8068 | } | ||
8069 | |||
8070 | protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules) | ||
7831 | { | 8071 | { |
7832 | if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) | 8072 | if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) |
7833 | return null; | 8073 | return null; |
7834 | 8074 | ||
7835 | int idx = 0; | 8075 | int idx = 0; |
7836 | int idxStart = 0; | ||
7837 | 8076 | ||
7838 | SceneObjectGroup parentgrp = part.ParentGroup; | 8077 | SceneObjectGroup parentgrp = part.ParentGroup; |
7839 | 8078 | ||
@@ -7844,11 +8083,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
7844 | { | 8083 | { |
7845 | while (idx < rules.Length) | 8084 | while (idx < rules.Length) |
7846 | { | 8085 | { |
7847 | ++rulesParsed; | ||
7848 | int code = rules.GetLSLIntegerItem(idx++); | 8086 | int code = rules.GetLSLIntegerItem(idx++); |
7849 | 8087 | ||
7850 | int remain = rules.Length - idx; | 8088 | int remain = rules.Length - idx; |
7851 | idxStart = idx; | ||
7852 | 8089 | ||
7853 | int face; | 8090 | int face; |
7854 | LSL_Vector v; | 8091 | LSL_Vector v; |
@@ -7878,17 +8115,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
7878 | return null; | 8115 | return null; |
7879 | 8116 | ||
7880 | LSL_Rotation q = rules.GetQuaternionItem(idx++); | 8117 | LSL_Rotation q = rules.GetQuaternionItem(idx++); |
8118 | SceneObjectPart rootPart = parentgrp.RootPart; | ||
7881 | // try to let this work as in SL... | 8119 | // try to let this work as in SL... |
7882 | if (part.ParentID == 0) | 8120 | if (rootPart == part) |
7883 | { | 8121 | { |
7884 | // special case: If we are root, rotate complete SOG to new rotation | 8122 | // special case: If we are root, rotate complete SOG to new rotation |
7885 | SetRot(part, q); | 8123 | SetRot(part, Rot2Quaternion(q)); |
7886 | } | 8124 | } |
7887 | else | 8125 | else |
7888 | { | 8126 | { |
7889 | // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask. | 8127 | // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask. |
7890 | SceneObjectPart rootPart = part.ParentGroup.RootPart; | 8128 | // sounds like sl bug that we need to replicate |
7891 | SetRot(part, rootPart.RotationOffset * (Quaternion)q); | 8129 | SetRot(part, rootPart.RotationOffset * Rot2Quaternion(q)); |
7892 | } | 8130 | } |
7893 | 8131 | ||
7894 | break; | 8132 | break; |
@@ -8062,7 +8300,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
8062 | LSL_Vector color=rules.GetVector3Item(idx++); | 8300 | LSL_Vector color=rules.GetVector3Item(idx++); |
8063 | double alpha=(double)rules.GetLSLFloatItem(idx++); | 8301 | double alpha=(double)rules.GetLSLFloatItem(idx++); |
8064 | 8302 | ||
8065 | part.SetFaceColorAlpha(face, color, alpha); | 8303 | part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); |
8304 | SetAlpha(part, alpha, face); | ||
8066 | 8305 | ||
8067 | break; | 8306 | break; |
8068 | 8307 | ||
@@ -8210,7 +8449,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
8210 | string primText = rules.GetLSLStringItem(idx++); | 8449 | string primText = rules.GetLSLStringItem(idx++); |
8211 | LSL_Vector primTextColor = rules.GetVector3Item(idx++); | 8450 | LSL_Vector primTextColor = rules.GetVector3Item(idx++); |
8212 | LSL_Float primTextAlpha = rules.GetLSLFloatItem(idx++); | 8451 | LSL_Float primTextAlpha = rules.GetLSLFloatItem(idx++); |
8213 | Vector3 av3 = Util.Clip(primTextColor, 0.0f, 1.0f); | 8452 | Vector3 av3 = new Vector3(Util.Clip((float)primTextColor.x, 0.0f, 1.0f), |
8453 | Util.Clip((float)primTextColor.y, 0.0f, 1.0f), | ||
8454 | Util.Clip((float)primTextColor.z, 0.0f, 1.0f)); | ||
8214 | part.SetText(primText, av3, Util.Clip((float)primTextAlpha, 0.0f, 1.0f)); | 8455 | part.SetText(primText, av3, Util.Clip((float)primTextAlpha, 0.0f, 1.0f)); |
8215 | 8456 | ||
8216 | break; | 8457 | break; |
@@ -8229,7 +8470,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
8229 | case (int)ScriptBaseClass.PRIM_ROT_LOCAL: | 8470 | case (int)ScriptBaseClass.PRIM_ROT_LOCAL: |
8230 | if (remain < 1) | 8471 | if (remain < 1) |
8231 | return null; | 8472 | return null; |
8232 | SetRot(part, rules.GetQuaternionItem(idx++)); | 8473 | LSL_Rotation lr = rules.GetQuaternionItem(idx++); |
8474 | SetRot(part, Rot2Quaternion(lr)); | ||
8233 | break; | 8475 | break; |
8234 | case (int)ScriptBaseClass.PRIM_OMEGA: | 8476 | case (int)ScriptBaseClass.PRIM_OMEGA: |
8235 | if (remain < 3) | 8477 | if (remain < 3) |
@@ -8239,12 +8481,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
8239 | LSL_Float gain = rules.GetLSLFloatItem(idx++); | 8481 | LSL_Float gain = rules.GetLSLFloatItem(idx++); |
8240 | TargetOmega(part, axis, (double)spinrate, (double)gain); | 8482 | TargetOmega(part, axis, (double)spinrate, (double)gain); |
8241 | break; | 8483 | break; |
8242 | case (int)ScriptBaseClass.PRIM_SLICE: | 8484 | |
8243 | if (remain < 1) | ||
8244 | return null; | ||
8245 | LSL_Vector slice = rules.GetVector3Item(idx++); | ||
8246 | part.UpdateSlice((float)slice.x, (float)slice.y); | ||
8247 | break; | ||
8248 | case (int)ScriptBaseClass.PRIM_LINK_TARGET: | 8485 | case (int)ScriptBaseClass.PRIM_LINK_TARGET: |
8249 | if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. | 8486 | if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. |
8250 | return null; | 8487 | return null; |
@@ -8253,12 +8490,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
8253 | } | 8490 | } |
8254 | } | 8491 | } |
8255 | } | 8492 | } |
8256 | catch (InvalidCastException e) | ||
8257 | { | ||
8258 | ShoutError(string.Format( | ||
8259 | "{0} error running rule #{1}: arg #{2} ", | ||
8260 | originFunc, rulesParsed, idx - idxStart) + e.Message); | ||
8261 | } | ||
8262 | finally | 8493 | finally |
8263 | { | 8494 | { |
8264 | if (positionChanged) | 8495 | if (positionChanged) |
@@ -8267,12 +8498,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
8267 | { | 8498 | { |
8268 | SceneObjectGroup parent = part.ParentGroup; | 8499 | SceneObjectGroup parent = part.ParentGroup; |
8269 | Util.FireAndForget(delegate(object x) { | 8500 | Util.FireAndForget(delegate(object x) { |
8270 | parent.UpdateGroupPosition(currentPosition); | 8501 | parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z)); |
8271 | }); | 8502 | }); |
8272 | } | 8503 | } |
8273 | else | 8504 | else |
8274 | { | 8505 | { |
8275 | part.OffsetPosition = currentPosition; | 8506 | part.OffsetPosition = new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z); |
8276 | SceneObjectGroup parent = part.ParentGroup; | 8507 | SceneObjectGroup parent = part.ParentGroup; |
8277 | parent.HasGroupChanged = true; | 8508 | parent.HasGroupChanged = true; |
8278 | parent.ScheduleGroupForTerseUpdate(); | 8509 | parent.ScheduleGroupForTerseUpdate(); |
@@ -8561,7 +8792,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
8561 | // and standing avatar since server 1.36 | 8792 | // and standing avatar since server 1.36 |
8562 | LSL_Vector lower; | 8793 | LSL_Vector lower; |
8563 | LSL_Vector upper; | 8794 | LSL_Vector upper; |
8564 | if (presence.Animator.Animations.ImplicitDefaultAnimation.AnimID | 8795 | if (presence.Animator.Animations.DefaultAnimation.AnimID |
8565 | == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) | 8796 | == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) |
8566 | { | 8797 | { |
8567 | // This is for ground sitting avatars | 8798 | // This is for ground sitting avatars |
@@ -8650,22 +8881,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
8650 | public LSL_List llGetPrimitiveParams(LSL_List rules) | 8881 | public LSL_List llGetPrimitiveParams(LSL_List rules) |
8651 | { | 8882 | { |
8652 | m_host.AddScriptLPS(1); | 8883 | m_host.AddScriptLPS(1); |
8653 | 8884 | return GetLinkPrimitiveParams(m_host, rules); | |
8654 | LSL_List result = new LSL_List(); | ||
8655 | |||
8656 | LSL_List remaining = GetPrimParams(m_host, rules, ref result); | ||
8657 | |||
8658 | while (remaining != null && remaining.Length > 2) | ||
8659 | { | ||
8660 | int linknumber = remaining.GetLSLIntegerItem(0); | ||
8661 | rules = remaining.GetSublist(1, -1); | ||
8662 | List<SceneObjectPart> parts = GetLinkParts(linknumber); | ||
8663 | |||
8664 | foreach (SceneObjectPart part in parts) | ||
8665 | remaining = GetPrimParams(part, rules, ref result); | ||
8666 | } | ||
8667 | |||
8668 | return result; | ||
8669 | } | 8885 | } |
8670 | 8886 | ||
8671 | public LSL_List llGetLinkPrimitiveParams(int linknumber, LSL_List rules) | 8887 | public LSL_List llGetLinkPrimitiveParams(int linknumber, LSL_List rules) |
@@ -8675,39 +8891,294 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
8675 | // acording to SL wiki this must indicate a single link number or link_root or link_this. | 8891 | // acording to SL wiki this must indicate a single link number or link_root or link_this. |
8676 | // keep other options as before | 8892 | // keep other options as before |
8677 | 8893 | ||
8678 | List<SceneObjectPart> parts; | 8894 | List<SceneObjectPart> parts = GetLinkParts(linknumber); |
8679 | List<ScenePresence> avatars; | 8895 | List<ScenePresence> avatars = GetLinkAvatars(linknumber); |
8680 | 8896 | ||
8681 | LSL_List res = new LSL_List(); | 8897 | LSL_List res = new LSL_List(); |
8682 | LSL_List remaining = null; | ||
8683 | 8898 | ||
8684 | while (rules.Length > 0) | 8899 | if (parts.Count > 0) |
8685 | { | 8900 | { |
8686 | parts = GetLinkParts(linknumber); | 8901 | foreach (var part in parts) |
8687 | avatars = GetLinkAvatars(linknumber); | ||
8688 | |||
8689 | remaining = null; | ||
8690 | foreach (SceneObjectPart part in parts) | ||
8691 | { | 8902 | { |
8692 | remaining = GetPrimParams(part, rules, ref res); | 8903 | LSL_List partRes = GetLinkPrimitiveParams(part, rules); |
8904 | res += partRes; | ||
8693 | } | 8905 | } |
8906 | } | ||
8907 | if (avatars.Count > 0) | ||
8908 | { | ||
8694 | foreach (ScenePresence avatar in avatars) | 8909 | foreach (ScenePresence avatar in avatars) |
8695 | { | 8910 | { |
8696 | remaining = GetPrimParams(avatar, rules, ref res); | 8911 | LSL_List avaRes = GetLinkPrimitiveParams(avatar, rules); |
8912 | res += avaRes; | ||
8697 | } | 8913 | } |
8914 | } | ||
8915 | return res; | ||
8916 | } | ||
8917 | |||
8918 | public LSL_List GetLinkPrimitiveParams(ScenePresence avatar, LSL_List rules) | ||
8919 | { | ||
8920 | // avatars case | ||
8921 | // replies as SL wiki | ||
8698 | 8922 | ||
8699 | if (remaining != null && remaining.Length > 0) | 8923 | LSL_List res = new LSL_List(); |
8924 | // SceneObjectPart sitPart = avatar.ParentPart; // most likelly it will be needed | ||
8925 | SceneObjectPart sitPart = World.GetSceneObjectPart(avatar.ParentID); // maybe better do this expensive search for it in case it's gone?? | ||
8926 | |||
8927 | int idx = 0; | ||
8928 | while (idx < rules.Length) | ||
8929 | { | ||
8930 | int code = (int)rules.GetLSLIntegerItem(idx++); | ||
8931 | int remain = rules.Length - idx; | ||
8932 | |||
8933 | switch (code) | ||
8700 | { | 8934 | { |
8701 | linknumber = remaining.GetLSLIntegerItem(0); | 8935 | case (int)ScriptBaseClass.PRIM_MATERIAL: |
8702 | rules = remaining.GetSublist(1, -1); | 8936 | res.Add(new LSL_Integer((int)SOPMaterialData.SopMaterial.Flesh)); |
8937 | break; | ||
8938 | |||
8939 | case (int)ScriptBaseClass.PRIM_PHYSICS: | ||
8940 | res.Add(new LSL_Integer(0)); | ||
8941 | break; | ||
8942 | |||
8943 | case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: | ||
8944 | res.Add(new LSL_Integer(0)); | ||
8945 | break; | ||
8946 | |||
8947 | case (int)ScriptBaseClass.PRIM_PHANTOM: | ||
8948 | res.Add(new LSL_Integer(0)); | ||
8949 | break; | ||
8950 | |||
8951 | case (int)ScriptBaseClass.PRIM_POSITION: | ||
8952 | |||
8953 | Vector3 pos = avatar.OffsetPosition; | ||
8954 | |||
8955 | Vector3 sitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f *2.0f); | ||
8956 | pos -= sitOffset; | ||
8957 | |||
8958 | if( sitPart != null) | ||
8959 | pos = sitPart.GetWorldPosition() + pos * sitPart.GetWorldRotation(); | ||
8960 | |||
8961 | res.Add(new LSL_Vector(pos.X,pos.Y,pos.Z)); | ||
8962 | break; | ||
8963 | |||
8964 | case (int)ScriptBaseClass.PRIM_SIZE: | ||
8965 | // as in llGetAgentSize above | ||
8966 | res.Add(new LSL_Vector(0.45f, 0.6f, avatar.Appearance.AvatarHeight)); | ||
8967 | break; | ||
8968 | |||
8969 | case (int)ScriptBaseClass.PRIM_ROTATION: | ||
8970 | Quaternion rot = avatar.Rotation; | ||
8971 | if (sitPart != null) | ||
8972 | { | ||
8973 | rot = sitPart.GetWorldRotation() * rot; // apply sit part world rotation | ||
8974 | } | ||
8975 | |||
8976 | res.Add(new LSL_Rotation (rot.X, rot.Y, rot.Z, rot.W)); | ||
8977 | break; | ||
8978 | |||
8979 | case (int)ScriptBaseClass.PRIM_TYPE: | ||
8980 | res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TYPE_BOX)); | ||
8981 | res.Add(new LSL_Integer(ScriptBaseClass.PRIM_HOLE_DEFAULT)); | ||
8982 | res.Add(new LSL_Vector(0f,1.0f,0f)); | ||
8983 | res.Add(new LSL_Float(0.0f)); | ||
8984 | res.Add(new LSL_Vector(0, 0, 0)); | ||
8985 | res.Add(new LSL_Vector(1.0f,1.0f,0f)); | ||
8986 | res.Add(new LSL_Vector(0, 0, 0)); | ||
8987 | break; | ||
8988 | |||
8989 | case (int)ScriptBaseClass.PRIM_TEXTURE: | ||
8990 | if (remain < 1) | ||
8991 | return res; | ||
8992 | |||
8993 | int face = (int)rules.GetLSLIntegerItem(idx++); | ||
8994 | if (face == ScriptBaseClass.ALL_SIDES) | ||
8995 | { | ||
8996 | for (face = 0; face < 21; face++) | ||
8997 | { | ||
8998 | res.Add(new LSL_String("")); | ||
8999 | res.Add(new LSL_Vector(0,0,0)); | ||
9000 | res.Add(new LSL_Vector(0,0,0)); | ||
9001 | res.Add(new LSL_Float(0.0)); | ||
9002 | } | ||
9003 | } | ||
9004 | else | ||
9005 | { | ||
9006 | if (face >= 0 && face < 21) | ||
9007 | { | ||
9008 | res.Add(new LSL_String("")); | ||
9009 | res.Add(new LSL_Vector(0,0,0)); | ||
9010 | res.Add(new LSL_Vector(0,0,0)); | ||
9011 | res.Add(new LSL_Float(0.0)); | ||
9012 | } | ||
9013 | } | ||
9014 | break; | ||
9015 | |||
9016 | case (int)ScriptBaseClass.PRIM_COLOR: | ||
9017 | if (remain < 1) | ||
9018 | return res; | ||
9019 | |||
9020 | face = (int)rules.GetLSLIntegerItem(idx++); | ||
9021 | |||
9022 | if (face == ScriptBaseClass.ALL_SIDES) | ||
9023 | { | ||
9024 | for (face = 0; face < 21; face++) | ||
9025 | { | ||
9026 | res.Add(new LSL_Vector(0,0,0)); | ||
9027 | res.Add(new LSL_Float(0)); | ||
9028 | } | ||
9029 | } | ||
9030 | else | ||
9031 | { | ||
9032 | res.Add(new LSL_Vector(0,0,0)); | ||
9033 | res.Add(new LSL_Float(0)); | ||
9034 | } | ||
9035 | break; | ||
9036 | |||
9037 | case (int)ScriptBaseClass.PRIM_BUMP_SHINY: | ||
9038 | if (remain < 1) | ||
9039 | return res; | ||
9040 | face = (int)rules.GetLSLIntegerItem(idx++); | ||
9041 | |||
9042 | if (face == ScriptBaseClass.ALL_SIDES) | ||
9043 | { | ||
9044 | for (face = 0; face < 21; face++) | ||
9045 | { | ||
9046 | res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE)); | ||
9047 | res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE)); | ||
9048 | } | ||
9049 | } | ||
9050 | else | ||
9051 | { | ||
9052 | res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE)); | ||
9053 | res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE)); | ||
9054 | } | ||
9055 | break; | ||
9056 | |||
9057 | case (int)ScriptBaseClass.PRIM_FULLBRIGHT: | ||
9058 | if (remain < 1) | ||
9059 | return res; | ||
9060 | face = (int)rules.GetLSLIntegerItem(idx++); | ||
9061 | |||
9062 | if (face == ScriptBaseClass.ALL_SIDES) | ||
9063 | { | ||
9064 | for (face = 0; face < 21; face++) | ||
9065 | { | ||
9066 | res.Add(new LSL_Integer(ScriptBaseClass.FALSE)); | ||
9067 | } | ||
9068 | } | ||
9069 | else | ||
9070 | { | ||
9071 | res.Add(new LSL_Integer(ScriptBaseClass.FALSE)); | ||
9072 | } | ||
9073 | break; | ||
9074 | |||
9075 | case (int)ScriptBaseClass.PRIM_FLEXIBLE: | ||
9076 | res.Add(new LSL_Integer(0)); | ||
9077 | res.Add(new LSL_Integer(0));// softness | ||
9078 | res.Add(new LSL_Float(0.0f)); // gravity | ||
9079 | res.Add(new LSL_Float(0.0f)); // friction | ||
9080 | res.Add(new LSL_Float(0.0f)); // wind | ||
9081 | res.Add(new LSL_Float(0.0f)); // tension | ||
9082 | res.Add(new LSL_Vector(0f,0f,0f)); | ||
9083 | break; | ||
9084 | |||
9085 | case (int)ScriptBaseClass.PRIM_TEXGEN: | ||
9086 | // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR) | ||
9087 | if (remain < 1) | ||
9088 | return res; | ||
9089 | face = (int)rules.GetLSLIntegerItem(idx++); | ||
9090 | |||
9091 | if (face == ScriptBaseClass.ALL_SIDES) | ||
9092 | { | ||
9093 | for (face = 0; face < 21; face++) | ||
9094 | { | ||
9095 | res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT)); | ||
9096 | } | ||
9097 | } | ||
9098 | else | ||
9099 | { | ||
9100 | res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT)); | ||
9101 | } | ||
9102 | break; | ||
9103 | |||
9104 | case (int)ScriptBaseClass.PRIM_POINT_LIGHT: | ||
9105 | res.Add(new LSL_Integer(0)); | ||
9106 | res.Add(new LSL_Vector(0f,0f,0f)); | ||
9107 | res.Add(new LSL_Float(0f)); // intensity | ||
9108 | res.Add(new LSL_Float(0f)); // radius | ||
9109 | res.Add(new LSL_Float(0f)); // falloff | ||
9110 | break; | ||
9111 | |||
9112 | case (int)ScriptBaseClass.PRIM_GLOW: | ||
9113 | if (remain < 1) | ||
9114 | return res; | ||
9115 | face = (int)rules.GetLSLIntegerItem(idx++); | ||
9116 | |||
9117 | if (face == ScriptBaseClass.ALL_SIDES) | ||
9118 | { | ||
9119 | for (face = 0; face < 21; face++) | ||
9120 | { | ||
9121 | res.Add(new LSL_Float(0f)); | ||
9122 | } | ||
9123 | } | ||
9124 | else | ||
9125 | { | ||
9126 | res.Add(new LSL_Float(0f)); | ||
9127 | } | ||
9128 | break; | ||
9129 | |||
9130 | case (int)ScriptBaseClass.PRIM_TEXT: | ||
9131 | res.Add(new LSL_String("")); | ||
9132 | res.Add(new LSL_Vector(0f,0f,0f)); | ||
9133 | res.Add(new LSL_Float(1.0f)); | ||
9134 | break; | ||
9135 | |||
9136 | case (int)ScriptBaseClass.PRIM_NAME: | ||
9137 | res.Add(new LSL_String(avatar.Name)); | ||
9138 | break; | ||
9139 | |||
9140 | case (int)ScriptBaseClass.PRIM_DESC: | ||
9141 | res.Add(new LSL_String("")); | ||
9142 | break; | ||
9143 | |||
9144 | case (int)ScriptBaseClass.PRIM_ROT_LOCAL: | ||
9145 | Quaternion lrot = avatar.Rotation; | ||
9146 | |||
9147 | if (sitPart != null && sitPart != sitPart.ParentGroup.RootPart) | ||
9148 | { | ||
9149 | lrot = sitPart.RotationOffset * lrot; // apply sit part rotation offset | ||
9150 | } | ||
9151 | res.Add(new LSL_Rotation(lrot.X, lrot.Y, lrot.Z, lrot.W)); | ||
9152 | break; | ||
9153 | |||
9154 | case (int)ScriptBaseClass.PRIM_POS_LOCAL: | ||
9155 | Vector3 lpos = avatar.OffsetPosition; // pos relative to sit part | ||
9156 | Vector3 lsitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f * 2.0f); | ||
9157 | lpos -= lsitOffset; | ||
9158 | |||
9159 | if (sitPart != null && sitPart != sitPart.ParentGroup.RootPart) | ||
9160 | { | ||
9161 | lpos = sitPart.OffsetPosition + (lpos * sitPart.RotationOffset); // make it relative to root prim | ||
9162 | } | ||
9163 | res.Add(new LSL_Vector(lpos.X,lpos.Y,lpos.Z)); | ||
9164 | break; | ||
9165 | |||
9166 | case (int)ScriptBaseClass.PRIM_LINK_TARGET: | ||
9167 | if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. | ||
9168 | return res; | ||
9169 | LSL_Integer new_linknumber = rules.GetLSLIntegerItem(idx++); | ||
9170 | LSL_List new_rules = rules.GetSublist(idx, -1); | ||
9171 | |||
9172 | res += llGetLinkPrimitiveParams((int)new_linknumber, new_rules); | ||
9173 | return res; | ||
8703 | } | 9174 | } |
8704 | } | 9175 | } |
8705 | |||
8706 | return res; | 9176 | return res; |
8707 | } | 9177 | } |
8708 | 9178 | ||
8709 | public LSL_List GetPrimParams(SceneObjectPart part, LSL_List rules, ref LSL_List res) | 9179 | public LSL_List GetLinkPrimitiveParams(SceneObjectPart part, LSL_List rules) |
8710 | { | 9180 | { |
9181 | LSL_List res = new LSL_List(); | ||
8711 | int idx=0; | 9182 | int idx=0; |
8712 | while (idx < rules.Length) | 9183 | while (idx < rules.Length) |
8713 | { | 9184 | { |
@@ -8845,7 +9316,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
8845 | 9316 | ||
8846 | case (int)ScriptBaseClass.PRIM_TEXTURE: | 9317 | case (int)ScriptBaseClass.PRIM_TEXTURE: |
8847 | if (remain < 1) | 9318 | if (remain < 1) |
8848 | return null; | 9319 | return res; |
8849 | 9320 | ||
8850 | int face = (int)rules.GetLSLIntegerItem(idx++); | 9321 | int face = (int)rules.GetLSLIntegerItem(idx++); |
8851 | Primitive.TextureEntry tex = part.Shape.Textures; | 9322 | Primitive.TextureEntry tex = part.Shape.Textures; |
@@ -8885,7 +9356,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
8885 | 9356 | ||
8886 | case (int)ScriptBaseClass.PRIM_COLOR: | 9357 | case (int)ScriptBaseClass.PRIM_COLOR: |
8887 | if (remain < 1) | 9358 | if (remain < 1) |
8888 | return null; | 9359 | return res; |
8889 | 9360 | ||
8890 | face=(int)rules.GetLSLIntegerItem(idx++); | 9361 | face=(int)rules.GetLSLIntegerItem(idx++); |
8891 | 9362 | ||
@@ -8914,8 +9385,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
8914 | 9385 | ||
8915 | case (int)ScriptBaseClass.PRIM_BUMP_SHINY: | 9386 | case (int)ScriptBaseClass.PRIM_BUMP_SHINY: |
8916 | if (remain < 1) | 9387 | if (remain < 1) |
8917 | return null; | 9388 | return res; |
8918 | |||
8919 | face = (int)rules.GetLSLIntegerItem(idx++); | 9389 | face = (int)rules.GetLSLIntegerItem(idx++); |
8920 | 9390 | ||
8921 | tex = part.Shape.Textures; | 9391 | tex = part.Shape.Textures; |
@@ -8971,8 +9441,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
8971 | 9441 | ||
8972 | case (int)ScriptBaseClass.PRIM_FULLBRIGHT: | 9442 | case (int)ScriptBaseClass.PRIM_FULLBRIGHT: |
8973 | if (remain < 1) | 9443 | if (remain < 1) |
8974 | return null; | 9444 | return res; |
8975 | |||
8976 | face = (int)rules.GetLSLIntegerItem(idx++); | 9445 | face = (int)rules.GetLSLIntegerItem(idx++); |
8977 | 9446 | ||
8978 | tex = part.Shape.Textures; | 9447 | tex = part.Shape.Textures; |
@@ -9026,8 +9495,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
9026 | case (int)ScriptBaseClass.PRIM_TEXGEN: | 9495 | case (int)ScriptBaseClass.PRIM_TEXGEN: |
9027 | // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR) | 9496 | // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR) |
9028 | if (remain < 1) | 9497 | if (remain < 1) |
9029 | return null; | 9498 | return res; |
9030 | |||
9031 | face = (int)rules.GetLSLIntegerItem(idx++); | 9499 | face = (int)rules.GetLSLIntegerItem(idx++); |
9032 | 9500 | ||
9033 | tex = part.Shape.Textures; | 9501 | tex = part.Shape.Textures; |
@@ -9075,8 +9543,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
9075 | 9543 | ||
9076 | case (int)ScriptBaseClass.PRIM_GLOW: | 9544 | case (int)ScriptBaseClass.PRIM_GLOW: |
9077 | if (remain < 1) | 9545 | if (remain < 1) |
9078 | return null; | 9546 | return res; |
9079 | |||
9080 | face = (int)rules.GetLSLIntegerItem(idx++); | 9547 | face = (int)rules.GetLSLIntegerItem(idx++); |
9081 | 9548 | ||
9082 | tex = part.Shape.Textures; | 9549 | tex = part.Shape.Textures; |
@@ -9120,24 +9587,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
9120 | case (int)ScriptBaseClass.PRIM_POS_LOCAL: | 9587 | case (int)ScriptBaseClass.PRIM_POS_LOCAL: |
9121 | res.Add(new LSL_Vector(GetPartLocalPos(part))); | 9588 | res.Add(new LSL_Vector(GetPartLocalPos(part))); |
9122 | break; | 9589 | break; |
9123 | case (int)ScriptBaseClass.PRIM_SLICE: | ||
9124 | PrimType prim_type = part.GetPrimType(); | ||
9125 | bool useProfileBeginEnd = (prim_type == PrimType.SPHERE || prim_type == PrimType.TORUS || prim_type == PrimType.TUBE || prim_type == PrimType.RING); | ||
9126 | res.Add(new LSL_Vector( | ||
9127 | (useProfileBeginEnd ? part.Shape.ProfileBegin : part.Shape.PathBegin) / 50000.0, | ||
9128 | 1 - (useProfileBeginEnd ? part.Shape.ProfileEnd : part.Shape.PathEnd) / 50000.0, | ||
9129 | 0 | ||
9130 | )); | ||
9131 | break; | ||
9132 | case (int)ScriptBaseClass.PRIM_LINK_TARGET: | ||
9133 | if(remain < 3) | ||
9134 | return null; | ||
9135 | 9590 | ||
9136 | return rules.GetSublist(idx, -1); | 9591 | case (int)ScriptBaseClass.PRIM_LINK_TARGET: |
9592 | if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. | ||
9593 | return res; | ||
9594 | LSL_Integer new_linknumber = rules.GetLSLIntegerItem(idx++); | ||
9595 | LSL_List new_rules = rules.GetSublist(idx, -1); | ||
9596 | LSL_List tres = llGetLinkPrimitiveParams((int)new_linknumber, new_rules); | ||
9597 | res += tres; | ||
9598 | return res; | ||
9137 | } | 9599 | } |
9138 | } | 9600 | } |
9139 | 9601 | return res; | |
9140 | return null; | ||
9141 | } | 9602 | } |
9142 | 9603 | ||
9143 | public LSL_List llGetPrimMediaParams(int face, LSL_List rules) | 9604 | public LSL_List llGetPrimMediaParams(int face, LSL_List rules) |
@@ -10050,10 +10511,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10050 | 10511 | ||
10051 | GridRegion info; | 10512 | GridRegion info; |
10052 | 10513 | ||
10053 | if (World.RegionInfo.RegionName == simulator) | 10514 | if (m_ScriptEngine.World.RegionInfo.RegionName == simulator) //Det data for this simulator? |
10054 | info = new GridRegion(World.RegionInfo); | 10515 | |
10516 | info = new GridRegion(m_ScriptEngine.World.RegionInfo); | ||
10055 | else | 10517 | else |
10056 | info = World.GridService.GetRegionByName(m_ScriptEngine.World.RegionInfo.ScopeID, simulator); | 10518 | info = m_ScriptEngine.World.GridService.GetRegionByName(m_ScriptEngine.World.RegionInfo.ScopeID, simulator); |
10057 | 10519 | ||
10058 | switch (data) | 10520 | switch (data) |
10059 | { | 10521 | { |
@@ -10063,24 +10525,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10063 | ScriptSleep(1000); | 10525 | ScriptSleep(1000); |
10064 | return UUID.Zero.ToString(); | 10526 | return UUID.Zero.ToString(); |
10065 | } | 10527 | } |
10066 | 10528 | if (m_ScriptEngine.World.RegionInfo.RegionName != simulator) | |
10067 | bool isHypergridRegion = false; | ||
10068 | |||
10069 | if (World.RegionInfo.RegionName != simulator && info.RegionSecret != "") | ||
10070 | { | ||
10071 | // Hypergrid is currently placing real destination region co-ords into RegionSecret. | ||
10072 | // But other code can also use this field for a genuine RegionSecret! Therefore, if | ||
10073 | // anything is present we need to disambiguate. | ||
10074 | // | ||
10075 | // FIXME: Hypergrid should be storing this data in a different field. | ||
10076 | RegionFlags regionFlags | ||
10077 | = (RegionFlags)m_ScriptEngine.World.GridService.GetRegionFlags( | ||
10078 | info.ScopeID, info.RegionID); | ||
10079 | isHypergridRegion = (regionFlags & RegionFlags.Hyperlink) != 0; | ||
10080 | } | ||
10081 | |||
10082 | if (isHypergridRegion) | ||
10083 | { | 10529 | { |
10530 | //Hypergrid Region co-ordinates | ||
10084 | uint rx = 0, ry = 0; | 10531 | uint rx = 0, ry = 0; |
10085 | Utils.LongToUInts(Convert.ToUInt64(info.RegionSecret), out rx, out ry); | 10532 | Utils.LongToUInts(Convert.ToUInt64(info.RegionSecret), out rx, out ry); |
10086 | 10533 | ||
@@ -10091,7 +10538,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10091 | } | 10538 | } |
10092 | else | 10539 | else |
10093 | { | 10540 | { |
10094 | // Local grid co-oridnates | 10541 | //Local-cooridnates |
10095 | reply = new LSL_Vector( | 10542 | reply = new LSL_Vector( |
10096 | info.RegionLocX, | 10543 | info.RegionLocX, |
10097 | info.RegionLocY, | 10544 | info.RegionLocY, |
@@ -10545,20 +10992,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10545 | switch ((ParcelMediaCommandEnum) Convert.ToInt32(aList.Data[i].ToString())) | 10992 | switch ((ParcelMediaCommandEnum) Convert.ToInt32(aList.Data[i].ToString())) |
10546 | { | 10993 | { |
10547 | case ParcelMediaCommandEnum.Url: | 10994 | case ParcelMediaCommandEnum.Url: |
10548 | list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaURL)); | 10995 | list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL)); |
10549 | break; | 10996 | break; |
10550 | case ParcelMediaCommandEnum.Desc: | 10997 | case ParcelMediaCommandEnum.Desc: |
10551 | list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).Description)); | 10998 | list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).Description)); |
10552 | break; | 10999 | break; |
10553 | case ParcelMediaCommandEnum.Texture: | 11000 | case ParcelMediaCommandEnum.Texture: |
10554 | list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaID.ToString())); | 11001 | list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaID.ToString())); |
10555 | break; | 11002 | break; |
10556 | case ParcelMediaCommandEnum.Type: | 11003 | case ParcelMediaCommandEnum.Type: |
10557 | list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaType)); | 11004 | list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaType)); |
10558 | break; | 11005 | break; |
10559 | case ParcelMediaCommandEnum.Size: | 11006 | case ParcelMediaCommandEnum.Size: |
10560 | list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaWidth)); | 11007 | list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaWidth)); |
10561 | list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaHeight)); | 11008 | list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaHeight)); |
10562 | break; | 11009 | break; |
10563 | default: | 11010 | default: |
10564 | ParcelMediaCommandEnum mediaCommandEnum = ParcelMediaCommandEnum.Url; | 11011 | ParcelMediaCommandEnum mediaCommandEnum = ParcelMediaCommandEnum.Url; |
@@ -10728,8 +11175,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10728 | ScenePresence avatar = World.GetScenePresence(detectedParams.Key); | 11175 | ScenePresence avatar = World.GetScenePresence(detectedParams.Key); |
10729 | if (avatar != null) | 11176 | if (avatar != null) |
10730 | { | 11177 | { |
10731 | avatar.ControllingClient.SendScriptTeleportRequest(m_host.Name, | 11178 | avatar.ControllingClient.SendScriptTeleportRequest(m_host.Name, simname, |
10732 | simname, pos, lookAt); | 11179 | new Vector3((float)pos.x, (float)pos.y, (float)pos.z), |
11180 | new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z)); | ||
10733 | } | 11181 | } |
10734 | 11182 | ||
10735 | ScriptSleep(1000); | 11183 | ScriptSleep(1000); |
@@ -10914,30 +11362,31 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10914 | public LSL_Float llListStatistics(int operation, LSL_List src) | 11362 | public LSL_Float llListStatistics(int operation, LSL_List src) |
10915 | { | 11363 | { |
10916 | m_host.AddScriptLPS(1); | 11364 | m_host.AddScriptLPS(1); |
11365 | LSL_List nums = LSL_List.ToDoubleList(src); | ||
10917 | switch (operation) | 11366 | switch (operation) |
10918 | { | 11367 | { |
10919 | case ScriptBaseClass.LIST_STAT_RANGE: | 11368 | case ScriptBaseClass.LIST_STAT_RANGE: |
10920 | return src.Range(); | 11369 | return nums.Range(); |
10921 | case ScriptBaseClass.LIST_STAT_MIN: | 11370 | case ScriptBaseClass.LIST_STAT_MIN: |
10922 | return src.Min(); | 11371 | return nums.Min(); |
10923 | case ScriptBaseClass.LIST_STAT_MAX: | 11372 | case ScriptBaseClass.LIST_STAT_MAX: |
10924 | return src.Max(); | 11373 | return nums.Max(); |
10925 | case ScriptBaseClass.LIST_STAT_MEAN: | 11374 | case ScriptBaseClass.LIST_STAT_MEAN: |
10926 | return src.Mean(); | 11375 | return nums.Mean(); |
10927 | case ScriptBaseClass.LIST_STAT_MEDIAN: | 11376 | case ScriptBaseClass.LIST_STAT_MEDIAN: |
10928 | return LSL_List.ToDoubleList(src).Median(); | 11377 | return nums.Median(); |
10929 | case ScriptBaseClass.LIST_STAT_NUM_COUNT: | 11378 | case ScriptBaseClass.LIST_STAT_NUM_COUNT: |
10930 | return src.NumericLength(); | 11379 | return nums.NumericLength(); |
10931 | case ScriptBaseClass.LIST_STAT_STD_DEV: | 11380 | case ScriptBaseClass.LIST_STAT_STD_DEV: |
10932 | return src.StdDev(); | 11381 | return nums.StdDev(); |
10933 | case ScriptBaseClass.LIST_STAT_SUM: | 11382 | case ScriptBaseClass.LIST_STAT_SUM: |
10934 | return src.Sum(); | 11383 | return nums.Sum(); |
10935 | case ScriptBaseClass.LIST_STAT_SUM_SQUARES: | 11384 | case ScriptBaseClass.LIST_STAT_SUM_SQUARES: |
10936 | return src.SumSqrs(); | 11385 | return nums.SumSqrs(); |
10937 | case ScriptBaseClass.LIST_STAT_GEOMETRIC_MEAN: | 11386 | case ScriptBaseClass.LIST_STAT_GEOMETRIC_MEAN: |
10938 | return src.GeometricMean(); | 11387 | return nums.GeometricMean(); |
10939 | case ScriptBaseClass.LIST_STAT_HARMONIC_MEAN: | 11388 | case ScriptBaseClass.LIST_STAT_HARMONIC_MEAN: |
10940 | return src.HarmonicMean(); | 11389 | return nums.HarmonicMean(); |
10941 | default: | 11390 | default: |
10942 | return 0.0; | 11391 | return 0.0; |
10943 | } | 11392 | } |
@@ -11295,7 +11744,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
11295 | public LSL_List llGetParcelDetails(LSL_Vector pos, LSL_List param) | 11744 | public LSL_List llGetParcelDetails(LSL_Vector pos, LSL_List param) |
11296 | { | 11745 | { |
11297 | m_host.AddScriptLPS(1); | 11746 | m_host.AddScriptLPS(1); |
11298 | LandData land = World.GetLandData(pos); | 11747 | LandData land = World.GetLandData((float)pos.x, (float)pos.y); |
11299 | if (land == null) | 11748 | if (land == null) |
11300 | { | 11749 | { |
11301 | return new LSL_List(0); | 11750 | return new LSL_List(0); |
@@ -11463,12 +11912,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
11463 | else | 11912 | else |
11464 | rot = obj.GetWorldRotation(); | 11913 | rot = obj.GetWorldRotation(); |
11465 | 11914 | ||
11466 | LSL_Rotation objrot = new LSL_Rotation(rot); | 11915 | LSL_Rotation objrot = new LSL_Rotation(rot.X, rot.Y, rot.Z, rot.W); |
11467 | ret.Add(objrot); | 11916 | ret.Add(objrot); |
11468 | } | 11917 | } |
11469 | break; | 11918 | break; |
11470 | case ScriptBaseClass.OBJECT_VELOCITY: | 11919 | case ScriptBaseClass.OBJECT_VELOCITY: |
11471 | ret.Add(new LSL_Vector(obj.Velocity)); | 11920 | Vector3 ovel = obj.Velocity; |
11921 | ret.Add(new LSL_Vector(ovel.X, ovel.Y, ovel.Z)); | ||
11472 | break; | 11922 | break; |
11473 | case ScriptBaseClass.OBJECT_OWNER: | 11923 | case ScriptBaseClass.OBJECT_OWNER: |
11474 | ret.Add(new LSL_String(obj.OwnerID.ToString())); | 11924 | ret.Add(new LSL_String(obj.OwnerID.ToString())); |
@@ -11555,12 +12005,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
11555 | 12005 | ||
11556 | internal void Deprecated(string command) | 12006 | internal void Deprecated(string command) |
11557 | { | 12007 | { |
11558 | throw new ScriptException("Command deprecated: " + command); | 12008 | throw new Exception("Command deprecated: " + command); |
11559 | } | 12009 | } |
11560 | 12010 | ||
11561 | internal void LSLError(string msg) | 12011 | internal void LSLError(string msg) |
11562 | { | 12012 | { |
11563 | throw new ScriptException("LSL Runtime Error: " + msg); | 12013 | throw new Exception("LSL Runtime Error: " + msg); |
11564 | } | 12014 | } |
11565 | 12015 | ||
11566 | public delegate void AssetRequestCallback(UUID assetID, AssetBase asset); | 12016 | public delegate void AssetRequestCallback(UUID assetID, AssetBase asset); |
@@ -11681,7 +12131,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
11681 | return tid.ToString(); | 12131 | return tid.ToString(); |
11682 | } | 12132 | } |
11683 | 12133 | ||
11684 | public void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules, string originFunc) | 12134 | public void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules) |
11685 | { | 12135 | { |
11686 | SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim)); | 12136 | SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim)); |
11687 | if (obj == null) | 12137 | if (obj == null) |
@@ -11690,41 +12140,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
11690 | if (obj.OwnerID != m_host.OwnerID) | 12140 | if (obj.OwnerID != m_host.OwnerID) |
11691 | return; | 12141 | return; |
11692 | 12142 | ||
11693 | uint rulesParsed = 0; | 12143 | LSL_List remaining = SetPrimParams(obj, rules); |
11694 | LSL_List remaining = SetPrimParams(obj, rules, originFunc, ref rulesParsed); | ||
11695 | 12144 | ||
11696 | while ((object)remaining != null && remaining.Length > 2) | 12145 | while ((object)remaining != null && remaining.Length > 2) |
11697 | { | 12146 | { |
11698 | LSL_Integer newLink = remaining.GetLSLIntegerItem(0); | 12147 | LSL_Integer newLink = remaining.GetLSLIntegerItem(0); |
11699 | LSL_List newrules = remaining.GetSublist(1, -1); | 12148 | LSL_List newrules = remaining.GetSublist(1, -1); |
11700 | foreach(SceneObjectPart part in GetLinkParts(obj, newLink)){ | 12149 | foreach(SceneObjectPart part in GetLinkParts(obj, newLink)){ |
11701 | remaining = SetPrimParams(part, newrules, originFunc, ref rulesParsed); | 12150 | remaining = SetPrimParams(part, newrules); |
11702 | } | 12151 | } |
11703 | } | 12152 | } |
11704 | } | 12153 | } |
11705 | 12154 | ||
11706 | public LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules) | 12155 | public LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules) |
11707 | { | 12156 | { |
11708 | SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim)); | 12157 | SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim)); |
12158 | if (obj == null) | ||
12159 | return new LSL_List(); | ||
11709 | 12160 | ||
11710 | LSL_List result = new LSL_List(); | 12161 | if (obj.OwnerID != m_host.OwnerID) |
11711 | 12162 | return new LSL_List(); | |
11712 | if (obj != null && obj.OwnerID != m_host.OwnerID) | ||
11713 | { | ||
11714 | LSL_List remaining = GetPrimParams(obj, rules, ref result); | ||
11715 | |||
11716 | while (remaining != null && remaining.Length > 2) | ||
11717 | { | ||
11718 | int linknumber = remaining.GetLSLIntegerItem(0); | ||
11719 | rules = remaining.GetSublist(1, -1); | ||
11720 | List<SceneObjectPart> parts = GetLinkParts(linknumber); | ||
11721 | |||
11722 | foreach (SceneObjectPart part in parts) | ||
11723 | remaining = GetPrimParams(part, rules, ref result); | ||
11724 | } | ||
11725 | } | ||
11726 | 12163 | ||
11727 | return result; | 12164 | return GetLinkPrimitiveParams(obj, rules); |
11728 | } | 12165 | } |
11729 | 12166 | ||
11730 | public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link) | 12167 | public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link) |
@@ -12087,8 +12524,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
12087 | 12524 | ||
12088 | m_host.AddScriptLPS(1); | 12525 | m_host.AddScriptLPS(1); |
12089 | 12526 | ||
12090 | Vector3 rayStart = start; | 12527 | Vector3 rayStart = new Vector3((float)start.x, (float)start.y, (float)start.z); |
12091 | Vector3 rayEnd = end; | 12528 | Vector3 rayEnd = new Vector3((float)end.x, (float)end.y, (float)end.z); |
12092 | Vector3 dir = rayEnd - rayStart; | 12529 | Vector3 dir = rayEnd - rayStart; |
12093 | 12530 | ||
12094 | float dist = Vector3.Mag(dir); | 12531 | float dist = Vector3.Mag(dir); |
@@ -12662,455 +13099,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
12662 | } | 13099 | } |
12663 | } | 13100 | } |
12664 | } | 13101 | } |
12665 | |||
12666 | protected LSL_List SetPrimParams(ScenePresence av, LSL_List rules, string originFunc, ref uint rulesParsed) | ||
12667 | { | ||
12668 | //This is a special version of SetPrimParams to deal with avatars which are sat on the linkset. | ||
12669 | |||
12670 | int idx = 0; | ||
12671 | int idxStart = 0; | ||
12672 | |||
12673 | bool positionChanged = false; | ||
12674 | Vector3 finalPos = Vector3.Zero; | ||
12675 | |||
12676 | try | ||
12677 | { | ||
12678 | while (idx < rules.Length) | ||
12679 | { | ||
12680 | ++rulesParsed; | ||
12681 | int code = rules.GetLSLIntegerItem(idx++); | ||
12682 | |||
12683 | int remain = rules.Length - idx; | ||
12684 | idxStart = idx; | ||
12685 | |||
12686 | switch (code) | ||
12687 | { | ||
12688 | case (int)ScriptBaseClass.PRIM_POSITION: | ||
12689 | case (int)ScriptBaseClass.PRIM_POS_LOCAL: | ||
12690 | { | ||
12691 | if (remain < 1) | ||
12692 | return null; | ||
12693 | |||
12694 | LSL_Vector v; | ||
12695 | v = rules.GetVector3Item(idx++); | ||
12696 | |||
12697 | SceneObjectPart part = World.GetSceneObjectPart(av.ParentID); | ||
12698 | if (part == null) | ||
12699 | break; | ||
12700 | |||
12701 | LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION; | ||
12702 | LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR; | ||
12703 | if (part.LinkNum > 1) | ||
12704 | { | ||
12705 | localRot = GetPartLocalRot(part); | ||
12706 | localPos = GetPartLocalPos(part); | ||
12707 | } | ||
12708 | |||
12709 | v -= localPos; | ||
12710 | v /= localRot; | ||
12711 | |||
12712 | LSL_Vector sitOffset = (llRot2Up(new LSL_Rotation(av.Rotation.X, av.Rotation.Y, av.Rotation.Z, av.Rotation.W)) * av.Appearance.AvatarHeight * 0.02638f); | ||
12713 | |||
12714 | v = v + 2 * sitOffset; | ||
12715 | |||
12716 | av.OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z); | ||
12717 | av.SendAvatarDataToAllAgents(); | ||
12718 | |||
12719 | } | ||
12720 | break; | ||
12721 | |||
12722 | case (int)ScriptBaseClass.PRIM_ROT_LOCAL: | ||
12723 | case (int)ScriptBaseClass.PRIM_ROTATION: | ||
12724 | { | ||
12725 | if (remain < 1) | ||
12726 | return null; | ||
12727 | |||
12728 | LSL_Rotation r; | ||
12729 | r = rules.GetQuaternionItem(idx++); | ||
12730 | |||
12731 | SceneObjectPart part = World.GetSceneObjectPart(av.ParentID); | ||
12732 | if (part == null) | ||
12733 | break; | ||
12734 | |||
12735 | LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION; | ||
12736 | LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR; | ||
12737 | |||
12738 | if (part.LinkNum > 1) | ||
12739 | localRot = GetPartLocalRot(part); | ||
12740 | |||
12741 | r = r * llGetRootRotation() / localRot; | ||
12742 | av.Rotation = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s); | ||
12743 | av.SendAvatarDataToAllAgents(); | ||
12744 | } | ||
12745 | break; | ||
12746 | |||
12747 | // parse rest doing nothing but number of parameters error check | ||
12748 | case (int)ScriptBaseClass.PRIM_SIZE: | ||
12749 | case (int)ScriptBaseClass.PRIM_MATERIAL: | ||
12750 | case (int)ScriptBaseClass.PRIM_PHANTOM: | ||
12751 | case (int)ScriptBaseClass.PRIM_PHYSICS: | ||
12752 | case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE: | ||
12753 | case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: | ||
12754 | case (int)ScriptBaseClass.PRIM_NAME: | ||
12755 | case (int)ScriptBaseClass.PRIM_DESC: | ||
12756 | if (remain < 1) | ||
12757 | return null; | ||
12758 | idx++; | ||
12759 | break; | ||
12760 | |||
12761 | case (int)ScriptBaseClass.PRIM_GLOW: | ||
12762 | case (int)ScriptBaseClass.PRIM_FULLBRIGHT: | ||
12763 | case (int)ScriptBaseClass.PRIM_TEXGEN: | ||
12764 | if (remain < 2) | ||
12765 | return null; | ||
12766 | idx += 2; | ||
12767 | break; | ||
12768 | |||
12769 | case (int)ScriptBaseClass.PRIM_TYPE: | ||
12770 | if (remain < 3) | ||
12771 | return null; | ||
12772 | code = (int)rules.GetLSLIntegerItem(idx++); | ||
12773 | remain = rules.Length - idx; | ||
12774 | switch (code) | ||
12775 | { | ||
12776 | case (int)ScriptBaseClass.PRIM_TYPE_BOX: | ||
12777 | case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER: | ||
12778 | case (int)ScriptBaseClass.PRIM_TYPE_PRISM: | ||
12779 | if (remain < 6) | ||
12780 | return null; | ||
12781 | idx += 6; | ||
12782 | break; | ||
12783 | |||
12784 | case (int)ScriptBaseClass.PRIM_TYPE_SPHERE: | ||
12785 | if (remain < 5) | ||
12786 | return null; | ||
12787 | idx += 5; | ||
12788 | break; | ||
12789 | |||
12790 | case (int)ScriptBaseClass.PRIM_TYPE_TORUS: | ||
12791 | case (int)ScriptBaseClass.PRIM_TYPE_TUBE: | ||
12792 | case (int)ScriptBaseClass.PRIM_TYPE_RING: | ||
12793 | if (remain < 11) | ||
12794 | return null; | ||
12795 | idx += 11; | ||
12796 | break; | ||
12797 | |||
12798 | case (int)ScriptBaseClass.PRIM_TYPE_SCULPT: | ||
12799 | if (remain < 2) | ||
12800 | return null; | ||
12801 | idx += 2; | ||
12802 | break; | ||
12803 | } | ||
12804 | break; | ||
12805 | |||
12806 | case (int)ScriptBaseClass.PRIM_COLOR: | ||
12807 | case (int)ScriptBaseClass.PRIM_TEXT: | ||
12808 | case (int)ScriptBaseClass.PRIM_BUMP_SHINY: | ||
12809 | case (int)ScriptBaseClass.PRIM_OMEGA: | ||
12810 | if (remain < 3) | ||
12811 | return null; | ||
12812 | idx += 3; | ||
12813 | break; | ||
12814 | |||
12815 | case (int)ScriptBaseClass.PRIM_TEXTURE: | ||
12816 | case (int)ScriptBaseClass.PRIM_POINT_LIGHT: | ||
12817 | case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL: | ||
12818 | if (remain < 5) | ||
12819 | return null; | ||
12820 | idx += 5; | ||
12821 | break; | ||
12822 | |||
12823 | case (int)ScriptBaseClass.PRIM_FLEXIBLE: | ||
12824 | if (remain < 7) | ||
12825 | return null; | ||
12826 | |||
12827 | idx += 7; | ||
12828 | break; | ||
12829 | |||
12830 | case (int)ScriptBaseClass.PRIM_LINK_TARGET: | ||
12831 | if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. | ||
12832 | return null; | ||
12833 | |||
12834 | return rules.GetSublist(idx, -1); | ||
12835 | } | ||
12836 | } | ||
12837 | } | ||
12838 | catch (InvalidCastException e) | ||
12839 | { | ||
12840 | ShoutError(string.Format( | ||
12841 | "{0} error running rule #{1}: arg #{2} ", | ||
12842 | originFunc, rulesParsed, idx - idxStart) + e.Message); | ||
12843 | } | ||
12844 | finally | ||
12845 | { | ||
12846 | if (positionChanged) | ||
12847 | { | ||
12848 | av.OffsetPosition = finalPos; | ||
12849 | // av.SendAvatarDataToAllAgents(); | ||
12850 | av.SendTerseUpdateToAllClients(); | ||
12851 | positionChanged = false; | ||
12852 | } | ||
12853 | } | ||
12854 | return null; | ||
12855 | } | ||
12856 | |||
12857 | public LSL_List GetPrimParams(ScenePresence avatar, LSL_List rules, ref LSL_List res) | ||
12858 | { | ||
12859 | // avatars case | ||
12860 | // replies as SL wiki | ||
12861 | |||
12862 | // SceneObjectPart sitPart = avatar.ParentPart; // most likelly it will be needed | ||
12863 | SceneObjectPart sitPart = World.GetSceneObjectPart(avatar.ParentID); // maybe better do this expensive search for it in case it's gone?? | ||
12864 | |||
12865 | int idx = 0; | ||
12866 | while (idx < rules.Length) | ||
12867 | { | ||
12868 | int code = (int)rules.GetLSLIntegerItem(idx++); | ||
12869 | int remain = rules.Length - idx; | ||
12870 | |||
12871 | switch (code) | ||
12872 | { | ||
12873 | case (int)ScriptBaseClass.PRIM_MATERIAL: | ||
12874 | res.Add(new LSL_Integer((int)SOPMaterialData.SopMaterial.Flesh)); | ||
12875 | break; | ||
12876 | |||
12877 | case (int)ScriptBaseClass.PRIM_PHYSICS: | ||
12878 | res.Add(new LSL_Integer(0)); | ||
12879 | break; | ||
12880 | |||
12881 | case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: | ||
12882 | res.Add(new LSL_Integer(0)); | ||
12883 | break; | ||
12884 | |||
12885 | case (int)ScriptBaseClass.PRIM_PHANTOM: | ||
12886 | res.Add(new LSL_Integer(0)); | ||
12887 | break; | ||
12888 | |||
12889 | case (int)ScriptBaseClass.PRIM_POSITION: | ||
12890 | |||
12891 | Vector3 pos = avatar.OffsetPosition; | ||
12892 | |||
12893 | Vector3 sitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f *2.0f); | ||
12894 | pos -= sitOffset; | ||
12895 | |||
12896 | if( sitPart != null) | ||
12897 | pos = sitPart.GetWorldPosition() + pos * sitPart.GetWorldRotation(); | ||
12898 | |||
12899 | res.Add(new LSL_Vector(pos.X,pos.Y,pos.Z)); | ||
12900 | break; | ||
12901 | |||
12902 | case (int)ScriptBaseClass.PRIM_SIZE: | ||
12903 | // as in llGetAgentSize above | ||
12904 | res.Add(new LSL_Vector(0.45f, 0.6f, avatar.Appearance.AvatarHeight)); | ||
12905 | break; | ||
12906 | |||
12907 | case (int)ScriptBaseClass.PRIM_ROTATION: | ||
12908 | Quaternion rot = avatar.Rotation; | ||
12909 | if (sitPart != null) | ||
12910 | { | ||
12911 | rot = sitPart.GetWorldRotation() * rot; // apply sit part world rotation | ||
12912 | } | ||
12913 | |||
12914 | res.Add(new LSL_Rotation (rot.X, rot.Y, rot.Z, rot.W)); | ||
12915 | break; | ||
12916 | |||
12917 | case (int)ScriptBaseClass.PRIM_TYPE: | ||
12918 | res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TYPE_BOX)); | ||
12919 | res.Add(new LSL_Integer(ScriptBaseClass.PRIM_HOLE_DEFAULT)); | ||
12920 | res.Add(new LSL_Vector(0f,1.0f,0f)); | ||
12921 | res.Add(new LSL_Float(0.0f)); | ||
12922 | res.Add(new LSL_Vector(0, 0, 0)); | ||
12923 | res.Add(new LSL_Vector(1.0f,1.0f,0f)); | ||
12924 | res.Add(new LSL_Vector(0, 0, 0)); | ||
12925 | break; | ||
12926 | |||
12927 | case (int)ScriptBaseClass.PRIM_TEXTURE: | ||
12928 | if (remain < 1) | ||
12929 | return null; | ||
12930 | |||
12931 | int face = (int)rules.GetLSLIntegerItem(idx++); | ||
12932 | if (face == ScriptBaseClass.ALL_SIDES) | ||
12933 | { | ||
12934 | for (face = 0; face < 21; face++) | ||
12935 | { | ||
12936 | res.Add(new LSL_String("")); | ||
12937 | res.Add(new LSL_Vector(0,0,0)); | ||
12938 | res.Add(new LSL_Vector(0,0,0)); | ||
12939 | res.Add(new LSL_Float(0.0)); | ||
12940 | } | ||
12941 | } | ||
12942 | else | ||
12943 | { | ||
12944 | if (face >= 0 && face < 21) | ||
12945 | { | ||
12946 | res.Add(new LSL_String("")); | ||
12947 | res.Add(new LSL_Vector(0,0,0)); | ||
12948 | res.Add(new LSL_Vector(0,0,0)); | ||
12949 | res.Add(new LSL_Float(0.0)); | ||
12950 | } | ||
12951 | } | ||
12952 | break; | ||
12953 | |||
12954 | case (int)ScriptBaseClass.PRIM_COLOR: | ||
12955 | if (remain < 1) | ||
12956 | return null; | ||
12957 | |||
12958 | face = (int)rules.GetLSLIntegerItem(idx++); | ||
12959 | |||
12960 | if (face == ScriptBaseClass.ALL_SIDES) | ||
12961 | { | ||
12962 | for (face = 0; face < 21; face++) | ||
12963 | { | ||
12964 | res.Add(new LSL_Vector(0,0,0)); | ||
12965 | res.Add(new LSL_Float(0)); | ||
12966 | } | ||
12967 | } | ||
12968 | else | ||
12969 | { | ||
12970 | res.Add(new LSL_Vector(0,0,0)); | ||
12971 | res.Add(new LSL_Float(0)); | ||
12972 | } | ||
12973 | break; | ||
12974 | |||
12975 | case (int)ScriptBaseClass.PRIM_BUMP_SHINY: | ||
12976 | if (remain < 1) | ||
12977 | return null; | ||
12978 | face = (int)rules.GetLSLIntegerItem(idx++); | ||
12979 | |||
12980 | if (face == ScriptBaseClass.ALL_SIDES) | ||
12981 | { | ||
12982 | for (face = 0; face < 21; face++) | ||
12983 | { | ||
12984 | res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE)); | ||
12985 | res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE)); | ||
12986 | } | ||
12987 | } | ||
12988 | else | ||
12989 | { | ||
12990 | res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE)); | ||
12991 | res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE)); | ||
12992 | } | ||
12993 | break; | ||
12994 | |||
12995 | case (int)ScriptBaseClass.PRIM_FULLBRIGHT: | ||
12996 | if (remain < 1) | ||
12997 | return null; | ||
12998 | face = (int)rules.GetLSLIntegerItem(idx++); | ||
12999 | |||
13000 | if (face == ScriptBaseClass.ALL_SIDES) | ||
13001 | { | ||
13002 | for (face = 0; face < 21; face++) | ||
13003 | { | ||
13004 | res.Add(new LSL_Integer(ScriptBaseClass.FALSE)); | ||
13005 | } | ||
13006 | } | ||
13007 | else | ||
13008 | { | ||
13009 | res.Add(new LSL_Integer(ScriptBaseClass.FALSE)); | ||
13010 | } | ||
13011 | break; | ||
13012 | |||
13013 | case (int)ScriptBaseClass.PRIM_FLEXIBLE: | ||
13014 | res.Add(new LSL_Integer(0)); | ||
13015 | res.Add(new LSL_Integer(0));// softness | ||
13016 | res.Add(new LSL_Float(0.0f)); // gravity | ||
13017 | res.Add(new LSL_Float(0.0f)); // friction | ||
13018 | res.Add(new LSL_Float(0.0f)); // wind | ||
13019 | res.Add(new LSL_Float(0.0f)); // tension | ||
13020 | res.Add(new LSL_Vector(0f,0f,0f)); | ||
13021 | break; | ||
13022 | |||
13023 | case (int)ScriptBaseClass.PRIM_TEXGEN: | ||
13024 | // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR) | ||
13025 | if (remain < 1) | ||
13026 | return null; | ||
13027 | face = (int)rules.GetLSLIntegerItem(idx++); | ||
13028 | |||
13029 | if (face == ScriptBaseClass.ALL_SIDES) | ||
13030 | { | ||
13031 | for (face = 0; face < 21; face++) | ||
13032 | { | ||
13033 | res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT)); | ||
13034 | } | ||
13035 | } | ||
13036 | else | ||
13037 | { | ||
13038 | res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT)); | ||
13039 | } | ||
13040 | break; | ||
13041 | |||
13042 | case (int)ScriptBaseClass.PRIM_POINT_LIGHT: | ||
13043 | res.Add(new LSL_Integer(0)); | ||
13044 | res.Add(new LSL_Vector(0f,0f,0f)); | ||
13045 | res.Add(new LSL_Float(0f)); // intensity | ||
13046 | res.Add(new LSL_Float(0f)); // radius | ||
13047 | res.Add(new LSL_Float(0f)); // falloff | ||
13048 | break; | ||
13049 | |||
13050 | case (int)ScriptBaseClass.PRIM_GLOW: | ||
13051 | if (remain < 1) | ||
13052 | return null; | ||
13053 | face = (int)rules.GetLSLIntegerItem(idx++); | ||
13054 | |||
13055 | if (face == ScriptBaseClass.ALL_SIDES) | ||
13056 | { | ||
13057 | for (face = 0; face < 21; face++) | ||
13058 | { | ||
13059 | res.Add(new LSL_Float(0f)); | ||
13060 | } | ||
13061 | } | ||
13062 | else | ||
13063 | { | ||
13064 | res.Add(new LSL_Float(0f)); | ||
13065 | } | ||
13066 | break; | ||
13067 | |||
13068 | case (int)ScriptBaseClass.PRIM_TEXT: | ||
13069 | res.Add(new LSL_String("")); | ||
13070 | res.Add(new LSL_Vector(0f,0f,0f)); | ||
13071 | res.Add(new LSL_Float(1.0f)); | ||
13072 | break; | ||
13073 | |||
13074 | case (int)ScriptBaseClass.PRIM_NAME: | ||
13075 | res.Add(new LSL_String(avatar.Name)); | ||
13076 | break; | ||
13077 | |||
13078 | case (int)ScriptBaseClass.PRIM_DESC: | ||
13079 | res.Add(new LSL_String("")); | ||
13080 | break; | ||
13081 | |||
13082 | case (int)ScriptBaseClass.PRIM_ROT_LOCAL: | ||
13083 | Quaternion lrot = avatar.Rotation; | ||
13084 | |||
13085 | if (sitPart != null && sitPart != sitPart.ParentGroup.RootPart) | ||
13086 | { | ||
13087 | lrot = sitPart.RotationOffset * lrot; // apply sit part rotation offset | ||
13088 | } | ||
13089 | res.Add(new LSL_Rotation(lrot.X, lrot.Y, lrot.Z, lrot.W)); | ||
13090 | break; | ||
13091 | |||
13092 | case (int)ScriptBaseClass.PRIM_POS_LOCAL: | ||
13093 | Vector3 lpos = avatar.OffsetPosition; // pos relative to sit part | ||
13094 | Vector3 lsitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f * 2.0f); | ||
13095 | lpos -= lsitOffset; | ||
13096 | |||
13097 | if (sitPart != null && sitPart != sitPart.ParentGroup.RootPart) | ||
13098 | { | ||
13099 | lpos = sitPart.OffsetPosition + (lpos * sitPart.RotationOffset); // make it relative to root prim | ||
13100 | } | ||
13101 | res.Add(new LSL_Vector(lpos.X,lpos.Y,lpos.Z)); | ||
13102 | break; | ||
13103 | |||
13104 | case (int)ScriptBaseClass.PRIM_LINK_TARGET: | ||
13105 | if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. | ||
13106 | return null; | ||
13107 | |||
13108 | return rules.GetSublist(idx, -1); | ||
13109 | } | ||
13110 | } | ||
13111 | |||
13112 | return null; | ||
13113 | } | ||
13114 | } | 13102 | } |
13115 | 13103 | ||
13116 | public class NotecardCache | 13104 | public class NotecardCache |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs index ceb4660..795de80 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs | |||
@@ -304,7 +304,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
304 | case (int)ScriptBaseClass.WL_CLOUD_DETAIL_XY_DENSITY: | 304 | case (int)ScriptBaseClass.WL_CLOUD_DETAIL_XY_DENSITY: |
305 | idx++; | 305 | idx++; |
306 | iV = rules.GetVector3Item(idx); | 306 | iV = rules.GetVector3Item(idx); |
307 | wl.cloudDetailXYDensity = iV; | 307 | wl.cloudDetailXYDensity = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); |
308 | break; | 308 | break; |
309 | case (int)ScriptBaseClass.WL_CLOUD_SCALE: | 309 | case (int)ScriptBaseClass.WL_CLOUD_SCALE: |
310 | idx++; | 310 | idx++; |
@@ -329,7 +329,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
329 | case (int)ScriptBaseClass.WL_CLOUD_XY_DENSITY: | 329 | case (int)ScriptBaseClass.WL_CLOUD_XY_DENSITY: |
330 | idx++; | 330 | idx++; |
331 | iV = rules.GetVector3Item(idx); | 331 | iV = rules.GetVector3Item(idx); |
332 | wl.cloudXYDensity = iV; | 332 | wl.cloudXYDensity = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); |
333 | break; | 333 | break; |
334 | case (int)ScriptBaseClass.WL_DENSITY_MULTIPLIER: | 334 | case (int)ScriptBaseClass.WL_DENSITY_MULTIPLIER: |
335 | idx++; | 335 | idx++; |
@@ -384,7 +384,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
384 | case (int)ScriptBaseClass.WL_REFLECTION_WAVELET_SCALE: | 384 | case (int)ScriptBaseClass.WL_REFLECTION_WAVELET_SCALE: |
385 | idx++; | 385 | idx++; |
386 | iV = rules.GetVector3Item(idx); | 386 | iV = rules.GetVector3Item(idx); |
387 | wl.reflectionWaveletScale = iV; | 387 | wl.reflectionWaveletScale = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); |
388 | break; | 388 | break; |
389 | case (int)ScriptBaseClass.WL_REFRACT_SCALE_ABOVE: | 389 | case (int)ScriptBaseClass.WL_REFRACT_SCALE_ABOVE: |
390 | idx++; | 390 | idx++; |
@@ -422,7 +422,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
422 | case (int)ScriptBaseClass.WL_WATER_COLOR: | 422 | case (int)ScriptBaseClass.WL_WATER_COLOR: |
423 | idx++; | 423 | idx++; |
424 | iV = rules.GetVector3Item(idx); | 424 | iV = rules.GetVector3Item(idx); |
425 | wl.waterColor = iV; | 425 | wl.waterColor = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); |
426 | break; | 426 | break; |
427 | case (int)ScriptBaseClass.WL_WATER_FOG_DENSITY_EXPONENT: | 427 | case (int)ScriptBaseClass.WL_WATER_FOG_DENSITY_EXPONENT: |
428 | idx++; | 428 | idx++; |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs index 8f34833..7844c75 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs | |||
@@ -95,13 +95,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
95 | 95 | ||
96 | internal void MODError(string msg) | 96 | internal void MODError(string msg) |
97 | { | 97 | { |
98 | throw new ScriptException("MOD Runtime Error: " + msg); | 98 | throw new Exception("MOD Runtime Error: " + msg); |
99 | } | 99 | } |
100 | 100 | ||
101 | /// <summary> | 101 | // |
102 | /// Dumps an error message on the debug console. | 102 | //Dumps an error message on the debug console. |
103 | /// </summary> | 103 | // |
104 | /// <param name='message'></param> | 104 | |
105 | internal void MODShoutError(string message) | 105 | internal void MODShoutError(string message) |
106 | { | 106 | { |
107 | if (message.Length > 1023) | 107 | if (message.Length > 1023) |
@@ -254,7 +254,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
254 | 254 | ||
255 | object[] convertedParms = new object[parms.Length]; | 255 | object[] convertedParms = new object[parms.Length]; |
256 | for (int i = 0; i < parms.Length; i++) | 256 | for (int i = 0; i < parms.Length; i++) |
257 | convertedParms[i] = ConvertFromLSL(parms[i],signature[i], fname); | 257 | convertedParms[i] = ConvertFromLSL(parms[i],signature[i]); |
258 | 258 | ||
259 | // now call the function, the contract with the function is that it will always return | 259 | // now call the function, the contract with the function is that it will always return |
260 | // non-null but don't trust it completely | 260 | // non-null but don't trust it completely |
@@ -294,7 +294,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
294 | 294 | ||
295 | /// <summary> | 295 | /// <summary> |
296 | /// </summary> | 296 | /// </summary> |
297 | protected object ConvertFromLSL(object lslparm, Type type, string fname) | 297 | protected object ConvertFromLSL(object lslparm, Type type) |
298 | { | 298 | { |
299 | // ---------- String ---------- | 299 | // ---------- String ---------- |
300 | if (lslparm is LSL_String) | 300 | if (lslparm is LSL_String) |
@@ -310,7 +310,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
310 | // ---------- Integer ---------- | 310 | // ---------- Integer ---------- |
311 | else if (lslparm is LSL_Integer) | 311 | else if (lslparm is LSL_Integer) |
312 | { | 312 | { |
313 | if (type == typeof(int) || type == typeof(float)) | 313 | if (type == typeof(int)) |
314 | return (int)(LSL_Integer)lslparm; | 314 | return (int)(LSL_Integer)lslparm; |
315 | } | 315 | } |
316 | 316 | ||
@@ -333,7 +333,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
333 | { | 333 | { |
334 | if (type == typeof(OpenMetaverse.Quaternion)) | 334 | if (type == typeof(OpenMetaverse.Quaternion)) |
335 | { | 335 | { |
336 | return (OpenMetaverse.Quaternion)((LSL_Rotation)lslparm); | 336 | LSL_Rotation rot = (LSL_Rotation)lslparm; |
337 | return new OpenMetaverse.Quaternion((float)rot.x,(float)rot.y,(float)rot.z,(float)rot.s); | ||
337 | } | 338 | } |
338 | } | 339 | } |
339 | 340 | ||
@@ -342,7 +343,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
342 | { | 343 | { |
343 | if (type == typeof(OpenMetaverse.Vector3)) | 344 | if (type == typeof(OpenMetaverse.Vector3)) |
344 | { | 345 | { |
345 | return (OpenMetaverse.Vector3)((LSL_Vector)lslparm); | 346 | LSL_Vector vect = (LSL_Vector)lslparm; |
347 | return new OpenMetaverse.Vector3((float)vect.x,(float)vect.y,(float)vect.z); | ||
346 | } | 348 | } |
347 | } | 349 | } |
348 | 350 | ||
@@ -359,27 +361,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
359 | result[i] = (string)(LSL_String)plist[i]; | 361 | result[i] = (string)(LSL_String)plist[i]; |
360 | else if (plist[i] is LSL_Integer) | 362 | else if (plist[i] is LSL_Integer) |
361 | result[i] = (int)(LSL_Integer)plist[i]; | 363 | result[i] = (int)(LSL_Integer)plist[i]; |
362 | // The int check exists because of the many plain old int script constants in ScriptBase which | ||
363 | // are not LSL_Integers. | ||
364 | else if (plist[i] is int) | ||
365 | result[i] = plist[i]; | ||
366 | else if (plist[i] is LSL_Float) | 364 | else if (plist[i] is LSL_Float) |
367 | result[i] = (float)(LSL_Float)plist[i]; | 365 | result[i] = (float)(LSL_Float)plist[i]; |
368 | else if (plist[i] is LSL_Key) | 366 | else if (plist[i] is LSL_Key) |
369 | result[i] = new UUID((LSL_Key)plist[i]); | 367 | result[i] = new UUID((LSL_Key)plist[i]); |
370 | else if (plist[i] is LSL_Rotation) | 368 | else if (plist[i] is LSL_Rotation) |
371 | result[i] = (Quaternion)((LSL_Rotation)plist[i]); | 369 | { |
370 | LSL_Rotation rot = (LSL_Rotation)plist[i]; | ||
371 | result[i] = new OpenMetaverse.Quaternion((float)rot.x,(float)rot.y,(float)rot.z,(float)rot.s); | ||
372 | } | ||
372 | else if (plist[i] is LSL_Vector) | 373 | else if (plist[i] is LSL_Vector) |
373 | result[i] = (Vector3)((LSL_Vector)plist[i]); | 374 | { |
375 | LSL_Vector vect = (LSL_Vector)plist[i]; | ||
376 | result[i] = new OpenMetaverse.Vector3((float)vect.x,(float)vect.y,(float)vect.z); | ||
377 | } | ||
374 | else | 378 | else |
375 | MODError(String.Format("{0}: unknown LSL list element type", fname)); | 379 | MODError("unknown LSL list element type"); |
376 | } | 380 | } |
377 | 381 | ||
378 | return result; | 382 | return result; |
379 | } | 383 | } |
380 | } | 384 | } |
381 | 385 | ||
382 | MODError(String.Format("{1}: parameter type mismatch; expecting {0}",type.Name, fname)); | 386 | MODError(String.Format("parameter type mismatch; expecting {0}",type.Name)); |
383 | return null; | 387 | return null; |
384 | } | 388 | } |
385 | 389 | ||
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 51c8c7e..80111f9 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs | |||
@@ -141,8 +141,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
141 | internal bool m_debuggerSafe = false; | 141 | internal bool m_debuggerSafe = false; |
142 | internal Dictionary<string, FunctionPerms > m_FunctionPerms = new Dictionary<string, FunctionPerms >(); | 142 | internal Dictionary<string, FunctionPerms > m_FunctionPerms = new Dictionary<string, FunctionPerms >(); |
143 | 143 | ||
144 | protected IUrlModule m_UrlModule = null; | ||
145 | |||
146 | public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item) | 144 | public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item) |
147 | { | 145 | { |
148 | m_ScriptEngine = ScriptEngine; | 146 | m_ScriptEngine = ScriptEngine; |
@@ -150,8 +148,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
150 | m_item = item; | 148 | m_item = item; |
151 | m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false); | 149 | m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false); |
152 | 150 | ||
153 | m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>(); | ||
154 | |||
155 | if (m_ScriptEngine.Config.GetBoolean("AllowOSFunctions", false)) | 151 | if (m_ScriptEngine.Config.GetBoolean("AllowOSFunctions", false)) |
156 | m_OSFunctionsEnabled = true; | 152 | m_OSFunctionsEnabled = true; |
157 | 153 | ||
@@ -218,7 +214,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
218 | } | 214 | } |
219 | else | 215 | else |
220 | { | 216 | { |
221 | throw new ScriptException("OSSL Runtime Error: " + msg); | 217 | throw new Exception("OSSL Runtime Error: " + msg); |
222 | } | 218 | } |
223 | } | 219 | } |
224 | 220 | ||
@@ -786,9 +782,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
786 | 782 | ||
787 | // We will launch the teleport on a new thread so that when the script threads are terminated | 783 | // We will launch the teleport on a new thread so that when the script threads are terminated |
788 | // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting. | 784 | // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting. |
789 | Util.FireAndForget(o => World.RequestTeleportLocation( | 785 | Util.FireAndForget( |
790 | presence.ControllingClient, regionName, position, | 786 | o => World.RequestTeleportLocation(presence.ControllingClient, regionName, |
791 | lookat, (uint)TPFlags.ViaLocation)); | 787 | new Vector3((float)position.x, (float)position.y, (float)position.z), |
788 | new Vector3((float)lookat.x, (float)lookat.y, (float)lookat.z), (uint)TPFlags.ViaLocation)); | ||
792 | 789 | ||
793 | ScriptSleep(5000); | 790 | ScriptSleep(5000); |
794 | 791 | ||
@@ -831,9 +828,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
831 | 828 | ||
832 | // We will launch the teleport on a new thread so that when the script threads are terminated | 829 | // We will launch the teleport on a new thread so that when the script threads are terminated |
833 | // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting. | 830 | // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting. |
834 | Util.FireAndForget(o => World.RequestTeleportLocation( | 831 | Util.FireAndForget( |
835 | presence.ControllingClient, regionHandle, | 832 | o => World.RequestTeleportLocation(presence.ControllingClient, regionHandle, |
836 | position, lookat, (uint)TPFlags.ViaLocation)); | 833 | new Vector3((float)position.x, (float)position.y, (float)position.z), |
834 | new Vector3((float)lookat.x, (float)lookat.y, (float)lookat.z), (uint)TPFlags.ViaLocation)); | ||
837 | 835 | ||
838 | ScriptSleep(5000); | 836 | ScriptSleep(5000); |
839 | 837 | ||
@@ -1682,11 +1680,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
1682 | return; | 1680 | return; |
1683 | } | 1681 | } |
1684 | 1682 | ||
1685 | MessageObject(objUUID, message); | ||
1686 | } | ||
1687 | |||
1688 | private void MessageObject(UUID objUUID, string message) | ||
1689 | { | ||
1690 | object[] resobj = new object[] { new LSL_Types.LSLString(m_host.UUID.ToString()), new LSL_Types.LSLString(message) }; | 1683 | object[] resobj = new object[] { new LSL_Types.LSLString(m_host.UUID.ToString()), new LSL_Types.LSLString(message) }; |
1691 | 1684 | ||
1692 | SceneObjectPart sceneOP = World.GetSceneObjectPart(objUUID); | 1685 | SceneObjectPart sceneOP = World.GetSceneObjectPart(objUUID); |
@@ -1789,24 +1782,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
1789 | protected string LoadNotecard(string notecardNameOrUuid) | 1782 | protected string LoadNotecard(string notecardNameOrUuid) |
1790 | { | 1783 | { |
1791 | UUID assetID = CacheNotecard(notecardNameOrUuid); | 1784 | UUID assetID = CacheNotecard(notecardNameOrUuid); |
1785 | StringBuilder notecardData = new StringBuilder(); | ||
1792 | 1786 | ||
1793 | if (assetID != UUID.Zero) | 1787 | for (int count = 0; count < NotecardCache.GetLines(assetID); count++) |
1794 | { | 1788 | { |
1795 | StringBuilder notecardData = new StringBuilder(); | 1789 | string line = NotecardCache.GetLine(assetID, count) + "\n"; |
1796 | 1790 | ||
1797 | for (int count = 0; count < NotecardCache.GetLines(assetID); count++) | 1791 | // m_log.DebugFormat("[OSSL]: From notecard {0} loading line {1}", notecardNameOrUuid, line); |
1798 | { | 1792 | |
1799 | string line = NotecardCache.GetLine(assetID, count) + "\n"; | 1793 | notecardData.Append(line); |
1800 | |||
1801 | // m_log.DebugFormat("[OSSL]: From notecard {0} loading line {1}", notecardNameOrUuid, line); | ||
1802 | |||
1803 | notecardData.Append(line); | ||
1804 | } | ||
1805 | |||
1806 | return notecardData.ToString(); | ||
1807 | } | 1794 | } |
1808 | 1795 | ||
1809 | return null; | 1796 | return notecardData.ToString(); |
1810 | } | 1797 | } |
1811 | 1798 | ||
1812 | /// <summary> | 1799 | /// <summary> |
@@ -2272,25 +2259,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2272 | CheckThreatLevel(ThreatLevel.High, "osGetLinkPrimitiveParams"); | 2259 | CheckThreatLevel(ThreatLevel.High, "osGetLinkPrimitiveParams"); |
2273 | m_host.AddScriptLPS(1); | 2260 | m_host.AddScriptLPS(1); |
2274 | InitLSL(); | 2261 | InitLSL(); |
2275 | // One needs to cast m_LSL_Api because we're using functions not | ||
2276 | // on the ILSL_Api interface. | ||
2277 | LSL_Api LSL_Api = (LSL_Api)m_LSL_Api; | ||
2278 | LSL_List retVal = new LSL_List(); | 2262 | LSL_List retVal = new LSL_List(); |
2279 | LSL_List remaining = null; | 2263 | List<SceneObjectPart> parts = ((LSL_Api)m_LSL_Api).GetLinkParts(linknumber); |
2280 | List<SceneObjectPart> parts = LSL_Api.GetLinkParts(linknumber); | ||
2281 | foreach (SceneObjectPart part in parts) | 2264 | foreach (SceneObjectPart part in parts) |
2282 | { | 2265 | { |
2283 | remaining = LSL_Api.GetPrimParams(part, rules, ref retVal); | 2266 | retVal += ((LSL_Api)m_LSL_Api).GetLinkPrimitiveParams(part, rules); |
2284 | } | ||
2285 | |||
2286 | while (remaining != null && remaining.Length > 2) | ||
2287 | { | ||
2288 | linknumber = remaining.GetLSLIntegerItem(0); | ||
2289 | rules = remaining.GetSublist(1, -1); | ||
2290 | parts = LSL_Api.GetLinkParts(linknumber); | ||
2291 | |||
2292 | foreach (SceneObjectPart part in parts) | ||
2293 | remaining = LSL_Api.GetPrimParams(part, rules, ref retVal); | ||
2294 | } | 2267 | } |
2295 | return retVal; | 2268 | return retVal; |
2296 | } | 2269 | } |
@@ -2379,18 +2352,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2379 | return UUID.Zero.ToString(); | 2352 | return UUID.Zero.ToString(); |
2380 | } | 2353 | } |
2381 | } | 2354 | } |
2382 | else | ||
2383 | { | ||
2384 | OSSLError(string.Format("osNpcCreate: Notecard reference '{0}' not found.", notecard)); | ||
2385 | } | ||
2386 | } | 2355 | } |
2387 | 2356 | ||
2357 | if (appearance == null) | ||
2358 | return new LSL_Key(UUID.Zero.ToString()); | ||
2359 | |||
2388 | UUID ownerID = UUID.Zero; | 2360 | UUID ownerID = UUID.Zero; |
2389 | if (owned) | 2361 | if (owned) |
2390 | ownerID = m_host.OwnerID; | 2362 | ownerID = m_host.OwnerID; |
2391 | UUID x = module.CreateNPC(firstname, | 2363 | UUID x = module.CreateNPC(firstname, |
2392 | lastname, | 2364 | lastname, |
2393 | position, | 2365 | new Vector3((float) position.x, (float) position.y, (float) position.z), |
2394 | ownerID, | 2366 | ownerID, |
2395 | senseAsAgent, | 2367 | senseAsAgent, |
2396 | World, | 2368 | World, |
@@ -2453,10 +2425,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2453 | return; | 2425 | return; |
2454 | 2426 | ||
2455 | string appearanceSerialized = LoadNotecard(notecard); | 2427 | string appearanceSerialized = LoadNotecard(notecard); |
2456 | |||
2457 | if (appearanceSerialized == null) | ||
2458 | OSSLError(string.Format("osNpcCreate: Notecard reference '{0}' not found.", notecard)); | ||
2459 | |||
2460 | OSDMap appearanceOsd = (OSDMap)OSDParser.DeserializeLLSDXml(appearanceSerialized); | 2428 | OSDMap appearanceOsd = (OSDMap)OSDParser.DeserializeLLSDXml(appearanceSerialized); |
2461 | // OSD a = OSDParser.DeserializeLLSDXml(appearanceSerialized); | 2429 | // OSD a = OSDParser.DeserializeLLSDXml(appearanceSerialized); |
2462 | // Console.WriteLine("appearanceSerialized {0}", appearanceSerialized); | 2430 | // Console.WriteLine("appearanceSerialized {0}", appearanceSerialized); |
@@ -2517,7 +2485,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2517 | return new LSL_Vector(0, 0, 0); | 2485 | return new LSL_Vector(0, 0, 0); |
2518 | } | 2486 | } |
2519 | 2487 | ||
2520 | public void osNpcMoveTo(LSL_Key npc, LSL_Vector pos) | 2488 | public void osNpcMoveTo(LSL_Key npc, LSL_Vector position) |
2521 | { | 2489 | { |
2522 | CheckThreatLevel(ThreatLevel.High, "osNpcMoveTo"); | 2490 | CheckThreatLevel(ThreatLevel.High, "osNpcMoveTo"); |
2523 | m_host.AddScriptLPS(1); | 2491 | m_host.AddScriptLPS(1); |
@@ -2532,6 +2500,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2532 | if (!module.CheckPermissions(npcId, m_host.OwnerID)) | 2500 | if (!module.CheckPermissions(npcId, m_host.OwnerID)) |
2533 | return; | 2501 | return; |
2534 | 2502 | ||
2503 | Vector3 pos = new Vector3((float) position.x, (float) position.y, (float) position.z); | ||
2535 | module.MoveToTarget(npcId, World, pos, false, true, false); | 2504 | module.MoveToTarget(npcId, World, pos, false, true, false); |
2536 | } | 2505 | } |
2537 | } | 2506 | } |
@@ -2551,10 +2520,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2551 | if (!module.CheckPermissions(npcId, m_host.OwnerID)) | 2520 | if (!module.CheckPermissions(npcId, m_host.OwnerID)) |
2552 | return; | 2521 | return; |
2553 | 2522 | ||
2523 | Vector3 pos = new Vector3((float)target.x, (float)target.y, (float)target.z); | ||
2554 | module.MoveToTarget( | 2524 | module.MoveToTarget( |
2555 | new UUID(npc.m_string), | 2525 | new UUID(npc.m_string), |
2556 | World, | 2526 | World, |
2557 | target, | 2527 | pos, |
2558 | (options & ScriptBaseClass.OS_NPC_NO_FLY) != 0, | 2528 | (options & ScriptBaseClass.OS_NPC_NO_FLY) != 0, |
2559 | (options & ScriptBaseClass.OS_NPC_LAND_AT_TARGET) != 0, | 2529 | (options & ScriptBaseClass.OS_NPC_LAND_AT_TARGET) != 0, |
2560 | (options & ScriptBaseClass.OS_NPC_RUNNING) != 0); | 2530 | (options & ScriptBaseClass.OS_NPC_RUNNING) != 0); |
@@ -2606,7 +2576,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2606 | ScenePresence sp = World.GetScenePresence(npcId); | 2576 | ScenePresence sp = World.GetScenePresence(npcId); |
2607 | 2577 | ||
2608 | if (sp != null) | 2578 | if (sp != null) |
2609 | sp.Rotation = rotation; | 2579 | sp.Rotation = LSL_Api.Rot2Quaternion(rotation); |
2610 | } | 2580 | } |
2611 | } | 2581 | } |
2612 | 2582 | ||
@@ -2966,7 +2936,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2966 | avatar.SpeedModifier = (float)SpeedModifier; | 2936 | avatar.SpeedModifier = (float)SpeedModifier; |
2967 | } | 2937 | } |
2968 | 2938 | ||
2969 | public void osKickAvatar(string FirstName, string SurName, string alert) | 2939 | public void osKickAvatar(string FirstName,string SurName,string alert) |
2970 | { | 2940 | { |
2971 | CheckThreatLevel(ThreatLevel.Severe, "osKickAvatar"); | 2941 | CheckThreatLevel(ThreatLevel.Severe, "osKickAvatar"); |
2972 | m_host.AddScriptLPS(1); | 2942 | m_host.AddScriptLPS(1); |
@@ -2980,21 +2950,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2980 | sp.ControllingClient.Kick(alert); | 2950 | sp.ControllingClient.Kick(alert); |
2981 | 2951 | ||
2982 | // ...and close on our side | 2952 | // ...and close on our side |
2983 | sp.Scene.IncomingCloseAgent(sp.UUID, false); | 2953 | sp.Scene.IncomingCloseAgent(sp.UUID); |
2984 | } | 2954 | } |
2985 | }); | 2955 | }); |
2986 | } | 2956 | } |
2987 | |||
2988 | public LSL_Float osGetHealth(string avatar) | ||
2989 | { | ||
2990 | CheckThreatLevel(ThreatLevel.None, "osGetHealth"); | ||
2991 | m_host.AddScriptLPS(1); | ||
2992 | |||
2993 | LSL_Float health = new LSL_Float(-1); | ||
2994 | ScenePresence presence = World.GetScenePresence(new UUID(avatar)); | ||
2995 | if (presence != null) health = presence.Health; | ||
2996 | return health; | ||
2997 | } | ||
2998 | 2957 | ||
2999 | public void osCauseDamage(string avatar, double damage) | 2958 | public void osCauseDamage(string avatar, double damage) |
3000 | { | 2959 | { |
@@ -3007,7 +2966,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3007 | ScenePresence presence = World.GetScenePresence(avatarId); | 2966 | ScenePresence presence = World.GetScenePresence(avatarId); |
3008 | if (presence != null) | 2967 | if (presence != null) |
3009 | { | 2968 | { |
3010 | LandData land = World.GetLandData(pos); | 2969 | LandData land = World.GetLandData((float)pos.X, (float)pos.Y); |
3011 | if ((land.Flags & (uint)ParcelFlags.AllowDamage) == (uint)ParcelFlags.AllowDamage) | 2970 | if ((land.Flags & (uint)ParcelFlags.AllowDamage) == (uint)ParcelFlags.AllowDamage) |
3012 | { | 2971 | { |
3013 | float health = presence.Health; | 2972 | float health = presence.Health; |
@@ -3054,7 +3013,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3054 | m_host.AddScriptLPS(1); | 3013 | m_host.AddScriptLPS(1); |
3055 | InitLSL(); | 3014 | InitLSL(); |
3056 | 3015 | ||
3057 | return m_LSL_Api.GetPrimitiveParamsEx(prim, rules); | 3016 | return m_LSL_Api.GetLinkPrimitiveParamsEx(prim, rules); |
3058 | } | 3017 | } |
3059 | 3018 | ||
3060 | public void osSetPrimitiveParams(LSL_Key prim, LSL_List rules) | 3019 | public void osSetPrimitiveParams(LSL_Key prim, LSL_List rules) |
@@ -3063,7 +3022,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3063 | m_host.AddScriptLPS(1); | 3022 | m_host.AddScriptLPS(1); |
3064 | InitLSL(); | 3023 | InitLSL(); |
3065 | 3024 | ||
3066 | m_LSL_Api.SetPrimitiveParamsEx(prim, rules, "osSetPrimitiveParams"); | 3025 | m_LSL_Api.SetPrimitiveParamsEx(prim, rules); |
3067 | } | 3026 | } |
3068 | 3027 | ||
3069 | /// <summary> | 3028 | /// <summary> |
@@ -3295,8 +3254,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3295 | } | 3254 | } |
3296 | } | 3255 | } |
3297 | 3256 | ||
3298 | #region Attachment commands | ||
3299 | |||
3300 | public void osForceAttachToAvatar(int attachmentPoint) | 3257 | public void osForceAttachToAvatar(int attachmentPoint) |
3301 | { | 3258 | { |
3302 | CheckThreatLevel(ThreatLevel.High, "osForceAttachToAvatar"); | 3259 | CheckThreatLevel(ThreatLevel.High, "osForceAttachToAvatar"); |
@@ -3386,175 +3343,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3386 | ((LSL_Api)m_LSL_Api).DetachFromAvatar(); | 3343 | ((LSL_Api)m_LSL_Api).DetachFromAvatar(); |
3387 | } | 3344 | } |
3388 | 3345 | ||
3389 | public LSL_List osGetNumberOfAttachments(LSL_Key avatar, LSL_List attachmentPoints) | ||
3390 | { | ||
3391 | CheckThreatLevel(ThreatLevel.Moderate, "osGetNumberOfAttachments"); | ||
3392 | |||
3393 | m_host.AddScriptLPS(1); | ||
3394 | |||
3395 | UUID targetUUID; | ||
3396 | ScenePresence target; | ||
3397 | LSL_List resp = new LSL_List(); | ||
3398 | |||
3399 | if (attachmentPoints.Length >= 1 && UUID.TryParse(avatar.ToString(), out targetUUID) && World.TryGetScenePresence(targetUUID, out target)) | ||
3400 | { | ||
3401 | foreach (object point in attachmentPoints.Data) | ||
3402 | { | ||
3403 | LSL_Integer ipoint = new LSL_Integer( | ||
3404 | (point is LSL_Integer || point is int || point is uint) ? | ||
3405 | (int)point : | ||
3406 | 0 | ||
3407 | ); | ||
3408 | resp.Add(ipoint); | ||
3409 | if (ipoint == 0) | ||
3410 | { | ||
3411 | // indicates zero attachments | ||
3412 | resp.Add(new LSL_Integer(0)); | ||
3413 | } | ||
3414 | else | ||
3415 | { | ||
3416 | // gets the number of attachments on the attachment point | ||
3417 | resp.Add(new LSL_Integer(target.GetAttachments((uint)ipoint).Count)); | ||
3418 | } | ||
3419 | } | ||
3420 | } | ||
3421 | |||
3422 | return resp; | ||
3423 | } | ||
3424 | |||
3425 | public void osMessageAttachments(LSL_Key avatar, string message, LSL_List attachmentPoints, int options) | ||
3426 | { | ||
3427 | CheckThreatLevel(ThreatLevel.Moderate, "osMessageAttachments"); | ||
3428 | m_host.AddScriptLPS(1); | ||
3429 | |||
3430 | UUID targetUUID; | ||
3431 | ScenePresence target; | ||
3432 | |||
3433 | if (attachmentPoints.Length >= 1 && UUID.TryParse(avatar.ToString(), out targetUUID) && World.TryGetScenePresence(targetUUID, out target)) | ||
3434 | { | ||
3435 | List<int> aps = new List<int>(); | ||
3436 | foreach (object point in attachmentPoints.Data) | ||
3437 | { | ||
3438 | int ipoint; | ||
3439 | if (int.TryParse(point.ToString(), out ipoint)) | ||
3440 | { | ||
3441 | aps.Add(ipoint); | ||
3442 | } | ||
3443 | } | ||
3444 | |||
3445 | List<SceneObjectGroup> attachments = new List<SceneObjectGroup>(); | ||
3446 | |||
3447 | bool msgAll = aps.Contains(ScriptBaseClass.OS_ATTACH_MSG_ALL); | ||
3448 | bool invertPoints = (options & ScriptBaseClass.OS_ATTACH_MSG_INVERT_POINTS) != 0; | ||
3449 | |||
3450 | if (msgAll && invertPoints) | ||
3451 | { | ||
3452 | return; | ||
3453 | } | ||
3454 | else if (msgAll || invertPoints) | ||
3455 | { | ||
3456 | attachments = target.GetAttachments(); | ||
3457 | } | ||
3458 | else | ||
3459 | { | ||
3460 | foreach (int point in aps) | ||
3461 | { | ||
3462 | if (point > 0) | ||
3463 | { | ||
3464 | attachments.AddRange(target.GetAttachments((uint)point)); | ||
3465 | } | ||
3466 | } | ||
3467 | } | ||
3468 | |||
3469 | // if we have no attachments at this point, exit now | ||
3470 | if (attachments.Count == 0) | ||
3471 | { | ||
3472 | return; | ||
3473 | } | ||
3474 | |||
3475 | List<SceneObjectGroup> ignoreThese = new List<SceneObjectGroup>(); | ||
3476 | |||
3477 | if (invertPoints) | ||
3478 | { | ||
3479 | foreach (SceneObjectGroup attachment in attachments) | ||
3480 | { | ||
3481 | if (aps.Contains((int)attachment.AttachmentPoint)) | ||
3482 | { | ||
3483 | ignoreThese.Add(attachment); | ||
3484 | } | ||
3485 | } | ||
3486 | } | ||
3487 | |||
3488 | foreach (SceneObjectGroup attachment in ignoreThese) | ||
3489 | { | ||
3490 | attachments.Remove(attachment); | ||
3491 | } | ||
3492 | ignoreThese.Clear(); | ||
3493 | |||
3494 | // if inverting removed all attachments to check, exit now | ||
3495 | if (attachments.Count < 1) | ||
3496 | { | ||
3497 | return; | ||
3498 | } | ||
3499 | |||
3500 | if ((options & ScriptBaseClass.OS_ATTACH_MSG_OBJECT_CREATOR) != 0) | ||
3501 | { | ||
3502 | foreach (SceneObjectGroup attachment in attachments) | ||
3503 | { | ||
3504 | if (attachment.RootPart.CreatorID != m_host.CreatorID) | ||
3505 | { | ||
3506 | ignoreThese.Add(attachment); | ||
3507 | } | ||
3508 | } | ||
3509 | |||
3510 | foreach (SceneObjectGroup attachment in ignoreThese) | ||
3511 | { | ||
3512 | attachments.Remove(attachment); | ||
3513 | } | ||
3514 | ignoreThese.Clear(); | ||
3515 | |||
3516 | // if filtering by same object creator removed all | ||
3517 | // attachments to check, exit now | ||
3518 | if (attachments.Count == 0) | ||
3519 | { | ||
3520 | return; | ||
3521 | } | ||
3522 | } | ||
3523 | |||
3524 | if ((options & ScriptBaseClass.OS_ATTACH_MSG_SCRIPT_CREATOR) != 0) | ||
3525 | { | ||
3526 | foreach (SceneObjectGroup attachment in attachments) | ||
3527 | { | ||
3528 | if (attachment.RootPart.CreatorID != m_item.CreatorID) | ||
3529 | { | ||
3530 | ignoreThese.Add(attachment); | ||
3531 | } | ||
3532 | } | ||
3533 | |||
3534 | foreach (SceneObjectGroup attachment in ignoreThese) | ||
3535 | { | ||
3536 | attachments.Remove(attachment); | ||
3537 | } | ||
3538 | ignoreThese.Clear(); | ||
3539 | |||
3540 | // if filtering by object creator must match originating | ||
3541 | // script creator removed all attachments to check, | ||
3542 | // exit now | ||
3543 | if (attachments.Count == 0) | ||
3544 | { | ||
3545 | return; | ||
3546 | } | ||
3547 | } | ||
3548 | |||
3549 | foreach (SceneObjectGroup attachment in attachments) | ||
3550 | { | ||
3551 | MessageObject(attachment.RootPart.UUID, message); | ||
3552 | } | ||
3553 | } | ||
3554 | } | ||
3555 | |||
3556 | #endregion | ||
3557 | |||
3558 | /// <summary> | 3346 | /// <summary> |
3559 | /// Checks if thing is a UUID. | 3347 | /// Checks if thing is a UUID. |
3560 | /// </summary> | 3348 | /// </summary> |
@@ -3604,166 +3392,5 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3604 | 3392 | ||
3605 | return new LSL_Key(m_host.ParentGroup.FromPartID.ToString()); | 3393 | return new LSL_Key(m_host.ParentGroup.FromPartID.ToString()); |
3606 | } | 3394 | } |
3607 | |||
3608 | /// <summary> | ||
3609 | /// Sets the response type for an HTTP request/response | ||
3610 | /// </summary> | ||
3611 | /// <returns></returns> | ||
3612 | public void osSetContentType(LSL_Key id, string type) | ||
3613 | { | ||
3614 | CheckThreatLevel(ThreatLevel.High, "osSetContentType"); | ||
3615 | |||
3616 | if (m_UrlModule != null) | ||
3617 | m_UrlModule.HttpContentType(new UUID(id),type); | ||
3618 | } | ||
3619 | |||
3620 | /// Shout an error if the object owner did not grant the script the specified permissions. | ||
3621 | /// </summary> | ||
3622 | /// <param name="perms"></param> | ||
3623 | /// <returns>boolean indicating whether an error was shouted.</returns> | ||
3624 | protected bool ShoutErrorOnLackingOwnerPerms(int perms, string errorPrefix) | ||
3625 | { | ||
3626 | m_host.AddScriptLPS(1); | ||
3627 | bool fail = false; | ||
3628 | if (m_item.PermsGranter != m_host.OwnerID) | ||
3629 | { | ||
3630 | fail = true; | ||
3631 | OSSLShoutError(string.Format("{0}. Permissions not granted to owner.", errorPrefix)); | ||
3632 | } | ||
3633 | else if ((m_item.PermsMask & perms) == 0) | ||
3634 | { | ||
3635 | fail = true; | ||
3636 | OSSLShoutError(string.Format("{0}. Permissions not granted.", errorPrefix)); | ||
3637 | } | ||
3638 | |||
3639 | return fail; | ||
3640 | } | ||
3641 | |||
3642 | protected void DropAttachment(bool checkPerms) | ||
3643 | { | ||
3644 | if (checkPerms && ShoutErrorOnLackingOwnerPerms(ScriptBaseClass.PERMISSION_ATTACH, "Cannot drop attachment")) | ||
3645 | { | ||
3646 | return; | ||
3647 | } | ||
3648 | |||
3649 | IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; | ||
3650 | ScenePresence sp = attachmentsModule == null ? null : m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.OwnerID); | ||
3651 | |||
3652 | if (attachmentsModule != null && sp != null) | ||
3653 | { | ||
3654 | attachmentsModule.DetachSingleAttachmentToGround(sp, m_host.ParentGroup.LocalId); | ||
3655 | } | ||
3656 | } | ||
3657 | |||
3658 | protected void DropAttachmentAt(bool checkPerms, LSL_Vector pos, LSL_Rotation rot) | ||
3659 | { | ||
3660 | if (checkPerms && ShoutErrorOnLackingOwnerPerms(ScriptBaseClass.PERMISSION_ATTACH, "Cannot drop attachment")) | ||
3661 | { | ||
3662 | return; | ||
3663 | } | ||
3664 | |||
3665 | IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; | ||
3666 | ScenePresence sp = attachmentsModule == null ? null : m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.OwnerID); | ||
3667 | |||
3668 | if (attachmentsModule != null && sp != null) | ||
3669 | { | ||
3670 | attachmentsModule.DetachSingleAttachmentToGround(sp, m_host.ParentGroup.LocalId, pos, rot); | ||
3671 | } | ||
3672 | } | ||
3673 | |||
3674 | public void osDropAttachment() | ||
3675 | { | ||
3676 | CheckThreatLevel(ThreatLevel.Moderate, "osDropAttachment"); | ||
3677 | m_host.AddScriptLPS(1); | ||
3678 | |||
3679 | DropAttachment(true); | ||
3680 | } | ||
3681 | |||
3682 | public void osForceDropAttachment() | ||
3683 | { | ||
3684 | CheckThreatLevel(ThreatLevel.High, "osForceDropAttachment"); | ||
3685 | m_host.AddScriptLPS(1); | ||
3686 | |||
3687 | DropAttachment(false); | ||
3688 | } | ||
3689 | |||
3690 | public void osDropAttachmentAt(LSL_Vector pos, LSL_Rotation rot) | ||
3691 | { | ||
3692 | CheckThreatLevel(ThreatLevel.Moderate, "osDropAttachmentAt"); | ||
3693 | m_host.AddScriptLPS(1); | ||
3694 | |||
3695 | DropAttachmentAt(true, pos, rot); | ||
3696 | } | ||
3697 | |||
3698 | public void osForceDropAttachmentAt(LSL_Vector pos, LSL_Rotation rot) | ||
3699 | { | ||
3700 | CheckThreatLevel(ThreatLevel.High, "osForceDropAttachmentAt"); | ||
3701 | m_host.AddScriptLPS(1); | ||
3702 | |||
3703 | DropAttachmentAt(false, pos, rot); | ||
3704 | } | ||
3705 | |||
3706 | public LSL_Integer osListenRegex(int channelID, string name, string ID, string msg, int regexBitfield) | ||
3707 | { | ||
3708 | CheckThreatLevel(ThreatLevel.Low, "osListenRegex"); | ||
3709 | m_host.AddScriptLPS(1); | ||
3710 | UUID keyID; | ||
3711 | UUID.TryParse(ID, out keyID); | ||
3712 | |||
3713 | // if we want the name to be used as a regular expression, ensure it is valid first. | ||
3714 | if ((regexBitfield & ScriptBaseClass.OS_LISTEN_REGEX_NAME) == ScriptBaseClass.OS_LISTEN_REGEX_NAME) | ||
3715 | { | ||
3716 | try | ||
3717 | { | ||
3718 | Regex.IsMatch("", name); | ||
3719 | } | ||
3720 | catch (Exception) | ||
3721 | { | ||
3722 | OSSLShoutError("Name regex is invalid."); | ||
3723 | return -1; | ||
3724 | } | ||
3725 | } | ||
3726 | |||
3727 | // if we want the msg to be used as a regular expression, ensure it is valid first. | ||
3728 | if ((regexBitfield & ScriptBaseClass.OS_LISTEN_REGEX_MESSAGE) == ScriptBaseClass.OS_LISTEN_REGEX_MESSAGE) | ||
3729 | { | ||
3730 | try | ||
3731 | { | ||
3732 | Regex.IsMatch("", msg); | ||
3733 | } | ||
3734 | catch (Exception) | ||
3735 | { | ||
3736 | OSSLShoutError("Message regex is invalid."); | ||
3737 | return -1; | ||
3738 | } | ||
3739 | } | ||
3740 | |||
3741 | IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); | ||
3742 | return (wComm == null) ? -1 : wComm.Listen( | ||
3743 | m_host.LocalId, | ||
3744 | m_item.ItemID, | ||
3745 | m_host.UUID, | ||
3746 | channelID, | ||
3747 | name, | ||
3748 | keyID, | ||
3749 | msg, | ||
3750 | regexBitfield | ||
3751 | ); | ||
3752 | } | ||
3753 | |||
3754 | public LSL_Integer osRegexIsMatch(string input, string pattern) | ||
3755 | { | ||
3756 | CheckThreatLevel(ThreatLevel.Low, "osRegexIsMatch"); | ||
3757 | m_host.AddScriptLPS(1); | ||
3758 | try | ||
3759 | { | ||
3760 | return Regex.IsMatch(input, pattern) ? 1 : 0; | ||
3761 | } | ||
3762 | catch (Exception) | ||
3763 | { | ||
3764 | OSSLShoutError("Possible invalid regular expression detected."); | ||
3765 | return 0; | ||
3766 | } | ||
3767 | } | ||
3768 | } | 3395 | } |
3769 | } | 3396 | } |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs index 4dd795d..678f9d5 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs | |||
@@ -352,7 +352,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins | |||
352 | q = avatar.Rotation; | 352 | q = avatar.Rotation; |
353 | } | 353 | } |
354 | 354 | ||
355 | LSL_Types.Quaternion r = new LSL_Types.Quaternion(q); | 355 | LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W); |
356 | LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r); | 356 | LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r); |
357 | double mag_fwd = LSL_Types.Vector3.Mag(forward_dir); | 357 | double mag_fwd = LSL_Types.Vector3.Mag(forward_dir); |
358 | 358 | ||
@@ -429,8 +429,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins | |||
429 | try | 429 | try |
430 | { | 430 | { |
431 | Vector3 diff = toRegionPos - fromRegionPos; | 431 | Vector3 diff = toRegionPos - fromRegionPos; |
432 | double dot = LSL_Types.Vector3.Dot(forward_dir, diff); | 432 | LSL_Types.Vector3 obj_dir = new LSL_Types.Vector3(diff.X, diff.Y, diff.Z); |
433 | double mag_obj = LSL_Types.Vector3.Mag(diff); | 433 | double dot = LSL_Types.Vector3.Dot(forward_dir, obj_dir); |
434 | double mag_obj = LSL_Types.Vector3.Mag(obj_dir); | ||
434 | ang_obj = Math.Acos(dot / (mag_fwd * mag_obj)); | 435 | ang_obj = Math.Acos(dot / (mag_fwd * mag_obj)); |
435 | } | 436 | } |
436 | catch | 437 | catch |
@@ -482,7 +483,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins | |||
482 | q = avatar.Rotation; | 483 | q = avatar.Rotation; |
483 | } | 484 | } |
484 | 485 | ||
485 | LSL_Types.Quaternion r = new LSL_Types.Quaternion(q); | 486 | LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W); |
486 | LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r); | 487 | LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r); |
487 | double mag_fwd = LSL_Types.Vector3.Mag(forward_dir); | 488 | double mag_fwd = LSL_Types.Vector3.Mag(forward_dir); |
488 | bool attached = (SensePoint.ParentGroup.AttachmentPoint != 0); | 489 | bool attached = (SensePoint.ParentGroup.AttachmentPoint != 0); |
@@ -563,8 +564,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins | |||
563 | double ang_obj = 0; | 564 | double ang_obj = 0; |
564 | try | 565 | try |
565 | { | 566 | { |
566 | LSL_Types.Vector3 obj_dir = new LSL_Types.Vector3( | 567 | Vector3 diff = toRegionPos - fromRegionPos; |
567 | toRegionPos - fromRegionPos); | 568 | LSL_Types.Vector3 obj_dir = new LSL_Types.Vector3(diff.X, diff.Y, diff.Z); |
568 | double dot = LSL_Types.Vector3.Dot(forward_dir, obj_dir); | 569 | double dot = LSL_Types.Vector3.Dot(forward_dir, obj_dir); |
569 | double mag_obj = LSL_Types.Vector3.Mag(obj_dir); | 570 | double mag_obj = LSL_Types.Vector3.Mag(obj_dir); |
570 | ang_obj = Math.Acos(dot / (mag_fwd * mag_obj)); | 571 | ang_obj = Math.Acos(dot / (mag_fwd * mag_obj)); |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs index 05c20f9..af35258 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs | |||
@@ -429,8 +429,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces | |||
429 | LSL_Integer llGetLinkNumberOfSides(LSL_Integer link); | 429 | LSL_Integer llGetLinkNumberOfSides(LSL_Integer link); |
430 | void llSetPhysicsMaterial(int material_bits, float material_gravity_modifier, float material_restitution, float material_friction, float material_density); | 430 | void llSetPhysicsMaterial(int material_bits, float material_gravity_modifier, float material_restitution, float material_friction, float material_density); |
431 | 431 | ||
432 | void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules, string originFunc); | 432 | void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules); |
433 | LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules); | ||
433 | void llSetKeyframedMotion(LSL_List frames, LSL_List options); | 434 | void llSetKeyframedMotion(LSL_List frames, LSL_List options); |
434 | LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules); | ||
435 | } | 435 | } |
436 | } | 436 | } |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs index c447d1f..8c34ed3 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs | |||
@@ -40,75 +40,16 @@ using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; | |||
40 | 40 | ||
41 | namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces | 41 | namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces |
42 | { | 42 | { |
43 | /// <summary> | ||
44 | /// To permit region owners to enable the extended scripting functionality | ||
45 | /// of OSSL, without allowing malicious scripts to access potentially | ||
46 | /// troublesome functions, each OSSL function is assigned a threat level, | ||
47 | /// and access to the functions is granted or denied based on a default | ||
48 | /// threshold set in OpenSim.ini (which can be overridden for individual | ||
49 | /// functions on a case-by-case basis) | ||
50 | /// </summary> | ||
51 | public enum ThreatLevel | 43 | public enum ThreatLevel |
52 | { | 44 | { |
53 | // Not documented, presumably means permanently disabled ? | ||
54 | NoAccess = -1, | 45 | NoAccess = -1, |
55 | |||
56 | /// <summary> | ||
57 | /// Function is no threat at all. It doesn't constitute a threat to | ||
58 | /// either users or the system and has no known side effects. | ||
59 | /// </summary> | ||
60 | None = 0, | 46 | None = 0, |
61 | |||
62 | /// <summary> | ||
63 | /// Abuse of this command can cause a nuisance to the region operator, | ||
64 | /// such as log message spew. | ||
65 | /// </summary> | ||
66 | Nuisance = 1, | 47 | Nuisance = 1, |
67 | |||
68 | /// <summary> | ||
69 | /// Extreme levels of abuse of this function can cause impaired | ||
70 | /// functioning of the region, or very gullible users can be tricked | ||
71 | /// into experiencing harmless effects. | ||
72 | /// </summary> | ||
73 | VeryLow = 2, | 48 | VeryLow = 2, |
74 | |||
75 | /// <summary> | ||
76 | /// Intentional abuse can cause crashes or malfunction under certain | ||
77 | /// circumstances, which can be easily rectified; or certain users can | ||
78 | /// be tricked into certain situations in an avoidable manner. | ||
79 | /// </summary> | ||
80 | Low = 3, | 49 | Low = 3, |
81 | |||
82 | /// <summary> | ||
83 | /// Intentional abuse can cause denial of service and crashes with | ||
84 | /// potential of data or state loss; or trusting users can be tricked | ||
85 | /// into embarrassing or uncomfortable situations. | ||
86 | /// </summary> | ||
87 | Moderate = 4, | 50 | Moderate = 4, |
88 | |||
89 | /// <summary> | ||
90 | /// Casual abuse can cause impaired functionality or temporary denial | ||
91 | /// of service conditions. Intentional abuse can easily cause crashes | ||
92 | /// with potential data loss, or can be used to trick experienced and | ||
93 | /// cautious users into unwanted situations, or changes global data | ||
94 | /// permanently and without undo ability. | ||
95 | /// </summary> | ||
96 | High = 5, | 51 | High = 5, |
97 | |||
98 | /// <summary> | ||
99 | /// Even normal use may, depending on the number of instances, or | ||
100 | /// frequency of use, result in severe service impairment or crash | ||
101 | /// with loss of data, or can be used to cause unwanted or harmful | ||
102 | /// effects on users without giving the user a means to avoid it. | ||
103 | /// </summary> | ||
104 | VeryHigh = 6, | 52 | VeryHigh = 6, |
105 | |||
106 | /// <summary> | ||
107 | /// Even casual use is a danger to region stability, or function allows | ||
108 | /// console or OS command execution, or function allows taking money | ||
109 | /// without consent, or allows deletion or modification of user data, | ||
110 | /// or allows the compromise of sensitive data by design. | ||
111 | /// </summary> | ||
112 | Severe = 7 | 53 | Severe = 7 |
113 | }; | 54 | }; |
114 | 55 | ||
@@ -157,7 +98,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces | |||
157 | void osAvatarPlayAnimation(string avatar, string animation); | 98 | void osAvatarPlayAnimation(string avatar, string animation); |
158 | void osAvatarStopAnimation(string avatar, string animation); | 99 | void osAvatarStopAnimation(string avatar, string animation); |
159 | 100 | ||
160 | #region Attachment commands | 101 | // Attachment commands |
161 | 102 | ||
162 | /// <summary> | 103 | /// <summary> |
163 | /// Attach the object containing this script to the avatar that owns it without asking for PERMISSION_ATTACH | 104 | /// Attach the object containing this script to the avatar that owns it without asking for PERMISSION_ATTACH |
@@ -192,29 +133,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces | |||
192 | /// <remarks>Nothing happens if the object is not attached.</remarks> | 133 | /// <remarks>Nothing happens if the object is not attached.</remarks> |
193 | void osForceDetachFromAvatar(); | 134 | void osForceDetachFromAvatar(); |
194 | 135 | ||
195 | /// <summary> | ||
196 | /// Returns a strided list of the specified attachment points and the number of attachments on those points. | ||
197 | /// </summary> | ||
198 | /// <param name="avatar">avatar UUID</param> | ||
199 | /// <param name="attachmentPoints">list of ATTACH_* constants</param> | ||
200 | /// <returns></returns> | ||
201 | LSL_List osGetNumberOfAttachments(LSL_Key avatar, LSL_List attachmentPoints); | ||
202 | |||
203 | /// <summary> | ||
204 | /// Sends a specified message to the specified avatar's attachments on | ||
205 | /// the specified attachment points. | ||
206 | /// </summary> | ||
207 | /// <remarks> | ||
208 | /// Behaves as osMessageObject(), without the sending script needing to know the attachment keys in advance. | ||
209 | /// </remarks> | ||
210 | /// <param name="avatar">avatar UUID</param> | ||
211 | /// <param name="message">message string</param> | ||
212 | /// <param name="attachmentPoints">list of ATTACH_* constants, or -1 for all attachments. If -1 is specified and OS_ATTACH_MSG_INVERT_POINTS is present in flags, no action is taken.</param> | ||
213 | /// <param name="flags">flags further constraining the attachments to deliver the message to.</param> | ||
214 | void osMessageAttachments(LSL_Key avatar, string message, LSL_List attachmentPoints, int flags); | ||
215 | |||
216 | #endregion | ||
217 | |||
218 | //texture draw functions | 136 | //texture draw functions |
219 | string osMovePen(string drawList, int x, int y); | 137 | string osMovePen(string drawList, int x, int y); |
220 | string osDrawLine(string drawList, int startX, int startY, int endX, int endY); | 138 | string osDrawLine(string drawList, int startX, int startY, int endX, int endY); |
@@ -340,7 +258,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces | |||
340 | int osGetSimulatorMemory(); | 258 | int osGetSimulatorMemory(); |
341 | void osKickAvatar(string FirstName,string SurName,string alert); | 259 | void osKickAvatar(string FirstName,string SurName,string alert); |
342 | void osSetSpeed(string UUID, LSL_Float SpeedModifier); | 260 | void osSetSpeed(string UUID, LSL_Float SpeedModifier); |
343 | LSL_Float osGetHealth(string avatar); | ||
344 | void osCauseHealing(string avatar, double healing); | 261 | void osCauseHealing(string avatar, double healing); |
345 | void osCauseDamage(string avatar, double damage); | 262 | void osCauseDamage(string avatar, double damage); |
346 | LSL_List osGetPrimitiveParams(LSL_Key prim, LSL_List rules); | 263 | LSL_List osGetPrimitiveParams(LSL_Key prim, LSL_List rules); |
@@ -388,59 +305,5 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces | |||
388 | /// </summary> | 305 | /// </summary> |
389 | /// <returns>Rezzing object key or NULL_KEY if rezzed by agent or otherwise unknown.</returns> | 306 | /// <returns>Rezzing object key or NULL_KEY if rezzed by agent or otherwise unknown.</returns> |
390 | LSL_Key osGetRezzingObject(); | 307 | LSL_Key osGetRezzingObject(); |
391 | |||
392 | /// <summary> | ||
393 | /// Sets the response type for an HTTP request/response | ||
394 | /// </summary> | ||
395 | /// <returns></returns> | ||
396 | void osSetContentType(LSL_Key id, string type); | ||
397 | |||
398 | /// <summary> | ||
399 | /// Attempts to drop an attachment to the ground | ||
400 | /// </summary> | ||
401 | void osDropAttachment(); | ||
402 | |||
403 | /// <summary> | ||
404 | /// Attempts to drop an attachment to the ground while bypassing the script permissions | ||
405 | /// </summary> | ||
406 | void osForceDropAttachment(); | ||
407 | |||
408 | /// <summary> | ||
409 | /// Attempts to drop an attachment at the specified coordinates. | ||
410 | /// </summary> | ||
411 | /// <param name="pos"></param> | ||
412 | /// <param name="rot"></param> | ||
413 | void osDropAttachmentAt(vector pos, rotation rot); | ||
414 | |||
415 | /// <summary> | ||
416 | /// Attempts to drop an attachment at the specified coordinates while bypassing the script permissions | ||
417 | /// </summary> | ||
418 | /// <param name="pos"></param> | ||
419 | /// <param name="rot"></param> | ||
420 | void osForceDropAttachmentAt(vector pos, rotation rot); | ||
421 | |||
422 | /// <summary> | ||
423 | /// Identical to llListen except for a bitfield which indicates which | ||
424 | /// string parameters should be parsed as regex patterns. | ||
425 | /// </summary> | ||
426 | /// <param name="channelID"></param> | ||
427 | /// <param name="name"></param> | ||
428 | /// <param name="ID"></param> | ||
429 | /// <param name="msg"></param> | ||
430 | /// <param name="regexBitfield"> | ||
431 | /// OS_LISTEN_REGEX_NAME | ||
432 | /// OS_LISTEN_REGEX_MESSAGE | ||
433 | /// </param> | ||
434 | /// <returns></returns> | ||
435 | LSL_Integer osListenRegex(int channelID, string name, string ID, | ||
436 | string msg, int regexBitfield); | ||
437 | |||
438 | /// <summary> | ||
439 | /// Wraps to bool Regex.IsMatch(string input, string pattern) | ||
440 | /// </summary> | ||
441 | /// <param name="input">string to test for match</param> | ||
442 | /// <param name="regex">string to use as pattern</param> | ||
443 | /// <returns>boolean</returns> | ||
444 | LSL_Integer osRegexIsMatch(string input, string pattern); | ||
445 | } | 308 | } |
446 | } | 309 | } |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs index 0dd5a57..f989cc6 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs | |||
@@ -237,58 +237,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase | |||
237 | public const int ATTACH_HUD_BOTTOM = 37; | 237 | public const int ATTACH_HUD_BOTTOM = 37; |
238 | public const int ATTACH_HUD_BOTTOM_RIGHT = 38; | 238 | public const int ATTACH_HUD_BOTTOM_RIGHT = 38; |
239 | 239 | ||
240 | #region osMessageAttachments constants | ||
241 | |||
242 | /// <summary> | ||
243 | /// Instructs osMessageAttachements to send the message to attachments | ||
244 | /// on every point. | ||
245 | /// </summary> | ||
246 | /// <remarks> | ||
247 | /// One might expect this to be named OS_ATTACH_ALL, but then one might | ||
248 | /// also expect functions designed to attach or detach or get | ||
249 | /// attachments to work with it too. Attaching a no-copy item to | ||
250 | /// many attachments could be dangerous. | ||
251 | /// when combined with OS_ATTACH_MSG_INVERT_POINTS, will prevent the | ||
252 | /// message from being sent. | ||
253 | /// if combined with OS_ATTACH_MSG_OBJECT_CREATOR or | ||
254 | /// OS_ATTACH_MSG_SCRIPT_CREATOR, could result in no message being | ||
255 | /// sent- this is expected behaviour. | ||
256 | /// </remarks> | ||
257 | public const int OS_ATTACH_MSG_ALL = -65535; | ||
258 | |||
259 | /// <summary> | ||
260 | /// Instructs osMessageAttachements to invert how the attachment points | ||
261 | /// list should be treated (e.g. go from inclusive operation to | ||
262 | /// exclusive operation). | ||
263 | /// </summary> | ||
264 | /// <remarks> | ||
265 | /// This might be used if you want to deliver a message to one set of | ||
266 | /// attachments and a different message to everything else. With | ||
267 | /// this flag, you only need to build one explicit list for both calls. | ||
268 | /// </remarks> | ||
269 | public const int OS_ATTACH_MSG_INVERT_POINTS = 1; | ||
270 | |||
271 | /// <summary> | ||
272 | /// Instructs osMessageAttachments to only send the message to | ||
273 | /// attachments with a CreatorID that matches the host object CreatorID | ||
274 | /// </summary> | ||
275 | /// <remarks> | ||
276 | /// This would be used if distributed in an object vendor/updater server. | ||
277 | /// </remarks> | ||
278 | public const int OS_ATTACH_MSG_OBJECT_CREATOR = 2; | ||
279 | |||
280 | /// <summary> | ||
281 | /// Instructs osMessageAttachments to only send the message to | ||
282 | /// attachments with a CreatorID that matches the sending script CreatorID | ||
283 | /// </summary> | ||
284 | /// <remarks> | ||
285 | /// This might be used if the script is distributed independently of a | ||
286 | /// containing object. | ||
287 | /// </remarks> | ||
288 | public const int OS_ATTACH_MSG_SCRIPT_CREATOR = 4; | ||
289 | |||
290 | #endregion | ||
291 | |||
292 | public const int LAND_LEVEL = 0; | 240 | public const int LAND_LEVEL = 0; |
293 | public const int LAND_RAISE = 1; | 241 | public const int LAND_RAISE = 1; |
294 | public const int LAND_LOWER = 2; | 242 | public const int LAND_LOWER = 2; |
@@ -381,7 +329,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase | |||
381 | public const int PRIM_OMEGA = 32; | 329 | public const int PRIM_OMEGA = 32; |
382 | public const int PRIM_POS_LOCAL = 33; | 330 | public const int PRIM_POS_LOCAL = 33; |
383 | public const int PRIM_LINK_TARGET = 34; | 331 | public const int PRIM_LINK_TARGET = 34; |
384 | public const int PRIM_SLICE = 35; | ||
385 | public const int PRIM_TEXGEN_DEFAULT = 0; | 332 | public const int PRIM_TEXGEN_DEFAULT = 0; |
386 | public const int PRIM_TEXGEN_PLANAR = 1; | 333 | public const int PRIM_TEXGEN_PLANAR = 1; |
387 | 334 | ||
@@ -613,7 +560,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase | |||
613 | public const int CLICK_ACTION_OPEN = 4; | 560 | public const int CLICK_ACTION_OPEN = 4; |
614 | public const int CLICK_ACTION_PLAY = 5; | 561 | public const int CLICK_ACTION_PLAY = 5; |
615 | public const int CLICK_ACTION_OPEN_MEDIA = 6; | 562 | public const int CLICK_ACTION_OPEN_MEDIA = 6; |
616 | public const int CLICK_ACTION_ZOOM = 7; | ||
617 | 563 | ||
618 | // constants for the llDetectedTouch* functions | 564 | // constants for the llDetectedTouch* functions |
619 | public const int TOUCH_INVALID_FACE = -1; | 565 | public const int TOUCH_INVALID_FACE = -1; |
@@ -741,15 +687,5 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase | |||
741 | public const int KFM_CMD_PLAY = 0; | 687 | public const int KFM_CMD_PLAY = 0; |
742 | public const int KFM_CMD_STOP = 1; | 688 | public const int KFM_CMD_STOP = 1; |
743 | public const int KFM_CMD_PAUSE = 2; | 689 | public const int KFM_CMD_PAUSE = 2; |
744 | |||
745 | /// <summary> | ||
746 | /// process name parameter as regex | ||
747 | /// </summary> | ||
748 | public const int OS_LISTEN_REGEX_NAME = 0x1; | ||
749 | |||
750 | /// <summary> | ||
751 | /// process message parameter as regex | ||
752 | /// </summary> | ||
753 | public const int OS_LISTEN_REGEX_MESSAGE = 0x2; | ||
754 | } | 690 | } |
755 | } | 691 | } |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs index afa9ae0..94405d2 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs | |||
@@ -289,7 +289,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase | |||
289 | m_OSSL_Functions.osAvatarStopAnimation(avatar, animation); | 289 | m_OSSL_Functions.osAvatarStopAnimation(avatar, animation); |
290 | } | 290 | } |
291 | 291 | ||
292 | #region Attachment commands | 292 | // Avatar functions |
293 | 293 | ||
294 | public void osForceAttachToAvatar(int attachmentPoint) | 294 | public void osForceAttachToAvatar(int attachmentPoint) |
295 | { | 295 | { |
@@ -311,18 +311,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase | |||
311 | m_OSSL_Functions.osForceDetachFromAvatar(); | 311 | m_OSSL_Functions.osForceDetachFromAvatar(); |
312 | } | 312 | } |
313 | 313 | ||
314 | public LSL_List osGetNumberOfAttachments(LSL_Key avatar, LSL_List attachmentPoints) | ||
315 | { | ||
316 | return m_OSSL_Functions.osGetNumberOfAttachments(avatar, attachmentPoints); | ||
317 | } | ||
318 | |||
319 | public void osMessageAttachments(LSL_Key avatar, string message, LSL_List attachmentPoints, int flags) | ||
320 | { | ||
321 | m_OSSL_Functions.osMessageAttachments(avatar, message, attachmentPoints, flags); | ||
322 | } | ||
323 | |||
324 | #endregion | ||
325 | |||
326 | // Texture Draw functions | 314 | // Texture Draw functions |
327 | 315 | ||
328 | public string osMovePen(string drawList, int x, int y) | 316 | public string osMovePen(string drawList, int x, int y) |
@@ -877,12 +865,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase | |||
877 | { | 865 | { |
878 | m_OSSL_Functions.osSetSpeed(UUID, SpeedModifier); | 866 | m_OSSL_Functions.osSetSpeed(UUID, SpeedModifier); |
879 | } | 867 | } |
880 | 868 | ||
881 | public LSL_Float osGetHealth(string avatar) | ||
882 | { | ||
883 | return m_OSSL_Functions.osGetHealth(avatar); | ||
884 | } | ||
885 | |||
886 | public void osCauseDamage(string avatar, double damage) | 869 | public void osCauseDamage(string avatar, double damage) |
887 | { | 870 | { |
888 | m_OSSL_Functions.osCauseDamage(avatar, damage); | 871 | m_OSSL_Functions.osCauseDamage(avatar, damage); |
@@ -967,40 +950,5 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase | |||
967 | { | 950 | { |
968 | return m_OSSL_Functions.osGetRezzingObject(); | 951 | return m_OSSL_Functions.osGetRezzingObject(); |
969 | } | 952 | } |
970 | |||
971 | public void osSetContentType(LSL_Key id, string type) | ||
972 | { | ||
973 | m_OSSL_Functions.osSetContentType(id,type); | ||
974 | } | ||
975 | |||
976 | public void osDropAttachment() | ||
977 | { | ||
978 | m_OSSL_Functions.osDropAttachment(); | ||
979 | } | ||
980 | |||
981 | public void osForceDropAttachment() | ||
982 | { | ||
983 | m_OSSL_Functions.osForceDropAttachment(); | ||
984 | } | ||
985 | |||
986 | public void osDropAttachmentAt(vector pos, rotation rot) | ||
987 | { | ||
988 | m_OSSL_Functions.osDropAttachmentAt(pos, rot); | ||
989 | } | ||
990 | |||
991 | public void osForceDropAttachmentAt(vector pos, rotation rot) | ||
992 | { | ||
993 | m_OSSL_Functions.osForceDropAttachmentAt(pos, rot); | ||
994 | } | ||
995 | |||
996 | public LSL_Integer osListenRegex(int channelID, string name, string ID, string msg, int regexBitfield) | ||
997 | { | ||
998 | return m_OSSL_Functions.osListenRegex(channelID, name, ID, msg, regexBitfield); | ||
999 | } | ||
1000 | |||
1001 | public LSL_Integer osRegexIsMatch(string input, string pattern) | ||
1002 | { | ||
1003 | return m_OSSL_Functions.osRegexIsMatch(input, pattern); | ||
1004 | } | ||
1005 | } | 953 | } |
1006 | } | 954 | } |
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs index 03be2ab..17a0d69 100644 --- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs +++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs | |||
@@ -546,8 +546,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools | |||
546 | "OpenSim.Region.ScriptEngine.Shared.dll")); | 546 | "OpenSim.Region.ScriptEngine.Shared.dll")); |
547 | parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, | 547 | parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, |
548 | "OpenSim.Region.ScriptEngine.Shared.Api.Runtime.dll")); | 548 | "OpenSim.Region.ScriptEngine.Shared.Api.Runtime.dll")); |
549 | parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, | ||
550 | "OpenMetaverseTypes.dll")); | ||
551 | 549 | ||
552 | if (lang == enumCompileType.yp) | 550 | if (lang == enumCompileType.yp) |
553 | { | 551 | { |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs index 22804f5..9e5fb24 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs | |||
@@ -164,11 +164,11 @@ namespace OpenSim.Region.ScriptEngine.Shared | |||
164 | else | 164 | else |
165 | { | 165 | { |
166 | // Set the values from the touch data provided by the client | 166 | // Set the values from the touch data provided by the client |
167 | touchST = new LSL_Types.Vector3(value.STCoord); | 167 | touchST = new LSL_Types.Vector3(value.STCoord.X, value.STCoord.Y, value.STCoord.Z); |
168 | touchUV = new LSL_Types.Vector3(value.UVCoord); | 168 | touchUV = new LSL_Types.Vector3(value.UVCoord.X, value.UVCoord.Y, value.UVCoord.Z); |
169 | touchNormal = new LSL_Types.Vector3(value.Normal); | 169 | touchNormal = new LSL_Types.Vector3(value.Normal.X, value.Normal.Y, value.Normal.Z); |
170 | touchBinormal = new LSL_Types.Vector3(value.Binormal); | 170 | touchBinormal = new LSL_Types.Vector3(value.Binormal.X, value.Binormal.Y, value.Binormal.Z); |
171 | touchPos = new LSL_Types.Vector3(value.Position); | 171 | touchPos = new LSL_Types.Vector3(value.Position.X, value.Position.Y, value.Position.Z); |
172 | touchFace = value.FaceIndex; | 172 | touchFace = value.FaceIndex; |
173 | } | 173 | } |
174 | } | 174 | } |
@@ -189,13 +189,19 @@ namespace OpenSim.Region.ScriptEngine.Shared | |||
189 | Country = account.UserCountry; | 189 | Country = account.UserCountry; |
190 | 190 | ||
191 | Owner = Key; | 191 | Owner = Key; |
192 | Position = new LSL_Types.Vector3(presence.AbsolutePosition); | 192 | Position = new LSL_Types.Vector3( |
193 | presence.AbsolutePosition.X, | ||
194 | presence.AbsolutePosition.Y, | ||
195 | presence.AbsolutePosition.Z); | ||
193 | Rotation = new LSL_Types.Quaternion( | 196 | Rotation = new LSL_Types.Quaternion( |
194 | presence.Rotation.X, | 197 | presence.Rotation.X, |
195 | presence.Rotation.Y, | 198 | presence.Rotation.Y, |
196 | presence.Rotation.Z, | 199 | presence.Rotation.Z, |
197 | presence.Rotation.W); | 200 | presence.Rotation.W); |
198 | Velocity = new LSL_Types.Vector3(presence.Velocity); | 201 | Velocity = new LSL_Types.Vector3( |
202 | presence.Velocity.X, | ||
203 | presence.Velocity.Y, | ||
204 | presence.Velocity.Z); | ||
199 | 205 | ||
200 | Type = 0x01; // Avatar | 206 | Type = 0x01; // Avatar |
201 | if (presence.PresenceType == PresenceType.Npc) | 207 | if (presence.PresenceType == PresenceType.Npc) |
@@ -248,12 +254,16 @@ namespace OpenSim.Region.ScriptEngine.Shared | |||
248 | } | 254 | } |
249 | } | 255 | } |
250 | 256 | ||
251 | Position = new LSL_Types.Vector3(part.AbsolutePosition); | 257 | Position = new LSL_Types.Vector3(part.AbsolutePosition.X, |
258 | part.AbsolutePosition.Y, | ||
259 | part.AbsolutePosition.Z); | ||
252 | 260 | ||
253 | Quaternion wr = part.ParentGroup.GroupRotation; | 261 | Quaternion wr = part.ParentGroup.GroupRotation; |
254 | Rotation = new LSL_Types.Quaternion(wr.X, wr.Y, wr.Z, wr.W); | 262 | Rotation = new LSL_Types.Quaternion(wr.X, wr.Y, wr.Z, wr.W); |
255 | 263 | ||
256 | Velocity = new LSL_Types.Vector3(part.Velocity); | 264 | Velocity = new LSL_Types.Vector3(part.Velocity.X, |
265 | part.Velocity.Y, | ||
266 | part.Velocity.Z); | ||
257 | } | 267 | } |
258 | } | 268 | } |
259 | 269 | ||
diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs index c9c4753..8adf4c5 100644 --- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs +++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs | |||
@@ -31,11 +31,6 @@ using System.Globalization; | |||
31 | using System.Text.RegularExpressions; | 31 | using System.Text.RegularExpressions; |
32 | using OpenSim.Framework; | 32 | using OpenSim.Framework; |
33 | 33 | ||
34 | using OpenMetaverse; | ||
35 | using OMV_Vector3 = OpenMetaverse.Vector3; | ||
36 | using OMV_Vector3d = OpenMetaverse.Vector3d; | ||
37 | using OMV_Quaternion = OpenMetaverse.Quaternion; | ||
38 | |||
39 | namespace OpenSim.Region.ScriptEngine.Shared | 34 | namespace OpenSim.Region.ScriptEngine.Shared |
40 | { | 35 | { |
41 | [Serializable] | 36 | [Serializable] |
@@ -59,20 +54,6 @@ namespace OpenSim.Region.ScriptEngine.Shared | |||
59 | z = (float)vector.z; | 54 | z = (float)vector.z; |
60 | } | 55 | } |
61 | 56 | ||
62 | public Vector3(OMV_Vector3 vector) | ||
63 | { | ||
64 | x = vector.X; | ||
65 | y = vector.Y; | ||
66 | z = vector.Z; | ||
67 | } | ||
68 | |||
69 | public Vector3(OMV_Vector3d vector) | ||
70 | { | ||
71 | x = vector.X; | ||
72 | y = vector.Y; | ||
73 | z = vector.Z; | ||
74 | } | ||
75 | |||
76 | public Vector3(double X, double Y, double Z) | 57 | public Vector3(double X, double Y, double Z) |
77 | { | 58 | { |
78 | x = X; | 59 | x = X; |
@@ -128,26 +109,6 @@ namespace OpenSim.Region.ScriptEngine.Shared | |||
128 | return new list(new object[] { vec }); | 109 | return new list(new object[] { vec }); |
129 | } | 110 | } |
130 | 111 | ||
131 | public static implicit operator OMV_Vector3(Vector3 vec) | ||
132 | { | ||
133 | return new OMV_Vector3((float)vec.x, (float)vec.y, (float)vec.z); | ||
134 | } | ||
135 | |||
136 | public static implicit operator Vector3(OMV_Vector3 vec) | ||
137 | { | ||
138 | return new Vector3(vec); | ||
139 | } | ||
140 | |||
141 | public static implicit operator OMV_Vector3d(Vector3 vec) | ||
142 | { | ||
143 | return new OMV_Vector3d(vec.x, vec.y, vec.z); | ||
144 | } | ||
145 | |||
146 | public static implicit operator Vector3(OMV_Vector3d vec) | ||
147 | { | ||
148 | return new Vector3(vec); | ||
149 | } | ||
150 | |||
151 | public static bool operator ==(Vector3 lhs, Vector3 rhs) | 112 | public static bool operator ==(Vector3 lhs, Vector3 rhs) |
152 | { | 113 | { |
153 | return (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z); | 114 | return (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z); |
@@ -361,14 +322,6 @@ namespace OpenSim.Region.ScriptEngine.Shared | |||
361 | s = 1; | 322 | s = 1; |
362 | } | 323 | } |
363 | 324 | ||
364 | public Quaternion(OMV_Quaternion rot) | ||
365 | { | ||
366 | x = rot.X; | ||
367 | y = rot.Y; | ||
368 | z = rot.Z; | ||
369 | s = rot.W; | ||
370 | } | ||
371 | |||
372 | #endregion | 325 | #endregion |
373 | 326 | ||
374 | #region Overriders | 327 | #region Overriders |
@@ -415,21 +368,6 @@ namespace OpenSim.Region.ScriptEngine.Shared | |||
415 | return new list(new object[] { r }); | 368 | return new list(new object[] { r }); |
416 | } | 369 | } |
417 | 370 | ||
418 | public static implicit operator OMV_Quaternion(Quaternion rot) | ||
419 | { | ||
420 | // LSL quaternions can normalize to 0, normal Quaternions can't. | ||
421 | if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0) | ||
422 | rot.z = 1; // ZERO_ROTATION = 0,0,0,1 | ||
423 | OMV_Quaternion omvrot = new OMV_Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s); | ||
424 | omvrot.Normalize(); | ||
425 | return omvrot; | ||
426 | } | ||
427 | |||
428 | public static implicit operator Quaternion(OMV_Quaternion rot) | ||
429 | { | ||
430 | return new Quaternion(rot); | ||
431 | } | ||
432 | |||
433 | public static bool operator ==(Quaternion lhs, Quaternion rhs) | 371 | public static bool operator ==(Quaternion lhs, Quaternion rhs) |
434 | { | 372 | { |
435 | // Return true if the fields match: | 373 | // Return true if the fields match: |
@@ -624,23 +562,12 @@ namespace OpenSim.Region.ScriptEngine.Shared | |||
624 | else if (m_data[itemIndex] is LSL_Types.LSLString) | 562 | else if (m_data[itemIndex] is LSL_Types.LSLString) |
625 | return new LSLInteger(m_data[itemIndex].ToString()); | 563 | return new LSLInteger(m_data[itemIndex].ToString()); |
626 | else | 564 | else |
627 | throw new InvalidCastException(string.Format( | 565 | throw new InvalidCastException(); |
628 | "{0} expected but {1} given", | ||
629 | typeof(LSL_Types.LSLInteger).Name, | ||
630 | m_data[itemIndex] != null ? | ||
631 | m_data[itemIndex].GetType().Name : "null")); | ||
632 | } | 566 | } |
633 | 567 | ||
634 | public LSL_Types.Vector3 GetVector3Item(int itemIndex) | 568 | public LSL_Types.Vector3 GetVector3Item(int itemIndex) |
635 | { | 569 | { |
636 | if(m_data[itemIndex] is LSL_Types.Vector3) | 570 | return (LSL_Types.Vector3)m_data[itemIndex]; |
637 | return (LSL_Types.Vector3)m_data[itemIndex]; | ||
638 | else | ||
639 | throw new InvalidCastException(string.Format( | ||
640 | "{0} expected but {1} given", | ||
641 | typeof(LSL_Types.Vector3).Name, | ||
642 | m_data[itemIndex] != null ? | ||
643 | m_data[itemIndex].GetType().Name : "null")); | ||
644 | } | 571 | } |
645 | 572 | ||
646 | public LSL_Types.Quaternion GetQuaternionItem(int itemIndex) | 573 | public LSL_Types.Quaternion GetQuaternionItem(int itemIndex) |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs deleted file mode 100644 index dd23be8..0000000 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs +++ /dev/null | |||
@@ -1,134 +0,0 @@ | |||
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 | using System.Collections.Generic; | ||
30 | using NUnit.Framework; | ||
31 | using OpenSim.Framework; | ||
32 | using OpenSim.Tests.Common; | ||
33 | using OpenSim.Region.ScriptEngine.Shared; | ||
34 | using OpenSim.Region.Framework.Scenes; | ||
35 | using Nini.Config; | ||
36 | using OpenSim.Region.ScriptEngine.Shared.Api; | ||
37 | using OpenSim.Region.ScriptEngine.Shared.ScriptBase; | ||
38 | using OpenMetaverse; | ||
39 | using OpenSim.Tests.Common.Mock; | ||
40 | |||
41 | using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; | ||
42 | using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; | ||
43 | using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list; | ||
44 | using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; | ||
45 | |||
46 | namespace OpenSim.Region.ScriptEngine.Shared.Tests | ||
47 | { | ||
48 | [TestFixture] | ||
49 | public class LSL_ApiListTests | ||
50 | { | ||
51 | private LSL_Api m_lslApi; | ||
52 | |||
53 | [SetUp] | ||
54 | public void SetUp() | ||
55 | { | ||
56 | IConfigSource initConfigSource = new IniConfigSource(); | ||
57 | IConfig config = initConfigSource.AddConfig("XEngine"); | ||
58 | config.Set("Enabled", "true"); | ||
59 | |||
60 | Scene scene = new SceneHelpers().SetupScene(); | ||
61 | SceneObjectPart part = SceneHelpers.AddSceneObject(scene).RootPart; | ||
62 | |||
63 | XEngine.XEngine engine = new XEngine.XEngine(); | ||
64 | engine.Initialise(initConfigSource); | ||
65 | engine.AddRegion(scene); | ||
66 | |||
67 | m_lslApi = new LSL_Api(); | ||
68 | m_lslApi.Initialize(engine, part, null); | ||
69 | } | ||
70 | |||
71 | [Test] | ||
72 | public void TestllListFindList() | ||
73 | { | ||
74 | TestHelpers.InMethod(); | ||
75 | |||
76 | LSL_List src = new LSL_List(new LSL_Integer(1), new LSL_Integer(2), new LSL_Integer(3)); | ||
77 | |||
78 | { | ||
79 | // Test for a single item that should be found | ||
80 | int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_Integer(4))); | ||
81 | Assert.That(result, Is.EqualTo(-1)); | ||
82 | } | ||
83 | |||
84 | { | ||
85 | // Test for a single item that should be found | ||
86 | int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_Integer(2))); | ||
87 | Assert.That(result, Is.EqualTo(1)); | ||
88 | } | ||
89 | |||
90 | { | ||
91 | // Test for a constant that should be found | ||
92 | int result = m_lslApi.llListFindList(src, new LSL_List(ScriptBaseClass.AGENT)); | ||
93 | Assert.That(result, Is.EqualTo(0)); | ||
94 | } | ||
95 | |||
96 | { | ||
97 | // Test for a list that should be found | ||
98 | int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_Integer(2), new LSL_Integer(3))); | ||
99 | Assert.That(result, Is.EqualTo(1)); | ||
100 | } | ||
101 | |||
102 | { | ||
103 | // Test for a single item not in the list | ||
104 | int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_Integer(4))); | ||
105 | Assert.That(result, Is.EqualTo(-1)); | ||
106 | } | ||
107 | |||
108 | { | ||
109 | // Test for something that should not be cast | ||
110 | int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_String("4"))); | ||
111 | Assert.That(result, Is.EqualTo(-1)); | ||
112 | } | ||
113 | |||
114 | { | ||
115 | // Test for a list not in the list | ||
116 | int result | ||
117 | = m_lslApi.llListFindList( | ||
118 | src, new LSL_List(new LSL_Integer(2), new LSL_Integer(3), new LSL_Integer(4))); | ||
119 | Assert.That(result, Is.EqualTo(-1)); | ||
120 | } | ||
121 | |||
122 | { | ||
123 | LSL_List srcWithConstants | ||
124 | = new LSL_List(new LSL_Integer(3), ScriptBaseClass.AGENT, ScriptBaseClass.OS_NPC_LAND_AT_TARGET); | ||
125 | |||
126 | // Test for constants that appears in the source list that should be found | ||
127 | int result | ||
128 | = m_lslApi.llListFindList(srcWithConstants, new LSL_List(new LSL_Integer(1), new LSL_Integer(2))); | ||
129 | |||
130 | Assert.That(result, Is.EqualTo(1)); | ||
131 | } | ||
132 | } | ||
133 | } | ||
134 | } \ No newline at end of file | ||
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs index c401794..c8718d9 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs | |||
@@ -75,6 +75,76 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests | |||
75 | m_engine.AddRegion(m_scene); | 75 | m_engine.AddRegion(m_scene); |
76 | } | 76 | } |
77 | 77 | ||
78 | /// <summary> | ||
79 | /// Test creation of an NPC where the appearance data comes from a notecard | ||
80 | /// </summary> | ||
81 | [Test] | ||
82 | public void TestOsNpcCreateUsingAppearanceFromNotecard() | ||
83 | { | ||
84 | TestHelpers.InMethod(); | ||
85 | // log4net.Config.XmlConfigurator.Configure(); | ||
86 | |||
87 | // Store an avatar with a different height from default in a notecard. | ||
88 | UUID userId = TestHelpers.ParseTail(0x1); | ||
89 | float newHeight = 1.9f; | ||
90 | |||
91 | ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); | ||
92 | sp.Appearance.AvatarHeight = newHeight; | ||
93 | SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); | ||
94 | SceneObjectPart part = so.RootPart; | ||
95 | m_scene.AddSceneObject(so); | ||
96 | |||
97 | OSSL_Api osslApi = new OSSL_Api(); | ||
98 | osslApi.Initialize(m_engine, part, null); | ||
99 | |||
100 | string notecardName = "appearanceNc"; | ||
101 | osslApi.osOwnerSaveAppearance(notecardName); | ||
102 | |||
103 | // Try creating a bot using the appearance in the notecard. | ||
104 | string npcRaw = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), notecardName); | ||
105 | Assert.That(npcRaw, Is.Not.Null); | ||
106 | |||
107 | UUID npcId = new UUID(npcRaw); | ||
108 | ScenePresence npc = m_scene.GetScenePresence(npcId); | ||
109 | Assert.That(npc, Is.Not.Null); | ||
110 | Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(newHeight)); | ||
111 | } | ||
112 | |||
113 | /// <summary> | ||
114 | /// Test creation of an NPC where the appearance data comes from an avatar already in the region. | ||
115 | /// </summary> | ||
116 | [Test] | ||
117 | public void TestOsNpcCreateUsingAppearanceFromAvatar() | ||
118 | { | ||
119 | TestHelpers.InMethod(); | ||
120 | // TestHelpers.EnableLogging(); | ||
121 | |||
122 | // Store an avatar with a different height from default in a notecard. | ||
123 | UUID userId = TestHelpers.ParseTail(0x1); | ||
124 | float newHeight = 1.9f; | ||
125 | |||
126 | ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); | ||
127 | sp.Appearance.AvatarHeight = newHeight; | ||
128 | SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); | ||
129 | SceneObjectPart part = so.RootPart; | ||
130 | m_scene.AddSceneObject(so); | ||
131 | |||
132 | OSSL_Api osslApi = new OSSL_Api(); | ||
133 | osslApi.Initialize(m_engine, part, null); | ||
134 | |||
135 | string notecardName = "appearanceNc"; | ||
136 | osslApi.osOwnerSaveAppearance(notecardName); | ||
137 | |||
138 | // Try creating a bot using the existing avatar's appearance | ||
139 | string npcRaw = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), sp.UUID.ToString()); | ||
140 | Assert.That(npcRaw, Is.Not.Null); | ||
141 | |||
142 | UUID npcId = new UUID(npcRaw); | ||
143 | ScenePresence npc = m_scene.GetScenePresence(npcId); | ||
144 | Assert.That(npc, Is.Not.Null); | ||
145 | Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(newHeight)); | ||
146 | } | ||
147 | |||
78 | [Test] | 148 | [Test] |
79 | public void TestOsOwnerSaveAppearance() | 149 | public void TestOsOwnerSaveAppearance() |
80 | { | 150 | { |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs index b49bcc2..25679a6 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs | |||
@@ -36,7 +36,6 @@ using OpenMetaverse; | |||
36 | using OpenMetaverse.Assets; | 36 | using OpenMetaverse.Assets; |
37 | using OpenMetaverse.StructuredData; | 37 | using OpenMetaverse.StructuredData; |
38 | using OpenSim.Framework; | 38 | using OpenSim.Framework; |
39 | using OpenSim.Region.CoreModules.Avatar.Attachments; | ||
40 | using OpenSim.Region.CoreModules.Avatar.AvatarFactory; | 39 | using OpenSim.Region.CoreModules.Avatar.AvatarFactory; |
41 | using OpenSim.Region.OptionalModules.World.NPC; | 40 | using OpenSim.Region.OptionalModules.World.NPC; |
42 | using OpenSim.Region.Framework.Scenes; | 41 | using OpenSim.Region.Framework.Scenes; |
@@ -72,8 +71,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests | |||
72 | config.Set("Enabled", "true"); | 71 | config.Set("Enabled", "true"); |
73 | 72 | ||
74 | m_scene = new SceneHelpers().SetupScene(); | 73 | m_scene = new SceneHelpers().SetupScene(); |
75 | SceneHelpers.SetupSceneModules( | 74 | SceneHelpers.SetupSceneModules(m_scene, initConfigSource, new AvatarFactoryModule(), new NPCModule()); |
76 | m_scene, initConfigSource, new AvatarFactoryModule(), new AttachmentsModule(), new NPCModule()); | ||
77 | 75 | ||
78 | m_engine = new XEngine.XEngine(); | 76 | m_engine = new XEngine.XEngine(); |
79 | m_engine.Initialise(initConfigSource); | 77 | m_engine.Initialise(initConfigSource); |
@@ -81,191 +79,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests | |||
81 | } | 79 | } |
82 | 80 | ||
83 | /// <summary> | 81 | /// <summary> |
84 | /// Test creation of an NPC where the appearance data comes from a notecard | ||
85 | /// </summary> | ||
86 | [Test] | ||
87 | public void TestOsNpcCreateUsingAppearanceFromNotecard() | ||
88 | { | ||
89 | TestHelpers.InMethod(); | ||
90 | |||
91 | // Store an avatar with a different height from default in a notecard. | ||
92 | UUID userId = TestHelpers.ParseTail(0x1); | ||
93 | float newHeight = 1.9f; | ||
94 | |||
95 | ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); | ||
96 | sp.Appearance.AvatarHeight = newHeight; | ||
97 | SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); | ||
98 | SceneObjectPart part = so.RootPart; | ||
99 | m_scene.AddSceneObject(so); | ||
100 | |||
101 | OSSL_Api osslApi = new OSSL_Api(); | ||
102 | osslApi.Initialize(m_engine, part, null); | ||
103 | |||
104 | string notecardName = "appearanceNc"; | ||
105 | osslApi.osOwnerSaveAppearance(notecardName); | ||
106 | |||
107 | // Try creating a bot using the appearance in the notecard. | ||
108 | string npcRaw = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), notecardName); | ||
109 | Assert.That(npcRaw, Is.Not.Null); | ||
110 | |||
111 | UUID npcId = new UUID(npcRaw); | ||
112 | ScenePresence npc = m_scene.GetScenePresence(npcId); | ||
113 | Assert.That(npc, Is.Not.Null); | ||
114 | Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(newHeight)); | ||
115 | } | ||
116 | |||
117 | [Test] | ||
118 | public void TestOsNpcCreateNotExistingNotecard() | ||
119 | { | ||
120 | TestHelpers.InMethod(); | ||
121 | |||
122 | UUID userId = TestHelpers.ParseTail(0x1); | ||
123 | |||
124 | SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); | ||
125 | m_scene.AddSceneObject(so); | ||
126 | |||
127 | OSSL_Api osslApi = new OSSL_Api(); | ||
128 | osslApi.Initialize(m_engine, so.RootPart, null); | ||
129 | |||
130 | string npcRaw; | ||
131 | bool gotExpectedException = false; | ||
132 | try | ||
133 | { | ||
134 | npcRaw | ||
135 | = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), "not existing notecard name"); | ||
136 | } | ||
137 | catch (ScriptException) | ||
138 | { | ||
139 | gotExpectedException = true; | ||
140 | } | ||
141 | |||
142 | Assert.That(gotExpectedException, Is.True); | ||
143 | } | ||
144 | |||
145 | /// <summary> | ||
146 | /// Test creation of an NPC where the appearance data comes from an avatar already in the region. | ||
147 | /// </summary> | ||
148 | [Test] | ||
149 | public void TestOsNpcCreateUsingAppearanceFromAvatar() | ||
150 | { | ||
151 | TestHelpers.InMethod(); | ||
152 | // TestHelpers.EnableLogging(); | ||
153 | |||
154 | // Store an avatar with a different height from default in a notecard. | ||
155 | UUID userId = TestHelpers.ParseTail(0x1); | ||
156 | float newHeight = 1.9f; | ||
157 | |||
158 | ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); | ||
159 | sp.Appearance.AvatarHeight = newHeight; | ||
160 | SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); | ||
161 | SceneObjectPart part = so.RootPart; | ||
162 | m_scene.AddSceneObject(so); | ||
163 | |||
164 | OSSL_Api osslApi = new OSSL_Api(); | ||
165 | osslApi.Initialize(m_engine, part, null); | ||
166 | |||
167 | string notecardName = "appearanceNc"; | ||
168 | osslApi.osOwnerSaveAppearance(notecardName); | ||
169 | |||
170 | // Try creating a bot using the existing avatar's appearance | ||
171 | string npcRaw = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), sp.UUID.ToString()); | ||
172 | Assert.That(npcRaw, Is.Not.Null); | ||
173 | |||
174 | UUID npcId = new UUID(npcRaw); | ||
175 | ScenePresence npc = m_scene.GetScenePresence(npcId); | ||
176 | Assert.That(npc, Is.Not.Null); | ||
177 | Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(newHeight)); | ||
178 | } | ||
179 | |||
180 | [Test] | ||
181 | public void TestOsNpcLoadAppearance() | ||
182 | { | ||
183 | TestHelpers.InMethod(); | ||
184 | |||
185 | // Store an avatar with a different height from default in a notecard. | ||
186 | UUID userId = TestHelpers.ParseTail(0x1); | ||
187 | float firstHeight = 1.9f; | ||
188 | float secondHeight = 2.1f; | ||
189 | string firstAppearanceNcName = "appearanceNc1"; | ||
190 | string secondAppearanceNcName = "appearanceNc2"; | ||
191 | |||
192 | ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); | ||
193 | sp.Appearance.AvatarHeight = firstHeight; | ||
194 | SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); | ||
195 | SceneObjectPart part = so.RootPart; | ||
196 | m_scene.AddSceneObject(so); | ||
197 | |||
198 | OSSL_Api osslApi = new OSSL_Api(); | ||
199 | osslApi.Initialize(m_engine, part, null); | ||
200 | |||
201 | osslApi.osOwnerSaveAppearance(firstAppearanceNcName); | ||
202 | |||
203 | string npcRaw | ||
204 | = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), firstAppearanceNcName); | ||
205 | |||
206 | // Create a second appearance notecard with a different height | ||
207 | sp.Appearance.AvatarHeight = secondHeight; | ||
208 | osslApi.osOwnerSaveAppearance(secondAppearanceNcName); | ||
209 | |||
210 | osslApi.osNpcLoadAppearance(npcRaw, secondAppearanceNcName); | ||
211 | |||
212 | UUID npcId = new UUID(npcRaw); | ||
213 | ScenePresence npc = m_scene.GetScenePresence(npcId); | ||
214 | Assert.That(npc, Is.Not.Null); | ||
215 | Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(secondHeight)); | ||
216 | } | ||
217 | |||
218 | [Test] | ||
219 | public void TestOsNpcLoadAppearanceNotExistingNotecard() | ||
220 | { | ||
221 | TestHelpers.InMethod(); | ||
222 | |||
223 | // Store an avatar with a different height from default in a notecard. | ||
224 | UUID userId = TestHelpers.ParseTail(0x1); | ||
225 | float firstHeight = 1.9f; | ||
226 | float secondHeight = 2.1f; | ||
227 | string firstAppearanceNcName = "appearanceNc1"; | ||
228 | string secondAppearanceNcName = "appearanceNc2"; | ||
229 | |||
230 | ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); | ||
231 | sp.Appearance.AvatarHeight = firstHeight; | ||
232 | SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); | ||
233 | SceneObjectPart part = so.RootPart; | ||
234 | m_scene.AddSceneObject(so); | ||
235 | |||
236 | OSSL_Api osslApi = new OSSL_Api(); | ||
237 | osslApi.Initialize(m_engine, part, null); | ||
238 | |||
239 | osslApi.osOwnerSaveAppearance(firstAppearanceNcName); | ||
240 | |||
241 | string npcRaw | ||
242 | = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), firstAppearanceNcName); | ||
243 | |||
244 | bool gotExpectedException = false; | ||
245 | try | ||
246 | { | ||
247 | osslApi.osNpcLoadAppearance(npcRaw, secondAppearanceNcName); | ||
248 | } | ||
249 | catch (ScriptException) | ||
250 | { | ||
251 | gotExpectedException = true; | ||
252 | } | ||
253 | |||
254 | Assert.That(gotExpectedException, Is.True); | ||
255 | |||
256 | UUID npcId = new UUID(npcRaw); | ||
257 | ScenePresence npc = m_scene.GetScenePresence(npcId); | ||
258 | Assert.That(npc, Is.Not.Null); | ||
259 | Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(firstHeight)); | ||
260 | } | ||
261 | |||
262 | /// <summary> | ||
263 | /// Test removal of an owned NPC. | 82 | /// Test removal of an owned NPC. |
264 | /// </summary> | 83 | /// </summary> |
265 | [Test] | 84 | [Test] |
266 | public void TestOsNpcRemoveOwned() | 85 | public void TestOsNpcRemoveOwned() |
267 | { | 86 | { |
268 | TestHelpers.InMethod(); | 87 | TestHelpers.InMethod(); |
88 | // log4net.Config.XmlConfigurator.Configure(); | ||
269 | 89 | ||
270 | // Store an avatar with a different height from default in a notecard. | 90 | // Store an avatar with a different height from default in a notecard. |
271 | UUID userId = TestHelpers.ParseTail(0x1); | 91 | UUID userId = TestHelpers.ParseTail(0x1); |
diff --git a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs index 9405075..5c4174e 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs | |||
@@ -96,12 +96,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
96 | if (part == null) | 96 | if (part == null) |
97 | return; | 97 | return; |
98 | 98 | ||
99 | if ((part.ScriptEvents & scriptEvents.money) == 0) | ||
100 | part = part.ParentGroup.RootPart; | ||
101 | |||
102 | m_log.Debug("Paid: " + objectID + " from " + agentID + ", amount " + amount); | 99 | m_log.Debug("Paid: " + objectID + " from " + agentID + ", amount " + amount); |
103 | 100 | ||
104 | // part = part.ParentGroup.RootPart; | 101 | part = part.ParentGroup.RootPart; |
105 | money(part.LocalId, agentID, amount); | 102 | money(part.LocalId, agentID, amount); |
106 | } | 103 | } |
107 | 104 | ||
@@ -155,7 +152,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
155 | det[0] = new DetectParams(); | 152 | det[0] = new DetectParams(); |
156 | det[0].Key = remoteClient.AgentId; | 153 | det[0].Key = remoteClient.AgentId; |
157 | det[0].Populate(myScriptEngine.World); | 154 | det[0].Populate(myScriptEngine.World); |
158 | det[0].OffsetPos = offsetPos; | 155 | det[0].OffsetPos = new LSL_Types.Vector3(offsetPos.X, |
156 | offsetPos.Y, | ||
157 | offsetPos.Z); | ||
159 | 158 | ||
160 | if (originalID == 0) | 159 | if (originalID == 0) |
161 | { | 160 | { |
@@ -299,7 +298,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
299 | foreach (DetectedObject detobj in col.Colliders) | 298 | foreach (DetectedObject detobj in col.Colliders) |
300 | { | 299 | { |
301 | DetectParams d = new DetectParams(); | 300 | DetectParams d = new DetectParams(); |
302 | d.Position = detobj.posVector; | 301 | d.Position = new LSL_Types.Vector3(detobj.posVector.X, |
302 | detobj.posVector.Y, | ||
303 | detobj.posVector.Z); | ||
303 | d.Populate(myScriptEngine.World); | 304 | d.Populate(myScriptEngine.World); |
304 | det.Add(d); | 305 | det.Add(d); |
305 | myScriptEngine.PostObjectEvent(localID, new EventParams( | 306 | myScriptEngine.PostObjectEvent(localID, new EventParams( |
@@ -317,7 +318,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
317 | foreach (DetectedObject detobj in col.Colliders) | 318 | foreach (DetectedObject detobj in col.Colliders) |
318 | { | 319 | { |
319 | DetectParams d = new DetectParams(); | 320 | DetectParams d = new DetectParams(); |
320 | d.Position = detobj.posVector; | 321 | d.Position = new LSL_Types.Vector3(detobj.posVector.X, |
322 | detobj.posVector.Y, | ||
323 | detobj.posVector.Z); | ||
321 | d.Populate(myScriptEngine.World); | 324 | d.Populate(myScriptEngine.World); |
322 | det.Add(d); | 325 | det.Add(d); |
323 | myScriptEngine.PostObjectEvent(localID, new EventParams( | 326 | myScriptEngine.PostObjectEvent(localID, new EventParams( |
@@ -334,7 +337,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
334 | foreach (DetectedObject detobj in col.Colliders) | 337 | foreach (DetectedObject detobj in col.Colliders) |
335 | { | 338 | { |
336 | DetectParams d = new DetectParams(); | 339 | DetectParams d = new DetectParams(); |
337 | d.Position = detobj.posVector; | 340 | d.Position = new LSL_Types.Vector3(detobj.posVector.X, |
341 | detobj.posVector.Y, | ||
342 | detobj.posVector.Z); | ||
338 | d.Populate(myScriptEngine.World); | 343 | d.Populate(myScriptEngine.World); |
339 | det.Add(d); | 344 | det.Add(d); |
340 | myScriptEngine.PostObjectEvent(localID, new EventParams( | 345 | myScriptEngine.PostObjectEvent(localID, new EventParams( |
@@ -376,8 +381,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
376 | myScriptEngine.PostObjectEvent(localID, new EventParams( | 381 | myScriptEngine.PostObjectEvent(localID, new EventParams( |
377 | "at_target", new object[] { | 382 | "at_target", new object[] { |
378 | new LSL_Types.LSLInteger(handle), | 383 | new LSL_Types.LSLInteger(handle), |
379 | new LSL_Types.Vector3(targetpos), | 384 | new LSL_Types.Vector3(targetpos.X,targetpos.Y,targetpos.Z), |
380 | new LSL_Types.Vector3(atpos) }, | 385 | new LSL_Types.Vector3(atpos.X,atpos.Y,atpos.Z) }, |
381 | new DetectParams[0])); | 386 | new DetectParams[0])); |
382 | } | 387 | } |
383 | 388 | ||
@@ -394,8 +399,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
394 | myScriptEngine.PostObjectEvent(localID, new EventParams( | 399 | myScriptEngine.PostObjectEvent(localID, new EventParams( |
395 | "at_rot_target", new object[] { | 400 | "at_rot_target", new object[] { |
396 | new LSL_Types.LSLInteger(handle), | 401 | new LSL_Types.LSLInteger(handle), |
397 | new LSL_Types.Quaternion(targetrot), | 402 | new LSL_Types.Quaternion(targetrot.X,targetrot.Y,targetrot.Z,targetrot.W), |
398 | new LSL_Types.Quaternion(atrot) }, | 403 | new LSL_Types.Quaternion(atrot.X,atrot.Y,atrot.Z,atrot.W) }, |
399 | new DetectParams[0])); | 404 | new DetectParams[0])); |
400 | } | 405 | } |
401 | 406 | ||
diff --git a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs index f331658..f247a0b 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs | |||
@@ -90,7 +90,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine.Tests | |||
90 | // log4net.Config.XmlConfigurator.Configure(); | 90 | // log4net.Config.XmlConfigurator.Configure(); |
91 | 91 | ||
92 | UUID userId = TestHelpers.ParseTail(0x1); | 92 | UUID userId = TestHelpers.ParseTail(0x1); |
93 | // UUID objectId = TestHelpers.ParseTail(0x100); | 93 | // UUID objectId = TestHelpers.ParseTail(0x2); |
94 | // UUID itemId = TestHelpers.ParseTail(0x3); | 94 | // UUID itemId = TestHelpers.ParseTail(0x3); |
95 | string itemName = "TestStartScript() Item"; | 95 | string itemName = "TestStartScript() Item"; |
96 | 96 | ||
@@ -105,18 +105,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine.Tests | |||
105 | 105 | ||
106 | m_scene.EventManager.OnChatFromWorld += OnChatFromWorld; | 106 | m_scene.EventManager.OnChatFromWorld += OnChatFromWorld; |
107 | 107 | ||
108 | SceneObjectPart partWhereRezzed = m_scene.RezNewScript(userId, itemTemplate); | 108 | m_scene.RezNewScript(userId, itemTemplate); |
109 | 109 | ||
110 | m_chatEvent.WaitOne(60000); | 110 | m_chatEvent.WaitOne(60000); |
111 | 111 | ||
112 | Assert.That(m_osChatMessageReceived, Is.Not.Null, "No chat message received in TestStartScript()"); | 112 | Assert.That(m_osChatMessageReceived, Is.Not.Null, "No chat message received in TestStartScript()"); |
113 | Assert.That(m_osChatMessageReceived.Message, Is.EqualTo("Script running")); | 113 | Assert.That(m_osChatMessageReceived.Message, Is.EqualTo("Script running")); |
114 | |||
115 | bool running; | ||
116 | TaskInventoryItem scriptItem = partWhereRezzed.Inventory.GetInventoryItem(itemName); | ||
117 | Assert.That( | ||
118 | SceneObjectPartInventory.TryGetScriptInstanceRunning(m_scene, scriptItem, out running), Is.True); | ||
119 | Assert.That(running, Is.True); | ||
120 | } | 114 | } |
121 | 115 | ||
122 | private void OnChatFromWorld(object sender, OSChatMessage oscm) | 116 | private void OnChatFromWorld(object sender, OSChatMessage oscm) |
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 9f05666..f6cb7df 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | |||
@@ -656,19 +656,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
656 | if (m_Assemblies.ContainsKey(instance.AssetID)) | 656 | if (m_Assemblies.ContainsKey(instance.AssetID)) |
657 | { | 657 | { |
658 | string assembly = m_Assemblies[instance.AssetID]; | 658 | string assembly = m_Assemblies[instance.AssetID]; |
659 | 659 | instance.SaveState(assembly); | |
660 | try | ||
661 | { | ||
662 | instance.SaveState(assembly); | ||
663 | } | ||
664 | catch (Exception e) | ||
665 | { | ||
666 | m_log.Error( | ||
667 | string.Format( | ||
668 | "[XEngine]: Failed final state save for script {0}.{1}, item UUID {2}, prim UUID {3} in {4}. Exception ", | ||
669 | instance.PrimName, instance.ScriptName, instance.ItemID, instance.ObjectID, World.Name) | ||
670 | , e); | ||
671 | } | ||
672 | } | 660 | } |
673 | 661 | ||
674 | // Clear the event queue and abort the instance thread | 662 | // Clear the event queue and abort the instance thread |
@@ -790,18 +778,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
790 | assembly = m_Assemblies[i.AssetID]; | 778 | assembly = m_Assemblies[i.AssetID]; |
791 | 779 | ||
792 | 780 | ||
793 | try | 781 | i.SaveState(assembly); |
794 | { | ||
795 | i.SaveState(assembly); | ||
796 | } | ||
797 | catch (Exception e) | ||
798 | { | ||
799 | m_log.Error( | ||
800 | string.Format( | ||
801 | "[XEngine]: Failed to save state of script {0}.{1}, item UUID {2}, prim UUID {3} in {4}. Exception ", | ||
802 | i.PrimName, i.ScriptName, i.ItemID, i.ObjectID, World.Name) | ||
803 | , e); | ||
804 | } | ||
805 | } | 782 | } |
806 | 783 | ||
807 | instances.Clear(); | 784 | instances.Clear(); |
@@ -994,8 +971,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
994 | // This delay exists to stop mono problems where script compilation and startup would stop the sim | 971 | // This delay exists to stop mono problems where script compilation and startup would stop the sim |
995 | // working properly for the session. | 972 | // working properly for the session. |
996 | System.Threading.Thread.Sleep(m_StartDelay); | 973 | System.Threading.Thread.Sleep(m_StartDelay); |
997 | |||
998 | m_log.InfoFormat("[XEngine]: Performing initial script startup on {0}", m_Scene.Name); | ||
999 | } | 974 | } |
1000 | 975 | ||
1001 | object[] o; | 976 | object[] o; |
@@ -1011,13 +986,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1011 | if (m_InitialStartup) | 986 | if (m_InitialStartup) |
1012 | if (scriptsStarted % 50 == 0) | 987 | if (scriptsStarted % 50 == 0) |
1013 | m_log.InfoFormat( | 988 | m_log.InfoFormat( |
1014 | "[XEngine]: Started {0} scripts in {1}", scriptsStarted, m_Scene.Name); | 989 | "[XEngine]: Started {0} scripts in {1}", scriptsStarted, m_Scene.RegionInfo.RegionName); |
1015 | } | 990 | } |
1016 | } | 991 | } |
1017 | 992 | ||
1018 | if (m_InitialStartup) | 993 | if (m_InitialStartup) |
1019 | m_log.InfoFormat( | 994 | m_log.InfoFormat( |
1020 | "[XEngine]: Completed starting {0} scripts on {1}", scriptsStarted, m_Scene.Name); | 995 | "[XEngine]: Completed starting {0} scripts on {1}", scriptsStarted, m_Scene.RegionInfo.RegionName); |
1021 | 996 | ||
1022 | // NOTE: Despite having a lockless queue, this lock is required | 997 | // NOTE: Despite having a lockless queue, this lock is required |
1023 | // to make sure there is never no compile thread while there | 998 | // to make sure there is never no compile thread while there |
@@ -1078,13 +1053,11 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1078 | return false; | 1053 | return false; |
1079 | } | 1054 | } |
1080 | 1055 | ||
1081 | m_log.DebugFormat( | ||
1082 | "[XEngine] Loading script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}", | ||
1083 | part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID, | ||
1084 | part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); | ||
1085 | |||
1086 | UUID assetID = item.AssetID; | 1056 | UUID assetID = item.AssetID; |
1087 | 1057 | ||
1058 | //m_log.DebugFormat("[XEngine] Compiling script {0} ({1} on object {2})", | ||
1059 | // item.Name, itemID.ToString(), part.ParentGroup.RootPart.Name); | ||
1060 | |||
1088 | ScenePresence presence = m_Scene.GetScenePresence(item.OwnerID); | 1061 | ScenePresence presence = m_Scene.GetScenePresence(item.OwnerID); |
1089 | 1062 | ||
1090 | string assembly = ""; | 1063 | string assembly = ""; |
@@ -1262,10 +1235,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1262 | item.Name, startParam, postOnRez, | 1235 | item.Name, startParam, postOnRez, |
1263 | stateSource, m_MaxScriptQueue); | 1236 | stateSource, m_MaxScriptQueue); |
1264 | 1237 | ||
1265 | // m_log.DebugFormat( | 1238 | m_log.DebugFormat( |
1266 | // "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}", | 1239 | "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}", |
1267 | // part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID, | 1240 | part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID, |
1268 | // part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); | 1241 | part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); |
1269 | 1242 | ||
1270 | if (presence != null) | 1243 | if (presence != null) |
1271 | { | 1244 | { |
@@ -1581,9 +1554,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1581 | else if (p[i] is string) | 1554 | else if (p[i] is string) |
1582 | lsl_p[i] = new LSL_Types.LSLString((string)p[i]); | 1555 | lsl_p[i] = new LSL_Types.LSLString((string)p[i]); |
1583 | else if (p[i] is Vector3) | 1556 | else if (p[i] is Vector3) |
1584 | lsl_p[i] = new LSL_Types.Vector3((Vector3)p[i]); | 1557 | lsl_p[i] = new LSL_Types.Vector3(((Vector3)p[i]).X, ((Vector3)p[i]).Y, ((Vector3)p[i]).Z); |
1585 | else if (p[i] is Quaternion) | 1558 | else if (p[i] is Quaternion) |
1586 | lsl_p[i] = new LSL_Types.Quaternion((Quaternion)p[i]); | 1559 | lsl_p[i] = new LSL_Types.Quaternion(((Quaternion)p[i]).X, ((Quaternion)p[i]).Y, ((Quaternion)p[i]).Z, ((Quaternion)p[i]).W); |
1587 | else if (p[i] is float) | 1560 | else if (p[i] is float) |
1588 | lsl_p[i] = new LSL_Types.LSLFloat((float)p[i]); | 1561 | lsl_p[i] = new LSL_Types.LSLFloat((float)p[i]); |
1589 | else | 1562 | else |
@@ -1607,9 +1580,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1607 | else if (p[i] is string) | 1580 | else if (p[i] is string) |
1608 | lsl_p[i] = new LSL_Types.LSLString((string)p[i]); | 1581 | lsl_p[i] = new LSL_Types.LSLString((string)p[i]); |
1609 | else if (p[i] is Vector3) | 1582 | else if (p[i] is Vector3) |
1610 | lsl_p[i] = new LSL_Types.Vector3((Vector3)p[i]); | 1583 | lsl_p[i] = new LSL_Types.Vector3(((Vector3)p[i]).X, ((Vector3)p[i]).Y, ((Vector3)p[i]).Z); |
1611 | else if (p[i] is Quaternion) | 1584 | else if (p[i] is Quaternion) |
1612 | lsl_p[i] = new LSL_Types.Quaternion((Quaternion)p[i]); | 1585 | lsl_p[i] = new LSL_Types.Quaternion(((Quaternion)p[i]).X, ((Quaternion)p[i]).Y, ((Quaternion)p[i]).Z, ((Quaternion)p[i]).W); |
1613 | else if (p[i] is float) | 1586 | else if (p[i] is float) |
1614 | lsl_p[i] = new LSL_Types.LSLFloat((float)p[i]); | 1587 | lsl_p[i] = new LSL_Types.LSLFloat((float)p[i]); |
1615 | else | 1588 | else |
diff --git a/OpenSim/Region/UserStatistics/WebStatsModule.cs b/OpenSim/Region/UserStatistics/WebStatsModule.cs index 625eba4..c11ea02 100644 --- a/OpenSim/Region/UserStatistics/WebStatsModule.cs +++ b/OpenSim/Region/UserStatistics/WebStatsModule.cs | |||
@@ -61,7 +61,7 @@ namespace OpenSim.Region.UserStatistics | |||
61 | /// <summary> | 61 | /// <summary> |
62 | /// User statistics sessions keyed by agent ID | 62 | /// User statistics sessions keyed by agent ID |
63 | /// </summary> | 63 | /// </summary> |
64 | private Dictionary<UUID, UserSession> m_sessions = new Dictionary<UUID, UserSession>(); | 64 | private Dictionary<UUID, UserSessionID> m_sessions = new Dictionary<UUID, UserSessionID>(); |
65 | 65 | ||
66 | private List<Scene> m_scenes = new List<Scene>(); | 66 | private List<Scene> m_scenes = new List<Scene>(); |
67 | private Dictionary<string, IStatsController> reports = new Dictionary<string, IStatsController>(); | 67 | private Dictionary<string, IStatsController> reports = new Dictionary<string, IStatsController>(); |
@@ -319,18 +319,14 @@ namespace OpenSim.Region.UserStatistics | |||
319 | 319 | ||
320 | private void OnMakeRootAgent(ScenePresence agent) | 320 | private void OnMakeRootAgent(ScenePresence agent) |
321 | { | 321 | { |
322 | // m_log.DebugFormat( | ||
323 | // "[WEB STATS MODULE]: Looking for session {0} for {1} in {2}", | ||
324 | // agent.ControllingClient.SessionId, agent.Name, agent.Scene.Name); | ||
325 | |||
326 | lock (m_sessions) | 322 | lock (m_sessions) |
327 | { | 323 | { |
328 | UserSession uid; | 324 | UserSessionID uid; |
329 | 325 | ||
330 | if (!m_sessions.ContainsKey(agent.UUID)) | 326 | if (!m_sessions.ContainsKey(agent.UUID)) |
331 | { | 327 | { |
332 | UserSessionData usd = UserSessionUtil.newUserSessionData(); | 328 | UserSessionData usd = UserSessionUtil.newUserSessionData(); |
333 | uid = new UserSession(); | 329 | uid = new UserSessionID(); |
334 | uid.name_f = agent.Firstname; | 330 | uid.name_f = agent.Firstname; |
335 | uid.name_l = agent.Lastname; | 331 | uid.name_l = agent.Lastname; |
336 | uid.session_data = usd; | 332 | uid.session_data = usd; |
@@ -415,9 +411,9 @@ namespace OpenSim.Region.UserStatistics | |||
415 | return String.Empty; | 411 | return String.Empty; |
416 | } | 412 | } |
417 | 413 | ||
418 | private UserSession ParseViewerStats(string request, UUID agentID) | 414 | private UserSessionID ParseViewerStats(string request, UUID agentID) |
419 | { | 415 | { |
420 | UserSession uid = new UserSession(); | 416 | UserSessionID uid = new UserSessionID(); |
421 | UserSessionData usd; | 417 | UserSessionData usd; |
422 | OSD message = OSDParser.DeserializeLLSDXml(request); | 418 | OSD message = OSDParser.DeserializeLLSDXml(request); |
423 | OSDMap mmap; | 419 | OSDMap mmap; |
@@ -429,25 +425,22 @@ namespace OpenSim.Region.UserStatistics | |||
429 | if (!m_sessions.ContainsKey(agentID)) | 425 | if (!m_sessions.ContainsKey(agentID)) |
430 | { | 426 | { |
431 | m_log.WarnFormat("[WEB STATS MODULE]: no session for stat disclosure for agent {0}", agentID); | 427 | m_log.WarnFormat("[WEB STATS MODULE]: no session for stat disclosure for agent {0}", agentID); |
432 | return new UserSession(); | 428 | return new UserSessionID(); |
433 | } | 429 | } |
434 | |||
435 | uid = m_sessions[agentID]; | 430 | uid = m_sessions[agentID]; |
436 | |||
437 | // m_log.DebugFormat("[WEB STATS MODULE]: Got session {0} for {1}", uid.session_id, agentID); | ||
438 | } | 431 | } |
439 | else | 432 | else |
440 | { | 433 | { |
441 | // parse through the beginning to locate the session | 434 | // parse through the beginning to locate the session |
442 | if (message.Type != OSDType.Map) | 435 | if (message.Type != OSDType.Map) |
443 | return new UserSession(); | 436 | return new UserSessionID(); |
444 | 437 | ||
445 | mmap = (OSDMap)message; | 438 | mmap = (OSDMap)message; |
446 | { | 439 | { |
447 | UUID sessionID = mmap["session_id"].AsUUID(); | 440 | UUID sessionID = mmap["session_id"].AsUUID(); |
448 | 441 | ||
449 | if (sessionID == UUID.Zero) | 442 | if (sessionID == UUID.Zero) |
450 | return new UserSession(); | 443 | return new UserSessionID(); |
451 | 444 | ||
452 | 445 | ||
453 | // search through each session looking for the owner | 446 | // search through each session looking for the owner |
@@ -466,7 +459,7 @@ namespace OpenSim.Region.UserStatistics | |||
466 | // can't find a session | 459 | // can't find a session |
467 | if (agentID == UUID.Zero) | 460 | if (agentID == UUID.Zero) |
468 | { | 461 | { |
469 | return new UserSession(); | 462 | return new UserSessionID(); |
470 | } | 463 | } |
471 | } | 464 | } |
472 | } | 465 | } |
@@ -475,12 +468,12 @@ namespace OpenSim.Region.UserStatistics | |||
475 | usd = uid.session_data; | 468 | usd = uid.session_data; |
476 | 469 | ||
477 | if (message.Type != OSDType.Map) | 470 | if (message.Type != OSDType.Map) |
478 | return new UserSession(); | 471 | return new UserSessionID(); |
479 | 472 | ||
480 | mmap = (OSDMap)message; | 473 | mmap = (OSDMap)message; |
481 | { | 474 | { |
482 | if (mmap["agent"].Type != OSDType.Map) | 475 | if (mmap["agent"].Type != OSDType.Map) |
483 | return new UserSession(); | 476 | return new UserSessionID(); |
484 | OSDMap agent_map = (OSDMap)mmap["agent"]; | 477 | OSDMap agent_map = (OSDMap)mmap["agent"]; |
485 | usd.agent_id = agentID; | 478 | usd.agent_id = agentID; |
486 | usd.name_f = uid.name_f; | 479 | usd.name_f = uid.name_f; |
@@ -500,18 +493,17 @@ namespace OpenSim.Region.UserStatistics | |||
500 | (float)agent_map["fps"].AsReal()); | 493 | (float)agent_map["fps"].AsReal()); |
501 | 494 | ||
502 | if (mmap["downloads"].Type != OSDType.Map) | 495 | if (mmap["downloads"].Type != OSDType.Map) |
503 | return new UserSession(); | 496 | return new UserSessionID(); |
504 | OSDMap downloads_map = (OSDMap)mmap["downloads"]; | 497 | OSDMap downloads_map = (OSDMap)mmap["downloads"]; |
505 | usd.d_object_kb = (float)downloads_map["object_kbytes"].AsReal(); | 498 | usd.d_object_kb = (float)downloads_map["object_kbytes"].AsReal(); |
506 | usd.d_texture_kb = (float)downloads_map["texture_kbytes"].AsReal(); | 499 | usd.d_texture_kb = (float)downloads_map["texture_kbytes"].AsReal(); |
507 | usd.d_world_kb = (float)downloads_map["workd_kbytes"].AsReal(); | 500 | usd.d_world_kb = (float)downloads_map["workd_kbytes"].AsReal(); |
508 | 501 | ||
509 | // m_log.DebugFormat("[WEB STATS MODULE]: mmap[\"session_id\"] = [{0}]", mmap["session_id"].AsUUID()); | ||
510 | 502 | ||
511 | usd.session_id = mmap["session_id"].AsUUID(); | 503 | usd.session_id = mmap["session_id"].AsUUID(); |
512 | 504 | ||
513 | if (mmap["system"].Type != OSDType.Map) | 505 | if (mmap["system"].Type != OSDType.Map) |
514 | return new UserSession(); | 506 | return new UserSessionID(); |
515 | OSDMap system_map = (OSDMap)mmap["system"]; | 507 | OSDMap system_map = (OSDMap)mmap["system"]; |
516 | 508 | ||
517 | usd.s_cpu = system_map["cpu"].AsString(); | 509 | usd.s_cpu = system_map["cpu"].AsString(); |
@@ -520,13 +512,13 @@ namespace OpenSim.Region.UserStatistics | |||
520 | usd.s_ram = system_map["ram"].AsInteger(); | 512 | usd.s_ram = system_map["ram"].AsInteger(); |
521 | 513 | ||
522 | if (mmap["stats"].Type != OSDType.Map) | 514 | if (mmap["stats"].Type != OSDType.Map) |
523 | return new UserSession(); | 515 | return new UserSessionID(); |
524 | 516 | ||
525 | OSDMap stats_map = (OSDMap)mmap["stats"]; | 517 | OSDMap stats_map = (OSDMap)mmap["stats"]; |
526 | { | 518 | { |
527 | 519 | ||
528 | if (stats_map["failures"].Type != OSDType.Map) | 520 | if (stats_map["failures"].Type != OSDType.Map) |
529 | return new UserSession(); | 521 | return new UserSessionID(); |
530 | OSDMap stats_failures = (OSDMap)stats_map["failures"]; | 522 | OSDMap stats_failures = (OSDMap)stats_map["failures"]; |
531 | usd.f_dropped = stats_failures["dropped"].AsInteger(); | 523 | usd.f_dropped = stats_failures["dropped"].AsInteger(); |
532 | usd.f_failed_resends = stats_failures["failed_resends"].AsInteger(); | 524 | usd.f_failed_resends = stats_failures["failed_resends"].AsInteger(); |
@@ -535,18 +527,18 @@ namespace OpenSim.Region.UserStatistics | |||
535 | usd.f_send_packet = stats_failures["send_packet"].AsInteger(); | 527 | usd.f_send_packet = stats_failures["send_packet"].AsInteger(); |
536 | 528 | ||
537 | if (stats_map["net"].Type != OSDType.Map) | 529 | if (stats_map["net"].Type != OSDType.Map) |
538 | return new UserSession(); | 530 | return new UserSessionID(); |
539 | OSDMap stats_net = (OSDMap)stats_map["net"]; | 531 | OSDMap stats_net = (OSDMap)stats_map["net"]; |
540 | { | 532 | { |
541 | if (stats_net["in"].Type != OSDType.Map) | 533 | if (stats_net["in"].Type != OSDType.Map) |
542 | return new UserSession(); | 534 | return new UserSessionID(); |
543 | 535 | ||
544 | OSDMap net_in = (OSDMap)stats_net["in"]; | 536 | OSDMap net_in = (OSDMap)stats_net["in"]; |
545 | usd.n_in_kb = (float)net_in["kbytes"].AsReal(); | 537 | usd.n_in_kb = (float)net_in["kbytes"].AsReal(); |
546 | usd.n_in_pk = net_in["packets"].AsInteger(); | 538 | usd.n_in_pk = net_in["packets"].AsInteger(); |
547 | 539 | ||
548 | if (stats_net["out"].Type != OSDType.Map) | 540 | if (stats_net["out"].Type != OSDType.Map) |
549 | return new UserSession(); | 541 | return new UserSessionID(); |
550 | OSDMap net_out = (OSDMap)stats_net["out"]; | 542 | OSDMap net_out = (OSDMap)stats_net["out"]; |
551 | 543 | ||
552 | usd.n_out_kb = (float)net_out["kbytes"].AsReal(); | 544 | usd.n_out_kb = (float)net_out["kbytes"].AsReal(); |
@@ -557,18 +549,11 @@ namespace OpenSim.Region.UserStatistics | |||
557 | 549 | ||
558 | uid.session_data = usd; | 550 | uid.session_data = usd; |
559 | m_sessions[agentID] = uid; | 551 | m_sessions[agentID] = uid; |
560 | |||
561 | // m_log.DebugFormat( | ||
562 | // "[WEB STATS MODULE]: Parse data for {0} {1}, session {2}", uid.name_f, uid.name_l, uid.session_id); | ||
563 | |||
564 | return uid; | 552 | return uid; |
565 | } | 553 | } |
566 | 554 | ||
567 | private void UpdateUserStats(UserSession uid, SqliteConnection db) | 555 | private void UpdateUserStats(UserSessionID uid, SqliteConnection db) |
568 | { | 556 | { |
569 | // m_log.DebugFormat( | ||
570 | // "[WEB STATS MODULE]: Updating user stats for {0} {1}, session {2}", uid.name_f, uid.name_l, uid.session_id); | ||
571 | |||
572 | if (uid.session_id == UUID.Zero) | 557 | if (uid.session_id == UUID.Zero) |
573 | return; | 558 | return; |
574 | 559 | ||
@@ -755,6 +740,7 @@ VALUES | |||
755 | s.min_ping = ArrayMin_f(__ping); | 740 | s.min_ping = ArrayMin_f(__ping); |
756 | s.max_ping = ArrayMax_f(__ping); | 741 | s.max_ping = ArrayMax_f(__ping); |
757 | s.mode_ping = ArrayMode_f(__ping); | 742 | s.mode_ping = ArrayMode_f(__ping); |
743 | |||
758 | } | 744 | } |
759 | 745 | ||
760 | #region Statistics | 746 | #region Statistics |
@@ -999,7 +985,7 @@ VALUES | |||
999 | } | 985 | } |
1000 | #region structs | 986 | #region structs |
1001 | 987 | ||
1002 | public class UserSession | 988 | public struct UserSessionID |
1003 | { | 989 | { |
1004 | public UUID session_id; | 990 | public UUID session_id; |
1005 | public UUID region_id; | 991 | public UUID region_id; |