mirror of
https://github.com/opensim/opensim.git
synced 2026-08-11 11:57:03 +08:00
Merge branch 'master' into careminster-presence-refactor
This commit is contained in:
@@ -36,7 +36,7 @@ using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
|
||||
namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||
{
|
||||
{
|
||||
public class AttachmentsModule : IAttachmentsModule, IRegionModule
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
@@ -67,6 +67,36 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public void AttachObject(IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, Quaternion rot, bool silent)
|
||||
{
|
||||
m_log.Debug("[ATTACHMENTS MODULE]: Invoking AttachObject");
|
||||
|
||||
// If we can't take it, we can't attach it!
|
||||
SceneObjectPart part = m_scene.GetSceneObjectPart(objectLocalID);
|
||||
if (part == null)
|
||||
return;
|
||||
|
||||
if (!m_scene.Permissions.CanTakeObject(part.UUID, remoteClient.AgentId))
|
||||
return;
|
||||
|
||||
// Calls attach with a Zero position
|
||||
if (AttachObject(remoteClient, objectLocalID, AttachmentPt, rot, Vector3.Zero, false))
|
||||
{
|
||||
m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.GetFromItemID(), remoteClient.AgentId);
|
||||
|
||||
// Save avatar attachment information
|
||||
ScenePresence presence;
|
||||
if (m_scene.AvatarFactory != null && m_scene.TryGetAvatar(remoteClient.AgentId, out presence))
|
||||
{
|
||||
m_log.Info(
|
||||
"[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId
|
||||
+ ", AttachmentPoint: " + AttachmentPt);
|
||||
|
||||
m_scene.AvatarFactory.UpdateDatabase(remoteClient.AgentId, presence.Appearance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool AttachObject(
|
||||
IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, Quaternion rot, Vector3 attachPos, bool silent)
|
||||
{
|
||||
@@ -138,12 +168,87 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public UUID RezSingleAttachmentFromInventory(IClientAPI remoteClient, UUID itemID, uint AttachmentPt)
|
||||
{
|
||||
m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing single attachment from item {0} for {1}", itemID, remoteClient.Name);
|
||||
|
||||
return RezSingleAttachmentFromInventory(remoteClient, itemID, AttachmentPt, true);
|
||||
}
|
||||
|
||||
public UUID RezSingleAttachmentFromInventory(
|
||||
IClientAPI remoteClient, UUID itemID, uint AttachmentPt, bool updateInventoryStatus)
|
||||
{
|
||||
SceneObjectGroup att = RezSingleAttachmentFromInventoryInternal(remoteClient, itemID, AttachmentPt);
|
||||
|
||||
if (updateInventoryStatus)
|
||||
{
|
||||
if (att == null)
|
||||
{
|
||||
ShowDetachInUserInventory(itemID, remoteClient);
|
||||
}
|
||||
|
||||
SetAttachmentInventoryStatus(att, remoteClient, itemID, AttachmentPt);
|
||||
}
|
||||
|
||||
if (null == att)
|
||||
return UUID.Zero;
|
||||
else
|
||||
return att.UUID;
|
||||
}
|
||||
|
||||
protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal(
|
||||
IClientAPI remoteClient, UUID itemID, uint AttachmentPt)
|
||||
{
|
||||
IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>();
|
||||
if (invAccess != null)
|
||||
{
|
||||
SceneObjectGroup objatt = invAccess.RezObject(remoteClient,
|
||||
itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
|
||||
false, false, remoteClient.AgentId, true);
|
||||
|
||||
// m_log.DebugFormat(
|
||||
// "[ATTACHMENTS MODULE]: Retrieved single object {0} for attachment to {1} on point {2}",
|
||||
// objatt.Name, remoteClient.Name, AttachmentPt);
|
||||
|
||||
if (objatt != null)
|
||||
{
|
||||
bool tainted = false;
|
||||
if (AttachmentPt != 0 && AttachmentPt != objatt.GetAttachmentPoint())
|
||||
tainted = true;
|
||||
|
||||
AttachObject(
|
||||
remoteClient, objatt.LocalId, AttachmentPt, Quaternion.Identity, objatt.AbsolutePosition, false);
|
||||
//objatt.ScheduleGroupForFullUpdate();
|
||||
|
||||
if (tainted)
|
||||
objatt.HasGroupChanged = true;
|
||||
|
||||
// Fire after attach, so we don't get messy perms dialogs
|
||||
// 3 == AttachedRez
|
||||
objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 3);
|
||||
|
||||
// Do this last so that event listeners have access to all the effects of the attachment
|
||||
m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, remoteClient.AgentId);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.WarnFormat(
|
||||
"[ATTACHMENTS MODULE]: Could not retrieve item {0} for attaching to avatar {1} at point {2}",
|
||||
itemID, remoteClient.Name, AttachmentPt);
|
||||
}
|
||||
|
||||
return objatt;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public UUID SetAttachmentInventoryStatus(
|
||||
SceneObjectGroup att, IClientAPI remoteClient, UUID itemID, uint AttachmentPt)
|
||||
{
|
||||
m_log.DebugFormat(
|
||||
"[ATTACHMENTS MODULEY]: Updating inventory of {0} to show attachment of {1} (item ID {2})",
|
||||
"[ATTACHMENTS MODULE]: Updating inventory of {0} to show attachment of {1} (item ID {2})",
|
||||
remoteClient.Name, att.Name, itemID);
|
||||
|
||||
if (!att.IsDeleted)
|
||||
@@ -204,7 +309,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||
if (m_scene.AvatarFactory != null)
|
||||
m_scene.AvatarFactory.UpdateDatabase(remoteClient.AgentId, presence.Appearance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ShowDetachInUserInventory(UUID itemID, IClientAPI remoteClient)
|
||||
{
|
||||
@@ -222,7 +327,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||
}
|
||||
|
||||
DetachSingleAttachmentToInv(itemID, remoteClient);
|
||||
}
|
||||
}
|
||||
|
||||
// What makes this method odd and unique is it tries to detach using an UUID.... Yay for standards.
|
||||
// To LocalId or UUID, *THAT* is the question. How now Brown UUID??
|
||||
@@ -252,6 +357,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -394,11 +394,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||
public IClientAPI LocateClientObject(UUID agentID)
|
||||
{
|
||||
Scene scene = GetClientScene(agentID);
|
||||
if(scene == null)
|
||||
if (scene == null)
|
||||
return null;
|
||||
|
||||
ScenePresence presence = scene.GetScenePresence(agentID);
|
||||
if(presence == null)
|
||||
if (presence == null)
|
||||
return null;
|
||||
|
||||
return presence.ControllingClient;
|
||||
@@ -481,7 +481,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||
m_log.DebugFormat("[FRIENDS]: {0} offered friendship to {1}", principalID, friendID);
|
||||
|
||||
// This user wants to be friends with the other user.
|
||||
// Let's add both relations to the DB, but one of them is inactive (-1)
|
||||
// Let's add the relation backwards, in case the other is not online
|
||||
FriendsService.StoreFriend(friendID, principalID.ToString(), 0);
|
||||
|
||||
// Now let's ask the other user to be friends with this user
|
||||
|
||||
@@ -108,7 +108,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
|
||||
if (!m_Enabled)
|
||||
return;
|
||||
|
||||
lock(m_Scenes)
|
||||
lock (m_Scenes)
|
||||
{
|
||||
m_Scenes.Remove(scene);
|
||||
}
|
||||
|
||||
@@ -576,7 +576,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||
foreach (SceneObjectPart part in partList)
|
||||
{
|
||||
if (part.OwnerID != item.Owner)
|
||||
{
|
||||
{
|
||||
part.LastOwnerID = part.OwnerID;
|
||||
part.OwnerID = item.Owner;
|
||||
part.Inventory.ChangeInventoryOwner(item.Owner);
|
||||
|
||||
@@ -56,6 +56,9 @@
|
||||
<RegionModule id="RemotePresenceServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence.RemotePresenceServicesConnector" />
|
||||
<RegionModule id="LocalUserAccountServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts.LocalUserAccountServicesConnector" />
|
||||
<RegionModule id="RemoteUserAccountServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts.RemoteUserAccountServicesConnector" />
|
||||
|
||||
<RegionModule id="LocalGridUserServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser.LocalGridUserServicesConnector" />
|
||||
|
||||
<RegionModule id="LocalSimulationConnectorModule" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation.LocalSimulationConnectorModule" />
|
||||
<RegionModule id="RemoteSimulationConnectorModule" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation.RemoteSimulationConnectorModule" />
|
||||
<!-- Service connectors IN modules -->
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence.Tests
|
||||
m_LocalConnector = new LocalPresenceServicesConnector(config);
|
||||
|
||||
// Let's stick in a test presence
|
||||
m_LocalConnector.m_PresenceService.LoginAgent(UUID.Zero.ToString(), UUID.Zero, UUID.Zero);
|
||||
m_LocalConnector.m_PresenceService.LoginAgent(UUID.Zero.ToString(), UUID.Zero, UUID.Zero);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -80,7 +80,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence.Tests
|
||||
p.Data = new Dictionary<string, string>();
|
||||
p.Data["Online"] = true.ToString();
|
||||
m_presenceData.Add(UUID.Zero, p);
|
||||
*/
|
||||
*/
|
||||
|
||||
string user1 = UUID.Zero.ToString();
|
||||
UUID session1 = UUID.Zero;
|
||||
|
||||
@@ -73,33 +73,31 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
|
||||
IConfig userConfig = source.Configs["UserAccountService"];
|
||||
if (userConfig == null)
|
||||
{
|
||||
m_log.Error("[USER CONNECTOR]: UserAccountService missing from OpenSim.ini");
|
||||
m_log.Error("[LOCAL USER ACCOUNT SERVICE CONNECTOR]: UserAccountService missing from OpenSim.ini");
|
||||
return;
|
||||
}
|
||||
|
||||
string serviceDll = userConfig.GetString("LocalServiceModule",
|
||||
String.Empty);
|
||||
string serviceDll = userConfig.GetString("LocalServiceModule", String.Empty);
|
||||
|
||||
if (serviceDll == String.Empty)
|
||||
{
|
||||
m_log.Error("[USER CONNECTOR]: No LocalServiceModule named in section UserService");
|
||||
m_log.Error("[LOCAL USER ACCOUNT SERVICE CONNECTOR]: No LocalServiceModule named in section UserService");
|
||||
return;
|
||||
}
|
||||
|
||||
Object[] args = new Object[] { source };
|
||||
m_UserService =
|
||||
ServerUtils.LoadPlugin<IUserAccountService>(serviceDll,
|
||||
args);
|
||||
m_UserService = ServerUtils.LoadPlugin<IUserAccountService>(serviceDll, args);
|
||||
|
||||
if (m_UserService == null)
|
||||
{
|
||||
m_log.Error("[USER CONNECTOR]: Can't load user account service");
|
||||
m_log.ErrorFormat(
|
||||
"[LOCAL USER ACCOUNT SERVICE CONNECTOR]: Cannot load user account service specified as {0}", serviceDll);
|
||||
return;
|
||||
}
|
||||
m_Enabled = true;
|
||||
m_Cache = new UserAccountCache();
|
||||
|
||||
m_log.Info("[USER CONNECTOR]: Local user connector enabled");
|
||||
m_log.Info("[LOCAL USER ACCOUNT SERVICE CONNECTOR]: Local user connector enabled");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -134,6 +132,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
|
||||
{
|
||||
if (!m_Enabled)
|
||||
return;
|
||||
|
||||
m_log.InfoFormat("[LOCAL USER ACCOUNT SERVICE CONNECTOR]: Enabled local user accounts for region {0}", scene.RegionInfo.RegionName);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -142,26 +142,27 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
|
||||
|
||||
public UserAccount GetUserAccount(UUID scopeID, UUID userID)
|
||||
{
|
||||
UserAccount account = m_Cache.Get(userID);
|
||||
if (account != null)
|
||||
bool inCache = false;
|
||||
UserAccount account = m_Cache.Get(userID, out inCache);
|
||||
if (inCache)
|
||||
return account;
|
||||
|
||||
account = m_UserService.GetUserAccount(scopeID, userID);
|
||||
if (account != null)
|
||||
m_Cache.Cache(account);
|
||||
m_Cache.Cache(userID, account);
|
||||
|
||||
return account;
|
||||
}
|
||||
|
||||
public UserAccount GetUserAccount(UUID scopeID, string firstName, string lastName)
|
||||
{
|
||||
UserAccount account = m_Cache.Get(firstName + " " + lastName);
|
||||
if (account != null)
|
||||
bool inCache = false;
|
||||
UserAccount account = m_Cache.Get(firstName + " " + lastName, out inCache);
|
||||
if (inCache)
|
||||
return account;
|
||||
|
||||
account = m_UserService.GetUserAccount(scopeID, firstName, lastName);
|
||||
if (account != null)
|
||||
m_Cache.Cache(account);
|
||||
m_Cache.Cache(account.PrincipalID, account);
|
||||
|
||||
return account;
|
||||
}
|
||||
|
||||
@@ -119,26 +119,27 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
|
||||
|
||||
public override UserAccount GetUserAccount(UUID scopeID, UUID userID)
|
||||
{
|
||||
UserAccount account = m_Cache.Get(userID);
|
||||
if (account != null)
|
||||
bool inCache = false;
|
||||
UserAccount account = m_Cache.Get(userID, out inCache);
|
||||
if (inCache)
|
||||
return account;
|
||||
|
||||
account = base.GetUserAccount(scopeID, userID);
|
||||
if (account != null)
|
||||
m_Cache.Cache(account);
|
||||
m_Cache.Cache(userID, account);
|
||||
|
||||
return account;
|
||||
}
|
||||
|
||||
public override UserAccount GetUserAccount(UUID scopeID, string firstName, string lastName)
|
||||
{
|
||||
UserAccount account = m_Cache.Get(firstName + " " + lastName);
|
||||
if (account != null)
|
||||
bool inCache = false;
|
||||
UserAccount account = m_Cache.Get(firstName + " " + lastName, out inCache);
|
||||
if (inCache)
|
||||
return account;
|
||||
|
||||
account = base.GetUserAccount(scopeID, firstName, lastName);
|
||||
if (account != null)
|
||||
m_Cache.Cache(account);
|
||||
m_Cache.Cache(account.PrincipalID, account);
|
||||
|
||||
return account;
|
||||
}
|
||||
|
||||
@@ -36,50 +36,58 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
|
||||
{
|
||||
public class UserAccountCache
|
||||
{
|
||||
//private static readonly ILog m_log =
|
||||
// LogManager.GetLogger(
|
||||
// MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private ICnmCache<UUID, UserAccount> m_UUIDCache;
|
||||
private Dictionary<string, UUID> m_NameCache;
|
||||
private static readonly ILog m_log =
|
||||
LogManager.GetLogger(
|
||||
MethodBase.GetCurrentMethod().DeclaringType);
|
||||
private ExpiringCache<UUID, UserAccount> m_UUIDCache;
|
||||
private ExpiringCache<string, UUID> m_NameCache;
|
||||
|
||||
public UserAccountCache()
|
||||
{
|
||||
// Warning: the size values are a bit fuzzy. What matters
|
||||
// most for this cache is the count value (128 entries).
|
||||
m_UUIDCache = CnmSynchronizedCache<UUID, UserAccount>.Synchronized(new CnmMemoryCache<UUID, UserAccount>(
|
||||
128, 128*512, TimeSpan.FromMinutes(30.0)));
|
||||
m_NameCache = new Dictionary<string, UUID>(); // this one is unbound
|
||||
m_UUIDCache = new ExpiringCache<UUID, UserAccount>();
|
||||
m_NameCache = new ExpiringCache<string, UUID>(); // this one is unbound
|
||||
}
|
||||
|
||||
public void Cache(UserAccount account)
|
||||
public void Cache(UUID userID, UserAccount account)
|
||||
{
|
||||
m_UUIDCache.Set(account.PrincipalID, account, 512);
|
||||
m_NameCache[account.Name] = account.PrincipalID;
|
||||
// Cache even null accounts
|
||||
m_UUIDCache.AddOrUpdate(userID, account, DateTime.Now + TimeSpan.FromMinutes(2.0d));
|
||||
if (account != null)
|
||||
m_NameCache.AddOrUpdate(account.Name, account.PrincipalID, DateTime.Now + TimeSpan.FromMinutes(2.0d));
|
||||
|
||||
//m_log.DebugFormat("[USER CACHE]: cached user {0} {1}", account.FirstName, account.LastName);
|
||||
m_log.DebugFormat("[USER CACHE]: cached user {0}", userID);
|
||||
}
|
||||
|
||||
public UserAccount Get(UUID userID)
|
||||
public UserAccount Get(UUID userID, out bool inCache)
|
||||
{
|
||||
UserAccount account = null;
|
||||
inCache = false;
|
||||
if (m_UUIDCache.TryGetValue(userID, out account))
|
||||
{
|
||||
//m_log.DebugFormat("[USER CACHE]: Account {0} {1} found in cache", account.FirstName, account.LastName);
|
||||
inCache = true;
|
||||
return account;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public UserAccount Get(string name)
|
||||
public UserAccount Get(string name, out bool inCache)
|
||||
{
|
||||
if (!m_NameCache.ContainsKey(name))
|
||||
inCache = false;
|
||||
if (!m_NameCache.Contains(name))
|
||||
return null;
|
||||
|
||||
UserAccount account = null;
|
||||
if (m_UUIDCache.TryGetValue(m_NameCache[name], out account))
|
||||
return account;
|
||||
UUID uuid = UUID.Zero;
|
||||
if (m_NameCache.TryGetValue(name, out uuid))
|
||||
if (m_UUIDCache.TryGetValue(uuid, out account))
|
||||
{
|
||||
inCache = true;
|
||||
return account;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -183,7 +183,7 @@ namespace OpenSim.Region.CoreModules.World.Land
|
||||
void ClientOnPreAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
|
||||
{
|
||||
//If we are forcing a position for them to go
|
||||
if( forcedPosition != null )
|
||||
if (forcedPosition != null)
|
||||
{
|
||||
ScenePresence clientAvatar = m_scene.GetScenePresence(remoteClient.AgentId);
|
||||
|
||||
@@ -199,7 +199,7 @@ namespace OpenSim.Region.CoreModules.World.Land
|
||||
forcedPosition = null;
|
||||
}
|
||||
//if we are far away, teleport
|
||||
else if(Vector3.Distance(clientAvatar.AbsolutePosition,forcedPosition.Value) > 3 )
|
||||
else if (Vector3.Distance(clientAvatar.AbsolutePosition,forcedPosition.Value) > 3)
|
||||
{
|
||||
Debug.WriteLine(string.Format("Teleporting out because {0} is too far from avatar position {1}",forcedPosition.Value,clientAvatar.AbsolutePosition));
|
||||
clientAvatar.Teleport(forcedPosition.Value);
|
||||
@@ -340,7 +340,7 @@ namespace OpenSim.Region.CoreModules.World.Land
|
||||
|
||||
public void SendYouAreRestrictedNotice(ScenePresence avatar)
|
||||
{
|
||||
avatar.ControllingClient.SendAlertMessage(
|
||||
avatar.ControllingClient.SendAlertMessage(
|
||||
"You are not allowed on this parcel because the land owner has restricted access.");
|
||||
|
||||
}
|
||||
@@ -475,7 +475,7 @@ namespace OpenSim.Region.CoreModules.World.Land
|
||||
ForceAvatarToPosition(clientAvatar, m_scene.GetNearestAllowedPosition(clientAvatar));
|
||||
}
|
||||
}
|
||||
else if ( parcel.IsRestrictedFromLand(clientAvatar.UUID))
|
||||
else if (parcel.IsRestrictedFromLand(clientAvatar.UUID))
|
||||
{
|
||||
//once we've sent the message once, keep going toward the target until we are done
|
||||
if (forcedPosition == null)
|
||||
@@ -487,7 +487,7 @@ namespace OpenSim.Region.CoreModules.World.Land
|
||||
else
|
||||
{
|
||||
//when we are finally in a safe place, lets release the forced position lock
|
||||
forcedPosition = null;
|
||||
forcedPosition = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -287,7 +287,7 @@ namespace OpenSim.Region.CoreModules.World.Land
|
||||
entry.Flags = AccessList.Ban;
|
||||
entry.Time = new DateTime();
|
||||
//See if they are on the list, but make sure the owner isn't banned
|
||||
if (LandData.ParcelAccessList.Contains(entry) && LandData.OwnerID != avatar )
|
||||
if (LandData.ParcelAccessList.Contains(entry) && LandData.OwnerID != avatar)
|
||||
{
|
||||
//They are banned, so lets send them a notice about this parcel
|
||||
return true;
|
||||
|
||||
@@ -618,7 +618,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
|
||||
return objectOwnerMask;
|
||||
|
||||
// Estate users should be able to edit anything in the sim if RegionOwnerIsGod is set
|
||||
if (IsEstateManager(user) && m_RegionOwnerIsGod)
|
||||
if (m_RegionOwnerIsGod && IsEstateManager(user) && !IsAdministrator(objectOwner))
|
||||
return objectOwnerMask;
|
||||
|
||||
// Admin should be able to edit anything in the sim (including admin objects)
|
||||
|
||||
Reference in New Issue
Block a user