Merge branch 'master' into httptests

httptests
UbitUmarov 2017-01-07 16:55:03 +00:00
commit add27a503e
23 changed files with 485 additions and 363 deletions

View File

@ -781,8 +781,8 @@ namespace OpenSim.Groups
if (groupID != UUID.Zero)
{
if (money != null)
money.ApplyCharge(remoteClient.AgentId, money.GroupCreationCharge, MoneyTransactionType.GroupCreate);
if (money != null && money.GroupCreationCharge > 0)
money.ApplyCharge(remoteClient.AgentId, money.GroupCreationCharge, MoneyTransactionType.GroupCreate, name);
remoteClient.SendCreateGroupReply(groupID, true, "Group created successfully");
@ -979,10 +979,28 @@ namespace OpenSim.Groups
{
if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
GroupRecord groupRecord = GetGroupRecord(groupID);
IMoneyModule money = remoteClient.Scene.RequestModuleInterface<IMoneyModule>();
// Should check to see if there's an outstanding invitation
if (money != null && groupRecord.MembershipFee > 0)
{
// Does the agent have the funds to cover the group join fee?
if (!money.AmountCovered(remoteClient.AgentId, groupRecord.MembershipFee))
{
remoteClient.SendAlertMessage("Insufficient funds to join the group.");
remoteClient.SendJoinGroupReply(groupID, false);
return;
}
}
string reason = string.Empty;
// Should check to see if OpenEnrollment, or if there's an outstanding invitation
if (m_groupData.AddAgentToGroup(GetRequestingAgentIDStr(remoteClient), GetRequestingAgentIDStr(remoteClient), groupID, UUID.Zero, string.Empty, out reason))
{
if (money != null && groupRecord.MembershipFee > 0)
money.ApplyCharge(remoteClient.AgentId, groupRecord.MembershipFee, MoneyTransactionType.GroupJoin, groupRecord.GroupName);
remoteClient.SendJoinGroupReply(groupID, true);

View File

@ -3053,11 +3053,13 @@ namespace OpenSim.ApplicationPlugins.RemoteController
{
if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0)
{
uint perms = item.CurrentPermissions;
PermissionsUtil.ApplyFoldedPermissions(item.CurrentPermissions, ref perms);
item.CurrentPermissions = perms;
if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
item.CurrentPermissions &= ~(uint)PermissionMask.Copy;
if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
item.CurrentPermissions &= ~(uint)PermissionMask.Transfer;
if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
}
item.CurrentPermissions &= item.NextPermissions;
item.BasePermissions &= item.NextPermissions;
item.EveryOnePermissions &= item.NextPermissions;

View File

@ -90,7 +90,7 @@ namespace OpenSim.Framework
public Vector3 LeftAxis;
public Vector3 UpAxis;
//public int GodLevel;
public OSD GodData = new OSDMap();
public OSD GodData = null;
public bool ChangedGrid;
// This probably shouldn't be here
@ -119,12 +119,15 @@ namespace OpenSim.Framework
args["far"] = OSD.FromReal(Far);
args["changed_grid"] = OSD.FromBoolean(ChangedGrid);
//args["god_level"] = OSD.FromString(GodLevel.ToString());
args["god_data"] = GodData;
OSDMap g = (OSDMap)GodData;
// Set legacy value
// TODO: remove after 0.9 is superseded
if (g.ContainsKey("ViewerUiIsGod"))
args["god_level"] = g["ViewerUiIsGod"].AsBoolean() ? 200 : 0;;
if(GodData != null)
{
args["god_data"] = GodData;
OSDMap g = (OSDMap)GodData;
// Set legacy value
// TODO: remove after 0.9 is superseded
if (g.ContainsKey("ViewerUiIsGod"))
args["god_level"] = g["ViewerUiIsGod"].AsBoolean() ? 200 : 0;
}
if ((Throttles != null) && (Throttles.Length > 0))
args["throttles"] = OSD.FromBinary(Throttles);
@ -185,7 +188,7 @@ namespace OpenSim.Framework
//if (args["god_level"] != null)
// Int32.TryParse(args["god_level"].AsString(), out GodLevel);
if (args["god_data"] != null)
if (args.ContainsKey("god_data") && args["god_data"] != null)
GodData = args["god_data"];
if (args["far"] != null)
@ -362,7 +365,7 @@ namespace OpenSim.Framework
public Quaternion BodyRotation;
public uint ControlFlags;
public float EnergyLevel;
public OSD GodData = new OSDMap();
public OSD GodData = null;
//public Byte GodLevel;
public bool AlwaysRun;
public UUID PreyAgent;
@ -438,10 +441,13 @@ namespace OpenSim.Framework
args["energy_level"] = OSD.FromReal(EnergyLevel);
//args["god_level"] = OSD.FromString(GodLevel.ToString());
args["god_data"] = GodData;
OSDMap g = (OSDMap)GodData;
if (g.ContainsKey("ViewerUiIsGod"))
args["god_level"] = g["ViewerUiIsGod"].AsBoolean() ? 200 : 0;;
if(GodData != null)
{
args["god_data"] = GodData;
OSDMap g = (OSDMap)GodData;
if (g.ContainsKey("ViewerUiIsGod"))
args["god_level"] = g["ViewerUiIsGod"].AsBoolean() ? 200 : 0;;
}
args["always_run"] = OSD.FromBoolean(AlwaysRun);
args["prey_agent"] = OSD.FromUUID(PreyAgent);
args["agent_access"] = OSD.FromString(AgentAccess.ToString());
@ -622,7 +628,7 @@ namespace OpenSim.Framework
//if (args["god_level"] != null)
// Byte.TryParse(args["god_level"].AsString(), out GodLevel);
if (args["god_data"] != null)
if (args.ContainsKey("god_data") && args["god_data"] != null)
GodData = args["god_data"];
if (args["always_run"] != null)

View File

@ -64,24 +64,5 @@ namespace OpenSim.Framework
str = ".";
return str;
}
/// <summary>
/// Applies an object's folded permissions to its regular permissions.
/// </summary>
/// <param name="foldedPerms">The folded permissions. Only the lowest 7 bits are examined.</param>
/// <param name="mainPerms">The permissions variable to modify.</param>
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 & ((uint)PermissionMask.Copy >> 13)) == 0)
mainPerms &= ~(uint)PermissionMask.Copy;
if ((foldedPerms & ((uint)PermissionMask.Transfer >> 13)) == 0)
mainPerms &= ~(uint)PermissionMask.Transfer;
if ((foldedPerms & ((uint)PermissionMask.Modify >> 13)) == 0)
mainPerms &= ~(uint)PermissionMask.Modify;
}
}
}

View File

@ -185,7 +185,13 @@ namespace OpenSim.Region.ClientStack.Linden
m_log.DebugFormat("[GetMeshModule] Closing");
foreach (Thread t in m_workerThreads)
Watchdog.AbortThread(t.ManagedThreadId);
m_queue.Clear();
// This will fail on region shutdown. Its harmless.
// Prevent red ink.
try
{
m_queue.Clear();
}
catch {}
}
}

View File

