diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
index 6864629bb2..fcd993cc66 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
@@ -1,1013 +1,1045 @@
-/*
- * Copyright (c) Contributors, http://opensimulator.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the OpenSimulator Project nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-using System;
-using System.Collections.Generic;
-using System.Reflection;
-using log4net;
-using OpenMetaverse;
-using OpenSim.Framework;
-using OpenSim.Region.Framework.Interfaces;
-using OpenSim.Region.Framework.Scenes;
-
-namespace OpenSim.Region.CoreModules.World.Land
-{
- ///
- /// Keeps track of a specific piece of land's information
- ///
- public class LandObject : ILandObject
- {
- #region Member Variables
-
- private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
- #pragma warning disable 0429
- private const int landArrayMax = ((int)((int)Constants.RegionSize / 4) >= 64) ? (int)((int)Constants.RegionSize / 4) : 64;
- #pragma warning restore 0429
- private bool[,] m_landBitmap = new bool[landArrayMax,landArrayMax];
-
- private int m_lastSeqId = 0;
-
- protected LandData m_landData = new LandData();
- protected Scene m_scene;
- protected List primsOverMe = new List();
-
- public bool[,] LandBitmap
- {
- get { return m_landBitmap; }
- set { m_landBitmap = value; }
- }
-
- #endregion
-
- #region ILandObject Members
-
- public LandData LandData
- {
- get { return m_landData; }
-
- set { m_landData = value; }
- }
-
- public UUID RegionUUID
- {
- get { return m_scene.RegionInfo.RegionID; }
- }
-
- #region Constructors
-
- public LandObject(UUID owner_id, bool is_group_owned, Scene scene)
- {
- m_scene = scene;
- LandData.OwnerID = owner_id;
- if (is_group_owned)
- LandData.GroupID = owner_id;
- else
- LandData.GroupID = UUID.Zero;
- LandData.IsGroupOwned = is_group_owned;
- }
-
- #endregion
-
- #region Member Functions
-
- #region General Functions
-
- ///
- /// Checks to see if this land object contains a point
- ///
- ///
- ///
- /// Returns true if the piece of land contains the specified point
- public bool ContainsPoint(int x, int y)
- {
- if (x >= 0 && y >= 0 && x <= Constants.RegionSize && y <= Constants.RegionSize)
- {
- return (LandBitmap[x / 4, y / 4] == true);
- }
- else
- {
- return false;
- }
- }
-
- public ILandObject Copy()
- {
- ILandObject newLand = new LandObject(LandData.OwnerID, LandData.IsGroupOwned, m_scene);
-
- //Place all new variables here!
- newLand.LandBitmap = (bool[,]) (LandBitmap.Clone());
- newLand.LandData = LandData.Copy();
-
- return newLand;
- }
-
- static overrideParcelMaxPrimCountDelegate overrideParcelMaxPrimCount;
- static overrideSimulatorMaxPrimCountDelegate overrideSimulatorMaxPrimCount;
-
- public void SetParcelObjectMaxOverride(overrideParcelMaxPrimCountDelegate overrideDel)
- {
- overrideParcelMaxPrimCount = overrideDel;
- }
- public void SetSimulatorObjectMaxOverride(overrideSimulatorMaxPrimCountDelegate overrideDel)
- {
- overrideSimulatorMaxPrimCount = overrideDel;
- }
-
- public int GetParcelMaxPrimCount(ILandObject thisObject)
- {
- if (overrideParcelMaxPrimCount != null)
- {
- return overrideParcelMaxPrimCount(thisObject);
- }
- else
- {
- // Normal Calculations
- return (int)Math.Round(((float)LandData.Area / 65536.0f) * (float)m_scene.RegionInfo.ObjectCapacity * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus);
- }
- }
- public int GetSimulatorMaxPrimCount(ILandObject thisObject)
- {
- if (overrideSimulatorMaxPrimCount != null)
- {
- return overrideSimulatorMaxPrimCount(thisObject);
- }
- else
- {
- //Normal Calculations
- return m_scene.RegionInfo.ObjectCapacity;
- }
- }
- #endregion
-
- #region Packet Request Handling
-
- public void SendLandProperties(int sequence_id, bool snap_selection, int request_result, IClientAPI remote_client)
- {
- IEstateModule estateModule = m_scene.RequestModuleInterface();
- uint regionFlags = 336723974 & ~((uint)(RegionFlags.AllowLandmark | RegionFlags.AllowSetHome));
- if (estateModule != null)
- regionFlags = estateModule.GetRegionFlags();
-
- // In a perfect world, this would have worked.
- //
-// if ((landData.Flags & (uint)ParcelFlags.AllowLandmark) != 0)
-// regionFlags |= (uint)RegionFlags.AllowLandmark;
-// if (landData.OwnerID == remote_client.AgentId)
-// regionFlags |= (uint)RegionFlags.AllowSetHome;
-
- int seq_id;
- if (snap_selection && (sequence_id == 0))
- {
- seq_id = m_lastSeqId;
- }
- else
- {
- seq_id = sequence_id;
- m_lastSeqId = seq_id;
- }
-
- remote_client.SendLandProperties(seq_id,
- snap_selection, request_result, LandData,
- (float)m_scene.RegionInfo.RegionSettings.ObjectBonus,
- GetParcelMaxPrimCount(this),
- GetSimulatorMaxPrimCount(this), regionFlags);
- }
-
- public void UpdateLandProperties(LandUpdateArgs args, IClientAPI remote_client)
- {
- if (m_scene.Permissions.CanEditParcel(remote_client.AgentId,this))
- {
- //Needs later group support
- bool snap_selection = false;
- LandData newData = LandData.Copy();
-
- if (args.AuthBuyerID != newData.AuthBuyerID || args.SalePrice != newData.SalePrice)
- {
- if (m_scene.Permissions.CanSellParcel(remote_client.AgentId, this))
- {
- newData.AuthBuyerID = args.AuthBuyerID;
- newData.SalePrice = args.SalePrice;
- snap_selection = true;
- }
- }
- newData.Category = args.Category;
- newData.Description = args.Desc;
- newData.GroupID = args.GroupID;
- newData.LandingType = args.LandingType;
- newData.MediaAutoScale = args.MediaAutoScale;
- newData.MediaID = args.MediaID;
- newData.MediaURL = args.MediaURL;
- newData.MusicURL = args.MusicURL;
- newData.Name = args.Name;
- newData.Flags = args.ParcelFlags;
- newData.PassHours = args.PassHours;
- newData.PassPrice = args.PassPrice;
- newData.SnapshotID = args.SnapshotID;
- newData.UserLocation = args.UserLocation;
- newData.UserLookAt = args.UserLookAt;
-
- m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
-
- SendLandUpdateToAvatarsOverMe(snap_selection);
- }
- }
-
- public void UpdateLandSold(UUID avatarID, UUID groupID, bool groupOwned, uint AuctionID, int claimprice, int area)
- {
- LandData newData = LandData.Copy();
- newData.OwnerID = avatarID;
- newData.GroupID = groupID;
- newData.IsGroupOwned = groupOwned;
- //newData.auctionID = AuctionID;
- newData.ClaimDate = Util.UnixTimeSinceEpoch();
- newData.ClaimPrice = claimprice;
- newData.SalePrice = 0;
- newData.AuthBuyerID = UUID.Zero;
- newData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory);
- m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
-
- SendLandUpdateToAvatarsOverMe(true);
- }
-
- public void DeedToGroup(UUID groupID)
- {
- LandData newData = LandData.Copy();
- newData.OwnerID = groupID;
- newData.GroupID = groupID;
- newData.IsGroupOwned = true;
-
- // Reset show in directory flag on deed
- newData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory);
-
- m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
-
- SendLandUpdateToAvatarsOverMe(true);
- }
-
- public bool IsEitherBannedOrRestricted(UUID avatar)
- {
- if (IsBannedFromLand(avatar))
- {
- return true;
- }
- else if (IsRestrictedFromLand(avatar))
- {
- return true;
- }
- return false;
- }
-
- public bool IsBannedFromLand(UUID avatar)
- {
- if (m_scene.Permissions.IsAdministrator(avatar))
- return false;
-
- if ((LandData.Flags & (uint) ParcelFlags.UseBanList) > 0)
- {
- ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
- entry.AgentID = avatar;
- entry.Flags = AccessList.Ban;
- entry.Time = new DateTime();
- //See if they are on the list, but make sure the owner isn't banned
- if (LandData.ParcelAccessList.Contains(entry) && LandData.OwnerID != avatar)
- {
- //They are banned, so lets send them a notice about this parcel
- return true;
- }
- }
- return false;
- }
-
- public bool IsRestrictedFromLand(UUID avatar)
- {
- if (m_scene.Permissions.IsAdministrator(avatar))
- return false;
-
- if ((LandData.Flags & (uint) ParcelFlags.UseAccessList) > 0)
- {
- ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
- entry.AgentID = avatar;
- entry.Flags = AccessList.Access;
- entry.Time = new DateTime();
-
- //If they are not on the access list and are not the owner
- if (!LandData.ParcelAccessList.Contains(entry) && LandData.OwnerID != avatar)
- {
- //They are not allowed in this parcel, but not banned, so lets send them a notice about this parcel
- return true;
- }
- }
- return false;
- }
-
- public void SendLandUpdateToClient(IClientAPI remote_client)
- {
- SendLandProperties(0, false, 0, remote_client);
- }
-
- public void SendLandUpdateToClient(bool snap_selection, IClientAPI remote_client)
- {
- SendLandProperties(0, snap_selection, 0, remote_client);
- }
-
- public void SendLandUpdateToAvatarsOverMe()
- {
- SendLandUpdateToAvatarsOverMe(false);
- }
-
- public void SendLandUpdateToAvatarsOverMe(bool snap_selection)
- {
- m_scene.ForEachScenePresence(delegate(ScenePresence avatar)
- {
- if (avatar.IsChildAgent)
- return;
-
- ILandObject over = null;
- try
- {
- over =
- m_scene.LandChannel.GetLandObject(Util.Clamp((int)Math.Round(avatar.AbsolutePosition.X), 0, ((int)Constants.RegionSize - 1)),
- Util.Clamp((int)Math.Round(avatar.AbsolutePosition.Y), 0, ((int)Constants.RegionSize - 1)));
- }
- catch (Exception)
- {
- m_log.Warn("[LAND]: " + "unable to get land at x: " + Math.Round(avatar.AbsolutePosition.X) + " y: " +
- Math.Round(avatar.AbsolutePosition.Y));
- }
-
- if (over != null)
- {
- if (over.LandData.LocalID == LandData.LocalID)
- {
- if (((over.LandData.Flags & (uint)ParcelFlags.AllowDamage) != 0) &&
- m_scene.RegionInfo.RegionSettings.AllowDamage)
- avatar.Invulnerable = false;
- else
- avatar.Invulnerable = true;
-
- SendLandUpdateToClient(snap_selection, avatar.ControllingClient);
- }
- }
- });
- }
-
- #endregion
-
- #region AccessList Functions
-
- public List CreateAccessListArrayByFlag(AccessList flag)
- {
- List list = new List();
- foreach (ParcelManager.ParcelAccessEntry entry in LandData.ParcelAccessList)
- {
- if (entry.Flags == flag)
- {
- list.Add(entry.AgentID);
- }
- }
- if (list.Count == 0)
- {
- list.Add(UUID.Zero);
- }
-
- return list;
- }
-
- public void SendAccessList(UUID agentID, UUID sessionID, uint flags, int sequenceID,
- IClientAPI remote_client)
- {
-
- if (flags == (uint) AccessList.Access || flags == (uint) AccessList.Both)
- {
- List avatars = CreateAccessListArrayByFlag(AccessList.Access);
- remote_client.SendLandAccessListData(avatars,(uint) AccessList.Access,LandData.LocalID);
- }
-
- if (flags == (uint) AccessList.Ban || flags == (uint) AccessList.Both)
- {
- List avatars = CreateAccessListArrayByFlag(AccessList.Ban);
- remote_client.SendLandAccessListData(avatars, (uint)AccessList.Ban, LandData.LocalID);
- }
- }
-
- public void UpdateAccessList(uint flags, List entries, IClientAPI remote_client)
- {
- LandData newData = LandData.Copy();
-
- if (entries.Count == 1 && entries[0].AgentID == UUID.Zero)
- {
- entries.Clear();
- }
-
- List toRemove = new List();
- foreach (ParcelManager.ParcelAccessEntry entry in newData.ParcelAccessList)
- {
- if (entry.Flags == (AccessList)flags)
- {
- toRemove.Add(entry);
- }
- }
-
- foreach (ParcelManager.ParcelAccessEntry entry in toRemove)
- {
- newData.ParcelAccessList.Remove(entry);
- }
- foreach (ParcelManager.ParcelAccessEntry entry in entries)
- {
- ParcelManager.ParcelAccessEntry temp = new ParcelManager.ParcelAccessEntry();
- temp.AgentID = entry.AgentID;
- temp.Time = new DateTime(); //Pointless? Yes.
- temp.Flags = (AccessList)flags;
-
- if (!newData.ParcelAccessList.Contains(temp))
- {
- newData.ParcelAccessList.Add(temp);
- }
- }
-
- m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
- }
-
- #endregion
-
- #region Update Functions
-
- public void UpdateLandBitmapByteArray()
- {
- LandData.Bitmap = ConvertLandBitmapToBytes();
- }
-
- ///
- /// Update all settings in land such as area, bitmap byte array, etc
- ///
- public void ForceUpdateLandInfo()
- {
- UpdateAABBAndAreaValues();
- UpdateLandBitmapByteArray();
- }
-
- public void SetLandBitmapFromByteArray()
- {
- LandBitmap = ConvertBytesToLandBitmap();
- }
-
- ///
- /// Updates the AABBMin and AABBMax values after area/shape modification of the land object
- ///
- private void UpdateAABBAndAreaValues()
- {
- int min_x = 64;
- int min_y = 64;
- int max_x = 0;
- int max_y = 0;
- int tempArea = 0;
- int x, y;
- for (x = 0; x < 64; x++)
- {
- for (y = 0; y < 64; y++)
- {
- if (LandBitmap[x, y] == true)
- {
- if (min_x > x) min_x = x;
- if (min_y > y) min_y = y;
- if (max_x < x) max_x = x;
- if (max_y < y) max_y = y;
- tempArea += 16; //16sqm peice of land
- }
- }
- }
- int tx = min_x * 4;
- if (tx > ((int)Constants.RegionSize - 1))
- tx = ((int)Constants.RegionSize - 1);
- int ty = min_y * 4;
- if (ty > ((int)Constants.RegionSize - 1))
- ty = ((int)Constants.RegionSize - 1);
- LandData.AABBMin =
- new Vector3((float) (min_x * 4), (float) (min_y * 4),
- (float) m_scene.Heightmap[tx, ty]);
-
- tx = max_x * 4;
- if (tx > ((int)Constants.RegionSize - 1))
- tx = ((int)Constants.RegionSize - 1);
- ty = max_y * 4;
- if (ty > ((int)Constants.RegionSize - 1))
- ty = ((int)Constants.RegionSize - 1);
- LandData.AABBMax =
- new Vector3((float) (max_x * 4), (float) (max_y * 4),
- (float) m_scene.Heightmap[tx, ty]);
- LandData.Area = tempArea;
- }
-
- #endregion
-
- #region Land Bitmap Functions
-
- ///
- /// Sets the land's bitmap manually
- ///
- /// 64x64 block representing where this land is on a map
- public void SetLandBitmap(bool[,] bitmap)
- {
- if (bitmap.GetLength(0) != 64 || bitmap.GetLength(1) != 64 || bitmap.Rank != 2)
- {
- //Throw an exception - The bitmap is not 64x64
- //throw new Exception("Error: Invalid Parcel Bitmap");
- }
- else
- {
- //Valid: Lets set it
- LandBitmap = bitmap;
- ForceUpdateLandInfo();
- }
- }
-
- ///
- /// Gets the land's bitmap manually
- ///
- ///
- public bool[,] GetLandBitmap()
- {
- return LandBitmap;
- }
-
- ///
- /// Full sim land object creation
- ///
- ///
- public bool[,] BasicFullRegionLandBitmap()
- {
- return GetSquareLandBitmap(0, 0, (int) Constants.RegionSize, (int) Constants.RegionSize);
- }
-
- ///
- /// Used to modify the bitmap between the x and y points. Points use 64 scale
- ///
- ///
- ///
- ///
- ///
- ///
- public bool[,] GetSquareLandBitmap(int start_x, int start_y, int end_x, int end_y)
- {
- bool[,] tempBitmap = new bool[64,64];
- tempBitmap.Initialize();
-
- tempBitmap = ModifyLandBitmapSquare(tempBitmap, start_x, start_y, end_x, end_y, true);
- return tempBitmap;
- }
-
- ///
- /// Change a land bitmap at within a square and set those points to a specific value
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public bool[,] ModifyLandBitmapSquare(bool[,] land_bitmap, int start_x, int start_y, int end_x, int end_y,
- bool set_value)
- {
- if (land_bitmap.GetLength(0) != 64 || land_bitmap.GetLength(1) != 64 || land_bitmap.Rank != 2)
- {
- //Throw an exception - The bitmap is not 64x64
- //throw new Exception("Error: Invalid Parcel Bitmap in modifyLandBitmapSquare()");
- }
-
- int x, y;
- for (y = 0; y < 64; y++)
- {
- for (x = 0; x < 64; x++)
- {
- if (x >= start_x / 4 && x < end_x / 4
- && y >= start_y / 4 && y < end_y / 4)
- {
- land_bitmap[x, y] = set_value;
- }
- }
- }
- return land_bitmap;
- }
-
- ///
- /// Join the true values of 2 bitmaps together
- ///
- ///
- ///
- ///
- public bool[,] MergeLandBitmaps(bool[,] bitmap_base, bool[,] bitmap_add)
- {
- if (bitmap_base.GetLength(0) != 64 || bitmap_base.GetLength(1) != 64 || bitmap_base.Rank != 2)
- {
- //Throw an exception - The bitmap is not 64x64
- throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_base in mergeLandBitmaps");
- }
- if (bitmap_add.GetLength(0) != 64 || bitmap_add.GetLength(1) != 64 || bitmap_add.Rank != 2)
- {
- //Throw an exception - The bitmap is not 64x64
- throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_add in mergeLandBitmaps");
- }
-
- int x, y;
- for (y = 0; y < 64; y++)
- {
- for (x = 0; x < 64; x++)
- {
- if (bitmap_add[x, y])
- {
- bitmap_base[x, y] = true;
- }
- }
- }
- return bitmap_base;
- }
-
- ///
- /// Converts the land bitmap to a packet friendly byte array
- ///
- ///
- private byte[] ConvertLandBitmapToBytes()
- {
- byte[] tempConvertArr = new byte[512];
- byte tempByte = 0;
- int x, y, i, byteNum = 0;
- i = 0;
- for (y = 0; y < 64; y++)
- {
- for (x = 0; x < 64; x++)
- {
- tempByte = Convert.ToByte(tempByte | Convert.ToByte(LandBitmap[x, y]) << (i++ % 8));
- if (i % 8 == 0)
- {
- tempConvertArr[byteNum] = tempByte;
- tempByte = (byte) 0;
- i = 0;
- byteNum++;
- }
- }
- }
- return tempConvertArr;
- }
-
- private bool[,] ConvertBytesToLandBitmap()
- {
- bool[,] tempConvertMap = new bool[landArrayMax, landArrayMax];
- tempConvertMap.Initialize();
- byte tempByte = 0;
- int x = 0, y = 0, i = 0, bitNum = 0;
- for (i = 0; i < 512; i++)
- {
- tempByte = LandData.Bitmap[i];
- for (bitNum = 0; bitNum < 8; bitNum++)
- {
- bool bit = Convert.ToBoolean(Convert.ToByte(tempByte >> bitNum) & (byte) 1);
- tempConvertMap[x, y] = bit;
- x++;
- if (x > 63)
- {
- x = 0;
- y++;
- }
- }
- }
- return tempConvertMap;
- }
-
- #endregion
-
- #region Object Select and Object Owner Listing
-
- public void SendForceObjectSelect(int local_id, int request_type, List returnIDs, IClientAPI remote_client)
- {
- if (m_scene.Permissions.CanEditParcel(remote_client.AgentId, this))
- {
- List resultLocalIDs = new List();
- try
- {
- lock (primsOverMe)
- {
- foreach (SceneObjectGroup obj in primsOverMe)
- {
- if (obj.LocalId > 0)
- {
- if (request_type == LandChannel.LAND_SELECT_OBJECTS_OWNER && obj.OwnerID == LandData.OwnerID)
- {
- resultLocalIDs.Add(obj.LocalId);
- }
- else if (request_type == LandChannel.LAND_SELECT_OBJECTS_GROUP && obj.GroupID == LandData.GroupID && LandData.GroupID != UUID.Zero)
- {
- resultLocalIDs.Add(obj.LocalId);
- }
- else if (request_type == LandChannel.LAND_SELECT_OBJECTS_OTHER &&
- obj.OwnerID != remote_client.AgentId)
- {
- resultLocalIDs.Add(obj.LocalId);
- }
- else if (request_type == (int)ObjectReturnType.List && returnIDs.Contains(obj.OwnerID))
- {
- resultLocalIDs.Add(obj.LocalId);
- }
- }
- }
- }
- } catch (InvalidOperationException)
- {
- m_log.Error("[LAND]: Unable to force select the parcel objects. Arr.");
- }
-
- remote_client.SendForceClientSelectObjects(resultLocalIDs);
- }
- }
-
- ///
- /// Notify the parcel owner each avatar that owns prims situated on their land. This notification includes
- /// aggreagete details such as the number of prims.
- ///
- ///
- ///
- /// A
- ///
- public void SendLandObjectOwners(IClientAPI remote_client)
- {
- if (m_scene.Permissions.CanEditParcel(remote_client.AgentId, this))
- {
- Dictionary primCount = new Dictionary();
- List groups = new List();
-
- lock (primsOverMe)
- {
- try
- {
-
- foreach (SceneObjectGroup obj in primsOverMe)
- {
- try
- {
- if (!primCount.ContainsKey(obj.OwnerID))
- {
- primCount.Add(obj.OwnerID, 0);
- }
- }
- catch (NullReferenceException)
- {
- m_log.Info("[LAND]: " + "Got Null Reference when searching land owners from the parcel panel");
- }
- try
- {
- primCount[obj.OwnerID] += obj.PrimCount;
- }
- catch (KeyNotFoundException)
- {
- m_log.Error("[LAND]: Unable to match a prim with it's owner.");
- }
- if (obj.OwnerID == obj.GroupID && (!groups.Contains(obj.OwnerID)))
- groups.Add(obj.OwnerID);
- }
- }
- catch (InvalidOperationException)
- {
- m_log.Error("[LAND]: Unable to Enumerate Land object arr.");
- }
- }
-
- remote_client.SendLandObjectOwners(LandData, groups, primCount);
- }
- }
-
- public Dictionary GetLandObjectOwners()
- {
- Dictionary ownersAndCount = new Dictionary();
- lock (primsOverMe)
- {
- try
- {
-
- foreach (SceneObjectGroup obj in primsOverMe)
- {
- if (!ownersAndCount.ContainsKey(obj.OwnerID))
- {
- ownersAndCount.Add(obj.OwnerID, 0);
- }
- ownersAndCount[obj.OwnerID] += obj.PrimCount;
- }
- }
- catch (InvalidOperationException)
- {
- m_log.Error("[LAND]: Unable to enumerate land owners. arr.");
- }
-
- }
- return ownersAndCount;
- }
-
- #endregion
-
- #region Object Returning
-
- public void ReturnObject(SceneObjectGroup obj)
- {
- SceneObjectGroup[] objs = new SceneObjectGroup[1];
- objs[0] = obj;
- m_scene.returnObjects(objs, obj.OwnerID);
- }
-
- public void ReturnLandObjects(uint type, UUID[] owners, UUID[] tasks, IClientAPI remote_client)
- {
- Dictionary> returns =
- new Dictionary>();
-
- lock (primsOverMe)
- {
- if (type == (uint)ObjectReturnType.Owner)
- {
- foreach (SceneObjectGroup obj in primsOverMe)
- {
- if (obj.OwnerID == m_landData.OwnerID)
- {
- if (!returns.ContainsKey(obj.OwnerID))
- returns[obj.OwnerID] =
- new List();
- returns[obj.OwnerID].Add(obj);
- }
- }
- }
- else if (type == (uint)ObjectReturnType.Group && m_landData.GroupID != UUID.Zero)
- {
- foreach (SceneObjectGroup obj in primsOverMe)
- {
- if (obj.GroupID == m_landData.GroupID)
- {
- if (!returns.ContainsKey(obj.OwnerID))
- returns[obj.OwnerID] =
- new List();
- returns[obj.OwnerID].Add(obj);
- }
- }
- }
- else if (type == (uint)ObjectReturnType.Other)
- {
- foreach (SceneObjectGroup obj in primsOverMe)
- {
- if (obj.OwnerID != m_landData.OwnerID &&
- (obj.GroupID != m_landData.GroupID ||
- m_landData.GroupID == UUID.Zero))
- {
- if (!returns.ContainsKey(obj.OwnerID))
- returns[obj.OwnerID] =
- new List();
- returns[obj.OwnerID].Add(obj);
- }
- }
- }
- else if (type == (uint)ObjectReturnType.List)
- {
- List ownerlist = new List(owners);
-
- foreach (SceneObjectGroup obj in primsOverMe)
- {
- if (ownerlist.Contains(obj.OwnerID))
- {
- if (!returns.ContainsKey(obj.OwnerID))
- returns[obj.OwnerID] =
- new List();
- returns[obj.OwnerID].Add(obj);
- }
- }
- }
- }
-
- foreach (List ol in returns.Values)
- {
- if (m_scene.Permissions.CanReturnObjects(this, remote_client.AgentId, ol))
- m_scene.returnObjects(ol.ToArray(), remote_client.AgentId);
- }
- }
-
- #endregion
-
- #region Object Adding/Removing from Parcel
-
- public void ResetLandPrimCounts()
- {
- LandData.GroupPrims = 0;
- LandData.OwnerPrims = 0;
- LandData.OtherPrims = 0;
- LandData.SelectedPrims = 0;
-
-
- lock (primsOverMe)
- primsOverMe.Clear();
- }
-
- public void AddPrimToCount(SceneObjectGroup obj)
- {
-
- UUID prim_owner = obj.OwnerID;
- int prim_count = obj.PrimCount;
-
- if (obj.IsSelected)
- {
- LandData.SelectedPrims += prim_count;
- }
- else
- {
- if (prim_owner == LandData.OwnerID)
- {
- LandData.OwnerPrims += prim_count;
- }
- else if ((obj.GroupID == LandData.GroupID ||
- prim_owner == LandData.GroupID) &&
- LandData.GroupID != UUID.Zero)
- {
- LandData.GroupPrims += prim_count;
- }
- else
- {
- LandData.OtherPrims += prim_count;
- }
- }
-
- lock (primsOverMe)
- primsOverMe.Add(obj);
- }
-
- public void RemovePrimFromCount(SceneObjectGroup obj)
- {
- lock (primsOverMe)
- {
- if (primsOverMe.Contains(obj))
- {
- UUID prim_owner = obj.OwnerID;
- int prim_count = obj.PrimCount;
-
- if (prim_owner == LandData.OwnerID)
- {
- LandData.OwnerPrims -= prim_count;
- }
- else if (obj.GroupID == LandData.GroupID ||
- prim_owner == LandData.GroupID)
- {
- LandData.GroupPrims -= prim_count;
- }
- else
- {
- LandData.OtherPrims -= prim_count;
- }
-
- primsOverMe.Remove(obj);
- }
- }
- }
-
- #endregion
-
- #endregion
-
- #endregion
-
- ///
- /// Set the media url for this land parcel
- ///
- ///
- public void SetMediaUrl(string url)
- {
- LandData.MediaURL = url;
- SendLandUpdateToAvatarsOverMe();
- }
-
- ///
- /// Set the music url for this land parcel
- ///
- ///
- public void SetMusicUrl(string url)
- {
- LandData.MusicURL = url;
- SendLandUpdateToAvatarsOverMe();
- }
- }
-}
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSimulator Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using log4net;
+using OpenMetaverse;
+using OpenSim.Framework;
+using OpenSim.Region.Framework.Interfaces;
+using OpenSim.Region.Framework.Scenes;
+
+namespace OpenSim.Region.CoreModules.World.Land
+{
+ ///
+ /// Keeps track of a specific piece of land's information
+ ///
+ public class LandObject : ILandObject
+ {
+ #region Member Variables
+
+ private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+ #pragma warning disable 0429
+ private const int landArrayMax = ((int)((int)Constants.RegionSize / 4) >= 64) ? (int)((int)Constants.RegionSize / 4) : 64;
+ #pragma warning restore 0429
+ private bool[,] m_landBitmap = new bool[landArrayMax,landArrayMax];
+
+ private int m_lastSeqId = 0;
+
+ protected LandData m_landData = new LandData();
+ protected Scene m_scene;
+ protected List primsOverMe = new List();
+
+ public bool[,] LandBitmap
+ {
+ get { return m_landBitmap; }
+ set { m_landBitmap = value; }
+ }
+
+ #endregion
+
+ #region ILandObject Members
+
+ public LandData LandData
+ {
+ get { return m_landData; }
+
+ set { m_landData = value; }
+ }
+
+ public UUID RegionUUID
+ {
+ get { return m_scene.RegionInfo.RegionID; }
+ }
+
+ #region Constructors
+
+ public LandObject(UUID owner_id, bool is_group_owned, Scene scene)
+ {
+ m_scene = scene;
+ LandData.OwnerID = owner_id;
+ if (is_group_owned)
+ LandData.GroupID = owner_id;
+ else
+ LandData.GroupID = UUID.Zero;
+ LandData.IsGroupOwned = is_group_owned;
+ }
+
+ #endregion
+
+ #region Member Functions
+
+ #region General Functions
+
+ ///
+ /// Checks to see if this land object contains a point
+ ///
+ ///
+ ///
+ /// Returns true if the piece of land contains the specified point
+ public bool ContainsPoint(int x, int y)
+ {
+ if (x >= 0 && y >= 0 && x <= Constants.RegionSize && y <= Constants.RegionSize)
+ {
+ return (LandBitmap[x / 4, y / 4] == true);
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ public ILandObject Copy()
+ {
+ ILandObject newLand = new LandObject(LandData.OwnerID, LandData.IsGroupOwned, m_scene);
+
+ //Place all new variables here!
+ newLand.LandBitmap = (bool[,]) (LandBitmap.Clone());
+ newLand.LandData = LandData.Copy();
+
+ return newLand;
+ }
+
+ static overrideParcelMaxPrimCountDelegate overrideParcelMaxPrimCount;
+ static overrideSimulatorMaxPrimCountDelegate overrideSimulatorMaxPrimCount;
+
+ public void SetParcelObjectMaxOverride(overrideParcelMaxPrimCountDelegate overrideDel)
+ {
+ overrideParcelMaxPrimCount = overrideDel;
+ }
+ public void SetSimulatorObjectMaxOverride(overrideSimulatorMaxPrimCountDelegate overrideDel)
+ {
+ overrideSimulatorMaxPrimCount = overrideDel;
+ }
+
+ public int GetParcelMaxPrimCount(ILandObject thisObject)
+ {
+ if (overrideParcelMaxPrimCount != null)
+ {
+ return overrideParcelMaxPrimCount(thisObject);
+ }
+ else
+ {
+ // Normal Calculations
+ return (int)Math.Round(((float)LandData.Area / 65536.0f) * (float)m_scene.RegionInfo.ObjectCapacity * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus);
+ }
+ }
+ public int GetSimulatorMaxPrimCount(ILandObject thisObject)
+ {
+ if (overrideSimulatorMaxPrimCount != null)
+ {
+ return overrideSimulatorMaxPrimCount(thisObject);
+ }
+ else
+ {
+ //Normal Calculations
+ return m_scene.RegionInfo.ObjectCapacity;
+ }
+ }
+ #endregion
+
+ #region Packet Request Handling
+
+ public void SendLandProperties(int sequence_id, bool snap_selection, int request_result, IClientAPI remote_client)
+ {
+ IEstateModule estateModule = m_scene.RequestModuleInterface();
+ uint regionFlags = 336723974 & ~((uint)(RegionFlags.AllowLandmark | RegionFlags.AllowSetHome));
+ if (estateModule != null)
+ regionFlags = estateModule.GetRegionFlags();
+
+ // In a perfect world, this would have worked.
+ //
+// if ((landData.Flags & (uint)ParcelFlags.AllowLandmark) != 0)
+// regionFlags |= (uint)RegionFlags.AllowLandmark;
+// if (landData.OwnerID == remote_client.AgentId)
+// regionFlags |= (uint)RegionFlags.AllowSetHome;
+
+ int seq_id;
+ if (snap_selection && (sequence_id == 0))
+ {
+ seq_id = m_lastSeqId;
+ }
+ else
+ {
+ seq_id = sequence_id;
+ m_lastSeqId = seq_id;
+ }
+
+ remote_client.SendLandProperties(seq_id,
+ snap_selection, request_result, LandData,
+ (float)m_scene.RegionInfo.RegionSettings.ObjectBonus,
+ GetParcelMaxPrimCount(this),
+ GetSimulatorMaxPrimCount(this), regionFlags);
+ }
+
+ public void UpdateLandProperties(LandUpdateArgs args, IClientAPI remote_client)
+ {
+ if (m_scene.Permissions.CanEditParcel(remote_client.AgentId,this))
+ {
+ //Needs later group support
+ bool snap_selection = false;
+ LandData newData = LandData.Copy();
+
+ if (args.AuthBuyerID != newData.AuthBuyerID || args.SalePrice != newData.SalePrice)
+ {
+ if (m_scene.Permissions.CanSellParcel(remote_client.AgentId, this))
+ {
+ newData.AuthBuyerID = args.AuthBuyerID;
+ newData.SalePrice = args.SalePrice;
+ snap_selection = true;
+ }
+ }
+ newData.Category = args.Category;
+ newData.Description = args.Desc;
+ newData.GroupID = args.GroupID;
+ newData.LandingType = args.LandingType;
+ newData.MediaAutoScale = args.MediaAutoScale;
+ newData.MediaID = args.MediaID;
+ newData.MediaURL = args.MediaURL;
+ newData.MusicURL = args.MusicURL;
+ newData.Name = args.Name;
+ newData.Flags = args.ParcelFlags;
+ newData.PassHours = args.PassHours;
+ newData.PassPrice = args.PassPrice;
+ newData.SnapshotID = args.SnapshotID;
+ newData.UserLocation = args.UserLocation;
+ newData.UserLookAt = args.UserLookAt;
+
+ m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
+
+ SendLandUpdateToAvatarsOverMe(snap_selection);
+ }
+ }
+
+ public void UpdateLandSold(UUID avatarID, UUID groupID, bool groupOwned, uint AuctionID, int claimprice, int area)
+ {
+ LandData newData = LandData.Copy();
+ newData.OwnerID = avatarID;
+ newData.GroupID = groupID;
+ newData.IsGroupOwned = groupOwned;
+ //newData.auctionID = AuctionID;
+ newData.ClaimDate = Util.UnixTimeSinceEpoch();
+ newData.ClaimPrice = claimprice;
+ newData.SalePrice = 0;
+ newData.AuthBuyerID = UUID.Zero;
+ newData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory);
+ m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
+
+ SendLandUpdateToAvatarsOverMe(true);
+ }
+
+ public void DeedToGroup(UUID groupID)
+ {
+ LandData newData = LandData.Copy();
+ newData.OwnerID = groupID;
+ newData.GroupID = groupID;
+ newData.IsGroupOwned = true;
+
+ // Reset show in directory flag on deed
+ newData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory);
+
+ m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
+
+ SendLandUpdateToAvatarsOverMe(true);
+ }
+
+ public bool IsEitherBannedOrRestricted(UUID avatar)
+ {
+ if (IsBannedFromLand(avatar))
+ {
+ return true;
+ }
+ else if (IsRestrictedFromLand(avatar))
+ {
+ return true;
+ }
+ return false;
+ }
+
+ public bool HasGroupAccess(UUID avatar)
+ {
+ if ((LandData.Flags & (uint)ParcelFlags.UseAccessGroup) == (uint)ParcelFlags.UseAccessGroup)
+ {
+ IGroupsModule groupsModule =
+ m_scene.RequestModuleInterface();
+
+ List agentGroups = new List();
+ if (groupsModule != null)
+ {
+ GroupMembershipData[] GroupMembership =
+ groupsModule.GetMembershipData(avatar);
+
+ if (GroupMembership != null)
+ {
+ for (int i = 0; i < GroupMembership.Length; i++)
+ {
+ if (LandData.GroupID == GroupMembership[i].GroupID)
+ {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ public bool IsBannedFromLand(UUID avatar)
+ {
+ if (m_scene.Permissions.IsAdministrator(avatar))
+ return false;
+
+ if ((LandData.Flags & (uint) ParcelFlags.UseBanList) > 0)
+ {
+ ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
+ entry.AgentID = avatar;
+ entry.Flags = AccessList.Ban;
+ entry.Time = new DateTime();
+ //See if they are on the list, but make sure the owner isn't banned
+ if (LandData.ParcelAccessList.Contains(entry) && LandData.OwnerID != avatar)
+ {
+ //They are banned, so lets send them a notice about this parcel
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public bool IsRestrictedFromLand(UUID avatar)
+ {
+ if (m_scene.Permissions.IsAdministrator(avatar))
+ return false;
+
+ if ((LandData.Flags & (uint) ParcelFlags.UseAccessList) > 0)
+ {
+ ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
+ entry.AgentID = avatar;
+ entry.Flags = AccessList.Access;
+ entry.Time = new DateTime();
+
+ //If they are not on the access list and are not the owner
+ if (!LandData.ParcelAccessList.Contains(entry) && LandData.OwnerID != avatar)
+ {
+ if (!HasGroupAccess(avatar))
+ {
+ //They are not allowed in this parcel, but not banned, so lets send them a notice about this parcel
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ public void SendLandUpdateToClient(IClientAPI remote_client)
+ {
+ SendLandProperties(0, false, 0, remote_client);
+ }
+
+ public void SendLandUpdateToClient(bool snap_selection, IClientAPI remote_client)
+ {
+ SendLandProperties(0, snap_selection, 0, remote_client);
+ }
+
+ public void SendLandUpdateToAvatarsOverMe()
+ {
+ SendLandUpdateToAvatarsOverMe(false);
+ }
+
+ public void SendLandUpdateToAvatarsOverMe(bool snap_selection)
+ {
+ m_scene.ForEachScenePresence(delegate(ScenePresence avatar)
+ {
+ if (avatar.IsChildAgent)
+ return;
+
+ ILandObject over = null;
+ try
+ {
+ over =
+ m_scene.LandChannel.GetLandObject(Util.Clamp((int)Math.Round(avatar.AbsolutePosition.X), 0, ((int)Constants.RegionSize - 1)),
+ Util.Clamp((int)Math.Round(avatar.AbsolutePosition.Y), 0, ((int)Constants.RegionSize - 1)));
+ }
+ catch (Exception)
+ {
+ m_log.Warn("[LAND]: " + "unable to get land at x: " + Math.Round(avatar.AbsolutePosition.X) + " y: " +
+ Math.Round(avatar.AbsolutePosition.Y));
+ }
+
+ if (over != null)
+ {
+ if (over.LandData.LocalID == LandData.LocalID)
+ {
+ if (((over.LandData.Flags & (uint)ParcelFlags.AllowDamage) != 0) &&
+ m_scene.RegionInfo.RegionSettings.AllowDamage)
+ avatar.Invulnerable = false;
+ else
+ avatar.Invulnerable = true;
+
+ SendLandUpdateToClient(snap_selection, avatar.ControllingClient);
+ }
+ }
+ });
+ }
+
+ #endregion
+
+ #region AccessList Functions
+
+ public List CreateAccessListArrayByFlag(AccessList flag)
+ {
+ List list = new List();
+ foreach (ParcelManager.ParcelAccessEntry entry in LandData.ParcelAccessList)
+ {
+ if (entry.Flags == flag)
+ {
+ list.Add(entry.AgentID);
+ }
+ }
+ if (list.Count == 0)
+ {
+ list.Add(UUID.Zero);
+ }
+
+ return list;
+ }
+
+ public void SendAccessList(UUID agentID, UUID sessionID, uint flags, int sequenceID,
+ IClientAPI remote_client)
+ {
+
+ if (flags == (uint) AccessList.Access || flags == (uint) AccessList.Both)
+ {
+ List avatars = CreateAccessListArrayByFlag(AccessList.Access);
+ remote_client.SendLandAccessListData(avatars,(uint) AccessList.Access,LandData.LocalID);
+ }
+
+ if (flags == (uint) AccessList.Ban || flags == (uint) AccessList.Both)
+ {
+ List avatars = CreateAccessListArrayByFlag(AccessList.Ban);
+ remote_client.SendLandAccessListData(avatars, (uint)AccessList.Ban, LandData.LocalID);
+ }
+ }
+
+ public void UpdateAccessList(uint flags, List entries, IClientAPI remote_client)
+ {
+ LandData newData = LandData.Copy();
+
+ if (entries.Count == 1 && entries[0].AgentID == UUID.Zero)
+ {
+ entries.Clear();
+ }
+
+ List toRemove = new List();
+ foreach (ParcelManager.ParcelAccessEntry entry in newData.ParcelAccessList)
+ {
+ if (entry.Flags == (AccessList)flags)
+ {
+ toRemove.Add(entry);
+ }
+ }
+
+ foreach (ParcelManager.ParcelAccessEntry entry in toRemove)
+ {
+ newData.ParcelAccessList.Remove(entry);
+ }
+ foreach (ParcelManager.ParcelAccessEntry entry in entries)
+ {
+ ParcelManager.ParcelAccessEntry temp = new ParcelManager.ParcelAccessEntry();
+ temp.AgentID = entry.AgentID;
+ temp.Time = new DateTime(); //Pointless? Yes.
+ temp.Flags = (AccessList)flags;
+
+ if (!newData.ParcelAccessList.Contains(temp))
+ {
+ newData.ParcelAccessList.Add(temp);
+ }
+ }
+
+ m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
+ }
+
+ #endregion
+
+ #region Update Functions
+
+ public void UpdateLandBitmapByteArray()
+ {
+ LandData.Bitmap = ConvertLandBitmapToBytes();
+ }
+
+ ///
+ /// Update all settings in land such as area, bitmap byte array, etc
+ ///
+ public void ForceUpdateLandInfo()
+ {
+ UpdateAABBAndAreaValues();
+ UpdateLandBitmapByteArray();
+ }
+
+ public void SetLandBitmapFromByteArray()
+ {
+ LandBitmap = ConvertBytesToLandBitmap();
+ }
+
+ ///
+ /// Updates the AABBMin and AABBMax values after area/shape modification of the land object
+ ///
+ private void UpdateAABBAndAreaValues()
+ {
+ int min_x = 64;
+ int min_y = 64;
+ int max_x = 0;
+ int max_y = 0;
+ int tempArea = 0;
+ int x, y;
+ for (x = 0; x < 64; x++)
+ {
+ for (y = 0; y < 64; y++)
+ {
+ if (LandBitmap[x, y] == true)
+ {
+ if (min_x > x) min_x = x;
+ if (min_y > y) min_y = y;
+ if (max_x < x) max_x = x;
+ if (max_y < y) max_y = y;
+ tempArea += 16; //16sqm peice of land
+ }
+ }
+ }
+ int tx = min_x * 4;
+ if (tx > ((int)Constants.RegionSize - 1))
+ tx = ((int)Constants.RegionSize - 1);
+ int ty = min_y * 4;
+ if (ty > ((int)Constants.RegionSize - 1))
+ ty = ((int)Constants.RegionSize - 1);
+ LandData.AABBMin =
+ new Vector3((float) (min_x * 4), (float) (min_y * 4),
+ (float) m_scene.Heightmap[tx, ty]);
+
+ tx = max_x * 4;
+ if (tx > ((int)Constants.RegionSize - 1))
+ tx = ((int)Constants.RegionSize - 1);
+ ty = max_y * 4;
+ if (ty > ((int)Constants.RegionSize - 1))
+ ty = ((int)Constants.RegionSize - 1);
+ LandData.AABBMax =
+ new Vector3((float) (max_x * 4), (float) (max_y * 4),
+ (float) m_scene.Heightmap[tx, ty]);
+ LandData.Area = tempArea;
+ }
+
+ #endregion
+
+ #region Land Bitmap Functions
+
+ ///
+ /// Sets the land's bitmap manually
+ ///
+ /// 64x64 block representing where this land is on a map
+ public void SetLandBitmap(bool[,] bitmap)
+ {
+ if (bitmap.GetLength(0) != 64 || bitmap.GetLength(1) != 64 || bitmap.Rank != 2)
+ {
+ //Throw an exception - The bitmap is not 64x64
+ //throw new Exception("Error: Invalid Parcel Bitmap");
+ }
+ else
+ {
+ //Valid: Lets set it
+ LandBitmap = bitmap;
+ ForceUpdateLandInfo();
+ }
+ }
+
+ ///
+ /// Gets the land's bitmap manually
+ ///
+ ///
+ public bool[,] GetLandBitmap()
+ {
+ return LandBitmap;
+ }
+
+ ///
+ /// Full sim land object creation
+ ///
+ ///
+ public bool[,] BasicFullRegionLandBitmap()
+ {
+ return GetSquareLandBitmap(0, 0, (int) Constants.RegionSize, (int) Constants.RegionSize);
+ }
+
+ ///
+ /// Used to modify the bitmap between the x and y points. Points use 64 scale
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public bool[,] GetSquareLandBitmap(int start_x, int start_y, int end_x, int end_y)
+ {
+ bool[,] tempBitmap = new bool[64,64];
+ tempBitmap.Initialize();
+
+ tempBitmap = ModifyLandBitmapSquare(tempBitmap, start_x, start_y, end_x, end_y, true);
+ return tempBitmap;
+ }
+
+ ///
+ /// Change a land bitmap at within a square and set those points to a specific value
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public bool[,] ModifyLandBitmapSquare(bool[,] land_bitmap, int start_x, int start_y, int end_x, int end_y,
+ bool set_value)
+ {
+ if (land_bitmap.GetLength(0) != 64 || land_bitmap.GetLength(1) != 64 || land_bitmap.Rank != 2)
+ {
+ //Throw an exception - The bitmap is not 64x64
+ //throw new Exception("Error: Invalid Parcel Bitmap in modifyLandBitmapSquare()");
+ }
+
+ int x, y;
+ for (y = 0; y < 64; y++)
+ {
+ for (x = 0; x < 64; x++)
+ {
+ if (x >= start_x / 4 && x < end_x / 4
+ && y >= start_y / 4 && y < end_y / 4)
+ {
+ land_bitmap[x, y] = set_value;
+ }
+ }
+ }
+ return land_bitmap;
+ }
+
+ ///
+ /// Join the true values of 2 bitmaps together
+ ///
+ ///
+ ///
+ ///
+ public bool[,] MergeLandBitmaps(bool[,] bitmap_base, bool[,] bitmap_add)
+ {
+ if (bitmap_base.GetLength(0) != 64 || bitmap_base.GetLength(1) != 64 || bitmap_base.Rank != 2)
+ {
+ //Throw an exception - The bitmap is not 64x64
+ throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_base in mergeLandBitmaps");
+ }
+ if (bitmap_add.GetLength(0) != 64 || bitmap_add.GetLength(1) != 64 || bitmap_add.Rank != 2)
+ {
+ //Throw an exception - The bitmap is not 64x64
+ throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_add in mergeLandBitmaps");
+ }
+
+ int x, y;
+ for (y = 0; y < 64; y++)
+ {
+ for (x = 0; x < 64; x++)
+ {
+ if (bitmap_add[x, y])
+ {
+ bitmap_base[x, y] = true;
+ }
+ }
+ }
+ return bitmap_base;
+ }
+
+ ///
+ /// Converts the land bitmap to a packet friendly byte array
+ ///
+ ///
+ private byte[] ConvertLandBitmapToBytes()
+ {
+ byte[] tempConvertArr = new byte[512];
+ byte tempByte = 0;
+ int x, y, i, byteNum = 0;
+ i = 0;
+ for (y = 0; y < 64; y++)
+ {
+ for (x = 0; x < 64; x++)
+ {
+ tempByte = Convert.ToByte(tempByte | Convert.ToByte(LandBitmap[x, y]) << (i++ % 8));
+ if (i % 8 == 0)
+ {
+ tempConvertArr[byteNum] = tempByte;
+ tempByte = (byte) 0;
+ i = 0;
+ byteNum++;
+ }
+ }
+ }
+ return tempConvertArr;
+ }
+
+ private bool[,] ConvertBytesToLandBitmap()
+ {
+ bool[,] tempConvertMap = new bool[landArrayMax, landArrayMax];
+ tempConvertMap.Initialize();
+ byte tempByte = 0;
+ int x = 0, y = 0, i = 0, bitNum = 0;
+ for (i = 0; i < 512; i++)
+ {
+ tempByte = LandData.Bitmap[i];
+ for (bitNum = 0; bitNum < 8; bitNum++)
+ {
+ bool bit = Convert.ToBoolean(Convert.ToByte(tempByte >> bitNum) & (byte) 1);
+ tempConvertMap[x, y] = bit;
+ x++;
+ if (x > 63)
+ {
+ x = 0;
+ y++;
+ }
+ }
+ }
+ return tempConvertMap;
+ }
+
+ #endregion
+
+ #region Object Select and Object Owner Listing
+
+ public void SendForceObjectSelect(int local_id, int request_type, List returnIDs, IClientAPI remote_client)
+ {
+ if (m_scene.Permissions.CanEditParcel(remote_client.AgentId, this))
+ {
+ List resultLocalIDs = new List();
+ try
+ {
+ lock (primsOverMe)
+ {
+ foreach (SceneObjectGroup obj in primsOverMe)
+ {
+ if (obj.LocalId > 0)
+ {
+ if (request_type == LandChannel.LAND_SELECT_OBJECTS_OWNER && obj.OwnerID == LandData.OwnerID)
+ {
+ resultLocalIDs.Add(obj.LocalId);
+ }
+ else if (request_type == LandChannel.LAND_SELECT_OBJECTS_GROUP && obj.GroupID == LandData.GroupID && LandData.GroupID != UUID.Zero)
+ {
+ resultLocalIDs.Add(obj.LocalId);
+ }
+ else if (request_type == LandChannel.LAND_SELECT_OBJECTS_OTHER &&
+ obj.OwnerID != remote_client.AgentId)
+ {
+ resultLocalIDs.Add(obj.LocalId);
+ }
+ else if (request_type == (int)ObjectReturnType.List && returnIDs.Contains(obj.OwnerID))
+ {
+ resultLocalIDs.Add(obj.LocalId);
+ }
+ }
+ }
+ }
+ } catch (InvalidOperationException)
+ {
+ m_log.Error("[LAND]: Unable to force select the parcel objects. Arr.");
+ }
+
+ remote_client.SendForceClientSelectObjects(resultLocalIDs);
+ }
+ }
+
+ ///
+ /// Notify the parcel owner each avatar that owns prims situated on their land. This notification includes
+ /// aggreagete details such as the number of prims.
+ ///
+ ///
+ ///
+ /// A
+ ///
+ public void SendLandObjectOwners(IClientAPI remote_client)
+ {
+ if (m_scene.Permissions.CanEditParcel(remote_client.AgentId, this))
+ {
+ Dictionary primCount = new Dictionary();
+ List groups = new List();
+
+ lock (primsOverMe)
+ {
+ try
+ {
+
+ foreach (SceneObjectGroup obj in primsOverMe)
+ {
+ try
+ {
+ if (!primCount.ContainsKey(obj.OwnerID))
+ {
+ primCount.Add(obj.OwnerID, 0);
+ }
+ }
+ catch (NullReferenceException)
+ {
+ m_log.Info("[LAND]: " + "Got Null Reference when searching land owners from the parcel panel");
+ }
+ try
+ {
+ primCount[obj.OwnerID] += obj.PrimCount;
+ }
+ catch (KeyNotFoundException)
+ {
+ m_log.Error("[LAND]: Unable to match a prim with it's owner.");
+ }
+ if (obj.OwnerID == obj.GroupID && (!groups.Contains(obj.OwnerID)))
+ groups.Add(obj.OwnerID);
+ }
+ }
+ catch (InvalidOperationException)
+ {
+ m_log.Error("[LAND]: Unable to Enumerate Land object arr.");
+ }
+ }
+
+ remote_client.SendLandObjectOwners(LandData, groups, primCount);
+ }
+ }
+
+ public Dictionary GetLandObjectOwners()
+ {
+ Dictionary ownersAndCount = new Dictionary();
+ lock (primsOverMe)
+ {
+ try
+ {
+
+ foreach (SceneObjectGroup obj in primsOverMe)
+ {
+ if (!ownersAndCount.ContainsKey(obj.OwnerID))
+ {
+ ownersAndCount.Add(obj.OwnerID, 0);
+ }
+ ownersAndCount[obj.OwnerID] += obj.PrimCount;
+ }
+ }
+ catch (InvalidOperationException)
+ {
+ m_log.Error("[LAND]: Unable to enumerate land owners. arr.");
+ }
+
+ }
+ return ownersAndCount;
+ }
+
+ #endregion
+
+ #region Object Returning
+
+ public void ReturnObject(SceneObjectGroup obj)
+ {
+ SceneObjectGroup[] objs = new SceneObjectGroup[1];
+ objs[0] = obj;
+ m_scene.returnObjects(objs, obj.OwnerID);
+ }
+
+ public void ReturnLandObjects(uint type, UUID[] owners, UUID[] tasks, IClientAPI remote_client)
+ {
+ Dictionary> returns =
+ new Dictionary>();
+
+ lock (primsOverMe)
+ {
+ if (type == (uint)ObjectReturnType.Owner)
+ {
+ foreach (SceneObjectGroup obj in primsOverMe)
+ {
+ if (obj.OwnerID == m_landData.OwnerID)
+ {
+ if (!returns.ContainsKey(obj.OwnerID))
+ returns[obj.OwnerID] =
+ new List();
+ returns[obj.OwnerID].Add(obj);
+ }
+ }
+ }
+ else if (type == (uint)ObjectReturnType.Group && m_landData.GroupID != UUID.Zero)
+ {
+ foreach (SceneObjectGroup obj in primsOverMe)
+ {
+ if (obj.GroupID == m_landData.GroupID)
+ {
+ if (!returns.ContainsKey(obj.OwnerID))
+ returns[obj.OwnerID] =
+ new List();
+ returns[obj.OwnerID].Add(obj);
+ }
+ }
+ }
+ else if (type == (uint)ObjectReturnType.Other)
+ {
+ foreach (SceneObjectGroup obj in primsOverMe)
+ {
+ if (obj.OwnerID != m_landData.OwnerID &&
+ (obj.GroupID != m_landData.GroupID ||
+ m_landData.GroupID == UUID.Zero))
+ {
+ if (!returns.ContainsKey(obj.OwnerID))
+ returns[obj.OwnerID] =
+ new List();
+ returns[obj.OwnerID].Add(obj);
+ }
+ }
+ }
+ else if (type == (uint)ObjectReturnType.List)
+ {
+ List ownerlist = new List(owners);
+
+ foreach (SceneObjectGroup obj in primsOverMe)
+ {
+ if (ownerlist.Contains(obj.OwnerID))
+ {
+ if (!returns.ContainsKey(obj.OwnerID))
+ returns[obj.OwnerID] =
+ new List();
+ returns[obj.OwnerID].Add(obj);
+ }
+ }
+ }
+ }
+
+ foreach (List ol in returns.Values)
+ {
+ if (m_scene.Permissions.CanReturnObjects(this, remote_client.AgentId, ol))
+ m_scene.returnObjects(ol.ToArray(), remote_client.AgentId);
+ }
+ }
+
+ #endregion
+
+ #region Object Adding/Removing from Parcel
+
+ public void ResetLandPrimCounts()
+ {
+ LandData.GroupPrims = 0;
+ LandData.OwnerPrims = 0;
+ LandData.OtherPrims = 0;
+ LandData.SelectedPrims = 0;
+
+
+ lock (primsOverMe)
+ primsOverMe.Clear();
+ }
+
+ public void AddPrimToCount(SceneObjectGroup obj)
+ {
+
+ UUID prim_owner = obj.OwnerID;
+ int prim_count = obj.PrimCount;
+
+ if (obj.IsSelected)
+ {
+ LandData.SelectedPrims += prim_count;
+ }
+ else
+ {
+ if (prim_owner == LandData.OwnerID)
+ {
+ LandData.OwnerPrims += prim_count;
+ }
+ else if ((obj.GroupID == LandData.GroupID ||
+ prim_owner == LandData.GroupID) &&
+ LandData.GroupID != UUID.Zero)
+ {
+ LandData.GroupPrims += prim_count;
+ }
+ else
+ {
+ LandData.OtherPrims += prim_count;
+ }
+ }
+
+ lock (primsOverMe)
+ primsOverMe.Add(obj);
+ }
+
+ public void RemovePrimFromCount(SceneObjectGroup obj)
+ {
+ lock (primsOverMe)
+ {
+ if (primsOverMe.Contains(obj))
+ {
+ UUID prim_owner = obj.OwnerID;
+ int prim_count = obj.PrimCount;
+
+ if (prim_owner == LandData.OwnerID)
+ {
+ LandData.OwnerPrims -= prim_count;
+ }
+ else if (obj.GroupID == LandData.GroupID ||
+ prim_owner == LandData.GroupID)
+ {
+ LandData.GroupPrims -= prim_count;
+ }
+ else
+ {
+ LandData.OtherPrims -= prim_count;
+ }
+
+ primsOverMe.Remove(obj);
+ }
+ }
+ }
+
+ #endregion
+
+ #endregion
+
+ #endregion
+
+ ///
+ /// Set the media url for this land parcel
+ ///
+ ///
+ public void SetMediaUrl(string url)
+ {
+ LandData.MediaURL = url;
+ SendLandUpdateToAvatarsOverMe();
+ }
+
+ ///
+ /// Set the music url for this land parcel
+ ///
+ ///
+ public void SetMusicUrl(string url)
+ {
+ LandData.MusicURL = url;
+ SendLandUpdateToAvatarsOverMe();
+ }
+ }
+}
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index cca296ee8d..fc8e0d7186 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -2053,13 +2053,9 @@ namespace OpenSim.Region.Framework.Scenes
//Console.WriteLine("Camera Eye ={0}", cameraEyeOffset);
//NOTE: SendSitResponse should be relative to the GROUP *NOT* THE PRIM if we're sitting on a child
- Quaternion roffset = Quaternion.Identity;
- if (SitTargetisSet)
- {
- roffset = part.RotationOffset;
- }
- ControllingClient.SendSitResponse(part.ParentGroup.UUID, ((offset * roffset) + part.OffsetPosition), sitOrientation / part.RotationOffset, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook);
+ ControllingClient.SendSitResponse(part.ParentGroup.UUID, ((offset * part.RotationOffset) + part.OffsetPosition), sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook);
+ m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target
// This calls HandleAgentSit twice, once from here, and the client calls
// HandleAgentSit itself after it gets to the location
// It doesn't get to the location until we've moved them there though
@@ -2444,7 +2440,10 @@ namespace OpenSim.Region.Framework.Scenes
}
m_linkedPrim = part.UUID;
- m_offsetRotation = m_offsetRotation / part.RotationOffset;
+ if (part.GetAvatarOnSitTarget() != UUID)
+ {
+ m_offsetRotation = m_offsetRotation / part.RotationOffset;
+ }
Velocity = Vector3.Zero;
RemoveFromPhysicalScene();
Animator.TrySetMovementAnimation(sitAnimation);