From 5e4d6cab00cb29cd088ab7b62ab13aff103b64cb Mon Sep 17 00:00:00 2001 From: onefang Date: Sun, 19 May 2019 21:24:15 +1000 Subject: Dump OpenSim 0.9.0.1 into it's own branch. --- .../CoreModules/World/Land/LandManagementModule.cs | 1333 ++++++++++++-------- 1 file changed, 793 insertions(+), 540 deletions(-) (limited to 'OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs') diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index 92f6c1b..b1f5122 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -41,6 +41,7 @@ using OpenSim.Framework; using OpenSim.Framework.Capabilities; using OpenSim.Framework.Console; using OpenSim.Framework.Servers; +using OpenSim.Framework.Monitoring; using OpenSim.Framework.Servers.HttpServer; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; @@ -52,7 +53,7 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion; namespace OpenSim.Region.CoreModules.World.Land { // used for caching - internal class ExtendedLandData + internal class ExtendedLandData { public LandData LandData; public ulong RegionHandle; @@ -69,9 +70,8 @@ namespace OpenSim.Region.CoreModules.World.Land /// /// Minimum land unit size in region co-ordinates. /// - public const int LandUnit = 4; - private static readonly string remoteParcelRequestPath = "0009/"; + public const int LandUnit = 4; private LandChannel landChannel; private Scene m_scene; @@ -89,20 +89,27 @@ namespace OpenSim.Region.CoreModules.World.Land /// /// Land objects keyed by local id /// - private readonly Dictionary m_landList = new Dictionary(); +// private readonly Dictionary m_landList = new Dictionary(); + + //ubit: removed the readonly so i can move it around + private Dictionary m_landList = new Dictionary(); + private Dictionary m_landUUIDList = new Dictionary(); private int m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1; private bool m_allowedForcefulBans = true; + private bool m_showBansLines = true; + private UUID DefaultGodParcelGroup; + private string DefaultGodParcelName; // caches ExtendedLandData private Cache parcelInfoCache; - /// /// Record positions that avatar's are currently being forced to move to due to parcel entry restrictions. /// - private Dictionary forcedPosition = new Dictionary(); + private HashSet forcedPosition = new HashSet(); + // Enables limiting parcel layer info transmission when doing simple updates private bool shouldLimitParcelLayerInfoToViewDistance { get; set; } @@ -125,6 +132,11 @@ namespace OpenSim.Region.CoreModules.World.Land { shouldLimitParcelLayerInfoToViewDistance = landManagementConfig.GetBoolean("LimitParcelLayerUpdateDistance", shouldLimitParcelLayerInfoToViewDistance); parcelLayerViewDistance = landManagementConfig.GetInt("ParcelLayerViewDistance", parcelLayerViewDistance); + DefaultGodParcelGroup = new UUID(landManagementConfig.GetString("DefaultAdministratorGroupUUID", UUID.Zero.ToString())); + DefaultGodParcelName = landManagementConfig.GetString("DefaultAdministratorParcelName", "Default Parcel"); + bool disablebans = landManagementConfig.GetBoolean("DisableParcelBans", !m_allowedForcefulBans); + m_allowedForcefulBans = !disablebans; + m_showBansLines = landManagementConfig.GetBoolean("ShowParcelBansLines", m_showBansLines); } } @@ -132,17 +144,20 @@ namespace OpenSim.Region.CoreModules.World.Land { m_scene = scene; m_landIDList = new int[m_scene.RegionInfo.RegionSizeX / LandUnit, m_scene.RegionInfo.RegionSizeY / LandUnit]; + landChannel = new LandChannel(scene, this); parcelInfoCache = new Cache(); parcelInfoCache.Size = 30; // the number of different parcel requests in this region to cache parcelInfoCache.DefaultTTL = new TimeSpan(0, 5, 0); + m_scene.EventManager.OnObjectAddedToScene += EventManagerOnParcelPrimCountAdd; m_scene.EventManager.OnParcelPrimCountAdd += EventManagerOnParcelPrimCountAdd; + + m_scene.EventManager.OnObjectBeingRemovedFromScene += EventManagerOnObjectBeingRemovedFromScene; m_scene.EventManager.OnParcelPrimCountUpdate += EventManagerOnParcelPrimCountUpdate; - m_scene.EventManager.OnObjectBeingRemovedFromScene += EventManagerOnObjectBeingRemovedFromScene; m_scene.EventManager.OnRequestParcelPrimCountUpdate += EventManagerOnRequestParcelPrimCountUpdate; - + m_scene.EventManager.OnAvatarEnteringNewParcel += EventManagerOnAvatarEnteringNewParcel; m_scene.EventManager.OnClientMovement += EventManagerOnClientMovement; m_scene.EventManager.OnValidateLandBuy += EventManagerOnValidateLandBuy; @@ -152,14 +167,14 @@ namespace OpenSim.Region.CoreModules.World.Land m_scene.EventManager.OnSignificantClientMovement += EventManagerOnSignificantClientMovement; m_scene.EventManager.OnNoticeNoLandDataFromStorage += EventManagerOnNoLandDataFromStorage; m_scene.EventManager.OnIncomingLandDataFromStorage += EventManagerOnIncomingLandDataFromStorage; - m_scene.EventManager.OnSetAllowForcefulBan += EventManagerOnSetAllowedForcefulBan; + m_scene.EventManager.OnSetAllowForcefulBan += EventManagerOnSetAllowedForcefulBan; m_scene.EventManager.OnRegisterCaps += EventManagerOnRegisterCaps; lock (m_scene) { m_scene.LandChannel = (ILandChannel)landChannel; } - + RegisterCommands(); } @@ -172,8 +187,8 @@ namespace OpenSim.Region.CoreModules.World.Land } public void RemoveRegion(Scene scene) - { - // TODO: Release event manager listeners here + { + // TODO: Release event manager listeners here } // private bool OnVerifyUserConnection(ScenePresence scenePresence, out string reason) @@ -181,7 +196,7 @@ namespace OpenSim.Region.CoreModules.World.Land // ILandObject nearestParcel = m_scene.GetNearestAllowedParcel(scenePresence.UUID, scenePresence.AbsolutePosition.X, scenePresence.AbsolutePosition.Y); // reason = "You are not allowed to enter this sim."; // return nearestParcel != null; -// } +// } void EventManagerOnNewClient(IClientAPI client) { @@ -199,18 +214,10 @@ namespace OpenSim.Region.CoreModules.World.Land client.OnParcelReclaim += ClientOnParcelReclaim; client.OnParcelInfoRequest += ClientOnParcelInfoRequest; client.OnParcelDeedToGroup += ClientOnParcelDeedToGroup; - client.OnPreAgentUpdate += ClientOnPreAgentUpdate; client.OnParcelEjectUser += ClientOnParcelEjectUser; client.OnParcelFreezeUser += ClientOnParcelFreezeUser; client.OnSetStartLocationRequest += ClientOnSetHome; - - - EntityBase presenceEntity; - if (m_scene.Entities.TryGetValue(client.AgentId, out presenceEntity) && presenceEntity is ScenePresence) - { - SendLandUpdate((ScenePresence)presenceEntity, true); - SendParcelOverlay(client); - } + client.OnParcelBuyPass += ClientParcelBuyPass; } public void EventMakeChildAgent(ScenePresence avatar) @@ -218,52 +225,6 @@ namespace OpenSim.Region.CoreModules.World.Land avatar.currentParcelUUID = UUID.Zero; } - void ClientOnPreAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) - { - //If we are forcing a position for them to go - if (forcedPosition.ContainsKey(remoteClient.AgentId)) - { - ScenePresence clientAvatar = m_scene.GetScenePresence(remoteClient.AgentId); - - //Putting the user into flying, both keeps the avatar in fligth when it bumps into something and stopped from going another direction AND - //When the avatar walks into a ban line on the ground, it prevents getting stuck - agentData.ControlFlags = (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY; - - //Make sure we stop if they get about to the right place to prevent yoyo and prevents getting stuck on banlines - if (Vector3.Distance(clientAvatar.AbsolutePosition, forcedPosition[remoteClient.AgentId]) < .2) - { -// m_log.DebugFormat( -// "[LAND MANAGEMENT MODULE]: Stopping force position of {0} because {1} is close enough to {2}", -// clientAvatar.Name, clientAvatar.AbsolutePosition, forcedPosition[remoteClient.AgentId]); - - forcedPosition.Remove(remoteClient.AgentId); - } - //if we are far away, teleport - else if (Vector3.Distance(clientAvatar.AbsolutePosition, forcedPosition[remoteClient.AgentId]) > 3) - { - Vector3 forcePosition = forcedPosition[remoteClient.AgentId]; -// m_log.DebugFormat( -// "[LAND MANAGEMENT MODULE]: Teleporting out {0} because {1} is too far from avatar position {2}", -// clientAvatar.Name, clientAvatar.AbsolutePosition, forcePosition); - - m_scene.RequestTeleportLocation(remoteClient, m_scene.RegionInfo.RegionHandle, - forcePosition, clientAvatar.Lookat, (uint)Constants.TeleportFlags.ForceRedirect); - - forcedPosition.Remove(remoteClient.AgentId); - } - else - { -// m_log.DebugFormat( -// "[LAND MANAGEMENT MODULE]: Forcing {0} from {1} to {2}", -// clientAvatar.Name, clientAvatar.AbsolutePosition, forcedPosition[remoteClient.AgentId]); - - //Forces them toward the forced position we want if they aren't there yet - agentData.UseClientAgentPosition = true; - agentData.ClientAgentPosition = forcedPosition[remoteClient.AgentId]; - } - } - } - public void Close() { } @@ -291,7 +252,10 @@ namespace OpenSim.Region.CoreModules.World.Land lock (m_landList) { if (m_landList.TryGetValue(local_id, out land)) + { land.LandData = newData; + m_landUUIDList[newData.GlobalID] = local_id; + } } if (land != null) @@ -312,28 +276,35 @@ namespace OpenSim.Region.CoreModules.World.Land //Remove all the land objects in the sim and add a blank, full sim land object set to public lock (m_landList) { + foreach(ILandObject parcel in m_landList.Values) + parcel.Clear(); + m_landList.Clear(); + m_landUUIDList.Clear(); m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1; + m_landIDList = new int[m_scene.RegionInfo.RegionSizeX / LandUnit, m_scene.RegionInfo.RegionSizeY / LandUnit]; } } - + /// /// Create a default parcel that spans the entire region and is owned by the estate owner. /// /// The parcel created. protected ILandObject CreateDefaultParcel() { - m_log.DebugFormat( - "[LAND MANAGEMENT MODULE]: Creating default parcel for region {0}", m_scene.RegionInfo.RegionName); - - ILandObject fullSimParcel = new LandObject(UUID.Zero, false, m_scene); + m_log.DebugFormat("{0} Creating default parcel for region {1}", LogHeader, m_scene.RegionInfo.RegionName); + + ILandObject fullSimParcel = new LandObject(UUID.Zero, false, m_scene); + fullSimParcel.SetLandBitmap(fullSimParcel.GetSquareLandBitmap(0, 0, (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY)); - fullSimParcel.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; - fullSimParcel.LandData.ClaimDate = Util.UnixTimeSinceEpoch(); - - return AddLandObject(fullSimParcel); + LandData ldata = fullSimParcel.LandData; + ldata.SimwideArea = ldata.Area; + ldata.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; + ldata.ClaimDate = Util.UnixTimeSinceEpoch(); + + return AddLandObject(fullSimParcel); } public List AllParcels() @@ -347,9 +318,9 @@ namespace OpenSim.Region.CoreModules.World.Land public List ParcelsNearPoint(Vector3 position) { List parcelsNear = new List(); - for (int x = -4; x <= 4; x += 4) + for (int x = -8; x <= 8; x += 4) { - for (int y = -4; y <= 4; y += 4) + for (int y = -8; y <= 8; y += 4) { ILandObject check = GetLandObject(position.X + x, position.Y + y); if (check != null) @@ -365,33 +336,99 @@ namespace OpenSim.Region.CoreModules.World.Land return parcelsNear; } - public void SendYouAreBannedNotice(ScenePresence avatar) + // checks and enforces bans or restrictions + // returns true if enforced + public bool EnforceBans(ILandObject land, ScenePresence avatar) { - if (AllowedForcefulBans) + Vector3 agentpos = avatar.AbsolutePosition; + float h = m_scene.GetGroundHeight(agentpos.X, agentpos.Y) + LandChannel.BAN_LINE_SAFETY_HEIGHT; + float zdif = avatar.AbsolutePosition.Z - h; + if (zdif > 0 ) + { + forcedPosition.Remove(avatar.UUID); + avatar.lastKnownAllowedPosition = agentpos; + return false; + } + + bool ban = false; + string reason = ""; + if (land.IsRestrictedFromLand(avatar.UUID)) { - avatar.ControllingClient.SendAlertMessage( - "You are not allowed on this parcel because you are banned. Please go away."); + reason = "You do not have access to the parcel"; + ban = true; + } + + if (land.IsBannedFromLand(avatar.UUID)) + { + if ( m_allowedForcefulBans) + { + reason ="You are banned from parcel"; + ban = true; + } + else if(!ban) + { + if (forcedPosition.Contains(avatar.UUID)) + avatar.ControllingClient.SendAlertMessage("You are banned from parcel, please leave by your own will"); + forcedPosition.Remove(avatar.UUID); + avatar.lastKnownAllowedPosition = agentpos; + return false; + } + } + + if(ban) + { + if (!forcedPosition.Contains(avatar.UUID)) + avatar.ControllingClient.SendAlertMessage(reason); + + if(zdif > -4f) + { + + agentpos.Z = h + 4.0f; + ForceAvatarToPosition(avatar, agentpos); + return true; + } + + if (land.ContainsPoint((int)avatar.lastKnownAllowedPosition.X, + (int) avatar.lastKnownAllowedPosition.Y)) + { + Vector3? pos = m_scene.GetNearestAllowedPosition(avatar); + if (pos == null) + { + forcedPosition.Remove(avatar.UUID); + m_scene.TeleportClientHome(avatar.UUID, avatar.ControllingClient); + } + else + ForceAvatarToPosition(avatar, (Vector3)pos); + } + else + { + ForceAvatarToPosition(avatar, avatar.lastKnownAllowedPosition); + } + return true; } else { - avatar.ControllingClient.SendAlertMessage( - "You are not allowed on this parcel because you are banned; however, the grid administrator has disabled ban lines globally. Please obey the land owner's requests or you can be banned from the entire sim!"); + forcedPosition.Remove(avatar.UUID); + avatar.lastKnownAllowedPosition = agentpos; + return false; } } private void ForceAvatarToPosition(ScenePresence avatar, Vector3? position) { if (m_scene.Permissions.IsGod(avatar.UUID)) return; - if (position.HasValue) - { - forcedPosition[avatar.ControllingClient.AgentId] = (Vector3)position; - } - } - public void SendYouAreRestrictedNotice(ScenePresence avatar) - { - avatar.ControllingClient.SendAlertMessage( - "You are not allowed on this parcel because the land owner has restricted access."); + if (!position.HasValue) + return; + + if(avatar.MovingToTarget) + avatar.ResetMoveToTarget(); + avatar.AbsolutePosition = position.Value; + avatar.lastKnownAllowedPosition = position.Value; + avatar.Velocity = Vector3.Zero; + if(avatar.IsSatOnObject) + avatar.StandUp(); + forcedPosition.Add(avatar.UUID); } public void EventManagerOnAvatarEnteringNewParcel(ScenePresence avatar, int localLandID, UUID regionID) @@ -404,29 +441,12 @@ namespace OpenSim.Region.CoreModules.World.Land parcelAvatarIsEntering = m_landList[localLandID]; } - if (parcelAvatarIsEntering != null) + if (parcelAvatarIsEntering != null && + avatar.currentParcelUUID != parcelAvatarIsEntering.LandData.GlobalID) { - if (avatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HIEGHT) - { - if (parcelAvatarIsEntering.IsBannedFromLand(avatar.UUID)) - { - SendYouAreBannedNotice(avatar); - ForceAvatarToPosition(avatar, m_scene.GetNearestAllowedPosition(avatar)); - } - else if (parcelAvatarIsEntering.IsRestrictedFromLand(avatar.UUID)) - { - SendYouAreRestrictedNotice(avatar); - ForceAvatarToPosition(avatar, m_scene.GetNearestAllowedPosition(avatar)); - } - else - { - avatar.sentMessageAboutRestrictedParcelFlyingDown = true; - } - } - else - { - avatar.sentMessageAboutRestrictedParcelFlyingDown = true; - } + SendLandUpdate(avatar, parcelAvatarIsEntering); + avatar.currentParcelUUID = parcelAvatarIsEntering.LandData.GlobalID; + EnforceBans(parcelAvatarIsEntering, avatar); } } } @@ -434,7 +454,7 @@ namespace OpenSim.Region.CoreModules.World.Land public void SendOutNearestBanLine(IClientAPI client) { ScenePresence sp = m_scene.GetScenePresence(client.AgentId); - if (sp == null || sp.IsChildAgent) + if (sp == null || sp.IsDeleted) return; List checkLandParcels = ParcelsNearPoint(sp.AbsolutePosition); @@ -454,98 +474,180 @@ namespace OpenSim.Region.CoreModules.World.Land return; } - public void SendLandUpdate(ScenePresence avatar, bool force) + public void sendClientInitialLandInfo(IClientAPI remoteClient) { - ILandObject over = GetLandObject((int)Math.Min(((int)m_scene.RegionInfo.RegionSizeX - 1), Math.Max(0, Math.Round(avatar.AbsolutePosition.X))), - (int)Math.Min(((int)m_scene.RegionInfo.RegionSizeY - 1), Math.Max(0, Math.Round(avatar.AbsolutePosition.Y)))); + ScenePresence avatar; - if (over != null) + if (!m_scene.TryGetScenePresence(remoteClient.AgentId, out avatar)) + return; + + if (!avatar.IsChildAgent) { - if (force) - { - if (!avatar.IsChildAgent) - { - over.SendLandUpdateToClient(avatar.ControllingClient); - m_scene.EventManager.TriggerAvatarEnteringNewParcel(avatar, over.LandData.LocalID, - m_scene.RegionInfo.RegionID); - } - } + ILandObject over = GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); + if (over == null) + return; - if (avatar.currentParcelUUID != over.LandData.GlobalID) - { - if (!avatar.IsChildAgent) - { - over.SendLandUpdateToClient(avatar.ControllingClient); - avatar.currentParcelUUID = over.LandData.GlobalID; - m_scene.EventManager.TriggerAvatarEnteringNewParcel(avatar, over.LandData.LocalID, - m_scene.RegionInfo.RegionID); - } - } + avatar.currentParcelUUID = over.LandData.GlobalID; + over.SendLandUpdateToClient(avatar.ControllingClient); } + SendParcelOverlay(remoteClient); } - public void SendLandUpdate(ScenePresence avatar) + public void SendLandUpdate(ScenePresence avatar, ILandObject over) { - SendLandUpdate(avatar, false); - } + if (avatar.IsChildAgent) + return; - public void EventManagerOnSignificantClientMovement(ScenePresence clientAvatar) - { - SendLandUpdate(clientAvatar); - SendOutNearestBanLine(clientAvatar.ControllingClient); - ILandObject parcel = GetLandObject(clientAvatar.AbsolutePosition.X, clientAvatar.AbsolutePosition.Y); - if (parcel != null) + if (over != null) { - if (clientAvatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HIEGHT && - clientAvatar.sentMessageAboutRestrictedParcelFlyingDown) - { - EventManagerOnAvatarEnteringNewParcel(clientAvatar, parcel.LandData.LocalID, - m_scene.RegionInfo.RegionID); - //They are going under the safety line! - if (!parcel.IsBannedFromLand(clientAvatar.UUID)) - { - clientAvatar.sentMessageAboutRestrictedParcelFlyingDown = false; - } - } - else if (clientAvatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HIEGHT && - parcel.IsBannedFromLand(clientAvatar.UUID)) - { - //once we've sent the message once, keep going toward the target until we are done - if (forcedPosition.ContainsKey(clientAvatar.ControllingClient.AgentId)) - { - SendYouAreBannedNotice(clientAvatar); - ForceAvatarToPosition(clientAvatar, m_scene.GetNearestAllowedPosition(clientAvatar)); - } - } - else if (parcel.IsRestrictedFromLand(clientAvatar.UUID)) - { - //once we've sent the message once, keep going toward the target until we are done - if (forcedPosition.ContainsKey(clientAvatar.ControllingClient.AgentId)) - { - SendYouAreRestrictedNotice(clientAvatar); - ForceAvatarToPosition(clientAvatar, m_scene.GetNearestAllowedPosition(clientAvatar)); - } - } - else - { - //when we are finally in a safe place, lets release the forced position lock - forcedPosition.Remove(clientAvatar.ControllingClient.AgentId); - } + over.SendLandUpdateToClient(avatar.ControllingClient); +// sl doesnt seem to send this now, as it used 2 +// SendParcelOverlay(avatar.ControllingClient); } } + public void EventManagerOnSignificantClientMovement(ScenePresence avatar) + { + if (avatar.IsChildAgent) + return; + + if ( m_allowedForcefulBans && m_showBansLines) + SendOutNearestBanLine(avatar.ControllingClient); + } + /// /// Like handleEventManagerOnSignificantClientMovement, but called with an AgentUpdate regardless of distance. /// /// public void EventManagerOnClientMovement(ScenePresence avatar) { + if (avatar.IsChildAgent) + return; + Vector3 pos = avatar.AbsolutePosition; ILandObject over = GetLandObject(pos.X, pos.Y); if (over != null) { - if (!over.IsRestrictedFromLand(avatar.UUID) && (!over.IsBannedFromLand(avatar.UUID) || pos.Z >= LandChannel.BAN_LINE_SAFETY_HIEGHT)) - avatar.lastKnownAllowedPosition = pos; + EnforceBans(over, avatar); + pos = avatar.AbsolutePosition; + ILandObject newover = GetLandObject(pos.X, pos.Y); + if(over != newover || avatar.currentParcelUUID != newover.LandData.GlobalID) + { + m_scene.EventManager.TriggerAvatarEnteringNewParcel(avatar, + newover.LandData.LocalID, m_scene.RegionInfo.RegionID); + } + } + } + + public void ClientParcelBuyPass(IClientAPI remote_client, UUID targetID, int landLocalID) + { + ILandObject land; + lock (m_landList) + { + m_landList.TryGetValue(landLocalID, out land); + } + // trivial checks + if(land == null) + return; + + LandData ldata = land.LandData; + + if(ldata == null) + return; + + if(ldata.OwnerID == targetID) + return; + + if(ldata.PassHours == 0) + return; + + // don't allow passes on group owned until we can give money to groups + if(ldata.IsGroupOwned) + { + remote_client.SendAgentAlertMessage("pass to group owned parcel not suported", false); + return; + } + + if((ldata.Flags & (uint)ParcelFlags.UsePassList) == 0) + return; + + int cost = ldata.PassPrice; + + int idx = land.LandData.ParcelAccessList.FindIndex( + delegate(LandAccessEntry e) + { + if (e.AgentID == targetID && e.Flags == AccessList.Access) + return true; + return false; + }); + int now = Util.UnixTimeSinceEpoch(); + int expires = (int)(3600.0 * ldata.PassHours + 0.5f); + int currenttime = -1; + if (idx != -1) + { + if(ldata.ParcelAccessList[idx].Expires == 0) + { + remote_client.SendAgentAlertMessage("You already have access to parcel", false); + return; + } + + currenttime = ldata.ParcelAccessList[idx].Expires - now; + if(currenttime > (int)(0.25f * expires + 0.5f)) + { + if(currenttime > 3600) + remote_client.SendAgentAlertMessage(string.Format("You already have a pass valid for {0:0.###} hours", + currenttime/3600f), false); + else if(currenttime > 60) + remote_client.SendAgentAlertMessage(string.Format("You already have a pass valid for {0:0.##} minutes", + currenttime/60f), false); + else + remote_client.SendAgentAlertMessage(string.Format("You already have a pass valid for {0:0.#} seconds", + currenttime), false); + return; + } + } + + LandAccessEntry entry = new LandAccessEntry(); + entry.AgentID = targetID; + entry.Flags = AccessList.Access; + entry.Expires = now + expires; + if(currenttime > 0) + entry.Expires += currenttime; + IMoneyModule mm = m_scene.RequestModuleInterface(); + if(cost != 0 && mm != null) + { + WorkManager.RunInThreadPool( + delegate + { + string regionName = m_scene.RegionInfo.RegionName; + + if (!mm.AmountCovered(remote_client.AgentId, cost)) + { + remote_client.SendAgentAlertMessage(String.Format("Insufficient funds in region '{0}' money system", regionName), true); + return; + } + + string payDescription = String.Format("Parcel '{0}' at region '{1} {2:0.###} hours access pass", ldata.Name, regionName, ldata.PassHours); + + if(!mm.MoveMoney(remote_client.AgentId, ldata.OwnerID, cost,MoneyTransactionType.LandPassSale, payDescription)) + { + remote_client.SendAgentAlertMessage("Sorry pass payment processing failed, please try again later", true); + return; + } + + if (idx != -1) + ldata.ParcelAccessList.RemoveAt(idx); + ldata.ParcelAccessList.Add(entry); + m_scene.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land); + return; + }, null, "ParcelBuyPass"); + } + else + { + if (idx != -1) + ldata.ParcelAccessList.RemoveAt(idx); + ldata.ParcelAccessList.Add(entry); + m_scene.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land); } } @@ -589,7 +691,7 @@ namespace OpenSim.Region.CoreModules.World.Land requiredPowers = GroupPowers.LandManageBanned; if (m_scene.Permissions.CanEditParcelProperties(agentID, - land, requiredPowers)) + land, requiredPowers, false)) { land.UpdateAccessList(flags, transactionID, sequenceID, sections, entries, remote_client); @@ -605,13 +707,11 @@ namespace OpenSim.Region.CoreModules.World.Land /// Adds a land object to the stored list and adds them to the landIDList to what they own /// /// - /// The land object being added. + /// The land object being added. /// Will return null if this overlaps with an existing parcel that has not had its bitmap adjusted. /// - public ILandObject AddLandObject(ILandObject land) + public ILandObject AddLandObject(ILandObject new_land) { - ILandObject new_land = land.Copy(); - // Only now can we add the prim counts to the land object - we rely on the global ID which is generated // as a random UUID inside LandData initialization if (m_primCountModule != null) @@ -623,18 +723,15 @@ namespace OpenSim.Region.CoreModules.World.Land new_land.LandData.LocalID = newLandLocalID; bool[,] landBitmap = new_land.GetLandBitmap(); - // m_log.DebugFormat("{0} AddLandObject. new_land.bitmapSize=({1},{2}). newLocalID={3}", - // LogHeader, landBitmap.GetLength(0), landBitmap.GetLength(1), newLandLocalID); - if (landBitmap.GetLength(0) != m_landIDList.GetLength(0) || landBitmap.GetLength(1) != m_landIDList.GetLength(1)) { // Going to variable sized regions can cause mismatches m_log.ErrorFormat("{0} AddLandObject. Added land bitmap different size than region ID map. bitmapSize=({1},{2}), landIDSize=({3},{4})", - LogHeader, landBitmap.GetLength(0), landBitmap.GetLength(1), m_landIDList.GetLength(0), m_landIDList.GetLength(1) ); + LogHeader, landBitmap.GetLength(0), landBitmap.GetLength(1), m_landIDList.GetLength(0), m_landIDList.GetLength(1)); } else { - // If other land objects still believe that they occupy any parts of the same space, + // If other land objects still believe that they occupy any parts of the same space, // then do not allow the add to proceed. for (int x = 0; x < landBitmap.GetLength(0); x++) { @@ -652,7 +749,7 @@ namespace OpenSim.Region.CoreModules.World.Land { m_log.ErrorFormat( "{0}: Cannot add parcel \"{1}\", local ID {2} at tile {3},{4} because this is still occupied by parcel \"{5}\", local ID {6} in {7}", - LogHeader, new_land.LandData.Name, new_land.LandData.LocalID, x, y, + LogHeader, new_land.LandData.Name, new_land.LandData.LocalID, x, y, lastRecordedLo.LandData.Name, lastRecordedLo.LandData.LocalID, m_scene.Name); return null; @@ -668,10 +765,10 @@ namespace OpenSim.Region.CoreModules.World.Land { if (landBitmap[x, y]) { - // m_log.DebugFormat( - // "[LAND MANAGEMENT MODULE]: Registering parcel {0} for land co-ord ({1}, {2}) on {3}", - // new_land.LandData.Name, x, y, m_scene.RegionInfo.RegionName); - + // m_log.DebugFormat( + // "[LAND MANAGEMENT MODULE]: Registering parcel {0} for land co-ord ({1}, {2}) on {3}", + // new_land.LandData.Name, x, y, m_scene.RegionInfo.RegionName); + m_landIDList[x, y] = newLandLocalID; } } @@ -679,6 +776,7 @@ namespace OpenSim.Region.CoreModules.World.Land } m_landList.Add(newLandLocalID, new_land); + m_landUUIDList[new_land.LandData.GlobalID] = newLandLocalID; m_lastLandLocalID++; } @@ -695,6 +793,7 @@ namespace OpenSim.Region.CoreModules.World.Land public void removeLandObject(int local_id) { ILandObject land; + UUID landGlobalID = UUID.Zero; lock (m_landList) { for (int x = 0; x < m_landIDList.GetLength(0); x++) @@ -713,37 +812,47 @@ namespace OpenSim.Region.CoreModules.World.Land land = m_landList[local_id]; m_landList.Remove(local_id); + if(land != null && land.LandData != null) + { + landGlobalID = land.LandData.GlobalID; + m_landUUIDList.Remove(landGlobalID); + } } - m_scene.EventManager.TriggerLandObjectRemoved(land.LandData.GlobalID); + if(landGlobalID != UUID.Zero) + { + m_scene.EventManager.TriggerLandObjectRemoved(landGlobalID); + land.Clear(); + } } - + /// /// Clear the scene of all parcels - /// + /// public void Clear(bool setupDefaultParcel) { - List parcels; + Dictionary landworkList; + // move to work pointer since we are deleting it all lock (m_landList) { - parcels = new List(m_landList.Values); + landworkList = m_landList; + m_landList = new Dictionary(); } - foreach (ILandObject lo in parcels) + // this 2 methods have locks (now) + ResetSimLandObjects(); + + if (setupDefaultParcel) + CreateDefaultParcel(); + + // fire outside events unlocked + foreach (ILandObject lo in landworkList.Values) { //m_scene.SimulationDataService.RemoveLandObject(lo.LandData.GlobalID); m_scene.EventManager.TriggerLandObjectRemoved(lo.LandData.GlobalID); } + landworkList.Clear(); - lock (m_landList) - { - m_landList.Clear(); - - ResetSimLandObjects(); - } - - if (setupDefaultParcel) - CreateDefaultParcel(); } private void performFinalLandJoin(ILandObject master, ILandObject slave) @@ -762,11 +871,29 @@ namespace OpenSim.Region.CoreModules.World.Land } } } - + master.LandData.Dwell += slave.LandData.Dwell; removeLandObject(slave.LandData.LocalID); UpdateLandObject(master.LandData.LocalID, master.LandData); } + public ILandObject GetLandObject(UUID globalID) + { + lock (m_landList) + { + int lid = -1; + if(m_landUUIDList.TryGetValue(globalID, out lid) && lid >= 0) + { + if (m_landList.ContainsKey(lid)) + { + return m_landList[lid]; + } + else + m_landUUIDList.Remove(globalID); // auto heal + } + } + return null; + } + public ILandObject GetLandObject(int parcelLocalID) { lock (m_landList) @@ -787,58 +914,37 @@ namespace OpenSim.Region.CoreModules.World.Land /// Land object at the point supplied public ILandObject GetLandObject(float x_float, float y_float) { - return GetLandObject((int)x_float, (int)y_float, true /* returnNullIfLandObjectNotFound */); - /* - int x; - int y; - - if (x_float >= m_scene.RegionInfo.RegionSizeX || x_float < 0 || y_float >= m_scene.RegionInfo.RegionSizeX || y_float < 0) - return null; + return GetLandObject((int)x_float, (int)y_float, true); + } - try - { - x = Convert.ToInt32(Math.Floor(Convert.ToDouble(x_float) / (float)landUnit)); - y = Convert.ToInt32(Math.Floor(Convert.ToDouble(y_float) / (float)landUnit)); - } - catch (OverflowException) - { - return null; - } + // if x,y is off region this will return the parcel at cliped x,y + // as did code it replaces + public ILandObject GetLandObjectClipedXY(float x, float y) + { + //do clip inline + int avx = (int)x; + if (avx < 0) + avx = 0; + else if (avx >= m_scene.RegionInfo.RegionSizeX) + avx = (int)Constants.RegionSize - 1; - if (x >= (m_scene.RegionInfo.RegionSizeX / landUnit) - || y >= (m_scene.RegionInfo.RegionSizeY / landUnit) - || x < 0 - || y < 0) - { - return null; - } + int avy = (int)y; + if (avy < 0) + avy = 0; + else if (avy >= m_scene.RegionInfo.RegionSizeY) + avy = (int)Constants.RegionSize - 1; - lock (m_landList) + lock (m_landIDList) { - // Corner case. If an autoreturn happens during sim startup - // we will come here with the list uninitialized - // -// int landId = m_landIDList[x, y]; - -// if (landId == 0) -// m_log.DebugFormat( -// "[LAND MANAGEMENT MODULE]: No land object found at ({0}, {1}) on {2}", -// x, y, m_scene.RegionInfo.RegionName); - try { - if (m_landList.ContainsKey(m_landIDList[x, y])) - return m_landList[m_landIDList[x, y]]; + return m_landList[m_landIDList[avx / LandUnit, avy / LandUnit]]; } - catch (Exception e) + catch (IndexOutOfRangeException) { - m_log.DebugFormat("{0} GetLandObject exception. x={1}, y={2}, m_landIDList.len=({3},{4})", - LogHeader, x, y, m_landIDList.GetLength(0), m_landIDList.GetLength(1)); + return null; } - - return null; } - */ } // Public entry. @@ -848,33 +954,32 @@ namespace OpenSim.Region.CoreModules.World.Land return GetLandObject(x, y, false /* returnNullIfLandObjectNotFound */); } - /// - /// Given a region position, return the parcel land object for that location - /// - /// - /// The land object. - /// - /// - /// - /// - /// Return null if the land object requested is not within the region's bounds. - /// - private ILandObject GetLandObject(int x, int y, bool returnNullIfLandObjectOutsideBounds) + public ILandObject GetLandObject(int x, int y, bool returnNullIfLandObjectOutsideBounds) { - if (x >= m_scene.RegionInfo.RegionSizeX || y >= m_scene.RegionInfo.RegionSizeY || x < 0 || y < 0) + if (x >= m_scene.RegionInfo.RegionSizeX || y >= m_scene.RegionInfo.RegionSizeY || x < 0 || y < 0) { // These exceptions here will cause a lot of complaints from the users specifically because // they happen every time at border crossings if (returnNullIfLandObjectOutsideBounds) return null; else - throw new Exception( - String.Format("{0} GetLandObject for non-existent position. Region={1}, pos=<{2},{3}", - LogHeader, m_scene.RegionInfo.RegionName, x, y) - ); + throw new Exception("Error: Parcel not found at point " + x + ", " + y); } - return m_landList[m_landIDList[x / 4, y / 4]]; + if(m_landList.Count == 0 || m_landIDList == null) + return null; + + lock (m_landIDList) + { + try + { + return m_landList[m_landIDList[x / 4, y / 4]]; + } + catch (IndexOutOfRangeException) + { + return null; + } + } } // Create a 'parcel is here' bitmap for the parcel identified by the passed landID @@ -926,7 +1031,7 @@ namespace OpenSim.Region.CoreModules.World.Land } } - public void FinalizeLandPrimCountUpdate() + private void FinalizeLandPrimCountUpdate() { //Get Simwide prim count for owner Dictionary> landOwnersAndParcels = new Dictionary>(); @@ -967,10 +1072,10 @@ namespace OpenSim.Region.CoreModules.World.Land public void EventManagerOnParcelPrimCountUpdate() { -// m_log.DebugFormat( -// "[LAND MANAGEMENT MODULE]: Triggered EventManagerOnParcelPrimCountUpdate() for {0}", -// m_scene.RegionInfo.RegionName); - + //m_log.DebugFormat( + // "[land management module]: triggered eventmanageronparcelprimcountupdate() for {0}", + // m_scene.RegionInfo.RegionName); + ResetOverMeRecords(); EntityBase[] entities = m_scene.Entities.GetEntities(); foreach (EntityBase obj in entities) @@ -1002,27 +1107,33 @@ namespace OpenSim.Region.CoreModules.World.Land /// North Point /// UUID of user who is trying to subdivide /// Returns true if successful - private void subdivide(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id) + public void Subdivide(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id) { //First, lets loop through the points and make sure they are all in the same peice of land //Get the land object at start ILandObject startLandObject = GetLandObject(start_x, start_y); - if (startLandObject == null) return; + if (startLandObject == null) + return; + + if (!m_scene.Permissions.CanEditParcelProperties(attempting_user_id, startLandObject, GroupPowers.LandDivideJoin, true)) + { + return; + } //Loop through the points try { - int totalX = end_x - start_x; - int totalY = end_y - start_y; - for (int y = 0; y < totalY; y++) + for (int y = start_y; y < end_y; y++) { - for (int x = 0; x < totalX; x++) + for (int x = start_x; x < end_x; x++) { - ILandObject tempLandObject = GetLandObject(start_x + x, start_y + y); - if (tempLandObject == null) return; - if (tempLandObject != startLandObject) return; + ILandObject tempLandObject = GetLandObject(x, y); + if (tempLandObject == null) + return; + if (tempLandObject != startLandObject) + return; } } } @@ -1031,22 +1142,22 @@ namespace OpenSim.Region.CoreModules.World.Land return; } - //If we are still here, then they are subdividing within one piece of land - //Check owner - if (!m_scene.Permissions.CanEditParcelProperties(attempting_user_id, startLandObject, GroupPowers.LandDivideJoin)) - { - return; - } - - //Lets create a new land object with bitmap activated at that point (keeping the old land objects info) + //Lets create a new land object with bitmap activated at that point (keeping the old land objects info) ILandObject newLand = startLandObject.Copy(); + newLand.LandData.Name = newLand.LandData.Name; newLand.LandData.GlobalID = UUID.Random(); newLand.LandData.Dwell = 0; + // Clear "Show in search" on the cut out parcel to prevent double-charging + newLand.LandData.Flags &= ~(uint)ParcelFlags.ShowDirectory; + // invalidate landing point + newLand.LandData.LandingType = (byte)LandingType.Direct; + newLand.LandData.UserLocation = Vector3.Zero; + newLand.LandData.UserLookAt = Vector3.Zero; newLand.SetLandBitmap(newLand.GetSquareLandBitmap(start_x, start_y, end_x, end_y)); - //Now, lets set the subdivision area of the original to false + //lets set the subdivision area of the original to false int startLandObjectIndex = startLandObject.LandData.LocalID; lock (m_landList) { @@ -1055,65 +1166,85 @@ namespace OpenSim.Region.CoreModules.World.Land m_landList[startLandObjectIndex].ForceUpdateLandInfo(); } - //Now add the new land object + //add the new land object ILandObject result = AddLandObject(newLand); - if (result != null) + UpdateLandObject(startLandObject.LandData.LocalID, startLandObject.LandData); + + if(startLandObject.LandData.LandingType == (byte)LandingType.LandingPoint) { - UpdateLandObject(startLandObject.LandData.LocalID, startLandObject.LandData); - result.SendLandUpdateToAvatarsOverMe(); - } + int x = (int)startLandObject.LandData.UserLocation.X; + int y = (int)startLandObject.LandData.UserLocation.Y; + if(!startLandObject.ContainsPoint(x, y)) + { + startLandObject.LandData.LandingType = (byte)LandingType.Direct; + startLandObject.LandData.UserLocation = Vector3.Zero; + startLandObject.LandData.UserLookAt = Vector3.Zero; + } + } + + m_scene.EventManager.TriggerParcelPrimCountTainted(); + + result.SendLandUpdateToAvatarsOverMe(); + startLandObject.SendLandUpdateToAvatarsOverMe(); + m_scene.ForEachClient(SendParcelOverlay); + } /// /// Join 2 land objects together /// - /// x value in first piece of land - /// y value in first piece of land - /// x value in second peice of land - /// y value in second peice of land + /// start x of selection area + /// start y of selection area + /// end x of selection area + /// end y of selection area /// UUID of the avatar trying to join the land objects /// Returns true if successful - private void join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id) + public void Join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id) { - end_x -= 4; - end_y -= 4; + int index = 0; + int maxindex = -1; + int maxArea = 0; List selectedLandObjects = new List(); - int stepYSelected; - for (stepYSelected = start_y; stepYSelected <= end_y; stepYSelected += 4) + for (int x = start_x; x < end_x; x += 4) { - int stepXSelected; - for (stepXSelected = start_x; stepXSelected <= end_x; stepXSelected += 4) + for (int y = start_y; y < end_y; y += 4) { - ILandObject p = GetLandObject(stepXSelected, stepYSelected); + ILandObject p = GetLandObject(x, y); if (p != null) { if (!selectedLandObjects.Contains(p)) { selectedLandObjects.Add(p); + if(p.LandData.Area > maxArea) + { + maxArea = p.LandData.Area; + maxindex = index; + } + index++; } } } } - ILandObject masterLandObject = selectedLandObjects[0]; - selectedLandObjects.RemoveAt(0); - if (selectedLandObjects.Count < 1) - { + if(maxindex < 0 || selectedLandObjects.Count < 2) return; - } - if (!m_scene.Permissions.CanEditParcelProperties(attempting_user_id, masterLandObject, GroupPowers.LandDivideJoin)) + + ILandObject masterLandObject = selectedLandObjects[maxindex]; + selectedLandObjects.RemoveAt(maxindex); + + if (!m_scene.Permissions.CanEditParcelProperties(attempting_user_id, masterLandObject, GroupPowers.LandDivideJoin, true)) { return; } + + UUID masterOwner = masterLandObject.LandData.OwnerID; foreach (ILandObject p in selectedLandObjects) { - if (p.LandData.OwnerID != masterLandObject.LandData.OwnerID) - { + if (p.LandData.OwnerID != masterOwner) return; - } } lock (m_landList) @@ -1126,29 +1257,14 @@ namespace OpenSim.Region.CoreModules.World.Land } } + m_scene.EventManager.TriggerParcelPrimCountTainted(); masterLandObject.SendLandUpdateToAvatarsOverMe(); + m_scene.ForEachClient(SendParcelOverlay); } - - public void Join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id) - { - join(start_x, start_y, end_x, end_y, attempting_user_id); - } - - public void Subdivide(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id) - { - subdivide(start_x, start_y, end_x, end_y, attempting_user_id); - } - #endregion #region Parcel Updating - // Send parcel layer info for the whole region - public void SendParcelOverlay(IClientAPI remote_client) - { - SendParcelOverlay(remote_client, 0, 0, (int)Constants.MaximumRegionSize); - } - /// /// Send the parcel overlay blocks to the client. We send the overlay packets /// around a location and limited by the 'parcelLayerViewDistance'. This number @@ -1162,145 +1278,115 @@ namespace OpenSim.Region.CoreModules.World.Land /// X position in the region to send surrounding parcel layer info /// y position in the region to send surrounding parcel layer info /// Distance from x,y position to send parcel layer info - private void SendParcelOverlay(IClientAPI remote_client, int xPlace, int yPlace, int layerViewDistance) + public void SendParcelOverlay(IClientAPI remote_client) { + if (remote_client.SceneAgent.PresenceType == PresenceType.Npc) + return; + const int LAND_BLOCKS_PER_PACKET = 1024; byte[] byteArray = new byte[LAND_BLOCKS_PER_PACKET]; int byteArrayCount = 0; int sequenceID = 0; - int xLow = 0; - int xHigh = (int)m_scene.RegionInfo.RegionSizeX; - int yLow = 0; - int yHigh = (int)m_scene.RegionInfo.RegionSizeY; - - if (shouldLimitParcelLayerInfoToViewDistance) + // Layer data is in LandUnit (4m) chunks + for (int y = 0; y < m_scene.RegionInfo.RegionSizeY; y += LandUnit) { - // Compute view distance around the given point - int txLow = xPlace - layerViewDistance; - int txHigh = xPlace + layerViewDistance; - // If the distance is outside the region area, move the view distance to ba all in the region - if (txLow < xLow) + for (int x = 0; x < m_scene.RegionInfo.RegionSizeX; x += LandUnit) { - txLow = xLow; - txHigh = Math.Min(yLow + (layerViewDistance * 2), xHigh); - } - if (txHigh > xHigh) - { - txLow = Math.Max(xLow, xHigh - (layerViewDistance * 2)); - txHigh = xHigh; - } - xLow = txLow; - xHigh = txHigh; + byte tempByte = 0; //This represents the byte for the current 4x4 - int tyLow = yPlace - layerViewDistance; - int tyHigh = yPlace + layerViewDistance; - if (tyLow < yLow) - { - tyLow = yLow; - tyHigh = Math.Min(yLow + (layerViewDistance * 2), yHigh); - } - if (tyHigh > yHigh) - { - tyLow = Math.Max(yLow, yHigh - (layerViewDistance * 2)); - tyHigh = yHigh; - } - yLow = tyLow; - yHigh = tyHigh; - } - // m_log.DebugFormat("{0} SendParcelOverlay: place=<{1},{2}>, vDist={3}, xLH=<{4},{5}, yLH=<{6},{7}>", - // LogHeader, xPlace, yPlace, layerViewDistance, xLow, xHigh, yLow, yHigh); + ILandObject currentParcelBlock = GetLandObject(x, y); - // Layer data is in landUnit (4m) chunks - for (int y = yLow; y < yHigh / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); y++) - { - for (int x = xLow; x < xHigh / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); x++) - { - byteArray[byteArrayCount] = BuildLayerByte(GetLandObject(x * LandUnit, y * LandUnit), x, y, remote_client); - byteArrayCount++; - if (byteArrayCount >= LAND_BLOCKS_PER_PACKET) + if (currentParcelBlock != null) { - // m_log.DebugFormat("{0} SendParcelOverlay, sending packet, bytes={1}", LogHeader, byteArray.Length); - remote_client.SendLandParcelOverlay(byteArray, sequenceID); - byteArrayCount = 0; - sequenceID++; - byteArray = new byte[LAND_BLOCKS_PER_PACKET]; - } + // types + if (currentParcelBlock.LandData.OwnerID == remote_client.AgentId) + { + //Owner Flag + tempByte = (byte)LandChannel.LAND_TYPE_OWNED_BY_REQUESTER; + } + else if (currentParcelBlock.LandData.IsGroupOwned && remote_client.IsGroupMember(currentParcelBlock.LandData.GroupID)) + { + tempByte = (byte)LandChannel.LAND_TYPE_OWNED_BY_GROUP; + } + else if (currentParcelBlock.LandData.SalePrice > 0 && + (currentParcelBlock.LandData.AuthBuyerID == UUID.Zero || + currentParcelBlock.LandData.AuthBuyerID == remote_client.AgentId)) + { + //Sale type + tempByte = (byte)LandChannel.LAND_TYPE_IS_FOR_SALE; + } + else if (currentParcelBlock.LandData.OwnerID == UUID.Zero) + { + //Public type + tempByte = (byte)LandChannel.LAND_TYPE_PUBLIC; // this does nothing, its zero + } + // LAND_TYPE_IS_BEING_AUCTIONED still unsuported + else + { + //Other Flag + tempByte = (byte)LandChannel.LAND_TYPE_OWNED_BY_OTHER; + } - } - } + // now flags + // border control - if (byteArrayCount != 0) - { - remote_client.SendLandParcelOverlay(byteArray, sequenceID); - // m_log.DebugFormat("{0} SendParcelOverlay, complete sending packet, bytes={1}", LogHeader, byteArray.Length); - } - } + ILandObject westParcel = null; + ILandObject southParcel = null; + if (x > 0) + { + westParcel = GetLandObject((x - 1), y); + } + if (y > 0) + { + southParcel = GetLandObject(x, (y - 1)); + } - private byte BuildLayerByte(ILandObject currentParcelBlock, int x, int y, IClientAPI remote_client) - { - byte tempByte = 0; //This represents the byte for the current 4x4 + if (x == 0) + { + tempByte |= (byte)LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST; + } + else if (westParcel != null && westParcel != currentParcelBlock) + { + tempByte |= (byte)LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST; + } - if (currentParcelBlock != null) - { - if (currentParcelBlock.LandData.OwnerID == remote_client.AgentId) - { - //Owner Flag - tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_REQUESTER); - } - else if (currentParcelBlock.LandData.SalePrice > 0 && - (currentParcelBlock.LandData.AuthBuyerID == UUID.Zero || - currentParcelBlock.LandData.AuthBuyerID == remote_client.AgentId)) - { - //Sale Flag - tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_IS_FOR_SALE); - } - else if (currentParcelBlock.LandData.OwnerID == UUID.Zero) - { - //Public Flag - tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_PUBLIC); - } - else - { - //Other Flag - tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_OTHER); - } + if (y == 0) + { + tempByte |= (byte)LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH; + } + else if (southParcel != null && southParcel != currentParcelBlock) + { + tempByte |= (byte)LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH; + } - //Now for border control + // local sound + if ((currentParcelBlock.LandData.Flags & (uint)ParcelFlags.SoundLocal) != 0) + tempByte |= (byte)LandChannel.LAND_FLAG_LOCALSOUND; - ILandObject westParcel = null; - ILandObject southParcel = null; - if (x > 0) - { - westParcel = GetLandObject((x - 1) * LandUnit, y * LandUnit); - } - if (y > 0) - { - southParcel = GetLandObject(x * LandUnit, (y - 1) * LandUnit); - } + // hide avatars + if (!currentParcelBlock.LandData.SeeAVs) + tempByte |= (byte)LandChannel.LAND_FLAG_HIDEAVATARS; - if (x == 0) - { - tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST); - } - else if (westParcel != null && westParcel != currentParcelBlock) - { - tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST); - } - if (y == 0) - { - tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH); - } - else if (southParcel != null && southParcel != currentParcelBlock) - { - tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH); + byteArray[byteArrayCount] = tempByte; + byteArrayCount++; + if (byteArrayCount >= LAND_BLOCKS_PER_PACKET) + { + remote_client.SendLandParcelOverlay(byteArray, sequenceID); + byteArrayCount = 0; + sequenceID++; + byteArray = new byte[LAND_BLOCKS_PER_PACKET]; + } + } } - } - return tempByte; + if (byteArrayCount > 0) + { + remote_client.SendLandParcelOverlay(byteArray, sequenceID); + } } public void ClientOnParcelPropertiesRequest(int start_x, int start_y, int end_x, int end_y, int sequence_id, @@ -1320,8 +1406,11 @@ namespace OpenSim.Region.CoreModules.World.Land { if (!temp.Contains(currentParcel)) { - currentParcel.ForceUpdateLandInfo(); - temp.Add(currentParcel); + if (!currentParcel.IsBannedFromLand(remote_client.AgentId)) + { + currentParcel.ForceUpdateLandInfo(); + temp.Add(currentParcel); + } } } } @@ -1338,8 +1427,44 @@ namespace OpenSim.Region.CoreModules.World.Land temp[i].SendLandProperties(sequence_id, snap_selection, requestResult, remote_client); } - // Also send the layer data around the point of interest - SendParcelOverlay(remote_client, (start_x + end_x) / 2, (start_y + end_y) / 2, parcelLayerViewDistance); +// SendParcelOverlay(remote_client); + } + + public void UpdateLandProperties(ILandObject land, LandUpdateArgs args, IClientAPI remote_client) + { + bool snap_selection = false; + bool needOverlay = false; + if (land.UpdateLandProperties(args, remote_client, out snap_selection, out needOverlay)) + { + UUID parcelID = land.LandData.GlobalID; + m_scene.ForEachScenePresence(delegate(ScenePresence avatar) + { + if (avatar.IsDeleted || avatar.IsNPC) + return; + + IClientAPI client = avatar.ControllingClient; + if (needOverlay) + SendParcelOverlay(client); + + if (avatar.IsChildAgent) + { + if(client == remote_client) + land.SendLandProperties(-10000, false, LandChannel.LAND_RESULT_SINGLE, client); + return; + } + + ILandObject aland = GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); + if (aland != null) + { + if(client == remote_client && land != aland) + land.SendLandProperties(-10000, false, LandChannel.LAND_RESULT_SINGLE, client); + else if (land == aland) + aland.SendLandProperties(0, false, LandChannel.LAND_RESULT_SINGLE, client); + } + if (avatar.currentParcelUUID == parcelID) + avatar.currentParcelUUID = parcelID; // force parcel flags review + }); + } } public void ClientOnParcelPropertiesUpdateRequest(LandUpdateArgs args, int localID, IClientAPI remote_client) @@ -1352,19 +1477,19 @@ namespace OpenSim.Region.CoreModules.World.Land if (land != null) { - land.UpdateLandProperties(args, remote_client); + UpdateLandProperties(land, args, remote_client); m_scene.EventManager.TriggerOnParcelPropertiesUpdateRequest(args, localID, remote_client); } } public void ClientOnParcelDivideRequest(int west, int south, int east, int north, IClientAPI remote_client) { - subdivide(west, south, east, north, remote_client.AgentId); + Subdivide(west, south, east, north, remote_client.AgentId); } public void ClientOnParcelJoinRequest(int west, int south, int east, int north, IClientAPI remote_client) { - join(west, south, east, north, remote_client.AgentId); + Join(west, south, east, north, remote_client.AgentId); } public void ClientOnParcelSelectObjects(int local_id, int request_type, @@ -1375,7 +1500,7 @@ namespace OpenSim.Region.CoreModules.World.Land public void ClientOnParcelObjectOwnerRequest(int local_id, IClientAPI remote_client) { - ILandObject land; + ILandObject land = null; lock (m_landList) { m_landList.TryGetValue(local_id, out land); @@ -1384,7 +1509,7 @@ namespace OpenSim.Region.CoreModules.World.Land if (land != null) { m_scene.EventManager.TriggerParcelPrimCountUpdate(); - m_landList[local_id].SendLandObjectOwners(remote_client); + land.SendLandObjectOwners(remote_client); } else { @@ -1394,7 +1519,7 @@ namespace OpenSim.Region.CoreModules.World.Land public void ClientOnParcelGodForceOwner(int local_id, UUID ownerID, IClientAPI remote_client) { - ILandObject land; + ILandObject land = null; lock (m_landList) { m_landList.TryGetValue(local_id, out land); @@ -1408,7 +1533,6 @@ namespace OpenSim.Region.CoreModules.World.Land land.LandData.GroupID = UUID.Zero; land.LandData.IsGroupOwned = false; land.LandData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory); - m_scene.ForEachClient(SendParcelOverlay); land.SendLandUpdateToClient(true, remote_client); UpdateLandObject(land.LandData.LocalID, land.LandData); @@ -1418,7 +1542,7 @@ namespace OpenSim.Region.CoreModules.World.Land public void ClientOnParcelAbandonRequest(int local_id, IClientAPI remote_client) { - ILandObject land; + ILandObject land = null; lock (m_landList) { m_landList.TryGetValue(local_id, out land); @@ -1432,7 +1556,7 @@ namespace OpenSim.Region.CoreModules.World.Land land.LandData.GroupID = UUID.Zero; land.LandData.IsGroupOwned = false; land.LandData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory); - + m_scene.ForEachClient(SendParcelOverlay); land.SendLandUpdateToClient(true, remote_client); UpdateLandObject(land.LandData.LocalID, land.LandData); @@ -1442,7 +1566,7 @@ namespace OpenSim.Region.CoreModules.World.Land public void ClientOnParcelReclaim(int local_id, IClientAPI remote_client) { - ILandObject land; + ILandObject land = null; lock (m_landList) { m_landList.TryGetValue(local_id, out land); @@ -1458,8 +1582,10 @@ namespace OpenSim.Region.CoreModules.World.Land land.LandData.IsGroupOwned = false; land.LandData.SalePrice = 0; land.LandData.AuthBuyerID = UUID.Zero; + land.LandData.SeeAVs = true; + land.LandData.AnyAVSounds = true; + land.LandData.GroupAVSounds = true; land.LandData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory); - m_scene.ForEachClient(SendParcelOverlay); land.SendLandUpdateToClient(true, remote_client); UpdateLandObject(land.LandData.LocalID, land.LandData); @@ -1526,17 +1652,16 @@ namespace OpenSim.Region.CoreModules.World.Land void ClientOnParcelDeedToGroup(int parcelLocalID, UUID groupID, IClientAPI remote_client) { - ILandObject land; + ILandObject land = null; lock (m_landList) { m_landList.TryGetValue(parcelLocalID, out land); } - if (!m_scene.Permissions.CanDeedParcel(remote_client.AgentId, land)) - return; - if (land != null) { + if (!m_scene.Permissions.CanDeedParcel(remote_client.AgentId, land)) + return; land.DeedToGroup(groupID); } } @@ -1545,17 +1670,12 @@ namespace OpenSim.Region.CoreModules.World.Land private void EventManagerOnIncomingLandDataFromStorage(List data) { -// m_log.DebugFormat( -// "[LAND MANAGMENT MODULE]: Processing {0} incoming parcels on {1}", data.Count, m_scene.Name); - - // Prevent race conditions from any auto-creation of new parcels for varregions whilst we are still loading - // the existing parcels. lock (m_landList) { for (int i = 0; i < data.Count; i++) IncomingLandObjectFromStorage(data[i]); - // Layer data is in landUnit (4m) chunks + // Layer data is in LandUnit (4m) chunks for (int y = 0; y < m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); y++) { for (int x = 0; x < m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); x++) @@ -1565,7 +1685,7 @@ namespace OpenSim.Region.CoreModules.World.Land if (m_landList.Count == 1) { m_log.DebugFormat( - "[{0}]: Auto-extending land parcel as landID at {1},{2} is 0 and only one land parcel is present in {3}", + "[{0}]: Auto-extending land parcel as landID at {1},{2} is 0 and only one land parcel is present in {3}", LogHeader, x, y, m_scene.Name); int onlyParcelID = 0; @@ -1588,11 +1708,11 @@ namespace OpenSim.Region.CoreModules.World.Land else if (m_landList.Count > 1) { m_log.DebugFormat( - "{0}: Auto-creating land parcel as landID at {1},{2} is 0 and more than one land parcel is present in {3}", + "{0}: Auto-creating land parcel as landID at {1},{2} is 0 and more than one land parcel is present in {3}", LogHeader, x, y, m_scene.Name); // There are several other parcels so we must create a new one for the unassigned space - ILandObject newLand = new LandObject(UUID.Zero, false, m_scene); + ILandObject newLand = new LandObject(UUID.Zero, false, m_scene); // Claim all the unclaimed "0" ids newLand.SetLandBitmap(CreateBitmapForID(0)); newLand.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; @@ -1603,20 +1723,23 @@ namespace OpenSim.Region.CoreModules.World.Land { // We should never reach this point as the separate code path when no land data exists should have fired instead. m_log.WarnFormat( - "{0}: Ignoring request to auto-create parcel in {1} as there are no other parcels present", + "{0}: Ignoring request to auto-create parcel in {1} as there are no other parcels present", LogHeader, m_scene.Name); } } } } + FinalizeLandPrimCountUpdate(); // update simarea information } } private void IncomingLandObjectFromStorage(LandData data) { - ILandObject new_land = new LandObject(data, m_scene); - new_land.SetLandBitmapFromByteArray(); + ILandObject new_land = new LandObject(data.OwnerID, data.IsGroupOwned, m_scene, data); + + new_land.SetLandBitmapFromByteArray(); AddLandObject(new_land); +// new_land.SendLandUpdateToAvatarsOverMe(); } public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient) @@ -1629,7 +1752,7 @@ namespace OpenSim.Region.CoreModules.World.Land m_landList.TryGetValue(localID, out selectedParcel); } - if (selectedParcel == null) + if (selectedParcel == null) return; selectedParcel.ReturnLandObjects(returnType, agentIDs, taskIDs, remoteClient); @@ -1670,9 +1793,9 @@ namespace OpenSim.Region.CoreModules.World.Land foreach (HashSet objs in returns.Values) { List objs2 = new List(objs); - if (m_scene.Permissions.CanReturnObjects(null, remoteClient.AgentId, objs2)) + if (m_scene.Permissions.CanReturnObjects(null, remoteClient, objs2)) { - m_scene.returnObjects(objs2.ToArray(), remoteClient.AgentId); + m_scene.returnObjects(objs2.ToArray(), remoteClient); } else { @@ -1710,12 +1833,13 @@ namespace OpenSim.Region.CoreModules.World.Land private void EventManagerOnRegisterCaps(UUID agentID, Caps caps) { + //string capsBase = "/CAPS/" + UUID.Random(); string capsBase = "/CAPS/" + caps.CapsObjectPath; caps.RegisterHandler( "RemoteParcelRequest", new RestStreamHandler( "POST", - capsBase + remoteParcelRequestPath, + capsBase, (request, path, param, httpRequest, httpResponse) => RemoteParcelRequest(request, path, param, agentID, caps), "RemoteParcelRequest", @@ -1735,7 +1859,7 @@ namespace OpenSim.Region.CoreModules.World.Land private string ProcessPropertiesUpdate(string request, string path, string param, UUID agentID, Caps caps) { IClientAPI client; - if (!m_scene.TryGetClient(agentID, out client)) + if (!m_scene.TryGetClient(agentID, out client)) { m_log.WarnFormat("[LAND MANAGEMENT MODULE]: Unable to retrieve IClientAPI for {0}", agentID); return LLSDHelpers.SerialiseLLSDReply(new LLSDEmpty()); @@ -1759,7 +1883,7 @@ namespace OpenSim.Region.CoreModules.World.Land land_update.MusicURL = properties.MusicURL; land_update.Name = properties.Name; land_update.ParcelFlags = (uint) properties.ParcelFlags; - land_update.PassHours = (int) properties.PassHours; + land_update.PassHours = properties.PassHours; land_update.PassPrice = (int) properties.PassPrice; land_update.SalePrice = (int) properties.SalePrice; land_update.SnapshotID = properties.SnapshotID; @@ -1773,7 +1897,20 @@ namespace OpenSim.Region.CoreModules.World.Land land_update.ObscureMusic = properties.ObscureMusic; land_update.ObscureMedia = properties.ObscureMedia; - ILandObject land; + if (args.ContainsKey("see_avs")) + { + land_update.SeeAVs = args["see_avs"].AsBoolean(); + land_update.AnyAVSounds = args["any_av_sounds"].AsBoolean(); + land_update.GroupAVSounds = args["group_av_sounds"].AsBoolean(); + } + else + { + land_update.SeeAVs = true; + land_update.AnyAVSounds = true; + land_update.GroupAVSounds = true; + } + + ILandObject land = null; lock (m_landList) { m_landList.TryGetValue(parcelID, out land); @@ -1781,13 +1918,14 @@ namespace OpenSim.Region.CoreModules.World.Land if (land != null) { - land.UpdateLandProperties(land_update, client); + UpdateLandProperties(land,land_update, client); m_scene.EventManager.TriggerOnParcelPropertiesUpdateRequest(land_update, parcelID, client); } else { m_log.WarnFormat("[LAND MANAGEMENT MODULE]: Unable to find parcelID {0}", parcelID); } + return LLSDHelpers.SerialiseLLSDReply(new LLSDEmpty()); } // we cheat here: As we don't have (and want) a grid-global parcel-store, we can't return the @@ -1815,9 +1953,9 @@ namespace OpenSim.Region.CoreModules.World.Land { Hashtable hash = new Hashtable(); hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request)); - if (hash.ContainsKey("region_id") && hash.ContainsKey("location")) + if (hash.ContainsKey("location")) { - UUID regionID = (UUID)hash["region_id"]; + UUID scope = m_scene.RegionInfo.ScopeID; ArrayList list = (ArrayList)hash["location"]; uint x = (uint)(double)list[0]; uint y = (uint)(double)list[1]; @@ -1826,19 +1964,46 @@ namespace OpenSim.Region.CoreModules.World.Land // if you do a "About Landmark" on a landmark a second time, the viewer sends the // region_handle it got earlier via RegionHandleRequest ulong regionHandle = Util.BytesToUInt64Big((byte[])hash["region_handle"]); - parcelID = Util.BuildFakeParcelID(regionHandle, x, y); + if(regionHandle == m_scene.RegionInfo.RegionHandle) + parcelID = Util.BuildFakeParcelID(regionHandle, x, y); + else + { + uint wx; + uint wy; + Util.RegionHandleToWorldLoc(regionHandle, out wx, out wy); + 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); + } + } } - else if (regionID == m_scene.RegionInfo.RegionID) + else if(hash.ContainsKey("region_id")) { + UUID regionID = (UUID)hash["region_id"]; + if (regionID == m_scene.RegionInfo.RegionID) + { // a parcel request for a local parcel => no need to query the grid - parcelID = Util.BuildFakeParcelID(m_scene.RegionInfo.RegionHandle, x, y); - } - else - { - // a parcel request for a parcel in another region. Ask the grid about the region - GridRegion info = m_scene.GridService.GetRegionByUUID(UUID.Zero, regionID); - if (info != null) - parcelID = Util.BuildFakeParcelID(info.RegionHandle, x, y); + parcelID = Util.BuildFakeParcelID(m_scene.RegionInfo.RegionHandle, x, y); + } + else + { + // a parcel request for a parcel in another region. Ask the grid about the region + GridRegion info = m_scene.GridService.GetRegionByUUID(scope, regionID); + if (info != null) + parcelID = Util.BuildFakeParcelID(info.RegionHandle, x, y); + } } } } @@ -1854,7 +2019,7 @@ namespace OpenSim.Region.CoreModules.World.Land LLSDRemoteParcelResponse response = new LLSDRemoteParcelResponse(); response.parcel_id = parcelID; - m_log.DebugFormat("[LAND MANAGEMENT MODULE]: Got parcelID {0}", parcelID); + //m_log.DebugFormat("[LAND MANAGEMENT MODULE]: Got parcelID {0}", parcelID); return LLSDHelpers.SerialiseLLSDReply(response); } @@ -1871,17 +2036,25 @@ namespace OpenSim.Region.CoreModules.World.Land { UUID parcel = UUID.Zero; UUID.TryParse(id, out parcel); + // assume we've got the parcelID we just computed in RemoteParcelRequest ExtendedLandData extLandData = new ExtendedLandData(); - Util.ParseFakeParcelID(parcel, out extLandData.RegionHandle, - out extLandData.X, out extLandData.Y); - m_log.DebugFormat("[LAND MANAGEMENT MODULE]: Got parcelinfo request for regionHandle {0}, x/y {1}/{2}", + if(!Util.ParseFakeParcelID(parcel, out extLandData.RegionHandle, + out extLandData.X, out extLandData.Y)) + return null; + m_log.DebugFormat("[LAND MANAGEMENT MODULE] : Got parcelinfo request for regionHandle {0}, x/y {1}/{2}", extLandData.RegionHandle, extLandData.X, extLandData.Y); // for this region or for somewhere else? if (extLandData.RegionHandle == m_scene.RegionInfo.RegionHandle) { - extLandData.LandData = this.GetLandObject(extLandData.X, extLandData.Y).LandData; + ILandObject extLandObject = this.GetLandObject(extLandData.X, extLandData.Y); + if(extLandObject == null) + { + m_log.DebugFormat("[LAND MANAGEMENT MODULE]: ParcelInfoRequest: a FakeParcelID points to outside the region"); + return null; + } + extLandData.LandData = extLandObject.LandData; extLandData.RegionAccess = m_scene.RegionInfo.AccessLevel; } else @@ -1907,6 +2080,9 @@ namespace OpenSim.Region.CoreModules.World.Land if (data.RegionHandle == m_scene.RegionInfo.RegionHandle) { info = new GridRegion(m_scene.RegionInfo); + IDwellModule dwellModule = m_scene.RequestModuleInterface(); + if (dwellModule != null) + data.LandData.Dwell = dwellModule.GetDwell(data.LandData); } else { @@ -1932,7 +2108,7 @@ namespace OpenSim.Region.CoreModules.World.Land public void setParcelOtherCleanTime(IClientAPI remoteClient, int localID, int otherCleanTime) { - ILandObject land; + ILandObject land = null; lock (m_landList) { m_landList.TryGetValue(localID, out land); @@ -1940,14 +2116,91 @@ namespace OpenSim.Region.CoreModules.World.Land if (land == null) return; - if (!m_scene.Permissions.CanEditParcelProperties(remoteClient.AgentId, land, GroupPowers.LandOptions)) + if (!m_scene.Permissions.CanEditParcelProperties(remoteClient.AgentId, land, GroupPowers.LandOptions, false)) return; land.LandData.OtherCleanTime = otherCleanTime; UpdateLandObject(localID, land.LandData); } - + + public void ClientOnParcelGodMark(IClientAPI client, UUID god, int landID) + { + ILandObject land = null; + List Land = ((Scene)client.Scene).LandChannel.AllParcels(); + foreach (ILandObject landObject in Land) + { + if (landObject.LandData.LocalID == landID) + { + land = landObject; + } + } + land.DeedToGroup(DefaultGodParcelGroup); + land.LandData.Name = DefaultGodParcelName; + land.SendLandUpdateToAvatarsOverMe(); + } + + private void ClientOnSimWideDeletes(IClientAPI client, UUID agentID, int flags, UUID targetID) + { + ScenePresence SP; + ((Scene)client.Scene).TryGetScenePresence(client.AgentId, out SP); + List returns = new List(); + if (SP.GodController.UserLevel != 0) + { + if (flags == 0) //All parcels, scripted or not + { + ((Scene)client.Scene).ForEachSOG(delegate(SceneObjectGroup e) + { + if (e.OwnerID == targetID) + { + returns.Add(e); + } + } + ); + } + if (flags == 4) //All parcels, scripted object + { + ((Scene)client.Scene).ForEachSOG(delegate(SceneObjectGroup e) + { + if (e.OwnerID == targetID) + { + if (e.ContainsScripts()) + { + returns.Add(e); + } + } + }); + } + if (flags == 4) //not target parcel, scripted object + { + ((Scene)client.Scene).ForEachSOG(delegate(SceneObjectGroup e) + { + if (e.OwnerID == targetID) + { + ILandObject landobject = ((Scene)client.Scene).LandChannel.GetLandObject(e.AbsolutePosition.X, e.AbsolutePosition.Y); + if (landobject.LandData.OwnerID != e.OwnerID) + { + if (e.ContainsScripts()) + { + returns.Add(e); + } + } + } + }); + } + foreach (SceneObjectGroup ol in returns) + { + ReturnObject(ol, client); + } + } + } + public void ReturnObject(SceneObjectGroup obj, IClientAPI client) + { + SceneObjectGroup[] objs = new SceneObjectGroup[1]; + objs[0] = obj; + ((Scene)client.Scene).returnObjects(objs, client); + } + Dictionary Timers = new Dictionary(); public void ClientOnParcelFreezeUser(IClientAPI client, UUID parcelowner, uint flags, UUID target) @@ -1958,12 +2211,12 @@ namespace OpenSim.Region.CoreModules.World.Land ((Scene)client.Scene).TryGetScenePresence(client.AgentId, out parcelManager); System.Threading.Timer Timer; - if (targetAvatar.UserLevel == 0) + if (targetAvatar.GodController.UserLevel < 200) { ILandObject land = ((Scene)client.Scene).LandChannel.GetLandObject(targetAvatar.AbsolutePosition.X, targetAvatar.AbsolutePosition.Y); - if (!((Scene)client.Scene).Permissions.CanEditParcelProperties(client.AgentId, land, GroupPowers.LandEjectAndFreeze)) + if (!((Scene)client.Scene).Permissions.CanEditParcelProperties(client.AgentId, land, GroupPowers.LandEjectAndFreeze, true)) return; - if (flags == 0) + if ((flags & 1) == 0) // only lowest bit has meaning for now { targetAvatar.AllowMovement = false; targetAvatar.ControllingClient.SendAlertMessage(parcelManager.Firstname + " " + parcelManager.Lastname + " has frozen you for 30 seconds. You cannot move or interact with the world."); @@ -1983,7 +2236,6 @@ namespace OpenSim.Region.CoreModules.World.Land } } } - private void OnEndParcelFrozen(object avatar) { ScenePresence targetAvatar = (ScenePresence)avatar; @@ -2010,12 +2262,13 @@ namespace OpenSim.Region.CoreModules.World.Land // Check if you even have permission to do this ILandObject land = m_scene.LandChannel.GetLandObject(targetAvatar.AbsolutePosition.X, targetAvatar.AbsolutePosition.Y); - if (!m_scene.Permissions.CanEditParcelProperties(client.AgentId, land, GroupPowers.LandEjectAndFreeze) && + if (!m_scene.Permissions.CanEditParcelProperties(client.AgentId, land, GroupPowers.LandEjectAndFreeze, true) && !m_scene.Permissions.IsAdministrator(client.AgentId)) return; + Vector3 pos = m_scene.GetNearestAllowedPosition(targetAvatar, land); - targetAvatar.TeleportWithMomentum(pos, null); + targetAvatar.TeleportOnEject(pos); targetAvatar.ControllingClient.SendAlertMessage("You have been ejected by " + parcelManager.Firstname + " " + parcelManager.Lastname); parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected."); @@ -2059,7 +2312,7 @@ namespace OpenSim.Region.CoreModules.World.Land if (// Required: local user; foreign users cannot set home m_scene.UserManagementModule.IsLocalGridUser(remoteClient.AgentId) && (// (a) gods and land managers can set home - m_scene.Permissions.IsAdministrator(remoteClient.AgentId) || + m_scene.Permissions.IsAdministrator(remoteClient.AgentId) || m_scene.Permissions.IsGod(remoteClient.AgentId) || // (b) land owners can set home remoteClient.AgentId == land.LandData.OwnerID || @@ -2111,8 +2364,8 @@ namespace OpenSim.Region.CoreModules.World.Land "If no local land ID is given, then summary information about all the parcels is shown.\n" + "If a local land ID is given then full information about that parcel is shown.", HandleShowCommand); - } - + } + protected void HandleClearCommand(string module, string[] args) { if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_scene)) @@ -2120,9 +2373,9 @@ namespace OpenSim.Region.CoreModules.World.Land string response = MainConsole.Instance.CmdPrompt( string.Format( - "Are you sure that you want to clear all land parcels from {0} (y or n)", m_scene.Name), + "Are you sure that you want to clear all land parcels from {0} (y or n)", m_scene.Name), "n"); - + if (response.ToLower() == "y") { Clear(true); @@ -2132,14 +2385,14 @@ namespace OpenSim.Region.CoreModules.World.Land { MainConsole.Instance.OutputFormat("Aborting clear of all parcels from {0}", m_scene.Name); } - } - + } + protected void HandleShowCommand(string module, string[] args) { if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_scene)) return; - StringBuilder report = new StringBuilder(); + StringBuilder report = new StringBuilder(); if (args.Length <= 2) { @@ -2152,10 +2405,10 @@ namespace OpenSim.Region.CoreModules.World.Land if (!ConsoleUtil.TryParseConsoleInt(MainConsole.Instance, args[2], out landLocalId)) return; - ILandObject lo; + ILandObject lo = null; lock (m_landList) - { + { if (!m_landList.TryGetValue(landLocalId, out lo)) { MainConsole.Instance.OutputFormat("No parcel found with local ID {0}", landLocalId); @@ -2170,7 +2423,7 @@ namespace OpenSim.Region.CoreModules.World.Land } private void AppendParcelsSummaryReport(StringBuilder report) - { + { report.AppendFormat("Land information for {0}\n", m_scene.Name); ConsoleDisplayTable cdt = new ConsoleDisplayTable(); @@ -2180,7 +2433,7 @@ namespace OpenSim.Region.CoreModules.World.Land cdt.AddColumn("Starts", ConsoleDisplayUtil.VectorSize); cdt.AddColumn("Ends", ConsoleDisplayUtil.VectorSize); cdt.AddColumn("Owner", ConsoleDisplayUtil.UserNameSize); - + lock (m_landList) { foreach (ILandObject lo in m_landList.Values) @@ -2202,7 +2455,7 @@ namespace OpenSim.Region.CoreModules.World.Land } report.Append(cdt.ToString()); - } + } private void AppendParcelReport(StringBuilder report, ILandObject lo) { @@ -2214,8 +2467,6 @@ namespace OpenSim.Region.CoreModules.World.Land cdl.AddRow("Description", ld.Description); cdl.AddRow("Snapshot ID", ld.SnapshotID); cdl.AddRow("Area", ld.Area); - cdl.AddRow("Starts", lo.StartPoint); - cdl.AddRow("Ends", lo.EndPoint); cdl.AddRow("AABB Min", ld.AABBMin); cdl.AddRow("AABB Max", ld.AABBMax); string ownerName; @@ -2233,7 +2484,7 @@ namespace OpenSim.Region.CoreModules.World.Land cdl.AddRow("GroupID", ld.GroupID); cdl.AddRow("Status", ld.Status); - cdl.AddRow("Flags", (ParcelFlags)ld.Flags); + cdl.AddRow("Flags", (ParcelFlags)ld.Flags); cdl.AddRow("Landing Type", (LandingType)ld.LandingType); cdl.AddRow("User Location", ld.UserLocation); @@ -2242,12 +2493,14 @@ namespace OpenSim.Region.CoreModules.World.Land cdl.AddRow("Other clean time", ld.OtherCleanTime); cdl.AddRow("Max Prims", lo.GetParcelMaxPrimCount()); + cdl.AddRow("Simwide Max Prims (owner)", lo.GetSimulatorMaxPrimCount()); IPrimCounts pc = lo.PrimCounts; cdl.AddRow("Owner Prims", pc.Owner); cdl.AddRow("Group Prims", pc.Group); cdl.AddRow("Other Prims", pc.Others); cdl.AddRow("Selected Prims", pc.Selected); cdl.AddRow("Total Prims", pc.Total); + cdl.AddRow("SimWide Prims (owner)", pc.Simulator); cdl.AddRow("Music URL", ld.MusicURL); cdl.AddRow("Obscure Music", ld.ObscureMusic); -- cgit v1.1