From 17421593528f4126256dea6d0c844da9c218fdb7 Mon Sep 17 00:00:00 2001 From: mingchen Date: Mon, 4 Jun 2007 14:09:19 +0000 Subject: Parcel Manager Changes: *Added Parcel Backup Support for DB4. Other storages currently do not save *Added parcelIDList in ParcelManager to speed up parcel fetching at position *Added ParcelData.cs and ParcelData class for better storage support *Documentation for parcel added *2 Parcel Related bug fixes --- .../ClientView.ProcessPackets.cs | 2 +- .../OpenSim.RegionServer/world/ParcelManager.cs | 499 +++++++++++---------- .../world/World.PacketHandlers.cs | 5 +- OpenSim/OpenSim.RegionServer/world/World.cs | 16 +- .../LocalStorageBerkeleyDB/BDBLocalStorage.cs | 11 + .../LocalStorageDb4o/Db4LocalStorage.cs | 43 +- .../LocalStorageSQLite/SQLiteLocalStorage.cs | 10 + OpenSim/OpenSim/OpenSimMain.cs | 6 + 8 files changed, 356 insertions(+), 236 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/OpenSim.RegionServer/ClientView.ProcessPackets.cs b/OpenSim/OpenSim.RegionServer/ClientView.ProcessPackets.cs index a5ab78a..1b3ff36 100644 --- a/OpenSim/OpenSim.RegionServer/ClientView.ProcessPackets.cs +++ b/OpenSim/OpenSim.RegionServer/ClientView.ProcessPackets.cs @@ -14,6 +14,7 @@ using OpenSim.Framework.Types; using OpenSim.Framework.Inventory; using OpenSim.Framework.Utilities; using OpenSim.world; +using OpenSim.RegionServer.world; using OpenSim.Assets; namespace OpenSim @@ -59,7 +60,6 @@ namespace OpenSim protected override void ProcessInPacket(Packet Pack) { ack_pack(Pack); - debug = true; if (debug) { if (Pack.Type != PacketType.AgentUpdate) diff --git a/OpenSim/OpenSim.RegionServer/world/ParcelManager.cs b/OpenSim/OpenSim.RegionServer/world/ParcelManager.cs index 7cc39ff..53b14f3 100644 --- a/OpenSim/OpenSim.RegionServer/world/ParcelManager.cs +++ b/OpenSim/OpenSim.RegionServer/world/ParcelManager.cs @@ -3,168 +3,54 @@ using System.Collections.Generic; using System.Text; using libsecondlife; using libsecondlife.Packets; +using OpenSim.world; +using OpenSim.Framework.Interfaces; +using OpenSim.Framework.Types; -namespace OpenSim.world +namespace OpenSim.RegionServer.world { public delegate void ParcelPropertiesRequest(int start_x, int start_y, int end_x, int end_y, int sequence_id, bool snap_selection, ClientView remote_client); - - #region Enums - public enum ParcelFlags : uint - { - /// No flags set - None = 0, - /// Allow avatars to fly (a client-side only restriction) - AllowFly = 1 << 0, - /// Allow foreign scripts to run - AllowOtherScripts = 1 << 1, - /// This parcel is for sale - ForSale = 1 << 2, - /// Allow avatars to create a landmark on this parcel - AllowLandmark = 1 << 3, - /// Allows all avatars to edit the terrain on this parcel - AllowTerraform = 1 << 4, - /// Avatars have health and can take damage on this parcel. - /// If set, avatars can be killed and sent home here - AllowDamage = 1 << 5, - /// Foreign avatars can create objects here - CreateObjects = 1 << 6, - /// All objects on this parcel can be purchased - ForSaleObjects = 1 << 7, - /// Access is restricted to a group - UseAccessGroup = 1 << 8, - /// Access is restricted to a whitelist - UseAccessList = 1 << 9, - /// Ban blacklist is enabled - UseBanList = 1 << 10, - /// Unknown - UsePassList = 1 << 11, - /// List this parcel in the search directory - ShowDirectory = 1 << 12, - /// Unknown - AllowDeedToGroup = 1 << 13, - /// Unknown - ContributeWithDeed = 1 << 14, - /// Restrict sounds originating on this parcel to the - /// parcel boundaries - SoundLocal = 1 << 15, - /// Objects on this parcel are sold when the land is - /// purchsaed - SellParcelObjects = 1 << 16, - /// Allow this parcel to be published on the web - AllowPublish = 1 << 17, - /// The information for this parcel is mature content - MaturePublish = 1 << 18, - /// The media URL is an HTML page - UrlWebPage = 1 << 19, - /// The media URL is a raw HTML string - UrlRawHtml = 1 << 20, - /// Restrict foreign object pushes - RestrictPushObject = 1 << 21, - /// Ban all non identified/transacted avatars - DenyAnonymous = 1 << 22, - /// Ban all identified avatars - DenyIdentified = 1 << 23, - /// Ban all transacted avatars - DenyTransacted = 1 << 24, - /// Allow group-owned scripts to run - AllowGroupScripts = 1 << 25, - /// Allow object creation by group members or group - /// objects - CreateGroupObjects = 1 << 26, - /// Allow all objects to enter this parcel - AllowAllObjectEntry = 1 << 27, - /// Only allow group and owner objects to enter this parcel - AllowGroupObjectEntry = 1 << 28, - } + + #region ParcelManager Class /// - /// Parcel ownership status + /// Handles Parcel objects and operations requiring information from other Parcel objects (divide, join, etc) /// - public enum ParcelStatus : sbyte + public class ParcelManager : OpenSim.Framework.Interfaces.ILocalStorageParcelReceiver { - /// Eh? - None = -1, - /// Land is owned - Leased = 0, - /// Land is for sale - LeasePending = 1, - /// Land is public - Abandoned = 2 - } - public enum ParcelCategory : sbyte - { - /// No assigned category - None = 0, - /// - Linden, - /// - Adult, - /// - Arts, - /// - Business, - /// - Educational, - /// - Gaming, - /// - Hangout, - /// - Newcomer, - /// - Park, - /// - Residential, - /// - Shopping, - /// - Stage, - /// - Other, - /// Not an actual category, only used for queries - Any = -1 - } - - #endregion - - #region ParcelManager Class - public class ParcelManager - { - #region Constants //Parcel types set with flags in ParcelOverlay. //Only one of these can be used. - public static byte PARCEL_TYPE_PUBLIC = (byte)0; //Equals 00000000 - public static byte PARCEL_TYPE_OWNED_BY_OTHER = (byte)1; //Equals 00000001 - public static byte PARCEL_TYPE_OWNED_BY_GROUP = (byte)2; //Equals 00000010 - public static byte PARCEL_TYPE_OWNED_BY_REQUESTER = (byte)3; //Equals 00000011 - public static byte PARCEL_TYPE_IS_FOR_SALE = (byte)4; //Equals 00000100 - public static byte PARCEL_TYPE_IS_BEING_AUCTIONED = (byte)5; //Equals 00000101 + public static byte PARCEL_TYPE_PUBLIC = (byte)0; //Equals 00000000 + public static byte PARCEL_TYPE_OWNED_BY_OTHER = (byte)1; //Equals 00000001 + public static byte PARCEL_TYPE_OWNED_BY_GROUP = (byte)2; //Equals 00000010 + public static byte PARCEL_TYPE_OWNED_BY_REQUESTER = (byte)3; //Equals 00000011 + public static byte PARCEL_TYPE_IS_FOR_SALE = (byte)4; //Equals 00000100 + public static byte PARCEL_TYPE_IS_BEING_AUCTIONED = (byte)5; //Equals 00000101 //Flags that when set, a border on the given side will be placed //NOTE: North and East is assumable by the west and south sides (if parcel to east has a west border, then I have an east border; etc) //This took forever to figure out -- jeesh. /blame LL for even having to send these - public static byte PARCEL_FLAG_PROPERTY_BORDER_WEST = (byte)64; //Equals 01000000 - public static byte PARCEL_FLAG_PROPERTY_BORDER_SOUTH = (byte)128; //Equals 10000000 + public static byte PARCEL_FLAG_PROPERTY_BORDER_WEST = (byte)64; //Equals 01000000 + public static byte PARCEL_FLAG_PROPERTY_BORDER_SOUTH = (byte)128; //Equals 10000000 #endregion #region Member Variables - private List parcelList; - private static World m_world; + public Dictionary parcelList = new Dictionary(); + private int lastParcelLocalID = -1; + private int[,] parcelIDList = new int[64, 64]; + + private static World m_world; #endregion #region Constructors public ParcelManager(World world) { - parcelList = new List(); + m_world = world; - - //NOTE: This is temporary until I get to storing the parcels out of memory - //This should later only be for new simulators - resetSimParcels(); Console.WriteLine("Created ParcelManager Object"); @@ -173,38 +59,112 @@ namespace OpenSim.world #region Member Functions - #region Parcel Add/Remove/Get - public void addParcel(Parcel new_parcel) + #region Parcel From Storage Functions + public void ParcelFromStorage(ParcelData data) { - parcelList.Add(new_parcel); + Parcel new_parcel = new Parcel(data.ownerID, data.isGroupOwned, m_world); + new_parcel.parcelData = data; + new_parcel.setParcelBitmapFromByteArray(); + + this.addParcel(new_parcel); } - public void removeParcel(Parcel old_parcel) + + public void NoParcelDataFromStorage() { - parcelList.Remove(old_parcel); + this.resetSimParcels(); } - public Parcel getParcel(int x, int y) + #endregion + + #region Parcel Add/Remove/Get/Create + /// + /// Creates a basic Parcel object without an owner (a zeroed key) + /// + /// + public Parcel createBaseParcel() + { + return new Parcel(new LLUUID(), false, m_world); + } + + /// + /// Adds a parcel to the stored list and adds them to the parcelIDList to what they own + /// + /// The parcel being added + public void addParcel(Parcel new_parcel) + { + lastParcelLocalID++; + new_parcel.parcelData.localID = lastParcelLocalID; + parcelList.Add(lastParcelLocalID, new_parcel); + + + bool[,] parcelBitmap = new_parcel.getParcelBitmap(); + int x, y; + for (x = 0; x < 64; x++) + { + for (y = 0; y < 64; y++) + { + if (parcelBitmap[x, y]) + { + parcelIDList[x, y] = lastParcelLocalID; + } + } + } + } + /// + /// Removes a parcel from the list. Will not remove if local_id is still owning an area in parcelIDList + /// + /// Parcel.localID of the parcel to remove. + public void removeParcel(int local_id) { - int searchParcel; - for(searchParcel = 0; searchParcel < this.parcelList.Count; searchParcel++) + int x, y; + for (x = 0; x < 64; x++) { - if(parcelList[searchParcel].containsPoint(x,y)) + for (y = 0; y < 64; y++) { - return this.parcelList[searchParcel]; + if (parcelIDList[x, y] == local_id) + { + throw new Exception("Could not remove parcel. Still being used at " + x + ", " + y); + } } } - throw new Exception("Error: Parcel not found at point " + x + ", " + y); + parcelList.Remove(local_id); + } + /// + /// Get the parcel at the specified point + /// + /// Value between 0 - 256 on the x axis of the point + /// Value between 0 - 256 on the y axis of the point + /// Parcel at the point supplied + public Parcel getParcel(int x, int y) + { + if (x > 256 || y > 256 || x < 0 || y < 0) + { + throw new Exception("Error: Parcel not found at point " + x + ", " + y); + } + else + { + return parcelList[parcelIDList[x / 4, y / 4]]; + } } #endregion #region Parcel Modification + /// + /// Subdivides a parcel + /// + /// West Point + /// South Point + /// East Point + /// North Point + /// LLUUID of user who is trying to subdivide + /// Returns true if successful public bool subdivide(int start_x, int start_y, int end_x, int end_y, LLUUID attempting_user_id) { //First, lets loop through the points and make sure they are all in the same parcel //Get the parcel at start Parcel startParcel = getParcel(start_x, start_y); - if(startParcel == null) return false; //No such parcel at the beginning - + if (startParcel == null) return false; //No such parcel at the beginning + //Loop through the points try { @@ -228,7 +188,7 @@ namespace OpenSim.world //If we are still here, then they are subdividing within one parcel //Check owner - if (startParcel.ownerID != attempting_user_id) + if (startParcel.parcelData.ownerID != attempting_user_id) { return false; //They cant do this! } @@ -236,17 +196,25 @@ namespace OpenSim.world //Lets create a new parcel with bitmap activated at that point (keeping the old parcels info) Parcel newParcel = startParcel; newParcel.setParcelBitmap(Parcel.getSquareParcelBitmap(start_x, start_y, end_x, end_y)); - + //Now, lets set the subdivision area of the original to false - int startParcelIndex = parcelList.IndexOf(startParcel); - parcelList[startParcelIndex].setParcelBitmap(Parcel.modifyParcelBitmapSquare(parcelList[startParcelIndex].getParcelBitmap(),start_x,start_y,end_x, end_y,false)); + int startParcelIndex = startParcel.parcelData.localID; + parcelList[startParcelIndex].setParcelBitmap(Parcel.modifyParcelBitmapSquare(parcelList[startParcelIndex].getParcelBitmap(), start_x, start_y, end_x, end_y, false)); //Now add the new parcel addParcel(newParcel); return true; } - + /// + /// Join 2 parcels together + /// + /// x value in first parcel + /// y value in first parcel + /// x value in second parcel + /// y value in second parcel + /// LLUUID of the avatar trying to join the parcels + /// Returns true if successful public bool join(int start_x, int start_y, int end_x, int end_y, LLUUID attempting_user_id) { //NOTE: The following only connects the parcels in each corner and not all the parcels that are within the selection box! @@ -262,11 +230,11 @@ namespace OpenSim.world return false; //Error occured when trying to get the start and end parcels } //Check the parcel owners: - if (startParcel.ownerID != endParcel.ownerID) + if (startParcel.parcelData.ownerID != endParcel.parcelData.ownerID) { return false; } - if (startParcel.ownerID != attempting_user_id) + if (startParcel.parcelData.ownerID != attempting_user_id) { //TODO: Group editing stuff. Avatar owner support for now return false; @@ -274,10 +242,10 @@ namespace OpenSim.world //Same owners! Lets join them //Merge them to startParcel - parcelList[parcelList.IndexOf(startParcel)].setParcelBitmap(Parcel.mergeParcelBitmaps(startParcel.getParcelBitmap(),endParcel.getParcelBitmap())); + parcelList[startParcel.parcelData.localID].setParcelBitmap(Parcel.mergeParcelBitmaps(startParcel.getParcelBitmap(), endParcel.getParcelBitmap())); //Remove the old parcel - parcelList.Remove(endParcel); + parcelList.Remove(endParcel.parcelData.localID); return true; @@ -307,17 +275,17 @@ namespace OpenSim.world byte tempByte = (byte)0; //This represents the byte for the current 4x4 Parcel currentParcelBlock = getParcel(x * 4, y * 4); - if (currentParcelBlock.ownerID == remote_client.AgentID) + if (currentParcelBlock.parcelData.ownerID == remote_client.AgentID) { //Owner Flag tempByte = Convert.ToByte(tempByte | PARCEL_TYPE_OWNED_BY_REQUESTER); } - else if (currentParcelBlock.salePrice > 0 && (currentParcelBlock.authBuyerID == LLUUID.Zero || currentParcelBlock.authBuyerID == remote_client.AgentID)) + else if (currentParcelBlock.parcelData.salePrice > 0 && (currentParcelBlock.parcelData.authBuyerID == LLUUID.Zero || currentParcelBlock.parcelData.authBuyerID == remote_client.AgentID)) { //Sale Flag tempByte = Convert.ToByte(tempByte | PARCEL_TYPE_IS_FOR_SALE); } - else if (currentParcelBlock.ownerID == LLUUID.Zero) + else if (currentParcelBlock.parcelData.ownerID == LLUUID.Zero) { //Public Flag tempByte = Convert.ToByte(tempByte | PARCEL_TYPE_PUBLIC); @@ -369,57 +337,45 @@ namespace OpenSim.world remote_client.OutPacket((Packet)packet); } #endregion + + /// + /// Resets the sim to the default parcel (full sim parcel owned by the default user) + /// public void resetSimParcels() { //Remove all the parcels in the sim and add a blank, full sim parcel set to public parcelList.Clear(); - Parcel fullSimParcel = new Parcel(LLUUID.Zero, false,m_world); + parcelIDList.Initialize(); + Parcel fullSimParcel = new Parcel(LLUUID.Zero, false, m_world); fullSimParcel.setParcelBitmap(Parcel.basicFullRegionParcelBitmap()); - fullSimParcel.parcelName = "Your Sim Parcel"; - fullSimParcel.parcelDesc = ""; - LLUUID Agent; - int AgentRand = OpenSim.Framework.Utilities.Util.RandomClass.Next(1, 9999); - Agent = new LLUUID("99998888-0100-" + AgentRand.ToString("0000") + "-8ec1-0b1d5cd6aead"); - - fullSimParcel.ownerID = Agent; - fullSimParcel.salePrice = 1; - fullSimParcel.parcelFlags = ParcelFlags.ForSale; + fullSimParcel.parcelData.parcelName = "Your Sim Parcel"; + fullSimParcel.parcelData.parcelDesc = ""; + fullSimParcel.parcelData.ownerID = LLUUID.Zero; + fullSimParcel.parcelData.salePrice = -1; + fullSimParcel.parcelData.parcelFlags = libsecondlife.Parcel.ParcelFlags.None; + fullSimParcel.parcelData.parcelStatus = libsecondlife.Parcel.ParcelStatus.Abandoned; addParcel(fullSimParcel); - - + + } #endregion } #endregion - + #region Parcel Class + /// + /// Keeps track of a specific parcel's information + /// public class Parcel { #region Member Variables - private bool[,] parcelBitmap = new bool[64,64]; - public string parcelName = ""; - public string parcelDesc = ""; - public LLUUID ownerID = new LLUUID(); - public bool isGroupOwned = false; - public LLVector3 AABBMin = new LLVector3(); - public LLVector3 AABBMax = new LLVector3(); - public int area = 0; - public uint auctionID = 0; //Unemplemented. If set to 0, not being auctioned - public LLUUID authBuyerID = new LLUUID(); //Unemplemented. Authorized Buyer's UUID - public ParcelCategory category = new ParcelCategory(); //Unemplemented. Parcel's chosen category - public int claimDate = 0; //Unemplemented - public int claimPrice = 0; //Unemplemented - public LLUUID groupID = new LLUUID(); //Unemplemented - public int groupPrims = 0; //Unemplemented - public int salePrice = 0; //Unemeplemented. Parcels price. - public ParcelStatus parcelStatus = ParcelStatus.None; - public ParcelFlags parcelFlags = ParcelFlags.None; - - private int localID; - private static int localIDCount = 0; - private World m_world; + public ParcelData parcelData = new ParcelData(); + public World m_world; + + private bool[,] parcelBitmap = new bool[64, 64]; + #endregion @@ -427,11 +383,8 @@ namespace OpenSim.world public Parcel(LLUUID owner_id, bool is_group_owned, World world) { m_world = world; - ownerID = owner_id; - isGroupOwned = is_group_owned; - - localID = localIDCount; - localIDCount++; + parcelData.ownerID = owner_id; + parcelData.isGroupOwned = is_group_owned; } #endregion @@ -440,6 +393,12 @@ namespace OpenSim.world #region Member Functions #region General Functions + /// + /// Checks to see if this parcel contains a point + /// + /// + /// + /// Returns true if the parcel contains the specified point public bool containsPoint(int x, int y) { if (x >= 0 && y >= 0 && x <= 256 && x <= 256) @@ -455,39 +414,45 @@ namespace OpenSim.world #region Packet Request Handling + /// + /// Sends parcel properties as requested + /// + /// ID sent by client for them to keep track of + /// Bool sent by client for them to use + /// Object representing the client public void sendParcelProperties(int sequence_id, bool snap_selection, ClientView remote_client) { ParcelPropertiesPacket updatePacket = new ParcelPropertiesPacket(); - updatePacket.ParcelData.AABBMax = AABBMax; - updatePacket.ParcelData.AABBMin = AABBMin; - updatePacket.ParcelData.Area = this.area; - updatePacket.ParcelData.AuctionID = this.auctionID; - updatePacket.ParcelData.AuthBuyerID = this.authBuyerID; //unemplemented + updatePacket.ParcelData.AABBMax = parcelData.AABBMax; + updatePacket.ParcelData.AABBMin = parcelData.AABBMin; + updatePacket.ParcelData.Area = this.parcelData.area; + updatePacket.ParcelData.AuctionID = this.parcelData.auctionID; + updatePacket.ParcelData.AuthBuyerID = this.parcelData.authBuyerID; //unemplemented updatePacket.ParcelData.Bitmap = this.convertParcelBitmapToBytes(); - updatePacket.ParcelData.Desc = libsecondlife.Helpers.StringToField(this.parcelDesc); - updatePacket.ParcelData.Category = (byte)this.category; - updatePacket.ParcelData.ClaimDate = this.claimDate; - updatePacket.ParcelData.ClaimPrice = this.claimPrice; - updatePacket.ParcelData.GroupID = this.groupID; - updatePacket.ParcelData.GroupPrims = this.groupPrims; - updatePacket.ParcelData.IsGroupOwned = this.isGroupOwned; + updatePacket.ParcelData.Desc = libsecondlife.Helpers.StringToField(this.parcelData.parcelDesc); + updatePacket.ParcelData.Category = (byte)this.parcelData.category; + updatePacket.ParcelData.ClaimDate = this.parcelData.claimDate; + updatePacket.ParcelData.ClaimPrice = this.parcelData.claimPrice; + updatePacket.ParcelData.GroupID = this.parcelData.groupID; + updatePacket.ParcelData.GroupPrims = this.parcelData.groupPrims; + updatePacket.ParcelData.IsGroupOwned = this.parcelData.isGroupOwned; updatePacket.ParcelData.LandingType = (byte)0; //unemplemented - updatePacket.ParcelData.LocalID = (byte)this.localID; + updatePacket.ParcelData.LocalID = (byte)this.parcelData.localID; updatePacket.ParcelData.MaxPrims = 1000; //unemplemented updatePacket.ParcelData.MediaAutoScale = (byte)0; //unemplemented updatePacket.ParcelData.MediaID = LLUUID.Zero; //unemplemented updatePacket.ParcelData.MediaURL = Helpers.StringToField(""); //unemplemented updatePacket.ParcelData.MusicURL = Helpers.StringToField(""); //unemplemented - updatePacket.ParcelData.Name = Helpers.StringToField(this.parcelName); + updatePacket.ParcelData.Name = Helpers.StringToField(this.parcelData.parcelName); updatePacket.ParcelData.OtherCleanTime = 0; //unemplemented updatePacket.ParcelData.OtherCount = 0; //unemplemented updatePacket.ParcelData.OtherPrims = 0; //unemplented - updatePacket.ParcelData.OwnerID = this.ownerID; + updatePacket.ParcelData.OwnerID = this.parcelData.ownerID; updatePacket.ParcelData.OwnerPrims = 0; //unemplemented - updatePacket.ParcelData.ParcelFlags = (uint)this.parcelFlags; //unemplemented + updatePacket.ParcelData.ParcelFlags = (uint)this.parcelData.parcelFlags; //unemplemented updatePacket.ParcelData.ParcelPrimBonus = (float)1.0; //unemplemented updatePacket.ParcelData.PassHours = (float)0.0; //unemplemented updatePacket.ParcelData.PassPrice = 0; //unemeplemented @@ -498,7 +463,7 @@ namespace OpenSim.world updatePacket.ParcelData.RegionPushOverride = true; //unemplemented updatePacket.ParcelData.RentPrice = 0; //?? updatePacket.ParcelData.RequestResult = 0;//?? - updatePacket.ParcelData.SalePrice = this.salePrice; //unemplemented + updatePacket.ParcelData.SalePrice = this.parcelData.salePrice; //unemplemented updatePacket.ParcelData.SelectedPrims = 0; //unemeplemented updatePacket.ParcelData.SelfCount = 0;//unemplemented updatePacket.ParcelData.SequenceID = sequence_id; @@ -506,17 +471,20 @@ namespace OpenSim.world updatePacket.ParcelData.SimWideTotalPrims = 0; //unemplemented updatePacket.ParcelData.SnapSelection = snap_selection; //Bleh - not important yet updatePacket.ParcelData.SnapshotID = LLUUID.Zero; //Unemplemented - updatePacket.ParcelData.Status = (byte)this.parcelStatus; //?? + updatePacket.ParcelData.Status = (byte)this.parcelData.parcelStatus; //?? updatePacket.ParcelData.TotalPrims = 0; //unemplemented updatePacket.ParcelData.UserLocation = LLVector3.Zero; //unemplemented updatePacket.ParcelData.UserLookAt = LLVector3.Zero; //unemeplemented - + remote_client.OutPacket((Packet)updatePacket); } #endregion #region Update Functions + /// + /// Updates the AABBMin and AABBMax values after area/shape modification of parcel + /// private void updateAABBAndAreaValues() { int min_x = 64; @@ -539,14 +507,27 @@ namespace OpenSim.world } } } - this.AABBMin = new LLVector3((float)(min_x * 4), (float)(min_y * 4), m_world.Terrain[(min_x * 4), (min_y * 4)]); - this.AABBMax = new LLVector3((float)(max_x * 4), (float)(max_y * 4), m_world.Terrain[(max_x * 4), (max_y * 4)]); - this.area = tempArea; + this.parcelData.AABBMin = new LLVector3((float)(min_x * 4), (float)(min_y * 4), m_world.Terrain[(min_x * 4), (min_y * 4)]); + this.parcelData.AABBMax = new LLVector3((float)(max_x * 4), (float)(max_y * 4), m_world.Terrain[(max_x * 4), (max_y * 4)]); + this.parcelData.area = tempArea; + } + + public void updateParcelBitmapByteArray() + { + parcelData.parcelBitmapByteArray = convertParcelBitmapToBytes(); + } + public void setParcelBitmapFromByteArray() + { + parcelBitmap = convertBytesToParcelBitmap(); } #endregion #region Parcel Bitmap Functions + /// + /// Sets the parcel's bitmap manually + /// + /// 64x64 block representing where this parcel is on a map public void setParcelBitmap(bool[,] bitmap) { if (bitmap.GetLength(0) != 64 || bitmap.GetLength(1) != 64 || bitmap.Rank != 2) @@ -559,23 +540,32 @@ namespace OpenSim.world //Valid: Lets set it this.parcelBitmap = bitmap; updateAABBAndAreaValues(); + updateParcelBitmapByteArray(); } } + /// + /// Gets the parcels bitmap manually + /// + /// public bool[,] getParcelBitmap() { return parcelBitmap; } + /// + /// Converts the parcel bitmap to a packet friendly byte array + /// + /// private byte[] convertParcelBitmapToBytes() { byte[] tempConvertArr = new byte[64 * 64 / 8]; byte tempByte = 0; - int x, y,i, byteNum = 0; + int x, y, i, byteNum = 0; i = 0; - for (x = 0; x < 64; x++) + for (y = 0; y < 64; y++) { - for (y = 0; y < 64; y++) + for (x = 0; x < 64; x++) { - tempByte = Convert.ToByte(tempByte | Convert.ToByte(parcelBitmap[x,y]) << (i++ % 8)); + tempByte = Convert.ToByte(tempByte | Convert.ToByte(parcelBitmap[x, y]) << (i++ % 8)); if (i % 8 == 0) { tempConvertArr[byteNum] = tempByte; @@ -585,14 +575,44 @@ namespace OpenSim.world } } } - tempByte.ToString(); return tempConvertArr; } + private bool[,] convertBytesToParcelBitmap() + { + bool[,] tempConvertMap = new bool[64, 64]; + + byte tempByte = 0; + int x = 0, y = 0, i = 0, bitNum = 0; + for(i = 0; i < 512; i++) + { + tempByte = parcelData.parcelBitmapByteArray[i]; + for(bitNum = 7; bitNum >= 0; bitNum--) + { + bool bit = Convert.ToBoolean(Convert.ToByte(tempByte >> bitNum) & (byte)1); + tempConvertMap[x, y] = bit; + if (x >= 64) y++; + } + } + return tempConvertMap; + } + /// + /// Full sim parcel creation + /// + /// public static bool[,] basicFullRegionParcelBitmap() { return getSquareParcelBitmap(0, 0, 256, 256); } + + /// + /// Used to modify the bitmap between the x and y points. Points use 64 scale + /// + /// + /// + /// + /// + /// public static bool[,] getSquareParcelBitmap(int start_x, int start_y, int end_x, int end_y) { @@ -602,6 +622,17 @@ namespace OpenSim.world tempBitmap = modifyParcelBitmapSquare(tempBitmap, start_x, start_y, end_x, end_x, true); return tempBitmap; } + + /// + /// Change a parcel's bitmap at within a square and set those points to a specific value + /// + /// + /// + /// + /// + /// + /// + /// public static bool[,] modifyParcelBitmapSquare(bool[,] parcel_bitmap, int start_x, int start_y, int end_x, int end_y, bool set_value) { if (parcel_bitmap.GetLength(0) != 64 || parcel_bitmap.GetLength(1) != 64 || parcel_bitmap.Rank != 2) @@ -624,6 +655,12 @@ namespace OpenSim.world } return parcel_bitmap; } + /// + /// Join the true values of 2 bitmaps together + /// + /// + /// + /// public static bool[,] mergeParcelBitmaps(bool[,] bitmap_base, bool[,] bitmap_add) { if (bitmap_base.GetLength(0) != 64 || bitmap_base.GetLength(1) != 64 || bitmap_base.Rank != 2) @@ -642,7 +679,7 @@ namespace OpenSim.world { for (y = 0; y < 64; y++) { - if (bitmap_add[x,y]) + if (bitmap_add[x, y]) { bitmap_base[x, y] = true; } @@ -653,6 +690,10 @@ namespace OpenSim.world #endregion #endregion + + } #endregion + + } diff --git a/OpenSim/OpenSim.RegionServer/world/World.PacketHandlers.cs b/OpenSim/OpenSim.RegionServer/world/World.PacketHandlers.cs index 74b8e9d..8924773 100644 --- a/OpenSim/OpenSim.RegionServer/world/World.PacketHandlers.cs +++ b/OpenSim/OpenSim.RegionServer/world/World.PacketHandlers.cs @@ -10,6 +10,7 @@ using OpenSim.Framework.Terrain; using OpenSim.Framework.Inventory; using OpenSim.Framework.Utilities; using OpenSim.Assets; +using OpenSim.RegionServer.world; namespace OpenSim.world { @@ -296,7 +297,7 @@ namespace OpenSim.world void ParcelPropertiesRequest(int start_x, int start_y, int end_x, int end_y, int sequence_id, bool snap_selection, ClientView remote_client) { //Get the parcels within the bounds - List temp = new List(); + List temp = new List(); int x, y; int inc_x = end_x - start_x; int inc_y = end_y - start_y; @@ -304,7 +305,7 @@ namespace OpenSim.world { for(y = 0; y < inc_y; y++) { - Parcel currentParcel = parcelManager.getParcel(start_x + x,start_y + y); + OpenSim.RegionServer.world.Parcel currentParcel = parcelManager.getParcel(start_x + x, start_y + y); if(!temp.Contains(currentParcel)) { temp.Add(currentParcel); diff --git a/OpenSim/OpenSim.RegionServer/world/World.cs b/OpenSim/OpenSim.RegionServer/world/World.cs index d2a13ca..92de6f0 100644 --- a/OpenSim/OpenSim.RegionServer/world/World.cs +++ b/OpenSim/OpenSim.RegionServer/world/World.cs @@ -35,7 +35,7 @@ namespace OpenSim.world private Dictionary m_scripts; private Mutex updateLock; public string m_datastore; - public ParcelManager parcelManager; + public OpenSim.RegionServer.world.ParcelManager parcelManager; #region Properties public PhysicsScene PhysScene @@ -86,7 +86,6 @@ namespace OpenSim.world Avatar.LoadAnims(); this.SetDefaultScripts(); this.LoadScriptEngines(); - parcelManager = new ParcelManager(this); } catch (Exception e) @@ -252,6 +251,17 @@ namespace OpenSim.world Entities[UUID].BackUp(); } + + //Parcel backup routines. Yay! + ParcelData[] parcels = new ParcelData[parcelManager.parcelList.Count]; + int i; + for(i = 0; i < parcelManager.parcelList.Count; i++) + { + parcels[i] = parcelManager.parcelList[i].parcelData; + } + localStorage.SaveParcels(parcels); + + // Backup successful return true; } @@ -576,7 +586,7 @@ namespace OpenSim.world agentClient.OnUpdatePrimScale += new ClientView.UpdatePrimVector(this.UpdatePrimScale); agentClient.OnDeRezObject += new ClientView.GenericCall4(this.DeRezObject); - agentClient.OnParcelPropertiesRequest += new ParcelPropertiesRequest(ParcelPropertiesRequest); + agentClient.OnParcelPropertiesRequest += new OpenSim.RegionServer.world.ParcelPropertiesRequest(ParcelPropertiesRequest); Avatar newAvatar = null; try { diff --git a/OpenSim/OpenSim.Storage/LocalStorageBerkeleyDB/BDBLocalStorage.cs b/OpenSim/OpenSim.Storage/LocalStorageBerkeleyDB/BDBLocalStorage.cs index d4db8c0..7c8ee88 100644 --- a/OpenSim/OpenSim.Storage/LocalStorageBerkeleyDB/BDBLocalStorage.cs +++ b/OpenSim/OpenSim.Storage/LocalStorageBerkeleyDB/BDBLocalStorage.cs @@ -86,6 +86,17 @@ namespace OpenSim.Storage.LocalStorageBDB { } + + public void SaveParcels(ParcelData[] parcel_data) + { + } + + + public void LoadParcels(ILocalStorageParcelReceiver recv) + { + recv.NoParcelDataFromStorage(); + } + public void ShutDown() { sim.GetDb().Close(); diff --git a/OpenSim/OpenSim.Storage/LocalStorageDb4o/Db4LocalStorage.cs b/OpenSim/OpenSim.Storage/LocalStorageDb4o/Db4LocalStorage.cs index 5dceb7f..087db96 100644 --- a/OpenSim/OpenSim.Storage/LocalStorageDb4o/Db4LocalStorage.cs +++ b/OpenSim/OpenSim.Storage/LocalStorageDb4o/Db4LocalStorage.cs @@ -28,11 +28,13 @@ using System; using System.Collections.Generic; using Db4objects.Db4o; using Db4objects.Db4o.Query; + using libsecondlife; using OpenSim.Framework.Interfaces; using OpenSim.Framework.Types; using OpenSim.Framework.Terrain; + namespace OpenSim.Storage.LocalStorageDb4o { /// @@ -173,10 +175,49 @@ namespace OpenSim.Storage.LocalStorageDb4o db.Commit(); } + public void SaveParcels(ParcelData[] parcel_data) + { + OpenSim.Framework.Console.MainConsole.Instance.WriteLine(OpenSim.Framework.Console.LogPriority.LOW, "Parcel Backup: Saving Parcels..."); + IObjectSet result = db.Get(typeof(ParcelData)); + foreach (ParcelData parcel in result) + { + db.Delete(parcel); + } + OpenSim.Framework.Console.MainConsole.Instance.WriteLine(OpenSim.Framework.Console.LogPriority.LOW, "Parcel Backup: Removing old entries complete. Adding new entries."); + int i; + for (i = 0; i < parcel_data.GetLength(0); i++) + { + OpenSim.Framework.Console.MainConsole.Instance.WriteLine(OpenSim.Framework.Console.LogPriority.LOW, "Adding : " + i); + db.Set(parcel_data[i]); + + } + db.Commit(); + OpenSim.Framework.Console.MainConsole.Instance.WriteLine(OpenSim.Framework.Console.LogPriority.LOW, "Parcel Backup: Parcel Save Complete"); + } + + public void LoadParcels(ILocalStorageParcelReceiver recv) + { + OpenSim.Framework.Console.MainConsole.Instance.WriteLine(OpenSim.Framework.Console.LogPriority.LOW, "Parcel Backup: Loading Parcels..."); + IObjectSet result = db.Get(typeof(ParcelData)); + if (result.Count > 0) + { + OpenSim.Framework.Console.MainConsole.Instance.WriteLine(OpenSim.Framework.Console.LogPriority.LOW, "Parcel Backup: Parcels exist in database."); + foreach (ParcelData parcelData in result) + { + recv.ParcelFromStorage(parcelData); + } + } + else + { + OpenSim.Framework.Console.MainConsole.Instance.WriteLine(OpenSim.Framework.Console.LogPriority.LOW, "Parcel Backup: No parcels exist. Creating basic parcel."); + recv.NoParcelDataFromStorage(); + } + OpenSim.Framework.Console.MainConsole.Instance.WriteLine(OpenSim.Framework.Console.LogPriority.LOW, "Parcel Backup: Parcels Restored"); + } public void ShutDown() { db.Commit(); db.Close(); } } -} +} \ No newline at end of file diff --git a/OpenSim/OpenSim.Storage/LocalStorageSQLite/SQLiteLocalStorage.cs b/OpenSim/OpenSim.Storage/LocalStorageSQLite/SQLiteLocalStorage.cs index 368405b..1f4c6be 100644 --- a/OpenSim/OpenSim.Storage/LocalStorageSQLite/SQLiteLocalStorage.cs +++ b/OpenSim/OpenSim.Storage/LocalStorageSQLite/SQLiteLocalStorage.cs @@ -167,6 +167,16 @@ namespace OpenSim.Storage.LocalStorageSQLite } + public void SaveParcels(ParcelData[] parcel_manager) + { + + } + + public void LoadParcels(ILocalStorageParcelReceiver recv) + { + recv.NoParcelDataFromStorage(); + } + public void ShutDown() { db.Close(); diff --git a/OpenSim/OpenSim/OpenSimMain.cs b/OpenSim/OpenSim/OpenSimMain.cs index 9025316..39ba55e 100644 --- a/OpenSim/OpenSim/OpenSimMain.cs +++ b/OpenSim/OpenSim/OpenSimMain.cs @@ -254,6 +254,12 @@ namespace OpenSim LocalWorld.LoadStorageDLL("OpenSim.Storage.LocalStorageDb4o.dll"); //all these dll names shouldn't be hard coded. LocalWorld.LoadWorldMap(); + Console.WriteLine("Creating ParcelManager"); + LocalWorld.parcelManager = new OpenSim.RegionServer.world.ParcelManager(this.LocalWorld); + + Console.WriteLine("Loading Parcels from DB..."); + LocalWorld.localStorage.LoadParcels((ILocalStorageParcelReceiver)LocalWorld.parcelManager); + m_console.WriteLine(OpenSim.Framework.Console.LogPriority.LOW, "Main.cs:Startup() - Starting up messaging system"); LocalWorld.PhysScene = this.physManager.GetPhysicsScene(this.m_physicsEngine); LocalWorld.PhysScene.SetTerrain(LocalWorld.Terrain.getHeights1D()); -- cgit v1.1