diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs index cf2e037e26..eb5d784011 100644 --- a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs +++ b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs @@ -2942,7 +2942,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController /// private void ApplyNextOwnerPermissions(InventoryItemBase item) { - if (item.InvType == (int)InventoryType.Object) + if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0) { uint perms = item.CurrentPermissions; PermissionsUtil.ApplyFoldedPermissions(item.CurrentPermissions, ref perms); diff --git a/OpenSim/Framework/PermissionsUtil.cs b/OpenSim/Framework/PermissionsUtil.cs index d785a781f5..5d3186da62 100644 --- a/OpenSim/Framework/PermissionsUtil.cs +++ b/OpenSim/Framework/PermissionsUtil.cs @@ -72,8 +72,8 @@ namespace OpenSim.Framework /// The permissions variable to modify. public static void ApplyFoldedPermissions(uint foldedPerms, ref uint mainPerms) { - if ((foldedPerms & 7) == 0) - return; // assume that if the folded permissions are 0 then this means that they weren't actually recorded +// if ((foldedPerms & 7) == 0) +// return; // assume that if the folded permissions are 0 then this means that they weren't actually recorded if ((foldedPerms & ((uint)PermissionMask.Copy >> 13)) == 0) mainPerms &= ~(uint)PermissionMask.Copy; diff --git a/OpenSim/Framework/WearableCacheItem.cs b/OpenSim/Framework/WearableCacheItem.cs index 1aecf79695..cde2862909 100644 --- a/OpenSim/Framework/WearableCacheItem.cs +++ b/OpenSim/Framework/WearableCacheItem.cs @@ -46,7 +46,7 @@ namespace OpenSim.Framework int itemmax = 21; WearableCacheItem[] retitems = new WearableCacheItem[itemmax]; for (uint i=0;i AvatarWearable.MAX_WEARABLES) - { - maxCacheitemsLoop = AvatarWearable.MAX_WEARABLES; - m_log.WarnFormat("[CACHEDBAKES]: Too Many Cache items Provided {0}, the max is {1}. Truncating!", cacheItems.Length, AvatarWearable.MAX_WEARABLES); - } +/* not in use. work done in AvatarFactoryModule ValidateBakedTextureCache() and UpdateBakedTextureCache() + private void CaptureAppearanceSettings(IClientAPI remoteClient, Primitive.TextureEntry textureEntry, byte[] visualParams, Vector3 avSize, WearableCacheItem[] cacheItems) + { + // if cacheItems.Length > 0 viewer is giving us current textures information. + // baked ones should had been uploaded and in assets cache as local itens - m_BakedTextureModule = m_scene.RequestModuleInterface(); - if (cacheItems.Length > 0) - { - m_log.Debug("[Cacheitems]: " + cacheItems.Length); - for (int iter = 0; iter < maxCacheitemsLoop; iter++) - { - m_log.Debug("[Cacheitems] {" + iter + "/" + cacheItems[iter].TextureIndex + "}: c-" + cacheItems[iter].CacheId + ", t-" + - cacheItems[iter].TextureID); - } - - ScenePresence p = null; - if (m_scene.TryGetScenePresence(remoteClient.AgentId, out p)) - { + + if (cacheItems.Length == 0) + return; // no textures information, nothing to do + + ScenePresence p = null; + if (!m_scene.TryGetScenePresence(remoteClient.AgentId, out p)) + return; // what are we doing if there is no presence to cache for? + + if (p.IsDeleted) + return; // does this really work? + + int maxCacheitemsLoop = cacheItems.Length; + if (maxCacheitemsLoop > 20) + { + maxCacheitemsLoop = AvatarWearable.MAX_WEARABLES; + m_log.WarnFormat("[CACHEDBAKES]: Too Many Cache items Provided {0}, the max is {1}. Truncating!", cacheItems.Length, AvatarWearable.MAX_WEARABLES); + } + + m_BakedTextureModule = m_scene.RequestModuleInterface(); + + + // some nice debug + m_log.Debug("[Cacheitems]: " + cacheItems.Length); + for (int iter = 0; iter < maxCacheitemsLoop; iter++) + { + m_log.Debug("[Cacheitems] {" + iter + "/" + cacheItems[iter].TextureIndex + "}: c-" + cacheItems[iter].CacheId + ", t-" + + cacheItems[iter].TextureID); + } + + // p.Appearance.WearableCacheItems is in memory primary cashID to textures mapper WearableCacheItem[] existingitems = p.Appearance.WearableCacheItems; + if (existingitems == null) { if (m_BakedTextureModule != null) @@ -161,38 +173,22 @@ namespace OpenSim.Region.ClientStack.Linden p.Appearance.WearableCacheItems = savedcache; p.Appearance.WearableCacheItemsDirty = false; } + } - } - /* - * The following Catch types DO NOT WORK with m_BakedTextureModule.Get - * it jumps to the General Packet Exception Handler if you don't catch Exception! - * - catch (System.Net.Sockets.SocketException) - { - cacheItems = null; - } - catch (WebException) - { - cacheItems = null; - } - catch (InvalidOperationException) - { - cacheItems = null; - } */ catch (Exception) { - // The service logs a sufficient error message. + // The service logs a sufficient error message. } - + if (savedcache != null) existingitems = savedcache; } } + // Existing items null means it's a fully new appearance if (existingitems == null) { - for (int i = 0; i < maxCacheitemsLoop; i++) { if (textureEntry.FaceTextures.Length > cacheItems[i].TextureIndex) @@ -205,7 +201,7 @@ namespace OpenSim.Region.ClientStack.Linden AppearanceManager.DEFAULT_AVATAR_TEXTURE; continue; } - cacheItems[i].TextureID =face.TextureID; + cacheItems[i].TextureID = face.TextureID; if (m_scene.AssetService != null) cacheItems[i].TextureAsset = m_scene.AssetService.GetCached(cacheItems[i].TextureID.ToString()); @@ -214,15 +210,10 @@ namespace OpenSim.Region.ClientStack.Linden { m_log.WarnFormat("[CACHEDBAKES]: Invalid Texture Index Provided, Texture doesn't exist or hasn't been uploaded yet {0}, the max is {1}. Skipping!", cacheItems[i].TextureIndex, textureEntry.FaceTextures.Length); } - - } } else - - - { - // for each uploaded baked texture + { for (int i = 0; i < maxCacheitemsLoop; i++) { if (textureEntry.FaceTextures.Length > cacheItems[i].TextureIndex) @@ -253,23 +244,24 @@ namespace OpenSim.Region.ClientStack.Linden } } } - - - p.Appearance.WearableCacheItems = cacheItems; - - if (m_BakedTextureModule != null) { m_BakedTextureModule.Store(remoteClient.AgentId, cacheItems); p.Appearance.WearableCacheItemsDirty = true; - + + } + else + p.Appearance.WearableCacheItemsDirty = false; + + for (int iter = 0; iter < maxCacheitemsLoop; iter++) + { + m_log.Debug("[CacheitemsLeaving] {" + iter + "/" + cacheItems[iter].TextureIndex + "}: c-" + cacheItems[iter].CacheId + ", t-" + + cacheItems[iter].TextureID); } } - } - } - + */ public void PostInitialise() { } diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 34a2797add..e9a087bd34 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -3684,6 +3684,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP avp.Sender.IsTrial = false; avp.Sender.ID = agentID; avp.AppearanceData = new AvatarAppearancePacket.AppearanceDataBlock[0]; + + // this need be use in future + // avp.AppearanceData[0].AppearanceVersion = 0; + // avp.AppearanceData[0].CofVersion = 0; + //m_log.DebugFormat("[CLIENT]: Sending appearance for {0} to {1}", agentID.ToString(), AgentId.ToString()); OutPacket(avp, ThrottleOutPacketType.Task); } @@ -6535,7 +6540,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP WearableCacheItem[] cacheitems = new WearableCacheItem[appear.WearableData.Length]; for (int i=0; i(); - // var item = fac.GetBakedTextureFaces(AgentId); - //WearableCacheItem[] items = fac.GetCachedItems(AgentId); - - IAssetService cache = m_scene.AssetService; - IBakedTextureModule bakedTextureModule = m_scene.RequestModuleInterface(); - //bakedTextureModule = null; int maxWearablesLoop = cachedtex.WearableData.Length; if (maxWearablesLoop > AvatarWearable.MAX_WEARABLES) maxWearablesLoop = AvatarWearable.MAX_WEARABLES; - if (bakedTextureModule != null && cache != null) + int cacheHits = 0; + + // We need to make sure the asset stored in the bake is available on this server also by it's assetid before we map it to a Cacheid + + WearableCacheItem[] cacheItems = null; + + ScenePresence p = m_scene.GetScenePresence(AgentId); + + if (p != null && p.Appearance != null) { - // We need to make sure the asset stored in the bake is available on this server also by it's assetid before we map it to a Cacheid + cacheItems = p.Appearance.WearableCacheItems; + } - WearableCacheItem[] cacheItems = null; - ScenePresence p = m_scene.GetScenePresence(AgentId); - if (p.Appearance != null) - if (p.Appearance.WearableCacheItems == null || p.Appearance.WearableCacheItemsDirty) - { - try - { - cacheItems = bakedTextureModule.Get(AgentId); - p.Appearance.WearableCacheItems = cacheItems; - p.Appearance.WearableCacheItemsDirty = false; - } - - /* - * The following Catch types DO NOT WORK, it jumps to the General Packet Exception Handler if you don't catch Exception! - * - catch (System.Net.Sockets.SocketException) - { - cacheItems = null; - } - catch (WebException) - { - cacheItems = null; - } - catch (InvalidOperationException) - { - cacheItems = null; - } */ - catch (Exception) - { - cacheItems = null; - } - - } - else if (p.Appearance.WearableCacheItems != null) - { - cacheItems = p.Appearance.WearableCacheItems; - } - - if (cache != null && cacheItems != null) + if (cacheItems != null) + { + for (int i = 0; i < maxWearablesLoop; i++) { - foreach (WearableCacheItem item in cacheItems) + int idx = cachedtex.WearableData[i].TextureIndex; + + cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); + cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; + cachedresp.WearableData[i].HostName = new byte[0]; + if (cachedtex.WearableData[i].ID == cacheItems[idx].CacheId) { - - if (cache.GetCached(item.TextureID.ToString()) == null) - { - item.TextureAsset.Temporary = true; - cache.Store(item.TextureAsset); - } - - + cachedresp.WearableData[i].TextureID = cacheItems[idx].TextureID; + cacheHits++; } - } - - if (cacheItems != null) - { - - for (int i = 0; i < maxWearablesLoop; i++) + else { - WearableCacheItem item = - WearableCacheItem.SearchTextureIndex(cachedtex.WearableData[i].TextureIndex,cacheItems); - - cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); - cachedresp.WearableData[i].TextureIndex= cachedtex.WearableData[i].TextureIndex; - cachedresp.WearableData[i].HostName = new byte[0]; - if (item != null && cachedtex.WearableData[i].ID == item.CacheId) - { - - cachedresp.WearableData[i].TextureID = item.TextureID; - } - else - { - cachedresp.WearableData[i].TextureID = UUID.Zero; - } - } - } - else - { - for (int i = 0; i < maxWearablesLoop; i++) - { - cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); - cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; cachedresp.WearableData[i].TextureID = UUID.Zero; - //UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46"); - cachedresp.WearableData[i].HostName = new byte[0]; } } } else { - if (cache == null) + for (int i = 0; i < maxWearablesLoop; i++) { - for (int i = 0; i < maxWearablesLoop; i++) - { - cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); - cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; - cachedresp.WearableData[i].TextureID = UUID.Zero; - //UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46"); - cachedresp.WearableData[i].HostName = new byte[0]; - } - } - else - { - for (int i = 0; i < maxWearablesLoop; i++) - { - cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); - cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; - - - - if (cache.GetCached(cachedresp.WearableData[i].TextureID.ToString()) == null) - cachedresp.WearableData[i].TextureID = UUID.Zero; - //UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46"); - else - cachedresp.WearableData[i].TextureID = UUID.Zero; - // UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46"); - cachedresp.WearableData[i].HostName = new byte[0]; - } + cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); + cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; + cachedresp.WearableData[i].TextureID = UUID.Zero; + //UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46"); + cachedresp.WearableData[i].HostName = new byte[0]; } } + + m_log.DebugFormat("texture cached: hits {0}", cacheHits); + cachedresp.Header.Zerocoded = true; OutPacket(cachedresp, ThrottleOutPacketType.Task); diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index b7c8594a6a..a3fdae1580 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -1750,25 +1750,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP endPoint, sessionInfo); - // Send ack straight away to let the viewer know that the connection is active. - // The client will be null if it already exists (e.g. if on a region crossing the client sends a use - // circuit code to the existing child agent. This is not particularly obvious. - SendAckImmediate(endPoint, uccp.Header.Sequence); - - // We only want to send initial data to new clients, not ones which are being converted from child to root. - if (client != null) - { - AgentCircuitData aCircuit = m_scene.AuthenticateHandler.GetAgentCircuitData(uccp.CircuitCode.Code); - bool tp = (aCircuit.teleportFlags > 0); - // Let's delay this for TP agents, otherwise the viewer doesn't know where to get resources from - if (!tp) - client.SceneAgent.SendInitialDataToMe(); - } - // Now we know we can handle more data - Thread.Sleep(200); +// Thread.Sleep(200); - // Obtain the queue and remove it from the cache + // Obtain the pending queue and remove it from the cache Queue queue = null; lock (m_pendingCache) @@ -1790,6 +1775,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP PacketReceived(buf); } queue = null; + + // Send ack straight away to let the viewer know that the connection is active. + // The client will be null if it already exists (e.g. if on a region crossing the client sends a use + // circuit code to the existing child agent. This is not particularly obvious. + SendAckImmediate(endPoint, uccp.Header.Sequence); + + // We only want to send initial data to new clients, not ones which are being converted from child to root. + if (client != null) + { + AgentCircuitData aCircuit = m_scene.AuthenticateHandler.GetAgentCircuitData(uccp.CircuitCode.Code); + bool tp = (aCircuit.teleportFlags > 0); + // Let's delay this for TP agents, otherwise the viewer doesn't know where to get resources from + if (!tp) + client.SceneAgent.SendInitialDataToMe(); + } } else { diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index 09cc9983a8..2e5c58a101 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs @@ -188,27 +188,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory // Process the visual params, this may change height as well if (visualParams != null) { - // string[] visualParamsStrings = new string[visualParams.Length]; - // for (int i = 0; i < visualParams.Length; i++) - // visualParamsStrings[i] = visualParams[i].ToString(); - // m_log.DebugFormat( - // "[AVFACTORY]: Setting visual params for {0} to {1}", - // client.Name, string.Join(", ", visualParamsStrings)); -/* - float oldHeight = sp.Appearance.AvatarHeight; changed = sp.Appearance.SetVisualParams(visualParams); - - if (sp.Appearance.AvatarHeight != oldHeight && sp.Appearance.AvatarHeight > 0) - ((ScenePresence)sp).SetHeight(sp.Appearance.AvatarHeight); - */ -// float oldoff = sp.Appearance.AvatarFeetOffset; -// Vector3 oldbox = sp.Appearance.AvatarBoxSize; - changed = sp.Appearance.SetVisualParams(visualParams); -// float off = sp.Appearance.AvatarFeetOffset; -// Vector3 box = sp.Appearance.AvatarBoxSize; -// if(oldoff != off || oldbox != box) -// ((ScenePresence)sp).SetSize(box,off); - } // Process the baked texture array @@ -222,9 +202,15 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory // WriteBakedTexturesReport(sp, m_log.DebugFormat); + // If bake textures are missing and this is not an NPC, request a rebake from client - if (!ValidateBakedTextureCache(sp) && (((ScenePresence)sp).PresenceType != PresenceType.Npc)) - RequestRebake(sp, true); + // rebake may messup caching, and should not be needed + + +// if (!UpdateBakedTextureCache(sp,cacheItems) && (((ScenePresence)sp).PresenceType != PresenceType.Npc)) +// RequestRebake(sp, true); + + UpdateBakedTextureCache(sp, cacheItems); // 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 @@ -377,121 +363,243 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory } } - public bool ValidateBakedTextureCache(IScenePresence sp) + // called on textures update + public bool UpdateBakedTextureCache(IScenePresence sp, WearableCacheItem[] cacheItems) { bool defonly = true; // are we only using default textures - IImprovedAssetCache cache = m_scene.RequestModuleInterface(); - IBakedTextureModule bakedModule = m_scene.RequestModuleInterface(); - WearableCacheItem[] wearableCache = null; - // Cache wearable data for teleport. - // Only makes sense if there's a bake module and a cache module - if (bakedModule != null && cache != null) + // uploaded baked textures will be in assets local cache + IAssetService cache = m_scene.AssetService; + + int validDirtyBakes = 0; + int hits = 0; + + // our main cacheIDs mapper is p.Appearance.WearableCacheItems + WearableCacheItem[] wearableCache = sp.Appearance.WearableCacheItems; + + if (wearableCache == null) { - try - { - wearableCache = bakedModule.Get(sp.UUID); - } - catch (Exception) - { - - } - if (wearableCache != null) - { - for (int i = 0; i < wearableCache.Length; i++) - { - cache.Cache(wearableCache[i].TextureAsset); - } - } + wearableCache = WearableCacheItem.GetDefaultCacheItem(); } - /* - IBakedTextureModule bakedModule = m_scene.RequestModuleInterface(); - if (invService.GetRootFolder(userID) != null) - { - WearableCacheItem[] wearableCache = null; - if (bakedModule != null) - { - try - { - wearableCache = bakedModule.Get(userID); - appearance.WearableCacheItems = wearableCache; - appearance.WearableCacheItemsDirty = false; - foreach (WearableCacheItem item in wearableCache) - { - appearance.Texture.FaceTextures[item.TextureIndex].TextureID = item.TextureID; - } - } - catch (Exception) - { - - } - } - */ - // Process the texture entry - for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++) + // Process received baked textures + for (int i = 0; i < cacheItems.Length; i++) { - int idx = AvatarAppearance.BAKE_INDICES[i]; + int idx = (int)cacheItems[i].TextureIndex; Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx]; - // No face, so lets check our baked service cache, teleport or login. + // No face if (face == null) { - if (wearableCache != null) - { - // If we find the an appearance item, set it as the textureentry and the face - WearableCacheItem searchitem = WearableCacheItem.SearchTextureIndex((uint) idx, wearableCache); - if (searchitem != null) - { - sp.Appearance.Texture.FaceTextures[idx] = sp.Appearance.Texture.CreateFace((uint) idx); - sp.Appearance.Texture.FaceTextures[idx].TextureID = searchitem.TextureID; - face = sp.Appearance.Texture.FaceTextures[idx]; - } - else - { - // if there is no texture entry and no baked cache, skip it - continue; - } - } - else - { - //No texture entry face and no cache. Skip this face. - 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) + // for some reason viewer is cleaning this + sp.Appearance.Texture.FaceTextures[idx] = sp.Appearance.Texture.CreateFace((uint) idx); + sp.Appearance.Texture.FaceTextures[idx].TextureID = AppearanceManager.DEFAULT_AVATAR_TEXTURE; + wearableCache[idx].CacheId = UUID.Zero; + wearableCache[idx].TextureID = UUID.Zero; + wearableCache[idx].TextureAsset = null; continue; - - defonly = false; // found a non-default texture reference - - if (cache != null) - { - if (!cache.Check(face.TextureID.ToString())) - return false; } else { - if (m_scene.AssetService.Get(face.TextureID.ToString()) == null) - return false; + if (face.TextureID == UUID.Zero || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE) + { + wearableCache[idx].CacheId = UUID.Zero; + wearableCache[idx].TextureID = UUID.Zero; + wearableCache[idx].TextureAsset = null; + continue; + } + + defonly = false; // found a non-default texture reference + + if(sp.Appearance.Texture.FaceTextures[idx].TextureID == wearableCache[idx].TextureID) + { + if(wearableCache[idx].CacheId != cacheItems[i].CacheId) + { + wearableCache[idx].CacheId = cacheItems[i].CacheId; + validDirtyBakes++; + hits++; + //assuming this can only happen if asset is in cache + } + continue; + } + + wearableCache[idx].TextureAsset = null; + if (cache != null) + wearableCache[idx].TextureAsset = cache.GetCached(face.TextureID.ToString()); + + if (wearableCache[idx].TextureAsset != null) + { + wearableCache[idx].CacheId = cacheItems[i].CacheId; + wearableCache[idx].TextureID = sp.Appearance.Texture.FaceTextures[idx].TextureID; + validDirtyBakes++; + hits++; + } + else + { + wearableCache[idx].CacheId = UUID.Zero; + wearableCache[idx].TextureID = UUID.Zero; + wearableCache[idx].TextureAsset = null; + continue; + } } } -// m_log.DebugFormat("[AVFACTORY]: Completed texture check for {0} {1}", sp.Name, sp.UUID); + sp.Appearance.WearableCacheItems = wearableCache; + + // if we got a full set of baked textures save all in BakedTextureModule + + if (validDirtyBakes == cacheItems.Length) + { + IBakedTextureModule m_BakedTextureModule = m_scene.RequestModuleInterface(); + if (m_BakedTextureModule != null) + { + m_log.Debug("[UpdateBakedCache] uploading to bakedModule cache"); + + WearableCacheItem[] toBakedModule = new WearableCacheItem[AvatarAppearance.BAKE_INDICES.Length]; + + for (int i = 0; i < cacheItems.Length; i++) + { + int idx = (int)cacheItems[i].TextureIndex; + cacheItems[i].CacheId = wearableCache[idx].CacheId; + cacheItems[i].TextureID = wearableCache[idx].TextureID; + cacheItems[i].TextureAsset = wearableCache[idx].TextureAsset; + } + m_BakedTextureModule.Store(sp.UUID, cacheItems); + } + } + + // debug + for (int iter = 0; iter < AvatarAppearance.BAKE_INDICES.Length; iter++) + { + int j = AvatarAppearance.BAKE_INDICES[iter]; + m_log.Debug("[UpdateBCache] {" + iter + "/" + + sp.Appearance.WearableCacheItems[j].TextureIndex + "}: c-" + + sp.Appearance.WearableCacheItems[j].CacheId + ", t-" + + sp.Appearance.WearableCacheItems[j].TextureID); + } // If we only found default textures, then the appearance is not cached return (defonly ? false : true); } + // called when we get a new root avatar + public bool ValidateBakedTextureCache(IScenePresence sp) + { + bool defonly = true; // are we only using default textures + IAssetService cache = m_scene.AssetService; + IBakedTextureModule bakedModule = m_scene.RequestModuleInterface(); + WearableCacheItem[] wearableCache = null; + WearableCacheItem[] bakedModuleCache = null; + + wearableCache = WearableCacheItem.GetDefaultCacheItem(); + + int hits = 0; + // Cache wearable data for teleport. + // Only makes sense if there's a bake module and a cache module + if (bakedModule != null && cache != null) + { + m_log.Debug("[ValidateBakedCache] calling bakedModule"); + try + { + bakedModuleCache = bakedModule.Get(sp.UUID); + } + catch (Exception) + { + bakedModuleCache = null; + } + + if (bakedModuleCache != null) + { + m_log.Debug("[ValidateBakedCache] got bakedModule cache " + bakedModuleCache.Length); + + for (int i = 0; i < bakedModuleCache.Length; i++) + { + int j = (int)bakedModuleCache[i].TextureIndex; + + if (bakedModuleCache[i].TextureAsset != null) + { + wearableCache[j].TextureID = bakedModuleCache[i].TextureID; + wearableCache[j].CacheId = bakedModuleCache[i].CacheId; + wearableCache[j].TextureAsset = bakedModuleCache[i].TextureAsset; + bakedModuleCache[i].TextureAsset.Temporary = true; + bakedModuleCache[i].TextureAsset.Local = true; + cache.Store(bakedModuleCache[i].TextureAsset); + } + } + } + } + + // Process the baked textures + for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++) + { + int idx = AvatarAppearance.BAKE_INDICES[i]; + Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx]; + + // No face, so lets check our cache + if (face == null || face.TextureID == UUID.Zero || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE) + { + sp.Appearance.Texture.FaceTextures[idx] = sp.Appearance.Texture.CreateFace((uint)idx); + if (wearableCache[idx].TextureID != UUID.Zero) + { + sp.Appearance.Texture.FaceTextures[idx].TextureID = wearableCache[idx].TextureID; + face = sp.Appearance.Texture.FaceTextures[idx]; + // let run to end of loop to check cache + } + else + { + sp.Appearance.Texture.FaceTextures[idx].TextureID = AppearanceManager.DEFAULT_AVATAR_TEXTURE; + face = sp.Appearance.Texture.FaceTextures[idx]; +// lets try not invalidating the cache entry +// wearableCache[idx].CacheId = UUID.Zero; +// wearableCache[idx].TextureAsset = null; + continue; + } + } + + if (face.TextureID == UUID.Zero || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE) + { + defonly = false; // found a non-default texture reference + continue; + } + + if(wearableCache[idx].TextureID != face.TextureID) + { + wearableCache[idx].CacheId = UUID.Zero; + wearableCache[idx].TextureID = UUID.Zero; + wearableCache[idx].TextureAsset = null; + continue; + } + + wearableCache[idx].TextureAsset = null; + if (cache != null) + { + wearableCache[idx].TextureAsset = m_scene.AssetService.Get(face.TextureID.ToString()); + if (wearableCache[idx].TextureAsset == null) + { + wearableCache[idx].CacheId = UUID.Zero; + wearableCache[idx].TextureID = UUID.Zero; + } + else + hits++; + } + } + + sp.Appearance.WearableCacheItems = wearableCache; + + m_log.DebugFormat("[AVFACTORY]: Completed texture check for {0} {1} {2} {3}", sp.Name, sp.UUID, hits, defonly.ToString()); + // debug + for (int iter = 0; iter < AvatarAppearance.BAKE_INDICES.Length; iter++) + { + int j = AvatarAppearance.BAKE_INDICES[iter]; + m_log.Debug("[ValidateBakedCache] {" + iter + "/" + + sp.Appearance.WearableCacheItems[j].TextureIndex + "}: c-" + + sp.Appearance.WearableCacheItems[j].CacheId + ", t-" + + sp.Appearance.WearableCacheItems[j].TextureID); + } + + // If we only found default textures, then the appearance is not cached + return (defonly ? false : true); + } public int RequestRebake(IScenePresence sp, bool missingTexturesOnly) { int texturesRebaked = 0; @@ -506,14 +614,6 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory 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; diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index e4f23f9655..7b13e0b02c 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -1032,15 +1032,18 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess // object itself before we rez. // // Only do these for the first object if we are rezzing a coalescence. - if (i == 0) + // nahh dont mess with coalescence objects, + // the name in inventory can be change for inventory purpuses only + if (objlist.Count == 1) { rootPart.Name = item.Name; rootPart.Description = item.Description; - if ((item.Flags & (uint)InventoryItemFlags.ObjectSlamSale) != 0) - { - rootPart.ObjectSaleType = item.SaleType; - rootPart.SalePrice = item.SalePrice; - } + } + + if ((item.Flags & (uint)InventoryItemFlags.ObjectSlamSale) != 0) + { + rootPart.ObjectSaleType = item.SaleType; + rootPart.SalePrice = item.SalePrice; } so.FromFolderID = item.Folder; diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 746b703031..8634a3a139 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1234,8 +1234,9 @@ namespace OpenSim.Region.Framework.Scenes { uint perms = taskItem.CurrentPermissions; PermissionsUtil.ApplyFoldedPermissions(taskItem.CurrentPermissions, ref perms); - agentItem.BasePermissions = perms | (uint)PermissionMask.Move; - agentItem.CurrentPermissions = agentItem.BasePermissions; +// agentItem.BasePermissions = perms | (uint)PermissionMask.Move; +// agentItem.CurrentPermissions = agentItem.BasePermissions; + agentItem.CurrentPermissions = perms | (uint)PermissionMask.Move; } else { diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs index 08e26c541f..dd0c828067 100644 --- a/OpenSim/Region/Framework/Scenes/SceneBase.cs +++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs @@ -1,581 +1,581 @@ -/* - * 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 System; -using System.Collections.Generic; -using System.Reflection; -using System.Threading; -using OpenMetaverse; -using log4net; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Framework.Console; - -using OpenSim.Region.Framework.Interfaces; -using GridRegion = OpenSim.Services.Interfaces.GridRegion; - -namespace OpenSim.Region.Framework.Scenes -{ - public abstract class SceneBase : IScene - { +/* + * 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 System; +using System.Collections.Generic; +using System.Reflection; +using System.Threading; +using OpenMetaverse; +using log4net; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Framework.Console; + +using OpenSim.Region.Framework.Interfaces; +using GridRegion = OpenSim.Services.Interfaces.GridRegion; + +namespace OpenSim.Region.Framework.Scenes +{ + public abstract class SceneBase : IScene + { protected static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - protected static readonly string LogHeader = "[SCENE]"; - - #region Events - - public event restart OnRestart; - - #endregion - - #region Fields - - public string Name { get { return RegionInfo.RegionName; } } - - public IConfigSource Config - { - get { return GetConfig(); } - } - - protected virtual IConfigSource GetConfig() - { - return null; - } - - /// - /// All the region modules attached to this scene. - /// - public Dictionary RegionModules - { - get { return m_regionModules; } - } - private Dictionary m_regionModules = new Dictionary(); - - /// - /// The module interfaces available from this scene. - /// - protected Dictionary> ModuleInterfaces = new Dictionary>(); - - protected Dictionary ModuleAPIMethods = new Dictionary(); - - /// - /// The module commanders available from this scene - /// - protected Dictionary m_moduleCommanders = new Dictionary(); - - /// - /// Registered classes that are capable of creating entities. - /// - protected Dictionary m_entityCreators = new Dictionary(); - - /// - /// The last allocated local prim id. When a new local id is requested, the next number in the sequence is - /// dispensed. - /// - protected uint m_lastAllocatedLocalId = 720000; - - private readonly Mutex _primAllocateMutex = new Mutex(false); - - protected readonly ClientManager m_clientManager = new ClientManager(); - - public bool LoginsEnabled - { - get - { - return m_loginsEnabled; - } - - set - { - if (m_loginsEnabled != value) - { - m_loginsEnabled = value; - EventManager.TriggerRegionLoginsStatusChange(this); - } - } - } - private bool m_loginsEnabled; - - public bool Ready - { - get - { - return m_ready; - } - - set - { - if (m_ready != value) - { - m_ready = value; - EventManager.TriggerRegionReadyStatusChange(this); - } - } - } - private bool m_ready; - - public float TimeDilation - { - get { return 1.0f; } - } - - protected ulong m_regionHandle; - protected string m_regionName; - - public ITerrainChannel Heightmap; - - /// - /// Allows retrieval of land information for this scene. - /// - public ILandChannel LandChannel; - - /// - /// Manage events that occur in this scene (avatar movement, script rez, etc.). Commonly used by region modules - /// to subscribe to scene events. - /// - public EventManager EventManager - { - get { return m_eventManager; } - } - protected EventManager m_eventManager; - - protected ScenePermissions m_permissions; - public ScenePermissions Permissions - { - get { return m_permissions; } - } - - protected string m_datastore; - - /* Used by the loadbalancer plugin on GForge */ - protected RegionStatus m_regStatus; - public RegionStatus RegionStatus - { - get { return m_regStatus; } - set { m_regStatus = value; } - } - - #endregion - - public SceneBase(RegionInfo regInfo) - { - RegionInfo = regInfo; - } - - #region Update Methods - - /// - /// Called to update the scene loop by a number of frames and until shutdown. - /// - /// - /// Number of frames to update. Exits on shutdown even if there are frames remaining. - /// If -1 then updates until shutdown. - /// - public abstract void Update(int frames); - - #endregion - - #region Terrain Methods - - /// - /// Loads the World heightmap - /// - public abstract void LoadWorldMap(); - - /// - /// Send the region heightmap to the client - /// - /// Client to send to - public virtual void SendLayerData(IClientAPI RemoteClient) - { - RemoteClient.SendLayerData(Heightmap.GetFloatsSerialised()); - } - - #endregion - - #region Add/Remove Agent/Avatar - - public abstract ISceneAgent AddNewAgent(IClientAPI client, PresenceType type); - - public abstract bool CloseAgent(UUID agentID, bool force); - - public bool TryGetScenePresence(UUID agentID, out object scenePresence) - { - scenePresence = null; - ScenePresence sp = null; - if (TryGetScenePresence(agentID, out sp)) - { - scenePresence = sp; - return true; - } - - return false; - } - - /// - /// Try to get a scene presence from the scene - /// - /// - /// null if there is no scene presence with the given agent id - /// true if there was a scene presence with the given id, false otherwise. - public abstract bool TryGetScenePresence(UUID agentID, out ScenePresence scenePresence); - - #endregion - - /// - /// - /// - /// - public virtual RegionInfo RegionInfo { get; private set; } - - #region admin stuff - - public abstract void OtherRegionUp(GridRegion otherRegion); - - public virtual string GetSimulatorVersion() - { - return "OpenSimulator Server"; - } - - #endregion - - #region Shutdown - - /// - /// Tidy before shutdown - /// - public virtual void Close() - { - try - { - EventManager.TriggerShutdown(); - } - catch (Exception e) - { - m_log.Error(string.Format("[SCENE]: SceneBase.cs: Close() - Failed with exception ", e)); - } - } - - #endregion - - /// - /// Returns a new unallocated local ID - /// - /// A brand new local ID - public uint AllocateLocalId() - { - uint myID; - - _primAllocateMutex.WaitOne(); - myID = ++m_lastAllocatedLocalId; - _primAllocateMutex.ReleaseMutex(); - - return myID; - } - - #region Module Methods - - /// - /// Add a region-module to this scene. TODO: This will replace AddModule in the future. - /// - /// - /// - public void AddRegionModule(string name, IRegionModuleBase module) - { - if (!RegionModules.ContainsKey(name)) - { - RegionModules.Add(name, module); - } - } - - public void RemoveRegionModule(string name) - { - RegionModules.Remove(name); - } - - /// - /// Register a module commander. - /// - /// - public void RegisterModuleCommander(ICommander commander) - { - lock (m_moduleCommanders) - { - m_moduleCommanders.Add(commander.Name, commander); - } - } - - /// - /// Unregister a module commander and all its commands - /// - /// - public void UnregisterModuleCommander(string name) - { - lock (m_moduleCommanders) - { - ICommander commander; - if (m_moduleCommanders.TryGetValue(name, out commander)) - m_moduleCommanders.Remove(name); - } - } - - /// - /// Get a module commander - /// - /// - /// The module commander, null if no module commander with that name was found - public ICommander GetCommander(string name) - { - lock (m_moduleCommanders) - { - if (m_moduleCommanders.ContainsKey(name)) - return m_moduleCommanders[name]; - } - - return null; - } - - public Dictionary GetCommanders() - { - return m_moduleCommanders; - } - - /// - /// Register an interface to a region module. This allows module methods to be called directly as - /// well as via events. If there is already a module registered for this interface, it is not replaced - /// (is this the best behaviour?) - /// - /// - public void RegisterModuleInterface(M mod) - { -// m_log.DebugFormat("[SCENE BASE]: Registering interface {0}", typeof(M)); - - List l = null; - if (!ModuleInterfaces.TryGetValue(typeof(M), out l)) - { - l = new List(); - ModuleInterfaces.Add(typeof(M), l); - } - - if (l.Count > 0) - return; - - l.Add(mod); - - if (mod is IEntityCreator) - { - IEntityCreator entityCreator = (IEntityCreator)mod; - foreach (PCode pcode in entityCreator.CreationCapabilities) - { - m_entityCreators[pcode] = entityCreator; - } - } - } - - public void UnregisterModuleInterface(M mod) - { - List l; - if (ModuleInterfaces.TryGetValue(typeof(M), out l)) - { - if (l.Remove(mod)) - { - if (mod is IEntityCreator) - { - IEntityCreator entityCreator = (IEntityCreator)mod; - foreach (PCode pcode in entityCreator.CreationCapabilities) - { - m_entityCreators[pcode] = null; - } - } - } - } - } - - public void StackModuleInterface(M mod) - { - List l; - if (ModuleInterfaces.ContainsKey(typeof(M))) - l = ModuleInterfaces[typeof(M)]; - else - l = new List(); - - if (l.Contains(mod)) - return; - - l.Add(mod); - - if (mod is IEntityCreator) - { - IEntityCreator entityCreator = (IEntityCreator)mod; - foreach (PCode pcode in entityCreator.CreationCapabilities) - { - m_entityCreators[pcode] = entityCreator; - } - } - - ModuleInterfaces[typeof(M)] = l; - } - - /// - /// For the given interface, retrieve the region module which implements it. - /// - /// null if there is no registered module implementing that interface - public T RequestModuleInterface() - { - if (ModuleInterfaces.ContainsKey(typeof(T)) && - (ModuleInterfaces[typeof(T)].Count > 0)) - return (T)ModuleInterfaces[typeof(T)][0]; - else - return default(T); - } - - /// - /// For the given interface, retrieve an array of region modules that implement it. - /// - /// an empty array if there are no registered modules implementing that interface - public T[] RequestModuleInterfaces() - { - if (ModuleInterfaces.ContainsKey(typeof(T))) - { - List ret = new List(); - - foreach (Object o in ModuleInterfaces[typeof(T)]) - ret.Add((T)o); - return ret.ToArray(); - } - else - { - return new T[] {}; - } - } - - #endregion - - /// - /// Call this from a region module to add a command to the OpenSim console. - /// - /// - /// - /// - /// - /// - public void AddCommand(IRegionModuleBase module, string command, string shorthelp, string longhelp, CommandDelegate callback) - { - AddCommand(module, command, shorthelp, longhelp, string.Empty, callback); - } - - /// - /// Call this from a region module to add a command to the OpenSim console. - /// - /// - /// The use of IRegionModuleBase is a cheap trick to get a different method signature, - /// though all new modules should be using interfaces descended from IRegionModuleBase anyway. - /// - /// - /// Category of the command. This is the section under which it will appear when the user asks for help - /// - /// - /// - /// - /// - public void AddCommand( - string category, IRegionModuleBase module, string command, string shorthelp, string longhelp, CommandDelegate callback) - { - AddCommand(category, module, command, shorthelp, longhelp, string.Empty, callback); - } - - /// - /// Call this from a region module to add a command to the OpenSim console. - /// - /// - /// - /// - /// - /// - /// - public void AddCommand(IRegionModuleBase module, string command, string shorthelp, string longhelp, string descriptivehelp, CommandDelegate callback) - { - string moduleName = ""; - - if (module != null) - moduleName = module.Name; - - AddCommand(moduleName, module, command, shorthelp, longhelp, descriptivehelp, callback); - } - - /// - /// Call this from a region module to add a command to the OpenSim console. - /// - /// - /// Category of the command. This is the section under which it will appear when the user asks for help - /// - /// - /// - /// - /// - /// - /// - public void AddCommand( - string category, IRegionModuleBase module, string command, - string shorthelp, string longhelp, string descriptivehelp, CommandDelegate callback) - { - if (MainConsole.Instance == null) - return; - - bool shared = false; - - if (module != null) - shared = module is ISharedRegionModule; - - MainConsole.Instance.Commands.AddCommand( - category, shared, command, shorthelp, longhelp, descriptivehelp, callback); - } - - public virtual ISceneObject DeserializeObject(string representation) - { - return null; - } - - public virtual bool AllowScriptCrossings - { - get { return false; } - } - - public virtual void Start() - { - } - - public void Restart() - { - // This has to be here to fire the event - restart handlerPhysicsCrash = OnRestart; - if (handlerPhysicsCrash != null) - handlerPhysicsCrash(RegionInfo); - } - - public abstract bool CheckClient(UUID agentID, System.Net.IPEndPoint ep); - } -} + protected static readonly string LogHeader = "[SCENE]"; + + #region Events + + public event restart OnRestart; + + #endregion + + #region Fields + + public string Name { get { return RegionInfo.RegionName; } } + + public IConfigSource Config + { + get { return GetConfig(); } + } + + protected virtual IConfigSource GetConfig() + { + return null; + } + + /// + /// All the region modules attached to this scene. + /// + public Dictionary RegionModules + { + get { return m_regionModules; } + } + private Dictionary m_regionModules = new Dictionary(); + + /// + /// The module interfaces available from this scene. + /// + protected Dictionary> ModuleInterfaces = new Dictionary>(); + + protected Dictionary ModuleAPIMethods = new Dictionary(); + + /// + /// The module commanders available from this scene + /// + protected Dictionary m_moduleCommanders = new Dictionary(); + + /// + /// Registered classes that are capable of creating entities. + /// + protected Dictionary m_entityCreators = new Dictionary(); + + /// + /// The last allocated local prim id. When a new local id is requested, the next number in the sequence is + /// dispensed. + /// + protected uint m_lastAllocatedLocalId = 720000; + + private readonly Mutex _primAllocateMutex = new Mutex(false); + + protected readonly ClientManager m_clientManager = new ClientManager(); + + public bool LoginsEnabled + { + get + { + return m_loginsEnabled; + } + + set + { + if (m_loginsEnabled != value) + { + m_loginsEnabled = value; + EventManager.TriggerRegionLoginsStatusChange(this); + } + } + } + private bool m_loginsEnabled; + + public bool Ready + { + get + { + return m_ready; + } + + set + { + if (m_ready != value) + { + m_ready = value; + EventManager.TriggerRegionReadyStatusChange(this); + } + } + } + private bool m_ready; + + public float TimeDilation + { + get { return 1.0f; } + } + + protected ulong m_regionHandle; + protected string m_regionName; + + public ITerrainChannel Heightmap; + + /// + /// Allows retrieval of land information for this scene. + /// + public ILandChannel LandChannel; + + /// + /// Manage events that occur in this scene (avatar movement, script rez, etc.). Commonly used by region modules + /// to subscribe to scene events. + /// + public EventManager EventManager + { + get { return m_eventManager; } + } + protected EventManager m_eventManager; + + protected ScenePermissions m_permissions; + public ScenePermissions Permissions + { + get { return m_permissions; } + } + + protected string m_datastore; + + /* Used by the loadbalancer plugin on GForge */ + protected RegionStatus m_regStatus; + public RegionStatus RegionStatus + { + get { return m_regStatus; } + set { m_regStatus = value; } + } + + #endregion + + public SceneBase(RegionInfo regInfo) + { + RegionInfo = regInfo; + } + + #region Update Methods + + /// + /// Called to update the scene loop by a number of frames and until shutdown. + /// + /// + /// Number of frames to update. Exits on shutdown even if there are frames remaining. + /// If -1 then updates until shutdown. + /// + public abstract void Update(int frames); + + #endregion + + #region Terrain Methods + + /// + /// Loads the World heightmap + /// + public abstract void LoadWorldMap(); + + /// + /// Send the region heightmap to the client + /// + /// Client to send to + public virtual void SendLayerData(IClientAPI RemoteClient) + { + RemoteClient.SendLayerData(Heightmap.GetFloatsSerialised()); + } + + #endregion + + #region Add/Remove Agent/Avatar + + public abstract ISceneAgent AddNewAgent(IClientAPI client, PresenceType type); + + public abstract bool CloseAgent(UUID agentID, bool force); + + public bool TryGetScenePresence(UUID agentID, out object scenePresence) + { + scenePresence = null; + ScenePresence sp = null; + if (TryGetScenePresence(agentID, out sp)) + { + scenePresence = sp; + return true; + } + + return false; + } + + /// + /// Try to get a scene presence from the scene + /// + /// + /// null if there is no scene presence with the given agent id + /// true if there was a scene presence with the given id, false otherwise. + public abstract bool TryGetScenePresence(UUID agentID, out ScenePresence scenePresence); + + #endregion + + /// + /// + /// + /// + public virtual RegionInfo RegionInfo { get; private set; } + + #region admin stuff + + public abstract void OtherRegionUp(GridRegion otherRegion); + + public virtual string GetSimulatorVersion() + { + return "OpenSimulator Server"; + } + + #endregion + + #region Shutdown + + /// + /// Tidy before shutdown + /// + public virtual void Close() + { + try + { + EventManager.TriggerShutdown(); + } + catch (Exception e) + { + m_log.Error(string.Format("[SCENE]: SceneBase.cs: Close() - Failed with exception ", e)); + } + } + + #endregion + + /// + /// Returns a new unallocated local ID + /// + /// A brand new local ID + public uint AllocateLocalId() + { + uint myID; + + _primAllocateMutex.WaitOne(); + myID = ++m_lastAllocatedLocalId; + _primAllocateMutex.ReleaseMutex(); + + return myID; + } + + #region Module Methods + + /// + /// Add a region-module to this scene. TODO: This will replace AddModule in the future. + /// + /// + /// + public void AddRegionModule(string name, IRegionModuleBase module) + { + if (!RegionModules.ContainsKey(name)) + { + RegionModules.Add(name, module); + } + } + + public void RemoveRegionModule(string name) + { + RegionModules.Remove(name); + } + + /// + /// Register a module commander. + /// + /// + public void RegisterModuleCommander(ICommander commander) + { + lock (m_moduleCommanders) + { + m_moduleCommanders.Add(commander.Name, commander); + } + } + + /// + /// Unregister a module commander and all its commands + /// + /// + public void UnregisterModuleCommander(string name) + { + lock (m_moduleCommanders) + { + ICommander commander; + if (m_moduleCommanders.TryGetValue(name, out commander)) + m_moduleCommanders.Remove(name); + } + } + + /// + /// Get a module commander + /// + /// + /// The module commander, null if no module commander with that name was found + public ICommander GetCommander(string name) + { + lock (m_moduleCommanders) + { + if (m_moduleCommanders.ContainsKey(name)) + return m_moduleCommanders[name]; + } + + return null; + } + + public Dictionary GetCommanders() + { + return m_moduleCommanders; + } + + /// + /// Register an interface to a region module. This allows module methods to be called directly as + /// well as via events. If there is already a module registered for this interface, it is not replaced + /// (is this the best behaviour?) + /// + /// + public void RegisterModuleInterface(M mod) + { +// m_log.DebugFormat("[SCENE BASE]: Registering interface {0}", typeof(M)); + + List l = null; + if (!ModuleInterfaces.TryGetValue(typeof(M), out l)) + { + l = new List(); + ModuleInterfaces.Add(typeof(M), l); + } + + if (l.Count > 0) + return; + + l.Add(mod); + + if (mod is IEntityCreator) + { + IEntityCreator entityCreator = (IEntityCreator)mod; + foreach (PCode pcode in entityCreator.CreationCapabilities) + { + m_entityCreators[pcode] = entityCreator; + } + } + } + + public void UnregisterModuleInterface(M mod) + { + List l; + if (ModuleInterfaces.TryGetValue(typeof(M), out l)) + { + if (l.Remove(mod)) + { + if (mod is IEntityCreator) + { + IEntityCreator entityCreator = (IEntityCreator)mod; + foreach (PCode pcode in entityCreator.CreationCapabilities) + { + m_entityCreators[pcode] = null; + } + } + } + } + } + + public void StackModuleInterface(M mod) + { + List l; + if (ModuleInterfaces.ContainsKey(typeof(M))) + l = ModuleInterfaces[typeof(M)]; + else + l = new List(); + + if (l.Contains(mod)) + return; + + l.Add(mod); + + if (mod is IEntityCreator) + { + IEntityCreator entityCreator = (IEntityCreator)mod; + foreach (PCode pcode in entityCreator.CreationCapabilities) + { + m_entityCreators[pcode] = entityCreator; + } + } + + ModuleInterfaces[typeof(M)] = l; + } + + /// + /// For the given interface, retrieve the region module which implements it. + /// + /// null if there is no registered module implementing that interface + public T RequestModuleInterface() + { + if (ModuleInterfaces.ContainsKey(typeof(T)) && + (ModuleInterfaces[typeof(T)].Count > 0)) + return (T)ModuleInterfaces[typeof(T)][0]; + else + return default(T); + } + + /// + /// For the given interface, retrieve an array of region modules that implement it. + /// + /// an empty array if there are no registered modules implementing that interface + public T[] RequestModuleInterfaces() + { + if (ModuleInterfaces.ContainsKey(typeof(T))) + { + List ret = new List(); + + foreach (Object o in ModuleInterfaces[typeof(T)]) + ret.Add((T)o); + return ret.ToArray(); + } + else + { + return new T[] {}; + } + } + + #endregion + + /// + /// Call this from a region module to add a command to the OpenSim console. + /// + /// + /// + /// + /// + /// + public void AddCommand(IRegionModuleBase module, string command, string shorthelp, string longhelp, CommandDelegate callback) + { + AddCommand(module, command, shorthelp, longhelp, string.Empty, callback); + } + + /// + /// Call this from a region module to add a command to the OpenSim console. + /// + /// + /// The use of IRegionModuleBase is a cheap trick to get a different method signature, + /// though all new modules should be using interfaces descended from IRegionModuleBase anyway. + /// + /// + /// Category of the command. This is the section under which it will appear when the user asks for help + /// + /// + /// + /// + /// + public void AddCommand( + string category, IRegionModuleBase module, string command, string shorthelp, string longhelp, CommandDelegate callback) + { + AddCommand(category, module, command, shorthelp, longhelp, string.Empty, callback); + } + + /// + /// Call this from a region module to add a command to the OpenSim console. + /// + /// + /// + /// + /// + /// + /// + public void AddCommand(IRegionModuleBase module, string command, string shorthelp, string longhelp, string descriptivehelp, CommandDelegate callback) + { + string moduleName = ""; + + if (module != null) + moduleName = module.Name; + + AddCommand(moduleName, module, command, shorthelp, longhelp, descriptivehelp, callback); + } + + /// + /// Call this from a region module to add a command to the OpenSim console. + /// + /// + /// Category of the command. This is the section under which it will appear when the user asks for help + /// + /// + /// + /// + /// + /// + /// + public void AddCommand( + string category, IRegionModuleBase module, string command, + string shorthelp, string longhelp, string descriptivehelp, CommandDelegate callback) + { + if (MainConsole.Instance == null) + return; + + bool shared = false; + + if (module != null) + shared = module is ISharedRegionModule; + + MainConsole.Instance.Commands.AddCommand( + category, shared, command, shorthelp, longhelp, descriptivehelp, callback); + } + + public virtual ISceneObject DeserializeObject(string representation) + { + return null; + } + + public virtual bool AllowScriptCrossings + { + get { return false; } + } + + public virtual void Start() + { + } + + public void Restart() + { + // This has to be here to fire the event + restart handlerPhysicsCrash = OnRestart; + if (handlerPhysicsCrash != null) + handlerPhysicsCrash(RegionInfo); + } + + public abstract bool CheckClient(UUID agentID, System.Net.IPEndPoint ep); + } +} diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 257e01e72e..a6a963b365 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -917,12 +917,14 @@ namespace OpenSim.Region.Framework.Scenes // in the serialization, transfer the correct name from the inventory to the // object itself before we rez. // Only do these for the first object if we are rezzing a coalescence. - if (i == 0) + // nahh dont mess with coalescence objects, + // the name in inventory can be change for inventory purpuses only + if (objlist.Count == 1) { rootPart.Name = item.Name; rootPart.Description = item.Description; } - +/* reverted to old code till part.ApplyPermissionsOnRez is better reviewed/fixed group.SetGroup(m_part.GroupID, null); foreach (SceneObjectPart part in group.Parts) @@ -938,7 +940,49 @@ namespace OpenSim.Region.Framework.Scenes part.ApplyPermissionsOnRez(dest, false, m_part.ParentGroup.Scene); } +*/ +// old code start + SceneObjectPart[] partList = group.Parts; + group.SetGroup(m_part.GroupID, null); + + // TODO: Remove magic number badness + if ((rootPart.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) // Magic number + { + if (m_part.ParentGroup.Scene.Permissions.PropagatePermissions()) + { + foreach (SceneObjectPart part in partList) + { + if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0) + part.EveryoneMask = item.EveryonePermissions; + if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0) + part.NextOwnerMask = item.NextPermissions; + if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0) + part.GroupMask = item.GroupPermissions; + } + + group.ApplyNextOwnerPermissions(); + } + } + + foreach (SceneObjectPart part in partList) + { + // TODO: Remove magic number badness + if ((part.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) // Magic number + { + part.LastOwnerID = part.OwnerID; + part.OwnerID = item.OwnerID; + part.Inventory.ChangeInventoryOwner(item.OwnerID); + } + + if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0) + part.EveryoneMask = item.EveryonePermissions; + if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0) + part.NextOwnerMask = item.NextPermissions; + if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0) + part.GroupMask = item.GroupPermissions; + } +// old code end rootPart.TrimPermissions(); } diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 24a92eb468..8fae032619 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -3369,11 +3369,7 @@ namespace OpenSim.Region.Framework.Scenes public void SendTerseUpdateToAgentClient(ScenePresence p) { - // messy checks because a client doesn't know what presence it belongs too - IClientAPI remoteClient = p.ControllingClient; - if (remoteClient == null) - return; if (!remoteClient.IsActive) return; @@ -3381,7 +3377,6 @@ namespace OpenSim.Region.Framework.Scenes if (ParcelHideThisAvatar && p.currentParcelUUID != currentParcelUUID && p.GodLevel < 200) return; - //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity); remoteClient.SendEntityUpdate( this, @@ -3507,7 +3502,7 @@ namespace OpenSim.Region.Framework.Scenes // If we aren't using a cached appearance, then clear out the baked textures if (!cachedappearance) { - Appearance.ResetAppearance(); +// Appearance.ResetAppearance(); // save what ???? // maybe needed so the tryretry repair works? if (m_scene.AvatarFactory != null) @@ -3530,7 +3525,7 @@ namespace OpenSim.Region.Framework.Scenes // send even grays if (cachedappearance) { - m_log.DebugFormat("[SCENE PRESENCE]: Baked textures are in the cache for {0} in {1}", Name, m_scene.Name); +// m_log.DebugFormat("[SCENE PRESENCE]: Baked textures are in the cache for {0} in {1}", Name, m_scene.Name); // If the avatars baked textures are all in the cache, then we have a // complete appearance... send it out, if not, then we'll send it when // the avatar finishes updating its appearance