diff --git a/OpenSim/Framework/IProfileModule.cs b/OpenSim/Framework/IProfileModule.cs new file mode 100644 index 0000000000..ef03d4a62a --- /dev/null +++ b/OpenSim/Framework/IProfileModule.cs @@ -0,0 +1,37 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using OpenMetaverse; + +namespace OpenSim.Framework +{ + public interface IProfileModule + { + void RequestAvatarProperties(IClientAPI remoteClient, UUID avatarID); + + } +} diff --git a/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs b/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs index 2bbc6c7477..8aa2ff3018 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs @@ -102,7 +102,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { m_currentPacket = 2; } - + while (sendMore && packetsSent < packetsToSend && m_currentPacket <= m_stopPacket) { sendMore = SendPacket(client); @@ -114,17 +114,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP return (m_currentPacket > m_stopPacket); } + /// + /// This is where we decide what we need to update + /// and assign the real discardLevel and packetNumber + /// assuming of course that the connected client might be bonkers + /// public void RunUpdate() { - //This is where we decide what we need to update - //and assign the real discardLevel and packetNumber - //assuming of course that the connected client might be bonkers - if (!HasAsset) { if (!m_assetRequested) { m_assetRequested = true; +// m_log.DebugFormat("[J2KIMAGE]: Requesting asset {0}", TextureID); AssetService.Get(TextureID.ToString(), this, AssetReceived); } } @@ -137,6 +139,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP { //Request decode m_decodeRequested = true; + +// m_log.DebugFormat("[J2KIMAGE]: Requesting decode of asset {0}", TextureID); + // Do we have a jpeg decoder? if (J2KDecoder != null) { @@ -149,7 +154,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Send it off to the jpeg decoder J2KDecoder.BeginDecode(TextureID, m_asset, J2KDecodedCallback); } - } else { @@ -331,14 +335,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP { if (m_currentPacket == 0) return 0; + if (m_currentPacket == 1) return FIRST_PACKET_SIZE; int result = FIRST_PACKET_SIZE + ((int)m_currentPacket - 2) * IMAGE_PACKET_SIZE; + if (result < 0) - { result = FIRST_PACKET_SIZE; - } + return result; } @@ -377,7 +382,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP { UUID assetID = UUID.Zero; if (asset != null) + { assetID = asset.FullID; + } else if ((InventoryAccessModule != null) && (sender != InventoryAccessModule)) { // Unfortunately we need this here, there's no other way. @@ -398,7 +405,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP } AssetDataCallback(assetID, asset); - } } } diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 083dcc0b0c..4d3a30ccd2 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -351,7 +351,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP protected Dictionary m_packetHandlers = new Dictionary(); protected Dictionary m_genericPacketHandlers = new Dictionary(); //PauPaw:Local Generic Message handlers protected Scene m_scene; - protected LLImageManager m_imageManager; + private LLImageManager m_imageManager; protected string m_firstName; protected string m_lastName; protected Thread m_clientThread; @@ -522,8 +522,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP IsActive = false; // Shutdown the image manager - if (m_imageManager != null) - m_imageManager.Close(); + m_imageManager.Close(); // Fire the callback for this connection closing if (OnConnectionClosed != null) @@ -601,7 +600,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// Add a handler for the given packet type. /// /// - /// The packet is handled on its own thread. If packets must be handled in the order in which thye + /// The packet is handled on its own thread. If packets must be handled in the order in which they /// are received then please use the synchronous version of this method. /// /// @@ -3984,14 +3983,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP } if ((categories & ThrottleOutPacketTypeFlags.Texture) != 0) - { - ProcessTextureRequests(); - } - } - - void ProcessTextureRequests() - { - if (m_imageManager != null) m_imageManager.ProcessImageQueue(m_udpServer.TextureSendLimit); } @@ -7540,12 +7531,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP if ((ImageType)block.Type == ImageType.Baked) args.Priority *= 2.0f; - // in the end, we null this, so we have to check if it's null - if (m_imageManager != null) - { - m_imageManager.EnqueueReq(args); - } + m_imageManager.EnqueueReq(args); } + return true; } diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLImageManager.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLImageManager.cs index e3a881f790..3e31b7d9cc 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLImageManager.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLImageManager.cs @@ -84,7 +84,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// public void EnqueueReq(TextureRequestArgs newRequest) { - //Make sure we're not shutting down.. if (!m_shuttingdown) { J2KImage imgrequest; @@ -99,19 +98,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP { //m_log.Debug("[TEX]: (CAN) ID=" + newRequest.RequestedAssetID); - try + try { lock (m_syncRoot) - m_priorityQueue.Delete(imgrequest.PriorityQueueHandle); + m_priorityQueue.Delete(imgrequest.PriorityQueueHandle); } catch (Exception) { } } else { +// m_log.DebugFormat( +// "[LL IMAGE MANAGER]: Received duplicate of existing request for {0}, start packet {1} from {2}", +// newRequest.RequestedAssetID, newRequest.PacketNumber, m_client.Name); + //m_log.DebugFormat("[TEX]: (UPD) ID={0}: D={1}, S={2}, P={3}", // newRequest.RequestedAssetID, newRequest.DiscardLevel, newRequest.PacketNumber, newRequest.Priority); - //Check the packet sequence to make sure this isn't older than + //Check the packet sequence to make sure this isn't older than //one we've already received if (newRequest.requestSequence > imgrequest.LastSequence) { @@ -126,11 +129,34 @@ namespace OpenSim.Region.ClientStack.LindenUDP //Update the requested priority imgrequest.Priority = newRequest.Priority; + UpdateImageInQueue(imgrequest); - //Run an update imgrequest.RunUpdate(); + +// J2KImage imgrequest2 = new J2KImage(this); +// imgrequest2.J2KDecoder = m_j2kDecodeModule; +// imgrequest2.AssetService = m_assetCache; +// imgrequest2.AgentID = m_client.AgentId; +// imgrequest2.InventoryAccessModule = m_client.Scene.RequestModuleInterface(); +// imgrequest2.DiscardLevel = newRequest.DiscardLevel; +// imgrequest2.StartPacket = Math.Max(1, newRequest.PacketNumber); +// imgrequest2.Priority = newRequest.Priority; +// imgrequest2.TextureID = newRequest.RequestedAssetID; +// imgrequest2.Priority = newRequest.Priority; +// +// //Add this download to the priority queue +// AddImageToQueue(imgrequest2); +// +// imgrequest2.RunUpdate(); + } +// else +// { +// m_log.DebugFormat( +// "[LL IMAGE MANAGER]: Ignoring duplicate of existing request for {0} (sequence {1}) from {2} as its request sequence {3} is not greater", +// newRequest.RequestedAssetID, imgrequest.LastSequence, m_client.Name, newRequest.requestSequence); +// } } } else @@ -142,6 +168,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP } else { +// m_log.DebugFormat( +// "[LL IMAGE MANAGER]: Received request for {0}, start packet {1} from {2}", +// newRequest.RequestedAssetID, newRequest.PacketNumber, m_client.Name); + //m_log.DebugFormat("[TEX]: (NEW) ID={0}: D={1}, S={2}, P={3}", // newRequest.RequestedAssetID, newRequest.DiscardLevel, newRequest.PacketNumber, newRequest.Priority); @@ -159,7 +189,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP //Add this download to the priority queue AddImageToQueue(imgrequest); - //Run an update imgrequest.RunUpdate(); } } @@ -176,7 +205,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // If null was returned, the texture priority queue is currently empty if (image == null) - return false; + break; if (image.IsDecoded) { @@ -194,10 +223,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP // written. Undecoded textures should not be going into the priority // queue, because a high priority undecoded texture will clog up the // pipeline for a client - return true; +// m_log.DebugFormat( +// "[LL IMAGE MANAGER]: Exiting image queue processing early on encountering undecoded image {0}", +// image.TextureID); + + break; } } +// if (packetsSent != 0) +// m_log.DebugFormat("[LL IMAGE MANAGER]: Processed {0} packets from image queue", packetsSent); + return m_priorityQueue.Count > 0; } @@ -219,7 +255,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP { if (m_priorityQueue.Count > 0) { - try { image = m_priorityQueue.FindMax(); } + try + { + image = m_priorityQueue.FindMax(); + } catch (Exception) { } } } @@ -232,7 +271,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP lock (m_syncRoot) { - try { m_priorityQueue.Add(ref image.PriorityQueueHandle, image); } + try + { + m_priorityQueue.Add(ref image.PriorityQueueHandle, image); + } catch (Exception) { } } } @@ -241,7 +283,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP { lock (m_syncRoot) { - try { m_priorityQueue.Delete(image.PriorityQueueHandle); } + try + { + m_priorityQueue.Delete(image.PriorityQueueHandle); + } catch (Exception) { } } } @@ -250,7 +295,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP { lock (m_syncRoot) { - try { m_priorityQueue.Replace(image.PriorityQueueHandle, image); } + try + { + m_priorityQueue.Replace(image.PriorityQueueHandle, image); + } catch (Exception) { image.PriorityQueueHandle = null; diff --git a/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs b/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs index 7dd90874b6..14dee84c24 100644 --- a/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs +++ b/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs @@ -103,6 +103,10 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender // If it's cached, return the cached results if (m_decodedCache.TryGetValue(assetID, out result)) { +// m_log.DebugFormat( +// "[J2KDecoderModule]: Returning existing cached {0} layers j2k decode for {1}", +// result.Length, assetID); + callback(assetID, result); } else diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index bc7bf664c2..9df0592d4c 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs @@ -156,7 +156,8 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory changed = sp.Appearance.SetTextureEntries(textureEntry) || changed; // WriteBakedTexturesReport(sp, m_log.DebugFormat); - ValidateBakedTextureCache(sp, false); + if (!ValidateBakedTextureCache(sp)) + RequestRebake(sp, true); // This appears to be set only in the final stage of the appearance // update transaction. In theory, we should be able to do an immediate @@ -250,15 +251,6 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory return true; } - /// - /// Check for the existence of the baked texture assets. - /// - /// - public bool ValidateBakedTextureCache(IScenePresence sp) - { - return ValidateBakedTextureCache(sp, true); - } - /// /// Queue up a request to send appearance. /// @@ -292,17 +284,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory } } - #endregion - - #region AvatarFactoryModule private methods - - /// - /// Check for the existence of the baked texture assets. Request a rebake - /// unless checkonly is true. - /// - /// - /// - private bool ValidateBakedTextureCache(IScenePresence sp, bool checkonly) + public bool ValidateBakedTextureCache(IScenePresence sp) { bool defonly = true; // are we only using default textures @@ -330,12 +312,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory defonly = false; // found a non-default texture reference if (m_scene.AssetService.Get(face.TextureID.ToString()) == null) - { - if (checkonly) - return false; - - sp.ControllingClient.SendRebakeAvatarTextures(face.TextureID); - } + return false; } m_log.DebugFormat("[AVFACTORY]: Completed texture check for {0}", sp.UUID); @@ -344,6 +321,52 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory return (defonly ? false : true); } + public void RequestRebake(IScenePresence sp, bool missingTexturesOnly) + { + for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++) + { + int idx = AvatarAppearance.BAKE_INDICES[i]; + Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx]; + + // if there is no texture entry, skip it + if (face == null) + continue; + +// m_log.DebugFormat( +// "[AVFACTORY]: Looking for texture {0}, id {1} for {2} {3}", +// face.TextureID, idx, client.Name, client.AgentId); + + // if the texture is one of the "defaults" then skip it + // this should probably be more intelligent (skirt texture doesnt matter + // if the avatar isnt wearing a skirt) but if any of the main baked + // textures is default then the rest should be as well + if (face.TextureID == UUID.Zero || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE) + continue; + + if (missingTexturesOnly) + { + if (m_scene.AssetService.Get(face.TextureID.ToString()) != null) + continue; + else + m_log.DebugFormat( + "[AVFACTORY]: Missing baked texture {0} ({1}) for {2}, requesting rebake.", + face.TextureID, idx, sp.Name); + } + else + { + m_log.DebugFormat( + "[AVFACTORY]: Requesting rebake of {0} ({1}) for {2}.", + face.TextureID, idx, sp.Name); + } + + sp.ControllingClient.SendRebakeAvatarTextures(face.TextureID); + } + } + + #endregion + + #region AvatarFactoryModule private methods + private Dictionary GetBakedTextureFaces(ScenePresence sp) { if (sp.IsChildAgent) diff --git a/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs b/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs index dee0ad4bfc..eb1e4b5f13 100644 --- a/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs @@ -43,7 +43,7 @@ using OpenSim.Services.Interfaces; namespace OpenSim.Region.CoreModules.Avatar.Profile { [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class BasicProfileModule : ISharedRegionModule + public class BasicProfileModule : IProfileModule, ISharedRegionModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -57,6 +57,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Profile public void Initialise(IConfigSource config) { + // This can be reduced later as the loader will determine + // whether we are needed if (config.Configs["Profile"] != null) { if (config.Configs["Profile"].GetString("Module", string.Empty) != "BasicProfileModule") @@ -65,14 +67,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Profile m_log.DebugFormat("[PROFILE MODULE]: Basic Profile Module enabled"); m_Enabled = true; - } public void AddRegion(Scene scene) { if (!m_Enabled) return; - + lock (m_Scenes) { if (!m_Scenes.Contains(scene)) @@ -80,6 +81,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Profile m_Scenes.Add(scene); // Hook up events scene.EventManager.OnNewClient += OnNewClient; + scene.RegisterModuleInterface(this); } } } @@ -116,7 +118,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Profile public Type ReplaceableInterface { - get { return null; } + get { return typeof(IProfileModule); } } #endregion @@ -170,4 +172,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Profile } } -} \ No newline at end of file +} diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs index dbe2560493..37292d66fd 100644 --- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs +++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs @@ -50,6 +50,9 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement public string LastName { get; set; } public string HomeURL { get; set; } public Dictionary ServerURLs { get; set; } + public string Title { get; set; } + public int Flags { get; set; } + public int Created { get; set; } } public class UserManagementModule : ISharedRegionModule, IUserManagement @@ -281,6 +284,94 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement return string.Empty; } + public int GetUserFlags(UUID userID) + { + UserData userdata; + lock (m_UserCache) + m_UserCache.TryGetValue(userID, out userdata); + + if (userdata.Flags == -1) + GetUserInfo(userID); + + if (userdata.Flags != -1) + return userdata.Flags; + + return 0; + } + + public int GetUserCreated(UUID userID) + { + UserData userdata; + lock (m_UserCache) + m_UserCache.TryGetValue(userID, out userdata); + + if (userdata.Flags == -1) + GetUserInfo(userID); + + if (userdata.Created != -1) + return userdata.Created; + + return 0; + } + + public string GetUserTitle(UUID userID) + { + UserData userdata; + lock (m_UserCache) + m_UserCache.TryGetValue(userID, out userdata); + + if (userdata.Flags == -1) + GetUserInfo(userID); + + if (userdata.Created != -1) + return userdata.Title; + + return string.Empty; + } + + // This will cache the user data + // Change this to return bool + private bool GetUserInfo(UUID userID) + { + UserData userdata; + lock (m_UserCache) + m_UserCache.TryGetValue(userID, out userdata); + + if (userdata != null) + { +// m_log.DebugFormat("[USER MANAGEMENT MODULE]: Requested url type {0} for {1}", serverType, userID); + + if (userdata.Flags >= 0) + { + // This is already populated + return true; + } + + if (userdata.HomeURL != null && userdata.HomeURL != string.Empty) + { + m_log.DebugFormat( + "[USER MANAGEMENT MODULE]: Requesting user flags from '{0}' for {1}", + userdata.HomeURL, userID); + + UserAgentServiceConnector uConn = new UserAgentServiceConnector(userdata.HomeURL); + Dictionary info = uConn.GetUserInfo(userID); + + // Pull our data now + if (info["result"].ToString() == "success") + { + userdata.Flags = (int)info["user_flags"]; + userdata.Created = (int)info["user_created"]; + userdata.Title = (string)info["user_title"]; + + return true; + } + } + } + + return false; + } + + public string GetUserUUI(UUID userID) { UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, userID); @@ -352,6 +443,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement { UserData user = new UserData(); user.Id = id; + user.Flags = -1; + user.Created = -1; if (creatorData != null && creatorData != string.Empty) { diff --git a/OpenSim/Region/Framework/Interfaces/IAvatarFactoryModule.cs b/OpenSim/Region/Framework/Interfaces/IAvatarFactoryModule.cs index 8670229e8b..04df9c3723 100644 --- a/OpenSim/Region/Framework/Interfaces/IAvatarFactoryModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IAvatarFactoryModule.cs @@ -61,7 +61,29 @@ namespace OpenSim.Region.Framework.Interfaces /// true if a valid agent was found, false otherwise bool SaveBakedTextures(UUID agentId); + /// + /// Validate that OpenSim can find the baked textures need to display a given avatar + /// + /// + /// + /// + /// true if all the baked textures referenced by the texture IDs exist or the appearance is only using default textures. false otherwise. + /// bool ValidateBakedTextureCache(IScenePresence sp); + + /// + /// Request a rebake of textures for an avatar. + /// + /// + /// This will send the request to the viewer, since it's there that the rebake is done. + /// + /// Avatar to rebake. + /// + /// If true, only request a rebake for the textures that are missing. + /// If false then we request a rebake of all textures for which we already have references. + /// + void RequestRebake(IScenePresence sp, bool missingTexturesOnly); + void QueueAppearanceSend(UUID agentid); void QueueAppearanceSave(UUID agentid); diff --git a/OpenSim/Region/Framework/Interfaces/IUserManagement.cs b/OpenSim/Region/Framework/Interfaces/IUserManagement.cs index ea0ba5935b..54dfaf4c63 100644 --- a/OpenSim/Region/Framework/Interfaces/IUserManagement.cs +++ b/OpenSim/Region/Framework/Interfaces/IUserManagement.cs @@ -14,6 +14,9 @@ namespace OpenSim.Region.Framework.Interfaces string GetUserHomeURL(UUID uuid); string GetUserUUI(UUID uuid); string GetUserServerURL(UUID uuid, string serverType); + int GetUserFlags(UUID userID); + int GetUserCreated(UUID userID); + string GetUserTitle(UUID userID); /// /// Add a user. diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 209a0a639e..74d9e60c49 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -405,6 +405,9 @@ namespace OpenSim.Region.Framework.Scenes public delegate void RegionUp(GridRegion region); public event RegionUp OnRegionUp; + public delegate void RegionStarted(Scene scene); + public event RegionStarted OnRegionStarted; + public delegate void LoginsEnabled(string regionName); public event LoginsEnabled OnLoginsEnabled; @@ -2267,6 +2270,27 @@ namespace OpenSim.Region.Framework.Scenes } } + public void TriggerOnRegionStarted(Scene scene) + { + RegionStarted handler = OnRegionStarted; + + if (handler != null) + { + foreach (RegionStarted d in handler.GetInvocationList()) + { + try + { + d(scene); + } + catch (Exception e) + { + m_log.ErrorFormat("[EVENT MANAGER]: Delegate for RegionStarted failed - continuing {0} - {1}", + e.Message, e.StackTrace); + } + } + } + } + public void TriggerLoginsEnabled (string regionName) { LoginsEnabled handler = OnLoginsEnabled; diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 26f915b28e..d2e0ab0790 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1236,6 +1236,7 @@ namespace OpenSim.Region.Framework.Scenes try { + m_eventManager.TriggerOnRegionStarted(this); while (!shuttingdown) Update(); } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index fa8b1c0174..c45cfb8f0a 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -2015,13 +2015,9 @@ namespace OpenSim.Region.Framework.Scenes axPos *= parentRot; Vector3 translationOffsetPosition = axPos; if(_parentID == 0) - { - return GroupPosition; - } - else - { - return ParentGroup.AbsolutePosition + translationOffsetPosition; //KF: Fix child prim position - } + return GroupPosition; + else + return ParentGroup.AbsolutePosition + translationOffsetPosition; } /// diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 845553a678..a301ccb304 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -2855,7 +2855,7 @@ namespace OpenSim.Region.Framework.Scenes Velocity = Vector3.Zero; AbsolutePosition = pos; - m_log.DebugFormat("[SCENE PRESENCE]: Prevented flyoff for {0} at {1}", Name, AbsolutePosition); +// m_log.DebugFormat("[SCENE PRESENCE]: Prevented flyoff for {0} at {1}", Name, AbsolutePosition); AddToPhysicalScene(isFlying); } diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs index 5f2f7d8119..3f249911fb 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs @@ -1279,7 +1279,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization writer.WriteElementString(name, flagsStr.Replace(",", "")); } - static void WriteTaskInventory(XmlTextWriter writer, TaskInventoryDictionary tinv, Dictionary options, Scene scene) + public static void WriteTaskInventory(XmlTextWriter writer, TaskInventoryDictionary tinv, Dictionary options, Scene scene) { if (tinv.Count > 0) // otherwise skip this { @@ -1333,7 +1333,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization } } - static void WriteShape(XmlTextWriter writer, PrimitiveBaseShape shp, Dictionary options) + public static void WriteShape(XmlTextWriter writer, PrimitiveBaseShape shp, Dictionary options) { if (shp != null) { @@ -1508,7 +1508,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization return obj; } - static TaskInventoryDictionary ReadTaskInventory(XmlTextReader reader, string name) + public static TaskInventoryDictionary ReadTaskInventory(XmlTextReader reader, string name) { TaskInventoryDictionary tinv = new TaskInventoryDictionary(); @@ -1548,7 +1548,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization /// The name of the xml element containing the shape /// true if any errors were encountered during parsing, false otherwise /// The shape parsed - static PrimitiveBaseShape ReadShape(XmlTextReader reader, string name, out bool errors) + public static PrimitiveBaseShape ReadShape(XmlTextReader reader, string name, out bool errors) { errors = false; diff --git a/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs b/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs index 1ce24f1745..7e15718c45 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs @@ -114,6 +114,16 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance "Send appearance data for each avatar in the simulator to other viewers.", "Optionally, you can specify that only a particular avatar's appearance data is sent.", HandleSendAppearanceCommand); + + scene.AddCommand( + this, "appearance rebake", + "appearance rebake ", + "Send a request to the user's viewer for it to rebake and reupload its appearance textures.", + "This is currently done for all baked texture references previously received, whether the simulator can find the asset or not." + + "\nThis will only work for texture ids that the viewer has already uploaded." + + "\nIf the viewer has not yet sent the server any texture ids then nothing will happen" + + "\nsince requests can only be made for ids that the client has already sent us", + HandleRebakeAppearanceCommand); } private void HandleSendAppearanceCommand(string module, string[] cmd) @@ -210,6 +220,34 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance } } } - } + } + + private void HandleRebakeAppearanceCommand(string module, string[] cmd) + { + if (cmd.Length != 4) + { + MainConsole.Instance.OutputFormat("Usage: appearance rebake "); + return; + } + + string firstname = cmd[2]; + string lastname = cmd[3]; + + lock (m_scenes) + { + foreach (Scene scene in m_scenes.Values) + { + ScenePresence sp = scene.GetScenePresence(firstname, lastname); + if (sp != null && !sp.IsChildAgent) + { + MainConsole.Instance.OutputFormat( + "Requesting rebake of uploaded textures for {0}", + sp.Name, scene.RegionInfo.RegionName); + + scene.AvatarFactory.RequestRebake(sp, false); + } + } + } + } } } \ No newline at end of file diff --git a/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs b/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs index 07c69624b7..1bd37062db 100644 --- a/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs +++ b/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs @@ -91,6 +91,7 @@ namespace OpenSim.Server.Handlers.Hypergrid server.AddXmlRPCHandler("status_notification", StatusNotification, false); server.AddXmlRPCHandler("get_online_friends", GetOnlineFriends, false); + server.AddXmlRPCHandler("get_user_info", GetUserInfo, false); server.AddXmlRPCHandler("get_server_urls", GetServerURLs, false); server.AddXmlRPCHandler("locate_user", LocateUser, false); @@ -299,6 +300,38 @@ namespace OpenSim.Server.Handlers.Hypergrid } + public XmlRpcResponse GetUserInfo(XmlRpcRequest request, IPEndPoint remoteClient) + { + Hashtable hash = new Hashtable(); + Hashtable requestData = (Hashtable)request.Params[0]; + + // This needs checking! + if (requestData.ContainsKey("userID")) + { + string userID_str = (string)requestData["userID"]; + UUID userID = UUID.Zero; + UUID.TryParse(userID_str, out userID); + + //int userFlags = m_HomeUsersService.GetUserFlags(userID); + Dictionary userInfo = m_HomeUsersService.GetUserInfo(userID); + if (userInfo.Count > 0) + { + foreach (KeyValuePair kvp in userInfo) + { + hash[kvp.Key] = kvp.Value; + } + } + else + { + hash["result"] = "failure"; + } + } + + XmlRpcResponse response = new XmlRpcResponse(); + response.Value = hash; + return response; + } + public XmlRpcResponse GetServerURLs(XmlRpcRequest request, IPEndPoint remoteClient) { Hashtable hash = new Hashtable(); diff --git a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs index a73bf9e946..d617aee04b 100644 --- a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs @@ -559,6 +559,60 @@ namespace OpenSim.Services.Connectors.Hypergrid return online; } + public Dictionary GetUserInfo (UUID userID) + { + Hashtable hash = new Hashtable(); + hash["userID"] = userID.ToString(); + + IList paramList = new ArrayList(); + paramList.Add(hash); + + XmlRpcRequest request = new XmlRpcRequest("get_user_info", paramList); + + Dictionary info = new Dictionary(); + XmlRpcResponse response = null; + try + { + response = request.Send(m_ServerURL, 10000); + } + catch + { + m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0} for GetUserInfo", m_ServerURL); + return info; + } + + if (response.IsFault) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} for GetServerURLs returned an error: {1}", m_ServerURL, response.FaultString); + return info; + } + + hash = (Hashtable)response.Value; + try + { + if (hash == null) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: GetUserInfo Got null response from {0}! THIS IS BAAAAD", m_ServerURL); + return info; + } + + // Here is the actual response + foreach (object key in hash.Keys) + { + if (hash[key] != null) + { + info.Add(key.ToString(), hash[key]); + } + } + } + catch + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on GetOnlineFriends response."); + } + + return info; + } + public Dictionary GetServerURLs(UUID userID) { Hashtable hash = new Hashtable(); diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs index 38bcce6906..1a839f3338 100644 --- a/OpenSim/Services/HypergridService/UserAgentService.cs +++ b/OpenSim/Services/HypergridService/UserAgentService.cs @@ -486,6 +486,31 @@ namespace OpenSim.Services.HypergridService return online; } + public Dictionary GetUserInfo(UUID userID) + { + Dictionary info = new Dictionary(); + + if (m_UserAccountService == null) + { + m_log.WarnFormat("[USER AGENT SERVICE]: Unable to get user flags because user account service is missing"); + info["result"] = "fail"; + info["message"] = "UserAccountService is missing!"; + return info; + } + + UserAccount account = m_UserAccountService.GetUserAccount(UUID.Zero /*!!!*/, userID); + + if (account != null) + { + info.Add("user_flags", (object)account.UserFlags); + info.Add("user_created", (object)account.Created); + info.Add("user_title", (object)account.UserTitle); + info.Add("result", "success"); + } + + return info; + } + public Dictionary GetServerURLs(UUID userID) { if (m_UserAccountService == null) diff --git a/OpenSim/Services/Interfaces/IHypergridServices.cs b/OpenSim/Services/Interfaces/IHypergridServices.cs index e86ec519e5..5b293acbee 100644 --- a/OpenSim/Services/Interfaces/IHypergridServices.cs +++ b/OpenSim/Services/Interfaces/IHypergridServices.cs @@ -55,6 +55,7 @@ namespace OpenSim.Services.Interfaces void LogoutAgent(UUID userID, UUID sessionID); GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt); Dictionary GetServerURLs(UUID userID); + Dictionary GetUserInfo(UUID userID); string LocateUser(UUID userID); // Tries to get the universal user identifier for the targetUserId diff --git a/OpenSim/Tools/pCampBot/pCampBot.cs b/OpenSim/Tools/pCampBot/pCampBot.cs index 6249fae019..a73fcbec8f 100644 --- a/OpenSim/Tools/pCampBot/pCampBot.cs +++ b/OpenSim/Tools/pCampBot/pCampBot.cs @@ -112,10 +112,10 @@ namespace pCampBot " -lastname lastname for the bots. Each lastname will have _ appended, e.g. Ima Bot_0\n" + " -password password for the bots\n" + " -b, behaviours behaviours for bots. Comma separated, e.g. p,g. Default is p\n" + - " current options are:" + - " p (physics)" + - " g (grab)" + - " t (teleport)" + + " current options are:\n" + + " p (physics)\n" + + " g (grab)\n" + + " t (teleport)\n" + // " c (cross)" + " -wear set appearance folder to load from (default: no)\n" + " -h, -help show this message"); diff --git a/bin/C5.dll b/bin/C5.dll index 1234ce9ff8..42093e5f84 100755 Binary files a/bin/C5.dll and b/bin/C5.dll differ