diff --git a/OpenSim/Framework/Cache.cs b/OpenSim/Framework/Cache.cs index 79e20fc88e..31cab4a021 100644 --- a/OpenSim/Framework/Cache.cs +++ b/OpenSim/Framework/Cache.cs @@ -199,7 +199,14 @@ namespace OpenSim.Framework // public class Cache { + /// + /// Must only be accessed under lock. + /// private List m_Index = new List(); + + /// + /// Must only be accessed under m_Index lock. + /// private Dictionary m_Lookup = new Dictionary(); @@ -320,19 +327,19 @@ namespace OpenSim.Framework { if (m_Lookup.ContainsKey(index)) item = m_Lookup[index]; - } - if (item == null) - { + if (item == null) + { + Expire(true); + return null; + } + + item.hits++; + item.lastUsed = DateTime.Now; + Expire(true); - return null; } - item.hits++; - item.lastUsed = DateTime.Now; - - Expire(true); - return item; } @@ -385,7 +392,10 @@ namespace OpenSim.Framework // public Object Find(Predicate d) { - CacheItemBase item = m_Index.Find(d); + CacheItemBase item; + + lock (m_Index) + item = m_Index.Find(d); if (item == null) return null; @@ -419,12 +429,12 @@ namespace OpenSim.Framework public virtual void Store(string index, Object data, Type container, Object[] parameters) { - Expire(false); - CacheItemBase item; lock (m_Index) { + Expire(false); + if (m_Index.Contains(new CacheItemBase(index))) { if ((m_Flags & CacheFlags.AllowUpdate) != 0) @@ -450,9 +460,17 @@ namespace OpenSim.Framework m_Index.Add(item); m_Lookup[index] = item; } + item.Store(data); } + /// + /// Expire items as appropriate. + /// + /// + /// Callers must lock m_Index. + /// + /// protected virtual void Expire(bool getting) { if (getting && (m_Strategy == CacheStrategy.Aggressive)) @@ -475,12 +493,10 @@ namespace OpenSim.Framework switch (m_Strategy) { - case CacheStrategy.Aggressive: - if (Count < Size) - return; + case CacheStrategy.Aggressive: + if (Count < Size) + return; - lock (m_Index) - { m_Index.Sort(new SortLRU()); m_Index.Reverse(); @@ -490,7 +506,7 @@ namespace OpenSim.Framework ExpireDelegate doExpire = OnExpire; - if (doExpire != null) + if (doExpire != null) { List candidates = m_Index.GetRange(target, Count - target); @@ -513,27 +529,34 @@ namespace OpenSim.Framework foreach (CacheItemBase item in m_Index) m_Lookup[item.uuid] = item; } - } - break; - default: - break; + + break; + + default: + break; } } public void Invalidate(string uuid) { - if (!m_Lookup.ContainsKey(uuid)) - return; + lock (m_Index) + { + if (!m_Lookup.ContainsKey(uuid)) + return; - CacheItemBase item = m_Lookup[uuid]; - m_Lookup.Remove(uuid); - m_Index.Remove(item); + CacheItemBase item = m_Lookup[uuid]; + m_Lookup.Remove(uuid); + m_Index.Remove(item); + } } public void Clear() { - m_Index.Clear(); - m_Lookup.Clear(); + lock (m_Index) + { + m_Index.Clear(); + m_Lookup.Clear(); + } } } -} +} \ No newline at end of file diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 6be2bd7501..91f36a5dff 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -1046,8 +1046,21 @@ namespace OpenSim.Framework void InPacket(object NewPack); void ProcessInPacket(Packet NewPack); + + /// + /// Close this client + /// void Close(); - void Close(bool sendStop); + + /// + /// Close this client + /// + /// + /// If true, attempts the close without checking active status. You do not want to try this except as a last + /// ditch attempt where Active == false but the ScenePresence still exists. + /// + void Close(bool sendStop, bool force); + void Kick(string message); /// diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index 6255515c32..9c7598a776 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs @@ -35,6 +35,7 @@ using System.Text; using System.Text.RegularExpressions; using System.Timers; using log4net; +using NDesk.Options; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; @@ -310,8 +311,11 @@ namespace OpenSim "Change the scale of a named prim", HandleEditScale); m_console.Commands.AddCommand("Users", false, "kick user", - "kick user [message]", - "Kick a user off the simulator", KickUserCommand); + "kick user [--force] [message]", + "Kick a user off the simulator", + "The --force option will kick the user without any checks to see whether it's already in the process of closing\n" + + "Only use this option if you are sure the avatar is inactive and a normal kick user operation does not removed them", + KickUserCommand); m_console.Commands.AddCommand("Users", false, "show users", "show users [full]", @@ -416,6 +420,7 @@ namespace OpenSim { RunCommandScript(m_shutdownCommandsFile); } + base.ShutdownSpecific(); } @@ -453,11 +458,17 @@ namespace OpenSim /// name of avatar to kick private void KickUserCommand(string module, string[] cmdparams) { - if (cmdparams.Length < 4) + bool force = false; + + OptionSet options = new OptionSet().Add("f|force", delegate (string v) { force = v != null; }); + + List mainParams = options.Parse(cmdparams); + + if (mainParams.Count < 4) return; string alert = null; - if (cmdparams.Length > 4) + if (mainParams.Count > 4) alert = String.Format("\n{0}\n", String.Join(" ", cmdparams, 4, cmdparams.Length - 4)); IList agents = SceneManager.GetCurrentSceneAvatars(); @@ -466,8 +477,8 @@ namespace OpenSim { RegionInfo regionInfo = presence.Scene.RegionInfo; - if (presence.Firstname.ToLower().Contains(cmdparams[2].ToLower()) && - presence.Lastname.ToLower().Contains(cmdparams[3].ToLower())) + if (presence.Firstname.ToLower().Contains(mainParams[2].ToLower()) && + presence.Lastname.ToLower().Contains(mainParams[3].ToLower())) { MainConsole.Instance.Output( String.Format( @@ -480,7 +491,7 @@ namespace OpenSim else presence.ControllingClient.Kick("\nYou have been logged out by an administrator.\n"); - presence.Scene.IncomingCloseAgent(presence.UUID); + presence.Scene.IncomingCloseAgent(presence.UUID, force); } } diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs index cd70410680..d604cf6f51 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 UUID spId = TestHelpers.ParseTail(0x1); SceneHelpers.AddScenePresence(m_scene, spId); - m_scene.IncomingCloseAgent(spId); + m_scene.IncomingCloseAgent(spId, false); // TODO: Add more assertions for the other aspects of event queues Assert.That(MainServer.Instance.GetPollServiceHandlerKeys().Count, Is.EqualTo(0)); diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index ddd8f18e11..2dcc9cb3c9 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -509,19 +509,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// public void Close() { - Close(true); + Close(true, false); } - /// - /// Shut down the client view - /// - public void Close(bool sendStop) + public void Close(bool sendStop, bool force) { // We lock here to prevent race conditions between two threads calling close simultaneously (e.g. // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection. lock (CloseSyncLock) { - if (!IsActive) + // We still perform a force close inside the sync lock since this is intended to attempt close where + // there is some unidentified connection problem, not where we have issues due to deadlock + if (!IsActive && !force) return; IsActive = false; @@ -12140,7 +12139,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { Kick(reason); Thread.Sleep(1000); - Close(); + Disconnect(); } public void Disconnect() diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index 7042c9a228..fb73e1d975 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -1515,7 +1515,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (!client.IsLoggingOut) { client.IsLoggingOut = true; - client.Close(false); + client.Close(false, false); } } } diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs index d9a619d15b..48f3a23e90 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs @@ -461,7 +461,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests SceneObjectGroup rezzedAtt = presence.GetAttachments()[0]; - scene.IncomingCloseAgent(presence.UUID); + scene.IncomingCloseAgent(presence.UUID, false); // Check that we can't retrieve this attachment from the scene. Assert.That(scene.GetSceneObjectGroup(rezzedAtt.UUID), Is.Null); diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 560f807167..c248f956a3 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -644,7 +644,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // an agent cannot teleport back to this region if it has teleported away. Thread.Sleep(2000); - sp.Scene.IncomingCloseAgent(sp.UUID); + sp.Scene.IncomingCloseAgent(sp.UUID, false); } else { diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs index 8b2f2f84e9..05eaaeceb0 100644 --- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs @@ -308,36 +308,44 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender try { - if (alpha == 256) - bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb); - else - bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); - - graph = Graphics.FromImage(bitmap); - - // this is really just to save people filling the - // background color in their scripts, only do when fully opaque - if (alpha >= 255) + // XXX: In testing, it appears that if multiple threads dispose of separate GDI+ objects simultaneously, + // the native malloc heap can become corrupted, possibly due to a double free(). This may be due to + // bugs in the underlying libcairo used by mono's libgdiplus.dll on Linux/OSX. These problems were + // seen with both libcario 1.10.2-6.1ubuntu3 and 1.8.10-2ubuntu1. They go away if disposal is perfomed + // under lock. + lock (this) { - using (SolidBrush bgFillBrush = new SolidBrush(bgColor)) - { - graph.FillRectangle(bgFillBrush, 0, 0, width, height); - } - } + if (alpha == 256) + bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb); + else + bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); - for (int w = 0; w < bitmap.Width; w++) - { - if (alpha <= 255) + graph = Graphics.FromImage(bitmap); + + // this is really just to save people filling the + // background color in their scripts, only do when fully opaque + if (alpha >= 255) { - for (int h = 0; h < bitmap.Height; h++) + using (SolidBrush bgFillBrush = new SolidBrush(bgColor)) { - bitmap.SetPixel(w, h, Color.FromArgb(alpha, bitmap.GetPixel(w, h))); + graph.FillRectangle(bgFillBrush, 0, 0, width, height); } } + + for (int w = 0; w < bitmap.Width; w++) + { + if (alpha <= 255) + { + for (int h = 0; h < bitmap.Height; h++) + { + bitmap.SetPixel(w, h, Color.FromArgb(alpha, bitmap.GetPixel(w, h))); + } + } + } + + GDIDraw(data, graph, altDataDelim); } - GDIDraw(data, graph, altDataDelim); - byte[] imageJ2000 = new byte[0]; try @@ -355,11 +363,19 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender } finally { - if (graph != null) - graph.Dispose(); - - if (bitmap != null) - bitmap.Dispose(); + // XXX: In testing, it appears that if multiple threads dispose of separate GDI+ objects simultaneously, + // the native malloc heap can become corrupted, possibly due to a double free(). This may be due to + // bugs in the underlying libcairo used by mono's libgdiplus.dll on Linux/OSX. These problems were + // seen with both libcario 1.10.2-6.1ubuntu3 and 1.8.10-2ubuntu1. They go away if disposal is perfomed + // under lock. + lock (this) + { + if (graph != null) + graph.Dispose(); + + if (bitmap != null) + bitmap.Dispose(); + } } } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs index 6eb99ea710..8ed1833aca 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs @@ -313,7 +313,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation if (m_scenes.ContainsKey(destination.RegionID)) { - Util.FireAndForget(delegate { m_scenes[destination.RegionID].IncomingCloseAgent(id); }); +// m_log.DebugFormat( +// "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate", +// s.RegionInfo.RegionName, destination.RegionHandle); + + Util.FireAndForget(delegate { m_scenes[destination.RegionID].IncomingCloseAgent(id, false); }); return true; } //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 619550c1c5..142567bff1 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -97,6 +97,13 @@ namespace OpenSim.Region.CoreModules.World.Archiver } } + /// + /// Used to cache lookups for valid groups. + /// + private IDictionary m_validGroupUuids = new Dictionary(); + + private IGroupsModule m_groupsModule; + public ArchiveReadRequest(Scene scene, string loadPath, bool merge, bool skipAssets, Guid requestId) { m_scene = scene; @@ -120,6 +127,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver // Zero can never be a valid user id m_validUserUuids[UUID.Zero] = false; + + m_groupsModule = m_scene.RequestModuleInterface(); } public ArchiveReadRequest(Scene scene, Stream loadStream, bool merge, bool skipAssets, Guid requestId) @@ -132,6 +141,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver // Zero can never be a valid user id m_validUserUuids[UUID.Zero] = false; + + m_groupsModule = m_scene.RequestModuleInterface(); } /// @@ -302,6 +313,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver if (!ResolveUserUuid(part.LastOwnerID)) part.LastOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; + if (!ResolveGroupUuid(part.GroupID)) + part.GroupID = UUID.Zero; + // And zap any troublesome sit target information // part.SitTargetOrientation = new Quaternion(0, 0, 0, 1); // part.SitTargetPosition = new Vector3(0, 0, 0); @@ -335,13 +349,18 @@ namespace OpenSim.Region.CoreModules.World.Archiver { kvp.Value.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; } + if (kvp.Value.CreatorData == null || kvp.Value.CreatorData == string.Empty) { if (!ResolveUserUuid(kvp.Value.CreatorID)) kvp.Value.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner; } + if (UserManager != null) UserManager.AddUser(kvp.Value.CreatorID, kvp.Value.CreatorData); + + if (!ResolveGroupUuid(kvp.Value.GroupID)) + kvp.Value.GroupID = UUID.Zero; } part.TaskInventory.LockItemsForRead(false); } @@ -382,9 +401,27 @@ namespace OpenSim.Region.CoreModules.World.Archiver foreach (string serialisedParcel in serialisedParcels) { LandData parcel = LandDataSerializer.Deserialize(serialisedParcel); + + // Validate User and Group UUID's + if (!ResolveUserUuid(parcel.OwnerID)) parcel.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; - + + if (!ResolveGroupUuid(parcel.GroupID)) + { + parcel.GroupID = UUID.Zero; + parcel.IsGroupOwned = false; + } + + List accessList = new List(); + foreach (LandAccessEntry entry in parcel.ParcelAccessList) + { + if (ResolveUserUuid(entry.AgentID)) + accessList.Add(entry); + // else, drop this access rule + } + parcel.ParcelAccessList = accessList; + // m_log.DebugFormat( // "[ARCHIVER]: Adding parcel {0}, local id {1}, area {2}", // parcel.Name, parcel.LocalID, parcel.Area); @@ -419,6 +456,30 @@ namespace OpenSim.Region.CoreModules.World.Archiver } /// + /// Look up the given group id to check whether it's one that is valid for this grid. + /// + /// + /// + private bool ResolveGroupUuid(UUID uuid) + { + if (uuid == UUID.Zero) + return true; // this means the object has no group + + if (!m_validGroupUuids.ContainsKey(uuid)) + { + bool exists; + + if (m_groupsModule == null) + exists = false; + else + exists = (m_groupsModule.GetGroupRecord(uuid) != null); + + m_validGroupUuids.Add(uuid, exists); + } + + return m_validGroupUuids[uuid]; + } + /// Load an asset /// /// diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs index 14c1a3947e..a2f09507ef 100644 --- a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs +++ b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs @@ -85,13 +85,15 @@ namespace OpenSim.Region.CoreModules.World.Sound dis = 0; } + float thisSpGain; + // Scale by distance if (radius == 0) - gain = (float)((double)gain * ((100.0 - dis) / 100.0)); + thisSpGain = (float)((double)gain * ((100.0 - dis) / 100.0)); else - gain = (float)((double)gain * ((radius - dis) / radius)); + thisSpGain = (float)((double)gain * ((radius - dis) / radius)); - sp.ControllingClient.SendPlayAttachedSound(soundID, objectID, ownerID, (float)gain, flags); + sp.ControllingClient.SendPlayAttachedSound(soundID, objectID, ownerID, thisSpGain, flags); }); } diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 0883913f8d..249946008b 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -4340,15 +4340,18 @@ namespace OpenSim.Region.Framework.Scenes /// Tell a single agent to disconnect from the region. /// /// - /// - public bool IncomingCloseAgent(UUID agentID, bool childOnly) + /// + /// Force the agent to close even if it might be in the middle of some other operation. You do not want to + /// force unless you are absolutely sure that the agent is dead and a normal close is not working. + /// + public bool IncomingCloseAgent(UUID agentID, bool force) { //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); ScenePresence presence = m_sceneGraph.GetScenePresence(agentID); if (presence != null) { - presence.ControllingClient.Close(); + presence.ControllingClient.Close(true, force); return true; } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 593e1d3afd..af06250899 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -3560,23 +3560,32 @@ namespace OpenSim.Region.Framework.Scenes } /// - /// Set the color of prim faces + /// Set the color & alpha of prim faces /// - /// /// - public void SetFaceColor(Vector3 color, int face) + /// + /// + public void SetFaceColorAlpha(int face, Vector3 color, double ?alpha) { + Vector3 clippedColor = Util.Clip(color, 0.0f, 1.0f); + float clippedAlpha = alpha.HasValue ? + Util.Clip((float)alpha.Value, 0.0f, 1.0f) : 0; + // The only way to get a deep copy/ If we don't do this, we can - // mever detect color changes further down. + // never detect color changes further down. Byte[] buf = Shape.Textures.GetBytes(); Primitive.TextureEntry tex = new Primitive.TextureEntry(buf, 0, buf.Length); Color4 texcolor; if (face >= 0 && face < GetNumberOfSides()) { texcolor = tex.CreateFace((uint)face).RGBA; - texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f); - texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f); - texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f); + texcolor.R = clippedColor.X; + texcolor.G = clippedColor.Y; + texcolor.B = clippedColor.Z; + if (alpha.HasValue) + { + texcolor.A = clippedAlpha; + } tex.FaceTextures[face].RGBA = texcolor; UpdateTextureEntry(tex.GetBytes()); return; @@ -3588,15 +3597,23 @@ namespace OpenSim.Region.Framework.Scenes if (tex.FaceTextures[i] != null) { texcolor = tex.FaceTextures[i].RGBA; - texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f); - texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f); - texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f); + texcolor.R = clippedColor.X; + texcolor.G = clippedColor.Y; + texcolor.B = clippedColor.Z; + if (alpha.HasValue) + { + texcolor.A = clippedAlpha; + } tex.FaceTextures[i].RGBA = texcolor; } texcolor = tex.DefaultTexture.RGBA; - texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f); - texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f); - texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f); + texcolor.R = clippedColor.X; + texcolor.G = clippedColor.Y; + texcolor.B = clippedColor.Z; + if (alpha.HasValue) + { + texcolor.A = clippedAlpha; + } tex.DefaultTexture.RGBA = texcolor; } UpdateTextureEntry(tex.GetBytes()); diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs index 5758869e7a..5faf131caf 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 TestScene scene = new SceneHelpers().SetupScene(); ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1)); - scene.IncomingCloseAgent(sp.UUID); + scene.IncomingCloseAgent(sp.UUID, false); Assert.That(scene.GetScenePresence(sp.UUID), Is.Null); Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID), Is.Null); diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index 3b83e58933..1660c45d30 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs @@ -890,10 +890,10 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server public void Close() { - Close(true); + Close(true, false); } - public void Close(bool sendStop) + public void Close(bool sendStop, bool force) { Disconnect(); } diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index d00a6c0516..625342e257 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -905,11 +905,13 @@ namespace OpenSim.Region.OptionalModules.World.NPC public void Close() { - Close(true); + Close(true, false); } - public void Close(bool sendStop) + public void Close(bool sendStop, bool force) { + // Remove ourselves from the scene + m_scene.RemoveClient(AgentId, false); } public void Start() diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 434638d822..0c7f49b126 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -1490,11 +1490,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api scale.y = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.y)); scale.z = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.z)); } - - // Next we clamp the scale to the non-physical min/max - scale.x = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.x)); - scale.y = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.y)); - scale.z = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.z)); + else + { + // If not physical, then we clamp the scale to the non-physical min/max + scale.x = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.x)); + scale.y = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.y)); + scale.z = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.z)); + } Vector3 tmp = part.Scale; tmp.X = (float)scale.x; @@ -1568,7 +1570,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (face == ScriptBaseClass.ALL_SIDES) face = SceneObjectPart.ALL_SIDES; - m_host.SetFaceColor(color, face); + m_host.SetFaceColorAlpha(face, color, null); } public void SetTexGen(SceneObjectPart part, int face,int style) @@ -3900,7 +3902,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api try { foreach (SceneObjectPart part in parts) - part.SetFaceColor(color, face); + part.SetFaceColorAlpha(face, color, null); } finally { @@ -8243,8 +8245,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api LSL_Vector color=rules.GetVector3Item(idx++); double alpha=(double)rules.GetLSLFloatItem(idx++); - part.SetFaceColor(color, face); - SetAlpha(part, alpha, face); + part.SetFaceColorAlpha(face, color, alpha); break; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 37766fbbb7..04c3184219 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -2925,7 +2925,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api avatar.SpeedModifier = (float)SpeedModifier; } - public void osKickAvatar(string FirstName,string SurName,string alert) + public void osKickAvatar(string FirstName, string SurName, string alert) { CheckThreatLevel(ThreatLevel.Severe, "osKickAvatar"); m_host.AddScriptLPS(1); @@ -2939,7 +2939,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api sp.ControllingClient.Kick(alert); // ...and close on our side - sp.Scene.IncomingCloseAgent(sp.UUID); + sp.Scene.IncomingCloseAgent(sp.UUID, false); } }); } diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs index 17a0d69838..03be2abf07 100644 --- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs +++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs @@ -546,6 +546,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools "OpenSim.Region.ScriptEngine.Shared.dll")); parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, "OpenSim.Region.ScriptEngine.Shared.Api.Runtime.dll")); + parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, + "OpenMetaverseTypes.dll")); if (lang == enumCompileType.yp) { diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs index 6add1305a8..4e3bc6738a 100644 --- a/OpenSim/Tests/Common/Mock/TestClient.cs +++ b/OpenSim/Tests/Common/Mock/TestClient.cs @@ -935,12 +935,12 @@ namespace OpenSim.Tests.Common.Mock Close(); } - public void Close(bool c) + public void Close() { - Close(); + Close(true, false); } - public void Close() + public void Close(bool sendStop, bool force) { // Fire the callback for this connection closing // This is necesary to get the presence detector to notice that a client has logged out. diff --git a/bin/lib32/BulletSim.dll b/bin/lib32/BulletSim.dll index cc55f00919..ce0dd9d636 100755 Binary files a/bin/lib32/BulletSim.dll and b/bin/lib32/BulletSim.dll differ diff --git a/bin/lib32/libBulletSim.so b/bin/lib32/libBulletSim.so index 26ad52ba23..d2d65408af 100755 Binary files a/bin/lib32/libBulletSim.so and b/bin/lib32/libBulletSim.so differ diff --git a/bin/lib64/BulletSim.dll b/bin/lib64/BulletSim.dll index 94dae95849..67d3f1c397 100755 Binary files a/bin/lib64/BulletSim.dll and b/bin/lib64/BulletSim.dll differ diff --git a/bin/lib64/libBulletSim.so b/bin/lib64/libBulletSim.so index 52e9960274..9a5c1712f3 100755 Binary files a/bin/lib64/libBulletSim.so and b/bin/lib64/libBulletSim.so differ diff --git a/prebuild.xml b/prebuild.xml index 09336b3594..f85550a3f1 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -1880,6 +1880,7 @@ +