@ -1118,7 +1118,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
SceneObjectGroup objatt;
UUID rezGroupID = sp.ControllingClient.ActiveGroupId;
UUID rezGroupID;
// This will fail if the user aborts login. sp will exist
// but ControllintClient will be null.
try
{
rezGroupID = sp.ControllingClient.ActiveGroupId;
}
catch
{
return null;
}
if (itemID != UUID.Zero)
objatt = m_invAccessModule.RezObject(sp.ControllingClient,

View File

@ -369,6 +369,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
public virtual bool SendFriendsOnlineIfNeeded(IClientAPI client)
{
if (client == null)
return false;
UUID agentID = client.AgentId;
// Check if the online friends list is needed

View File

@ -194,14 +194,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
int godlevel = 200;
// update level so higher gods can kick lower ones
ScenePresence god = m_scene.GetScenePresence(godID);
if(god != null && god.GodController.GodLevel > godlevel)
godlevel = god.GodController.GodLevel;
if(god != null && god.GodController.EffectiveLevel > godlevel)
godlevel = god.GodController.EffectiveLevel;
if(agentID == ALL_AGENTS)
{
m_scene.ForEachRootScenePresence(delegate(ScenePresence p)
{
if (p.UUID != godID && godlevel > p.GodController.GodLevel)
if (p.UUID != godID && godlevel > p.GodController.EffectiveLevel)
doKickmodes(godID, p, kickflags, reason);
});
return;
@ -224,7 +224,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
return;
}
if (godlevel <= sp.GodController.GodLevel) // no god wars
if (godlevel <= sp.GodController.EffectiveLevel) // no god wars
return;
if(sp.UUID == godID)

View File

@ -1999,8 +1999,16 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
IClientAPI spClient = sp.ControllingClient;
if (!seeds.ContainsKey(currentRegionHandler))
seeds.Add(currentRegionHandler, spClient.RequestClientInfo().CapsPath);
// This will fail if the user aborts login
try
{
if (!seeds.ContainsKey(currentRegionHandler))
seeds.Add(currentRegionHandler, spClient.RequestClientInfo().CapsPath);
}
catch
{
return;
}
AgentCircuitData currentAgentCircuit =
spScene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);

View File

@ -322,7 +322,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection,
bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment)
{
m_log.DebugFormat("[HGScene]: RezObject itemID={0} fromTaskID={1}", itemID, fromTaskID);
//m_log.DebugFormat("[HGScene]: RezObject itemID={0} fromTaskID={1}", itemID, fromTaskID);
//if (fromTaskID.Equals(UUID.Zero))
//{

View File

@ -532,17 +532,13 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
}
else
{
AddPermissions(item, objlist[0], objlist, remoteClient);
item.CreationDate = Util.UnixTimeSinceEpoch();
item.Description = asset.Description;
item.Name = asset.Name;
item.AssetType = asset.Type;
//preserve perms on return
if(DeRezAction.Return == action)
AddPermissions(item, objlist[0], objlist, null);
else
AddPermissions(item, objlist[0], objlist, remoteClient);
m_Scene.AddInventoryItem(item);
if (remoteClient != null && item.Owner == remoteClient.AgentId)
@ -599,15 +595,16 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
}
effectivePerms |= (uint)PermissionMask.Move;
//PermissionsUtil.LogPermissions(item.Name, "Before AddPermissions", item.BasePermissions, item.CurrentPermissions, item.NextPermissions);
if (remoteClient != null && (remoteClient.AgentId != so.RootPart.OwnerID) && m_Scene.Permissions.PropagatePermissions())
{
// Changing ownership, so apply the "Next Owner" permissions to all of the
// inventory item's permissions.
uint perms = effectivePerms;
PermissionsUtil.ApplyFoldedPermissions(effectivePerms, ref perms);
uint nextPerms = (perms & 7) << 13;
if ((nextPerms & (uint)PermissionMask.Copy) == 0)
perms &= ~(uint)PermissionMask.Copy;
if ((nextPerms & (uint)PermissionMask.Transfer) == 0)
perms &= ~(uint)PermissionMask.Transfer;
if ((nextPerms & (uint)PermissionMask.Modify) == 0)
perms &= ~(uint)PermissionMask.Modify;
item.BasePermissions = perms & so.RootPart.NextOwnerMask;
item.CurrentPermissions = item.BasePermissions;
@ -620,13 +617,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
}
else
{
// Not changing ownership.
// In this case we apply the permissions in the object's items ONLY to the inventory
// item's "Next Owner" permissions, but NOT to its "Current", "Base", etc. permissions.
// E.g., if the object contains a No-Transfer item then the item's "Next Owner"
// permissions are also No-Transfer.
PermissionsUtil.ApplyFoldedPermissions(effectivePerms, ref allObjectsNextOwnerPerms);
item.BasePermissions = effectivePerms;
item.CurrentPermissions = effectivePerms;
item.NextPermissions = so.RootPart.NextOwnerMask & effectivePerms;
@ -640,10 +630,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
(uint)PermissionMask.Move |
(uint)PermissionMask.Export |
7); // Preserve folded permissions
}
//PermissionsUtil.LogPermissions(item.Name, "After AddPermissions", item.BasePermissions, item.CurrentPermissions, item.NextPermissions);
}
return item;
}
@ -1153,6 +1141,12 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
part.OwnerID = item.Owner;
part.RezzerID = item.Owner;
part.Inventory.ChangeInventoryOwner(item.Owner);
// This applies the base mask from the item as the next
// permissions for the object. This is correct because the
// giver's base mask was masked by the giver's next owner
// mask, so the base mask equals the original next owner mask.
part.NextOwnerMask = item.BasePermissions;
}
so.ApplyNextOwnerPermissions();
@ -1164,10 +1158,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
{
if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0)
{
if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
part.EveryoneMask = item.EveryOnePermissions & part.BaseMask;
if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
part.NextOwnerMask = item.NextPermissions & part.BaseMask;
part.EveryoneMask = item.EveryOnePermissions & part.BaseMask;
part.NextOwnerMask = item.NextPermissions & part.BaseMask;
}
}
}

View File

@ -1818,13 +1818,20 @@ namespace OpenSim.Region.CoreModules.World.Land
uint wx;
uint wy;
Util.RegionHandleToWorldLoc(regionHandle, out wx, out wy);
wx += x;
wy += y;
GridRegion info = m_scene.GridService.GetRegionByPosition(scope, (int)wx, (int)wy);
if(info != null)
{
wx -= (uint)info.RegionLocX;
wy -= (uint)info.RegionLocY;
wx += x;
wy += y;
// Firestorm devs have no ideia how to do handlers math
// on all cases
if(wx > info.RegionSizeX || wy > info.RegionSizeY)
{
wx = x;
wy = y;
}
parcelID = Util.BuildFakeParcelID(info.RegionHandle, wx, wy);
}
}
@ -1845,8 +1852,6 @@ namespace OpenSim.Region.CoreModules.World.Land
parcelID = Util.BuildFakeParcelID(info.RegionHandle, x, y);
}
}
}
}
catch (LLSD.LLSDParseException e)

View File

@ -211,7 +211,13 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell
item.InvType = (int)InventoryType.Object;
item.Folder = categoryID;
PermissionsUtil.ApplyFoldedPermissions(perms, ref perms);
uint nextPerms=(perms & 7) << 13;
if ((nextPerms & (uint)PermissionMask.Copy) == 0)
perms &= ~(uint)PermissionMask.Copy;
if ((nextPerms & (uint)PermissionMask.Transfer) == 0)
perms &= ~(uint)PermissionMask.Transfer;
if ((nextPerms & (uint)PermissionMask.Modify) == 0)
perms &= ~(uint)PermissionMask.Modify;
item.BasePermissions = perms & part.NextOwnerMask;
item.CurrentPermissions = perms & part.NextOwnerMask;

View File

@ -99,7 +99,9 @@ namespace OpenSim.Region.CoreModules.World.Permissions
private bool m_allowGridGods = false;
private bool m_RegionOwnerIsGod = false;
private bool m_RegionManagerIsGod = false;
private bool m_ParcelOwnerIsGod = false;
private bool m_forceGridGodsOnly;
private bool m_forceGodModeAlwaysOn;
private bool m_allowGodActionsWithoutGodMode;
private bool m_SimpleBuildPermissions = false;
@ -168,21 +170,27 @@ namespace OpenSim.Region.CoreModules.World.Permissions
m_Enabled = true;
m_allowGridGods = Util.GetConfigVarFromSections<bool>(config, "allow_grid_gods",
new string[] { "Startup", "Permissions" }, false);
m_bypassPermissions = !Util.GetConfigVarFromSections<bool>(config, "serverside_object_permissions",
new string[] { "Startup", "Permissions" }, true);
m_propagatePermissions = Util.GetConfigVarFromSections<bool>(config, "propagate_permissions",
new string[] { "Startup", "Permissions" }, true);
m_RegionOwnerIsGod = Util.GetConfigVarFromSections<bool>(config, "region_owner_is_god",
new string[] { "Startup", "Permissions" }, true);
m_RegionManagerIsGod = Util.GetConfigVarFromSections<bool>(config, "region_manager_is_god",
new string[] { "Startup", "Permissions" }, false);
m_ParcelOwnerIsGod = Util.GetConfigVarFromSections<bool>(config, "parcel_owner_is_god",
new string[] { "Startup", "Permissions" }, false);
string[] sections = new string[] { "Startup", "Permissions" };
m_SimpleBuildPermissions = Util.GetConfigVarFromSections<bool>(config, "simple_build_permissions",
new string[] { "Startup", "Permissions" }, false);
m_allowGridGods = Util.GetConfigVarFromSections<bool>(config, "allow_grid_gods", sections, false);
m_bypassPermissions = !Util.GetConfigVarFromSections<bool>(config, "serverside_object_permissions", sections, true);
m_propagatePermissions = Util.GetConfigVarFromSections<bool>(config, "propagate_permissions", sections, true);
m_forceGridGodsOnly = Util.GetConfigVarFromSections<bool>(config, "force_grid_gods_only", sections, false);
if(!m_forceGridGodsOnly)
{
m_RegionOwnerIsGod = Util.GetConfigVarFromSections<bool>(config, "region_owner_is_god",sections, true);
m_RegionManagerIsGod = Util.GetConfigVarFromSections<bool>(config, "region_manager_is_god",sections, false);
}
else
m_allowGridGods = true;
m_forceGodModeAlwaysOn = Util.GetConfigVarFromSections<bool>(config, "automatic_gods", sections, false);
m_allowGodActionsWithoutGodMode = Util.GetConfigVarFromSections<bool>(config, "implicit_gods", sections, false);
if(m_allowGodActionsWithoutGodMode)
m_forceGodModeAlwaysOn = false;
m_SimpleBuildPermissions = Util.GetConfigVarFromSections<bool>(config, "simple_build_permissions",sections, false);
m_allowedScriptCreators
= ParseUserSetConfigSetting(config, "allowed_script_creators", m_allowedScriptCreators);
@ -718,6 +726,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
if (IsAdministrator(user))
return PermissionClass.Owner;
/* to review later
// Users should be able to edit what is over their land.
Vector3 taskPos = obj.AbsolutePosition;
ILandObject parcel = m_scene.LandChannel.GetLandObject(taskPos.X, taskPos.Y);
@ -727,7 +736,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
if (!IsAdministrator(objectOwner))
return PermissionClass.Owner;
}
*/
// Group permissions
if ((obj.GroupID != UUID.Zero) && IsGroupMember(obj.GroupID, user, 0))
return PermissionClass.Group;

View File

@ -47,23 +47,35 @@ namespace OpenSim.Region.Framework.Scenes
{
public class GodController
{
public enum ImplicitGodLevels : int
{
EstateManager = 210, // estate manager implicit god level
RegionOwner = 220 // region owner implicit god level should be >= than estate
}
ScenePresence m_scenePresence;
Scene m_scene;
protected bool m_allowGridGods;
protected bool m_forceGridGodsOnly;
protected bool m_regionOwnerIsGod;
protected bool m_regionManagerIsGod;
protected bool m_parcelOwnerIsGod;
protected bool m_forceGodModeAlwaysOn;
protected bool m_allowGodActionsWithoutGodMode;
protected bool m_viewerUiIsGod = false;
protected int m_userLevel = 0;
// the god level from local or grid user rights
protected int m_rightsGodLevel = 0;
// the level seen by viewers
protected int m_godlevel = 0;
// new level that can be fixed or equal to godlevel, acording to options
protected int m_effectivegodlevel = 0;
protected int m_lastLevelToViewer = 0;
public GodController(Scene scene, ScenePresence sp)
public GodController(Scene scene, ScenePresence sp, int userlevel)
{
m_scene = scene;
m_scenePresence = sp;
m_userLevel = userlevel;
IConfigSource config = scene.Config;
@ -76,21 +88,27 @@ namespace OpenSim.Region.Framework.Scenes
Util.GetConfigVarFromSections<bool>(config,
"allow_grid_gods", sections, false);
// The owner of a region is a god in his region only.
m_regionOwnerIsGod =
// If grid gods are active, dont allow any other gods
m_forceGridGodsOnly =
Util.GetConfigVarFromSections<bool>(config,
"force_grid_gods_only", sections, false);
if(!m_forceGridGodsOnly)
{
// The owner of a region is a god in his region only.
m_regionOwnerIsGod =
Util.GetConfigVarFromSections<bool>(config,
"region_owner_is_god", sections, true);
// Region managers are gods in the regions they manage.
m_regionManagerIsGod =
// Region managers are gods in the regions they manage.
m_regionManagerIsGod =
Util.GetConfigVarFromSections<bool>(config,
"region_manager_is_god", sections, false);
// Parcel owners are gods in their own parcels only.
m_parcelOwnerIsGod =
Util.GetConfigVarFromSections<bool>(config,
"parcel_owner_is_god", sections, false);
}
else
m_allowGridGods = true; // reduce potencial user mistakes
// God mode should be turned on in the viewer whenever
// the user has god rights somewhere. They may choose
// to turn it off again, though.
@ -105,78 +123,121 @@ namespace OpenSim.Region.Framework.Scenes
Util.GetConfigVarFromSections<bool>(config,
"implicit_gods", sections, false);
m_rightsGodLevel = CalcRightsGodLevel();
if(m_allowGodActionsWithoutGodMode)
{
m_effectivegodlevel = m_rightsGodLevel;
m_forceGodModeAlwaysOn = false;
}
else if(m_forceGodModeAlwaysOn)
{
m_godlevel = m_rightsGodLevel;
m_effectivegodlevel = m_rightsGodLevel;
}
m_scenePresence.isGod = (m_effectivegodlevel >= 200);
m_scenePresence.isLegacyGod = (m_godlevel >= 200);
}
// calculates god level at sp creation from local and grid user god rights
// for now this is assumed static until user leaves region.
// later estate and gride level updates may update this
protected int CalcRightsGodLevel()
{
int level = 0;
if (m_allowGridGods && m_userLevel >= 200)
level = m_userLevel;
if(m_forceGridGodsOnly || level >= (int)ImplicitGodLevels.RegionOwner)
return level;
if (m_regionOwnerIsGod && m_scene.RegionInfo.EstateSettings.IsEstateOwner(m_scenePresence.UUID))
level = (int)ImplicitGodLevels.RegionOwner;
if(level >= (int)ImplicitGodLevels.EstateManager)
return level;
if (m_regionManagerIsGod && m_scene.Permissions.IsEstateManager(m_scenePresence.UUID))
level = (int)ImplicitGodLevels.EstateManager;
return level;
}
protected bool CanBeGod()
{
bool canBeGod = false;
if (m_allowGridGods && m_userLevel > 0)
canBeGod = true;
if (m_regionOwnerIsGod && m_scene.RegionInfo.EstateSettings.IsEstateOwner(m_scenePresence.UUID))
canBeGod = true;
if (m_regionManagerIsGod && m_scene.Permissions.IsEstateManager(m_scenePresence.UUID))
canBeGod = true;
if (!canBeGod && m_parcelOwnerIsGod) // Skip expensive check if we're already god!
{
Vector3 pos = m_scenePresence.AbsolutePosition;
ILandObject parcel = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
if (parcel != null && parcel.LandData.OwnerID == m_scenePresence.UUID)
canBeGod = true;
}
return canBeGod;
return m_rightsGodLevel >= 200;
}
protected void SyncViewerState()
protected void UpdateGodLevels(bool viewerState)
{
bool canBeGod = CanBeGod();
bool shoudBeGod = m_forceGodModeAlwaysOn ? canBeGod : (m_viewerUiIsGod && canBeGod);
int godLevel = m_allowGridGods ? m_userLevel : 200;
if (!shoudBeGod)
godLevel = 0;
if (m_viewerUiIsGod != shoudBeGod)
if(!CanBeGod())
{
m_scenePresence.ControllingClient.SendAdminResponse(UUID.Zero, (uint)godLevel);
m_viewerUiIsGod = shoudBeGod;
m_godlevel = 0;
m_effectivegodlevel = 0;
m_scenePresence.isGod = false;
m_scenePresence.isLegacyGod = false;
return;
}
// legacy some are controled by viewer, others are static
if(m_allowGodActionsWithoutGodMode)
{
if(viewerState)
m_godlevel = m_rightsGodLevel;
else
m_godlevel = 0;
m_effectivegodlevel = m_rightsGodLevel;
}
else
{
// new all change with viewer
if(viewerState)
{
m_godlevel = m_rightsGodLevel;
m_effectivegodlevel = m_rightsGodLevel;
}
else
{
m_godlevel = 0;
m_effectivegodlevel = 0;
}
}
m_scenePresence.isGod = (m_effectivegodlevel >= 200);
m_scenePresence.isLegacyGod = (m_godlevel >= 200);
}
public bool RequestGodMode(bool god)
public void SyncViewerState()
{
if (!god)
{
if (m_viewerUiIsGod)
m_scenePresence.ControllingClient.SendAdminResponse(UUID.Zero, 0);
if(m_lastLevelToViewer == m_godlevel)
return;
m_viewerUiIsGod = false;
m_lastLevelToViewer = m_godlevel;
return true;
}
if(m_scenePresence.IsChildAgent)
return;
if (!CanBeGod())
return false;
int godLevel = m_allowGridGods ? m_userLevel : 200;
if (!m_viewerUiIsGod)
m_scenePresence.ControllingClient.SendAdminResponse(UUID.Zero, (uint)godLevel);
m_viewerUiIsGod = true;
return true;
m_scenePresence.ControllingClient.SendAdminResponse(UUID.Zero, (uint)m_godlevel);
}
public OSD State()
public void RequestGodMode(bool god)
{
UpdateGodLevels(god);
if(m_lastLevelToViewer != m_godlevel)
{
m_scenePresence.ControllingClient.SendAdminResponse(UUID.Zero, (uint)m_godlevel);
m_lastLevelToViewer = m_godlevel;
}
}
public OSD State()
{
OSDMap godMap = new OSDMap(2);
bool m_viewerUiIsGod = m_godlevel >= 200;
godMap.Add("ViewerUiIsGod", OSD.FromBoolean(m_viewerUiIsGod));
return godMap;
@ -184,45 +245,42 @@ namespace OpenSim.Region.Framework.Scenes
public void SetState(OSD state)
{
OSDMap s = (OSDMap)state;
bool newstate = false;
if(m_forceGodModeAlwaysOn)
newstate = true;
else
{
if(state != null)
{
OSDMap s = (OSDMap)state;
if (s.ContainsKey("ViewerUiIsGod"))
m_viewerUiIsGod = s["ViewerUiIsGod"].AsBoolean();
if (s.ContainsKey("ViewerUiIsGod"))
newstate = s["ViewerUiIsGod"].AsBoolean();
m_lastLevelToViewer = m_godlevel; // we are not changing viewer level by default
}
}
UpdateGodLevels(newstate);
}
SyncViewerState();
public void HasMovedAway()
{
m_lastLevelToViewer = 0;
}
public int UserLevel
{
get { return m_userLevel; }
set { m_userLevel = UserLevel; }
set { m_userLevel = value; }
}
public int GodLevel
{
get
{
int godLevel = m_allowGridGods ? m_userLevel : 200;
if (!m_viewerUiIsGod)
godLevel = 0;
return godLevel;
}
get { return m_godlevel; }
}
public int EffectiveLevel
{
get
{
int godLevel = m_allowGridGods ? m_userLevel : 200;
if (m_viewerUiIsGod)
return godLevel;
if (m_allowGodActionsWithoutGodMode && CanBeGod())
return godLevel;
return 0;
}
get { return m_effectivegodlevel; }
}
}
}

View File

@ -627,6 +627,7 @@ namespace OpenSim.Region.Framework.Scenes
itemCopy.AssetType = item.AssetType;
itemCopy.InvType = item.InvType;
itemCopy.Folder = recipientFolderId;
itemCopy.Flags = item.Flags;
if (Permissions.PropagatePermissions() && recipient != senderId)
{
@ -643,7 +644,7 @@ namespace OpenSim.Region.Framework.Scenes
//
// Transfer
// Copy
// Modufy
// Modify
uint permsMask = ~ ((uint)PermissionMask.Copy |
(uint)PermissionMask.Transfer |
(uint)PermissionMask.Modify);
@ -681,13 +682,17 @@ namespace OpenSim.Region.Framework.Scenes
// a mask
if (item.InvType == (int)InventoryType.Object)
{
// Create a safe mask for the current perms
uint foldedPerms = (item.CurrentPermissions & 7) << 13;
foldedPerms |= permsMask;
bool isRootMod = (item.CurrentPermissions &
(uint)PermissionMask.Modify) != 0 ?
true : false;
// Mask the owner perms to the folded perms
PermissionsUtil.ApplyFoldedPermissions(item.CurrentPermissions, ref ownerPerms);
PermissionsUtil.ApplyFoldedPermissions(item.CurrentPermissions, ref basePerms);
ownerPerms &= foldedPerms;
basePerms &= foldedPerms;
// If the root was mod, let the mask reflect that
// We also need to adjust the base here, because
@ -714,6 +719,10 @@ namespace OpenSim.Region.Framework.Scenes
itemCopy.BasePermissions = basePerms;
itemCopy.CurrentPermissions = ownerPerms;
itemCopy.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm;
// Need to clear the other inventory slam options.
// That is so we can handle the case where the recipient
// changes the bits in inventory before rezzing
itemCopy.Flags &= ~(uint)(InventoryItemFlags.ObjectOverwriteBase | InventoryItemFlags.ObjectOverwriteOwner | InventoryItemFlags.ObjectOverwriteGroup | InventoryItemFlags.ObjectOverwriteEveryone | InventoryItemFlags.ObjectOverwriteNextOwner);
itemCopy.NextPermissions = item.NextPermissions;
@ -763,9 +772,8 @@ namespace OpenSim.Region.Framework.Scenes
itemCopy.GroupID = UUID.Zero;
itemCopy.GroupOwned = false;
itemCopy.Flags = item.Flags;
itemCopy.SalePrice = item.SalePrice;
itemCopy.SaleType = item.SaleType;
itemCopy.SalePrice = 0; //item.SalePrice;
itemCopy.SaleType = 0; //item.SaleType;
IInventoryAccessModule invAccess = RequestModuleInterface<IInventoryAccessModule>();
if (invAccess != null)
@ -1240,26 +1248,18 @@ namespace OpenSim.Region.Framework.Scenes
{
agentItem.BasePermissions = taskItem.BasePermissions & (taskItem.NextPermissions | (uint)PermissionMask.Move);
if (taskItem.InvType == (int)InventoryType.Object)
{
// Bake the new base permissions from folded permissions
// The folded perms are in the lowest 3 bits of the current perms
// We use base permissions here to avoid baking the "Locked" status
// into the item as it is passed.
uint perms = taskItem.BasePermissions & taskItem.NextPermissions;
PermissionsUtil.ApplyFoldedPermissions(taskItem.CurrentPermissions, ref perms);
// Avoid the "lock trap" - move must always be enabled but the above may remove it
// Add it back here.
agentItem.BasePermissions = perms | (uint)PermissionMask.Move;
// Newly given items cannot be "locked" on rez. Make sure by
// setting current equal to base.
}
agentItem.CurrentPermissions = agentItem.BasePermissions & (((taskItem.CurrentPermissions & 7) << 13) | (taskItem.CurrentPermissions & (uint)PermissionMask.Move));
else
agentItem.CurrentPermissions = agentItem.BasePermissions & taskItem.CurrentPermissions;
agentItem.CurrentPermissions = agentItem.BasePermissions;
agentItem.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm;
agentItem.Flags &= ~(uint)(InventoryItemFlags.ObjectOverwriteBase | InventoryItemFlags.ObjectOverwriteOwner | InventoryItemFlags.ObjectOverwriteGroup | InventoryItemFlags.ObjectOverwriteEveryone | InventoryItemFlags.ObjectOverwriteNextOwner);
agentItem.NextPermissions = taskItem.NextPermissions;
agentItem.EveryOnePermissions = taskItem.EveryonePermissions & (taskItem.NextPermissions | (uint)PermissionMask.Move);
agentItem.GroupPermissions = taskItem.GroupPermissions & taskItem.NextPermissions;
// Group permissions make no sense here
agentItem.GroupPermissions = 0;
}
else
{
@ -1267,7 +1267,7 @@ namespace OpenSim.Region.Framework.Scenes
agentItem.CurrentPermissions = taskItem.CurrentPermissions;
agentItem.NextPermissions = taskItem.NextPermissions;
agentItem.EveryOnePermissions = taskItem.EveryonePermissions;
agentItem.GroupPermissions = taskItem.GroupPermissions;
agentItem.GroupPermissions = 0;
}
message = null;

View File

@ -5242,6 +5242,7 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter
BaseMask &= NextOwnerMask | (uint)PermissionMask.Export;
OwnerMask &= NextOwnerMask;
EveryoneMask &= NextOwnerMask | (uint)PermissionMask.Export;
GroupMask = 0; // Giving an object zaps group permissions
Inventory.ApplyNextOwnerPermissions();
}

View File

@ -1358,6 +1358,10 @@ namespace OpenSim.Region.Framework.Scenes
{
if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0)
{
// m_log.DebugFormat (
// "[SCENE OBJECT PART INVENTORY]: Applying next permissions {0} to {1} in {2} with current {3}, base {4}, everyone {5}",
// item.NextPermissions, item.Name, m_part.Name, item.CurrentPermissions, item.BasePermissions, item.EveryonePermissions);
if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
item.CurrentPermissions &= ~(uint)PermissionMask.Copy;
if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)

View File

@ -92,6 +92,14 @@ namespace OpenSim.Region.Framework.Scenes
public bool isNPC { get; private set; }
// simple yes or no isGOD from god level >= 200
// should only be set by GodController
// we have two to suport legacy behaviour
// isLegacyGod was controlled by viewer in older versions
// isGod may now be also controled by viewer acording to options
public bool isLegacyGod { get; set; }
public bool isGod { get; set; }
private PresenceType m_presenceType;
public PresenceType PresenceType {
get {return m_presenceType;}
@ -155,7 +163,7 @@ namespace OpenSim.Region.Framework.Scenes
public static readonly float MOVEMENT = .25f;
public static readonly float SIGNIFICANT_MOVEMENT = 16.0f;
public static readonly float CHILDUPDATES_MOVEMENT = 100.0f;
public static readonly float CHILDUPDATES_TIME = 10000f; // min time between child updates (ms)
public static readonly float CHILDUPDATES_TIME = 2000f; // min time between child updates (ms)
private UUID m_previusParcelUUID = UUID.Zero;
private UUID m_currentParcelUUID = UUID.Zero;
@ -186,7 +194,7 @@ namespace OpenSim.Region.Framework.Scenes
m_currentParcelHide = true;
if (m_previusParcelUUID != UUID.Zero || checksame)
ParcelCrossCheck(m_currentParcelUUID,m_previusParcelUUID,m_currentParcelHide, m_previusParcelHide, oldhide,checksame);
ParcelCrossCheck(m_currentParcelUUID, m_previusParcelUUID, m_currentParcelHide, m_previusParcelHide, oldhide,checksame);
}
}
}
@ -267,8 +275,6 @@ namespace OpenSim.Region.Framework.Scenes
private ScriptControlled IgnoredControls = ScriptControlled.CONTROL_ZERO;
private ScriptControlled LastCommands = ScriptControlled.CONTROL_ZERO;
private bool MouseDown = false;
// private SceneObjectGroup proxyObjectGroup;
//private SceneObjectPart proxyObjectPart = null;
public Vector3 lastKnownAllowedPosition;
public bool sentMessageAboutRestrictedParcelFlyingDown;
public Vector4 CollisionPlane = Vector4.UnitW;
@ -281,9 +287,6 @@ namespace OpenSim.Region.Framework.Scenes
private bool m_followCamAuto = false;
// private object m_forceToApplyLock = new object();
// private bool m_forceToApplyValid;
// private Vector3 m_forceToApply;
private int m_userFlags;
public int UserFlags
{
@ -304,9 +307,6 @@ namespace OpenSim.Region.Framework.Scenes
set { PhysicsActor.IsColliding = value; }
}
// private int m_lastColCount = -1; //KF: Look for Collision chnages
// private int m_updateCount = 0; //KF: Update Anims for a while
// private static readonly int UPDATE_COUNT = 10; // how many frames to update for
private List<uint> m_lastColliders = new List<uint>();
private TeleportFlags m_teleportFlags;
@ -332,8 +332,10 @@ namespace OpenSim.Region.Framework.Scenes
private float m_sitAvatarHeight = 2.0f;
private bool childUpdatesBusy = false;
private int lastChildUpdatesTime;
private bool m_childUpdatesBusy = false;
private int m_lastChildUpdatesTime;
private int m_lastChildAgentUpdateGodLevel;
private float m_lastChildAgentUpdateDrawDistance;
private Vector3 m_lastChildAgentUpdatePosition;
// private Vector3 m_lastChildAgentUpdateCamPosition;
@ -348,8 +350,6 @@ namespace OpenSim.Region.Framework.Scenes
private float m_healRate = 1f;
private float m_healRatePerFrame = 0.05f;
// protected ulong crossingFromRegion;
private readonly Vector3[] Dir_Vectors = new Vector3[12];
protected int m_reprioritizationLastTime;
@ -372,10 +372,7 @@ namespace OpenSim.Region.Framework.Scenes
private const int NumMovementsBetweenRayCast = 5;
private bool CameraConstraintActive;
//private int m_moveToPositionStateStatus;
//*****************************************************
//private bool m_collisionEventFlag = false;
private object m_collisionEventLock = new Object();
private int m_movementAnimationUpdateCounter = 0;
@ -529,7 +526,6 @@ namespace OpenSim.Region.Framework.Scenes
private bool m_doingCamRayCast = false;
public Vector3 CameraPosition { get; set; }
public Quaternion CameraRotation { get; private set; }
// Use these three vectors to figure out what the agent is looking at
@ -589,7 +585,6 @@ namespace OpenSim.Region.Framework.Scenes
public bool AllowMovement { get; set; }
private bool m_setAlwaysRun;
public bool SetAlwaysRun
{
get
@ -613,7 +608,6 @@ namespace OpenSim.Region.Framework.Scenes
}
}
public byte State { get; set; }
private AgentManager.ControlFlags m_AgentControlFlags;
@ -935,27 +929,7 @@ namespace OpenSim.Region.Framework.Scenes
seeds = Scene.CapsModule.GetChildrenSeeds(UUID);
else
seeds = new Dictionary<ulong, string>();
/* we can't do this anymore
List<ulong> old = new List<ulong>();
foreach (ulong handle in seeds.Keys)
{
uint x, y;
Util.RegionHandleToRegionLoc(handle, out x, out y);
// if (Util.IsOutsideView(DrawDistance, x, Scene.RegionInfo.RegionLocX, y, Scene.RegionInfo.RegionLocY,))
{
old.Add(handle);
}
}
DropOldNeighbours(old);
if (Scene.CapsModule != null)
Scene.CapsModule.SetChildrenSeed(UUID, seeds);
*/
KnownRegions = seeds;
//m_log.Debug(" ++++++++++AFTER+++++++++++++ ");
//DumpKnownRegions();
}
public void DumpKnownRegions()
@ -1045,8 +1019,6 @@ namespace OpenSim.Region.Framework.Scenes
public ScenePresence(
IClientAPI client, Scene world, AvatarAppearance appearance, PresenceType type)
{
GodController = new GodController(world, this);
m_scene = world;
AttachmentsSyncLock = new Object();
AllowMovement = true;
@ -1072,8 +1044,11 @@ namespace OpenSim.Region.Framework.Scenes
else
m_userFlags = 0;
int userlevel = 0;
if (account != null)
GodController.UserLevel = account.UserLevel;
userlevel = account.UserLevel;
GodController = new GodController(world, this, userlevel);
// IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
// if (gm != null)
@ -1087,7 +1062,7 @@ namespace OpenSim.Region.Framework.Scenes
m_reprioritizationLastDrawDistance = DrawDistance;
// disable updates workjobs for now
childUpdatesBusy = true;
m_childUpdatesBusy = true;
m_reprioritizationBusy = true;
AdjustKnownSeeds();
@ -1289,7 +1264,7 @@ namespace OpenSim.Region.Framework.Scenes
IsLoggingIn = false;
}
IsChildAgent = false;
IsChildAgent = false;
}
m_log.DebugFormat("[MakeRootAgent] out lock: {0}ms", Util.EnvironmentTickCountSubtract(ts));
@ -1299,7 +1274,6 @@ namespace OpenSim.Region.Framework.Scenes
// Should not be needed if we are not trying to tell this region to close
// DoNotCloseAfterTeleport = false;
RegionHandle = m_scene.RegionInfo.RegionHandle;
m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene);
@ -1442,7 +1416,6 @@ namespace OpenSim.Region.Framework.Scenes
}
}
m_log.DebugFormat("[MakeRootAgent] position and physical: {0}ms", Util.EnvironmentTickCountSubtract(ts));
m_scene.SwapRootAgentCount(false);
@ -1777,17 +1750,14 @@ namespace OpenSim.Region.Framework.Scenes
if (m_AngularVelocity.Z > 0)
{
float leftOverToMin = m_AngularVelocity.Z - rollMinRadians;
if (amount > leftOverToMin)
return -leftOverToMin;
else
return -amount;
}
else
{
float leftOverToMin = -m_AngularVelocity.Z - rollMinRadians;
if (amount > leftOverToMin)
return leftOverToMin;
@ -1796,8 +1766,6 @@ namespace OpenSim.Region.Framework.Scenes
}
}
// neighbouring regions we have enabled a child agent in
// holds the seed cap for the child agent in that region
private Dictionary<ulong, string> m_knownChildRegions = new Dictionary<ulong, string>();
@ -1810,7 +1778,6 @@ namespace OpenSim.Region.Framework.Scenes
private Dictionary<ulong, spRegionSizeInfo> m_knownChildRegionsSizeInfo = new Dictionary<ulong, spRegionSizeInfo>();
public void AddNeighbourRegionSizeInfo(GridRegion region)
{
lock (m_knownChildRegions)
@ -1941,7 +1908,6 @@ namespace OpenSim.Region.Framework.Scenes
lock (m_originRegionIDAccessLock)
originID = m_originRegionID;
while (originID.Equals(UUID.Zero) && count-- > 0)
{
lock (m_originRegionIDAccessLock)
@ -2063,13 +2029,11 @@ namespace OpenSim.Region.Framework.Scenes
m_log.DebugFormat("[CompleteMovement]: Missing COF for {0} is {1}", client.AgentId, COF);
}
// Tell the client that we're totally ready
ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look);
m_log.DebugFormat("[CompleteMovement] MoveAgentIntoRegion: {0}ms", Util.EnvironmentTickCountSubtract(ts));
if (!string.IsNullOrEmpty(m_callbackURI))
{
// We cannot sleep here since this would hold up the inbound packet processing thread, as
@ -2098,7 +2062,6 @@ namespace OpenSim.Region.Framework.Scenes
// client.Name, client.AgentId, m_scene.RegionInfo.RegionName);
// }
m_log.DebugFormat("[CompleteMovement] ReleaseAgent: {0}ms", Util.EnvironmentTickCountSubtract(ts));
if(m_teleportFlags > 0)
@ -2118,17 +2081,19 @@ namespace OpenSim.Region.Framework.Scenes
m_log.DebugFormat("[CompleteMovement] HG");
}
if(!IsChildAgent && !isNPC)
// start sending terrain patchs
if (!gotCrossUpdate && !isNPC)
Scene.SendLayerData(ControllingClient);
m_previusParcelHide = false;
m_previusParcelUUID = UUID.Zero;
m_currentParcelHide = false;
m_currentParcelUUID = UUID.Zero;
if(!isNPC)
{
GodController.SyncViewerState();
// start sending terrain patchs
if (!gotCrossUpdate)
Scene.SendLayerData(ControllingClient);
}
// send initial land overlay and parcel
ILandChannel landch = m_scene.LandChannel;
if (landch != null)
@ -2177,7 +2142,6 @@ namespace OpenSim.Region.Framework.Scenes
if (haveAnims)
SendAnimPackToAgent(this, animIDs, animseqs, animsobjs);
// we should be able to receive updates, etc
// so release them
m_inTransit = false;
@ -2192,7 +2156,7 @@ namespace OpenSim.Region.Framework.Scenes
if (p == this)
continue;
if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodController.GodLevel < 200)
if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.isLegacyGod)
continue;
SendAppearanceToAgentNF(p);
@ -2242,7 +2206,7 @@ namespace OpenSim.Region.Framework.Scenes
continue;
}
if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodController.GodLevel < 200)
if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.isLegacyGod)
continue;
SendAttachmentsToAgentNF(p);
@ -2259,10 +2223,13 @@ namespace OpenSim.Region.Framework.Scenes
{
m_agentTransfer.EnableChildAgents(this);
}
// let updates be sent, with some delay
lastChildUpdatesTime = Util.EnvironmentTickCount() + 10000;
childUpdatesBusy = false; // allow them
}
// let updates be sent, with some delay
m_lastChildUpdatesTime = Util.EnvironmentTickCount() + 10000;
m_lastChildAgentUpdateGodLevel = GodController.GodLevel;
m_lastChildAgentUpdateDrawDistance = DrawDistance;
m_lastChildAgentUpdatePosition = AbsolutePosition;
m_childUpdatesBusy = false; // allow them
}
m_log.DebugFormat("[CompleteMovement] openChildAgents: {0}ms", Util.EnvironmentTickCountSubtract(ts));
@ -2292,7 +2259,6 @@ namespace OpenSim.Region.Framework.Scenes
m_log.DebugFormat("[CompleteMovement] friendsModule: {0}ms", Util.EnvironmentTickCountSubtract(ts));
}
}
finally
{
@ -2301,14 +2267,7 @@ namespace OpenSim.Region.Framework.Scenes
crossingFlags = 0;
m_inTransit = false;
}
// if hide force a check
// if (!IsChildAgent && newhide)
// {
// ParcelLoginCheck(m_currentParcelUUID);
// m_currentParcelHide = newhide;
// }
m_scene.EventManager.OnRegionHeartbeatEnd += RegionHeartbeatEnd;
m_log.DebugFormat("[CompleteMovement] end: {0}ms", Util.EnvironmentTickCountSubtract(ts));
@ -3220,7 +3179,6 @@ namespace OpenSim.Region.Framework.Scenes
if (part == null)
return;
if (PhysicsActor != null)
m_sitAvatarHeight = PhysicsActor.Size.Z * 0.5f;
@ -3249,7 +3207,6 @@ namespace OpenSim.Region.Framework.Scenes
if (canSit)
{
if (PhysicsActor != null)
{
// We can remove the physicsActor until they stand up.
@ -3360,7 +3317,6 @@ namespace OpenSim.Region.Framework.Scenes
return false;
}
private bool CanEnterLandPosition(Vector3 testPos)
{
ILandObject land = m_scene.LandChannel.GetLandObject(testPos.X, testPos.Y);
@ -3440,7 +3396,6 @@ namespace OpenSim.Region.Framework.Scenes
ControllingClient.SendSitResponse(
part.ParentGroup.UUID, offset, Orientation, true, cameraAtOffset, cameraEyeOffset, forceMouselook);
SendAvatarDataToAllAgents();
if (status == 3)
@ -3650,8 +3605,6 @@ namespace OpenSim.Region.Framework.Scenes
Animator.avnChangeAnim(animID, addRemove, sendPack);
}
/// <summary>
/// Rotate the avatar to the given rotation and apply a movement in the given relative vector
/// </summary>
@ -3858,7 +3811,7 @@ namespace OpenSim.Region.Framework.Scenes
if (!remoteClient.IsActive)
return;
if (ParcelHideThisAvatar && p.currentParcelUUID != currentParcelUUID && p.GodController.GodLevel < 200)
if (ParcelHideThisAvatar && p.currentParcelUUID != currentParcelUUID && !p.isLegacyGod)
return;
//m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity);
@ -3968,7 +3921,7 @@ namespace OpenSim.Region.Framework.Scenes
// get the avatar, then a kill if can't see it
p.SendInitialAvatarDataToAgent(this);
if (p.ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && GodController.GodLevel < 200)
if (p.ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !isLegacyGod)
return;
p.SendAppearanceToAgentNF(this);
@ -4016,7 +3969,7 @@ namespace OpenSim.Region.Framework.Scenes
foreach (ScenePresence p in presences)
{
p.ControllingClient.SendAvatarDataImmediate(this);
if (p != this && ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodController.GodLevel < 200)
if (p != this && ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.isLegacyGod)
// either just kill the object
// p.ControllingClient.SendKillObject(new List<uint> {LocalId});
// or also attachments viewer may still know about
@ -4029,7 +3982,7 @@ namespace OpenSim.Region.Framework.Scenes
public void SendInitialAvatarDataToAgent(ScenePresence p)
{
p.ControllingClient.SendAvatarDataImmediate(this);
if (p != this && ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodController.GodLevel < 200)
if (p != this && ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.isLegacyGod)
// either just kill the object
// p.ControllingClient.SendKillObject(new List<uint> {LocalId});
// or also attachments viewer may still know about
@ -4043,7 +3996,7 @@ namespace OpenSim.Region.Framework.Scenes
public void SendAvatarDataToAgent(ScenePresence avatar)
{
//m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAgent from {0} ({1}) to {2} ({3})", Name, UUID, avatar.Name, avatar.UUID);
if (ParcelHideThisAvatar && currentParcelUUID != avatar.currentParcelUUID && avatar.GodController.GodLevel < 200)
if (ParcelHideThisAvatar && currentParcelUUID != avatar.currentParcelUUID && !avatar.isLegacyGod)
return;
avatar.ControllingClient.SendAvatarDataImmediate(this);
}
@ -4088,7 +4041,7 @@ namespace OpenSim.Region.Framework.Scenes
{
// m_log.DebugFormat(
// "[SCENE PRESENCE]: Sending appearance data from {0} {1} to {2} {3}", Name, m_uuid, avatar.Name, avatar.UUID);
if (ParcelHideThisAvatar && currentParcelUUID != avatar.currentParcelUUID && avatar.GodController.GodLevel < 200)
if (ParcelHideThisAvatar && currentParcelUUID != avatar.currentParcelUUID && !avatar.isLegacyGod)
return;
SendAppearanceToAgentNF(avatar);
}
@ -4104,7 +4057,7 @@ namespace OpenSim.Region.Framework.Scenes
if (IsChildAgent || Animator == null)
return;
if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodController.GodLevel < 200)
if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.isLegacyGod)
return;
Animator.SendAnimPackToClient(p.ControllingClient);
@ -4115,7 +4068,7 @@ namespace OpenSim.Region.Framework.Scenes
if (IsChildAgent)
return;
if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodController.GodLevel < 200)
if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.isLegacyGod)
return;
p.ControllingClient.SendAnimations(animations, seqs, ControllingClient.AgentId, objectIDs);
@ -4140,7 +4093,7 @@ namespace OpenSim.Region.Framework.Scenes
m_scene.ForEachScenePresence(delegate(ScenePresence p)
{
if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodController.GodLevel < 200)
if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.isLegacyGod)
return;
p.ControllingClient.SendAnimations(animations, seqs, ControllingClient.AgentId, objectIDs);
});
@ -4175,7 +4128,7 @@ namespace OpenSim.Region.Framework.Scenes
if(DrawDistance > minregionSize && m_reprioritizationLastDrawDistance > minregionSize)
byDrawdistance = false;
else
byDrawdistance = (Math.Abs(DrawDistance-m_reprioritizationLastDrawDistance) > 0.5f * limit);
byDrawdistance = (Math.Abs(DrawDistance - m_reprioritizationLastDrawDistance) > 0.5f * limit);
}
int tdiff = Util.EnvironmentTickCountSubtract(m_reprioritizationLastTime);
@ -4224,7 +4177,7 @@ namespace OpenSim.Region.Framework.Scenes
// updates priority recalc
checkRePrioritization();
if(childUpdatesBusy)
if(m_childUpdatesBusy)
return;
//possible KnownRegionHandles always contains current region and this check is not needed
@ -4234,37 +4187,52 @@ namespace OpenSim.Region.Framework.Scenes
if(KnownRegionHandles.Count > minhandles)
{
int tdiff = Util.EnvironmentTickCountSubtract(lastChildUpdatesTime);
if(tdiff > CHILDUPDATES_TIME)
int tdiff = Util.EnvironmentTickCountSubtract(m_lastChildUpdatesTime);
if(tdiff < CHILDUPDATES_TIME)
return;
bool doUpdate = false;
if(m_lastChildAgentUpdateGodLevel != GodController.GodLevel)
doUpdate = true;
if(!doUpdate && Math.Abs(DrawDistance - m_lastChildAgentUpdateDrawDistance) > 32.0f)
doUpdate = true;
if(!doUpdate)
{
diff = pos - m_lastChildAgentUpdatePosition;
if (diff.LengthSquared() > CHILDUPDATES_MOVEMENT)
{
childUpdatesBusy = true;
m_lastChildAgentUpdatePosition = pos;
doUpdate = true;
}
if(doUpdate)
{
m_childUpdatesBusy = true;
m_lastChildAgentUpdatePosition = pos;
m_lastChildAgentUpdateGodLevel = GodController.GodLevel;
m_lastChildAgentUpdateDrawDistance = DrawDistance;
// m_lastChildAgentUpdateCamPosition = CameraPosition;
AgentPosition agentpos = new AgentPosition();
agentpos.AgentID = new UUID(UUID.Guid);
agentpos.SessionID = ControllingClient.SessionId;
agentpos.Size = Appearance.AvatarSize;
agentpos.Center = CameraPosition;
agentpos.Far = DrawDistance;
agentpos.Position = AbsolutePosition;
agentpos.Velocity = Velocity;
agentpos.RegionHandle = RegionHandle;
agentpos.GodData = GodController.State();
agentpos.Throttles = ControllingClient.GetThrottlesPacked(1);
AgentPosition agentpos = new AgentPosition();
agentpos.AgentID = new UUID(UUID.Guid);
agentpos.SessionID = ControllingClient.SessionId;
agentpos.Size = Appearance.AvatarSize;
agentpos.Center = CameraPosition;
agentpos.Far = DrawDistance;
agentpos.Position = AbsolutePosition;
agentpos.Velocity = Velocity;
agentpos.RegionHandle = RegionHandle;
agentpos.GodData = GodController.State();
agentpos.Throttles = ControllingClient.GetThrottlesPacked(1);
// Let's get this out of the update loop
Util.FireAndForget(
o =>
{
m_scene.SendOutChildAgentUpdates(agentpos, this);
lastChildUpdatesTime = Util.EnvironmentTickCount();
childUpdatesBusy = false;
}, null, "ScenePresence.SendOutChildAgentUpdates");
}
// Let's get this out of the update loop
Util.FireAndForget(
o =>
{
m_scene.SendOutChildAgentUpdates(agentpos, this);
m_lastChildUpdatesTime = Util.EnvironmentTickCount();
m_childUpdatesBusy = false;
}, null, "ScenePresence.SendOutChildAgentUpdates");
}
}
}
@ -4505,9 +4473,10 @@ namespace OpenSim.Region.Framework.Scenes
if (isNPC)
return;
bool success = GodController.RequestGodMode(godStatus);
if (success && godStatus)
parcelGodCheck(m_currentParcelUUID, GodController.GodLevel >= 200);
bool wasgod = isLegacyGod;
GodController.RequestGodMode(godStatus);
if (wasgod != isLegacyGod)
parcelGodCheck(m_currentParcelUUID);
}
#region Child Agent Updates
@ -4606,6 +4575,7 @@ namespace OpenSim.Region.Framework.Scenes
cAgent.UpAxis = CameraUpAxis;
cAgent.Far = DrawDistance;
cAgent.GodData = GodController.State();
// Throttles
cAgent.Throttles = ControllingClient.GetThrottlesPacked(1);
@ -4686,7 +4656,6 @@ namespace OpenSim.Region.Framework.Scenes
Quaternion camRot = Util.Axes2Rot(CameraAtAxis, CameraLeftAxis, CameraUpAxis);
CameraRotation = camRot;
ParentUUID = cAgent.ParentPart;
PrevSitOffset = cAgent.SitOffset;
@ -4872,7 +4841,6 @@ namespace OpenSim.Region.Framework.Scenes
ControllingClient.SendAgentAlertMessage("Physics is having a problem with your avatar. You may not be able to move until you relog.", true);
}
/// <summary>
/// Event called by the physics plugin to tell the avatar about a collision.
/// </summary>
@ -4941,7 +4909,7 @@ namespace OpenSim.Region.Framework.Scenes
RaiseCollisionScriptEvents(coldata);
// Gods do not take damage and Invulnerable is set depending on parcel/region flags
if (Invulnerable || GodController.GodLevel > 0)
if (Invulnerable || isLegacyGod)
return;
// The following may be better in the ICombatModule
@ -5226,7 +5194,7 @@ namespace OpenSim.Region.Framework.Scenes
if (p != this && sog.HasPrivateAttachmentPoint)
return;
if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodController.GodLevel < 200)
if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.isLegacyGod)
return;
SendTerseUpdateToAgentNF(p);
@ -5340,7 +5308,7 @@ namespace OpenSim.Region.Framework.Scenes
if (p == this)
continue;
if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodController.GodLevel < 200)
if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.isLegacyGod)
continue;
p.ControllingClient.SendEntityUpdate(rootpart, rootflag);
@ -5392,14 +5360,13 @@ namespace OpenSim.Region.Framework.Scenes
if (sog.HasPrivateAttachmentPoint)
return;
List<ScenePresence> allPresences = m_scene.GetScenePresences();
foreach (ScenePresence p in allPresences)
{
if (p == this)
continue;
if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodController.GodLevel < 200)
if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.isLegacyGod)
continue;
p.ControllingClient.SendEntityUpdate(rootpart, flag);
@ -5449,7 +5416,7 @@ namespace OpenSim.Region.Framework.Scenes
if (p == this)
continue;
if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodController.GodLevel < 200)
if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.isLegacyGod)
continue;
p.ControllingClient.SendEntityUpdate(part, flag);
@ -5490,7 +5457,7 @@ namespace OpenSim.Region.Framework.Scenes
{
if (p == this)
continue;
if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodController.GodLevel < 200)
if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.isLegacyGod)
continue;
p.ControllingClient.SendEntityUpdate(part, flag);
@ -6128,7 +6095,7 @@ namespace OpenSim.Region.Framework.Scenes
// the TP point. This behaviour mimics agni.
if (land.LandData.LandingType == (byte)LandingType.LandingPoint &&
land.LandData.UserLocation != Vector3.Zero &&
GodController.GodLevel < 200 &&
!isLegacyGod &&
((land.LandData.OwnerID != m_uuid &&
!m_scene.Permissions.IsGod(m_uuid) &&
!m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_uuid)) ||
@ -6153,7 +6120,7 @@ namespace OpenSim.Region.Framework.Scenes
string reason;
// dont mess with gods
if(GodController.GodLevel >= 200 || m_scene.Permissions.IsGod(m_uuid))
if(isLegacyGod || m_scene.Permissions.IsGod(m_uuid))
return true;
// respect region owner and managers
@ -6439,7 +6406,7 @@ namespace OpenSim.Region.Framework.Scenes
}
private void parcelGodCheck(UUID currentParcelID, bool isGod)
private void parcelGodCheck(UUID currentParcelID)
{
List<ScenePresence> allpresences = m_scene.GetScenePresences();
@ -6450,7 +6417,7 @@ namespace OpenSim.Region.Framework.Scenes
if (p.ParcelHideThisAvatar && p.currentParcelUUID != currentParcelID)
{
if (isGod)
if (isLegacyGod)
p.SendViewTo(this);
else
p.SendKillTo(this);
@ -6459,7 +6426,7 @@ namespace OpenSim.Region.Framework.Scenes
}
private void ParcelCrossCheck(UUID currentParcelID,UUID previusParcelID,
bool currentParcelHide, bool previusParcelHide, bool oldhide,bool check)
bool currentParcelHide, bool previusParcelHide, bool oldhide, bool check)
{
List<ScenePresence> killsToSendto = new List<ScenePresence>();
List<ScenePresence> killsToSendme = new List<ScenePresence>();
@ -6501,7 +6468,7 @@ namespace OpenSim.Region.Framework.Scenes
continue;
// those not on parcel dont see me
if (currentParcelID != p.currentParcelUUID && p.GodController.GodLevel < 200)
if (currentParcelID != p.currentParcelUUID && !p.isLegacyGod)
{
killsToSendto.Add(p); // they dont see me
}
@ -6527,9 +6494,9 @@ namespace OpenSim.Region.Framework.Scenes
// only those on previus parcel need receive kills
if (previusParcelID == p.currentParcelUUID)
{
if(p.GodController.GodLevel < 200)
if(!p.isLegacyGod)
killsToSendto.Add(p); // they dont see me
if(GodController.GodLevel < 200)
if(!isLegacyGod)
killsToSendme.Add(p); // i dont see them
}
// only those on new parcel need see
@ -6551,7 +6518,7 @@ namespace OpenSim.Region.Framework.Scenes
continue;
// those not on new parcel dont see me
if (currentParcelID != p.currentParcelUUID && p.GodController.GodLevel < 200)
if (currentParcelID != p.currentParcelUUID && !p.isLegacyGod)
{
killsToSendto.Add(p); // they dont see me
}
@ -6577,7 +6544,7 @@ namespace OpenSim.Region.Framework.Scenes
if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
continue;
// only those old parcel need kills
if (previusParcelID == p.currentParcelUUID && GodController.GodLevel < 200)
if (previusParcelID == p.currentParcelUUID && !isLegacyGod)
{
killsToSendme.Add(p); // i dont see them
}
@ -6634,13 +6601,12 @@ namespace OpenSim.Region.Framework.Scenes
public void HasMovedAway(bool nearRegion)
{
if (nearRegion)
{
if (Scene.AttachmentsModule != null)
Scene.AttachmentsModule.DeleteAttachmentsFromScene(this, true);
if (!ParcelHideThisAvatar || GodController.GodLevel >= 200)
if (!ParcelHideThisAvatar || isLegacyGod)
return;
List<ScenePresence> allpresences = m_scene.GetScenePresences();
@ -6657,6 +6623,7 @@ namespace OpenSim.Region.Framework.Scenes
}
else
{
GodController.HasMovedAway();
List<ScenePresence> allpresences = m_scene.GetScenePresences();
foreach (ScenePresence p in allpresences)
{

View File

@ -134,7 +134,7 @@ namespace OpenSim.Region.OptionalModules.ViewerSupport
}
else
{
using (FileStream fs = File.Open(dialogData.XmlName + ".xml", FileMode.Open))
using (FileStream fs = File.Open(dialogData.XmlName + ".xml", FileMode.Open, FileAccess.Read))
{
using (StreamReader sr = new StreamReader(fs))
xml = sr.ReadToEnd().Replace("\n", "");

View File

@ -182,7 +182,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
private ScriptCompileQueue m_CompileQueue = new ScriptCompileQueue();
IWorkItemResult m_CurrentCompile = null;
private Dictionary<UUID, int> m_CompileDict = new Dictionary<UUID, int>();
private Dictionary<UUID, ScriptCompileInfo> m_CompileDict = new Dictionary<UUID, ScriptCompileInfo>();
private ScriptEngineConsoleCommands m_consoleCommands;
@ -236,6 +236,11 @@ namespace OpenSim.Region.ScriptEngine.XEngine
get { return m_ConfigSource; }
}
private class ScriptCompileInfo
{
public List<EventParams> eventList = new List<EventParams>();
}
/// <summary>
/// Event fired after the script engine has finished removing a script.
/// </summary>
@ -1009,7 +1014,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
{
lock (m_CompileDict)
{
m_CompileDict[itemID] = 0;
// m_log.DebugFormat("[XENGINE]: Set compile dict for {0}", itemID);
m_CompileDict[itemID] = new ScriptCompileInfo();
}
DoOnRezScript(parms);
@ -1017,7 +1023,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
else
{
lock (m_CompileDict)
m_CompileDict[itemID] = 0;
m_CompileDict[itemID] = new ScriptCompileInfo();
// m_log.DebugFormat("[XENGINE]: Set compile dict for {0} delayed", itemID);
// This must occur after the m_CompileDict so that an existing compile thread cannot hit the check
// in DoOnRezScript() before m_CompileDict has been updated.
@ -1135,7 +1142,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine
{
if (!m_CompileDict.ContainsKey(itemID))
return false;
m_CompileDict.Remove(itemID);
}
// Get the asset ID of the script, so we can check if we
@ -1150,6 +1156,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
m_log.ErrorFormat("[Script]: SceneObjectPart with localID {0} unavailable. Script NOT started.", localID);
m_ScriptErrorMessage += "SceneObjectPart unavailable. Script NOT started.\n";
m_ScriptFailCount++;
lock (m_CompileDict)
m_CompileDict.Remove(itemID);
return false;
}
@ -1158,6 +1166,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
{
m_ScriptErrorMessage += "Can't find script inventory item.\n";
m_ScriptFailCount++;
lock (m_CompileDict)
m_CompileDict.Remove(itemID);
return false;
}
@ -1275,6 +1285,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
// e.Message.ToString());
// }
lock (m_CompileDict)
m_CompileDict.Remove(itemID);
return false;
}
}
@ -1345,6 +1357,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
{
m_AddingAssemblies[assemblyPath]--;
}
lock (m_CompileDict)
m_CompileDict.Remove(itemID);
return false;
}
}
@ -1402,6 +1416,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
assemblyName.FullName, World.Name),
e2);
lock (m_CompileDict)
m_CompileDict.Remove(itemID);
return false;
}
@ -1451,6 +1467,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
assemblyName.FullName, World.Name),
e2);
lock (m_CompileDict)
m_CompileDict.Remove(itemID);
return false;
}
@ -1478,7 +1496,11 @@ namespace OpenSim.Region.ScriptEngine.XEngine
if(!instance.Load(scriptObj, coopSleepHandle, assemblyPath,
Path.Combine(ScriptEnginePath, World.RegionInfo.RegionID.ToString()), stateSource, coopTerminationForThisScript))
return false;
{
lock (m_CompileDict)
m_CompileDict.Remove(itemID);
return false;
}
// if (DebugLevel >= 1)
// m_log.DebugFormat(
@ -1518,7 +1540,16 @@ namespace OpenSim.Region.ScriptEngine.XEngine
}
if (instance != null)
{
instance.Init();
lock (m_CompileDict)
{
foreach (EventParams pp in m_CompileDict[itemID].eventList)
instance.PostEvent(pp);
}
}
lock (m_CompileDict)
m_CompileDict.Remove(itemID);
bool runIt;
if (m_runFlags.TryGetValue(itemID, out runIt))
@ -1742,6 +1773,17 @@ namespace OpenSim.Region.ScriptEngine.XEngine
instance.PostEvent(p);
result = true;
}
else
{
lock (m_CompileDict)
{
if (m_CompileDict.ContainsKey(itemID))
{
m_CompileDict[itemID].eventList.Add(p);
result = true;
}
}
}
}
}
@ -1763,6 +1805,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
instance.PostEvent(p);
return true;
}
lock (m_CompileDict)
{
if (m_CompileDict.ContainsKey(itemID))
{
m_CompileDict[itemID].eventList.Add(p);
return true;
}
}
return false;
}

View File

@ -947,7 +947,6 @@ namespace OpenSim.Services.UserAccountService
if (item.InvType == (int)InventoryType.Object)
{
uint perms = item.CurrentPermissions;
PermissionsUtil.ApplyFoldedPermissions(item.CurrentPermissions, ref perms);
item.CurrentPermissions = perms;
}

View File

@ -483,10 +483,6 @@
; Allow region managers to assume god powers in regions they manage
;region_manager_is_god = false
; Allow parcel owners to assume god powers in their parcels
; you really do not want this...
;parcel_owner_is_god = false
; God mode should be turned on in the viewer whenever
; the user has god rights somewhere. They may choose
; to turn it off again, though.