From 109b51758398d24a96a16900e8feb24361aee29d Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Sat, 11 Sep 2010 20:43:06 -0700 Subject: Fixed the naming mess around data connectors for simulation data --- OpenSim/Data/MSSQL/MSSQLLegacyRegionData.cs | 1572 -------------- OpenSim/Data/MSSQL/MSSQLSimulationData.cs | 1572 ++++++++++++++ OpenSim/Data/MySQL/MySQLLegacyRegionData.cs | 1820 ---------------- OpenSim/Data/MySQL/MySQLSimulationData.cs | 1820 ++++++++++++++++ OpenSim/Data/Null/NullDataStore.cs | 112 - OpenSim/Data/Null/NullSimulationData.cs | 112 + OpenSim/Data/SQLite/SQLiteRegionData.cs | 2355 --------------------- OpenSim/Data/SQLite/SQLiteSimulationData.cs | 2355 +++++++++++++++++++++ OpenSim/Data/SQLiteLegacy/SQLiteRegionData.cs | 2261 -------------------- OpenSim/Data/SQLiteLegacy/SQLiteSimulationData.cs | 2261 ++++++++++++++++++++ OpenSim/Data/Tests/RegionTests.cs | 12 +- 11 files changed, 8126 insertions(+), 8126 deletions(-) delete mode 100644 OpenSim/Data/MSSQL/MSSQLLegacyRegionData.cs create mode 100644 OpenSim/Data/MSSQL/MSSQLSimulationData.cs delete mode 100644 OpenSim/Data/MySQL/MySQLLegacyRegionData.cs create mode 100644 OpenSim/Data/MySQL/MySQLSimulationData.cs delete mode 100644 OpenSim/Data/Null/NullDataStore.cs create mode 100644 OpenSim/Data/Null/NullSimulationData.cs delete mode 100644 OpenSim/Data/SQLite/SQLiteRegionData.cs create mode 100644 OpenSim/Data/SQLite/SQLiteSimulationData.cs delete mode 100644 OpenSim/Data/SQLiteLegacy/SQLiteRegionData.cs create mode 100644 OpenSim/Data/SQLiteLegacy/SQLiteSimulationData.cs (limited to 'OpenSim/Data') diff --git a/OpenSim/Data/MSSQL/MSSQLLegacyRegionData.cs b/OpenSim/Data/MSSQL/MSSQLLegacyRegionData.cs deleted file mode 100644 index 77b8a10..0000000 --- a/OpenSim/Data/MSSQL/MSSQLLegacyRegionData.cs +++ /dev/null @@ -1,1572 +0,0 @@ -/* - * 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.Data; -using System.Data.SqlClient; -using System.Drawing; -using System.IO; -using System.Reflection; -using log4net; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Data.MSSQL -{ - /// - /// A MSSQL Interface for the Region Server. - /// - public class MSSQLRegionDataStore : IRegionDataStore - { - private const string _migrationStore = "RegionStore"; - - // private static FileSystemDataStore Instance = new FileSystemDataStore(); - private static readonly ILog _Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - /// - /// The database manager - /// - private MSSQLManager _Database; - private string m_connectionString; - /// - /// Initialises the region datastore - /// - /// The connection string. - public void Initialise(string connectionString) - { - m_connectionString = connectionString; - _Database = new MSSQLManager(connectionString); - - - //Migration settings - _Database.CheckMigration(_migrationStore); - } - - /// - /// Dispose the database - /// - public void Dispose() { } - - #region SceneObjectGroup region for loading and Store of the scene. - - /// - /// Loads the objects present in the region. - /// - /// The region UUID. - /// - public List LoadObjects(UUID regionUUID) - { - UUID lastGroupID = UUID.Zero; - - Dictionary prims = new Dictionary(); - Dictionary objects = new Dictionary(); - SceneObjectGroup grp = null; - - string sql = "SELECT *, " + - "sort = CASE WHEN prims.UUID = prims.SceneGroupID THEN 0 ELSE 1 END " + - "FROM prims " + - "LEFT JOIN primshapes ON prims.UUID = primshapes.UUID " + - "WHERE RegionUUID = @RegionUUID " + - "ORDER BY SceneGroupID asc, sort asc, LinkNumber asc"; - - using (SqlConnection conn = new SqlConnection(m_connectionString)) - using (SqlCommand command = new SqlCommand(sql, conn)) - { - command.Parameters.Add(_Database.CreateParameter("@regionUUID", regionUUID)); - conn.Open(); - using (SqlDataReader reader = command.ExecuteReader()) - { - while (reader.Read()) - { - SceneObjectPart sceneObjectPart = BuildPrim(reader); - if (reader["Shape"] is DBNull) - sceneObjectPart.Shape = PrimitiveBaseShape.Default; - else - sceneObjectPart.Shape = BuildShape(reader); - - prims[sceneObjectPart.UUID] = sceneObjectPart; - - UUID groupID = new UUID((Guid)reader["SceneGroupID"]); - - if (groupID != lastGroupID) // New SOG - { - if (grp != null) - objects[grp.UUID] = grp; - - lastGroupID = groupID; - - // There sometimes exist OpenSim bugs that 'orphan groups' so that none of the prims are - // recorded as the root prim (for which the UUID must equal the persisted group UUID). In - // this case, force the UUID to be the same as the group UUID so that at least these can be - // deleted (we need to change the UUID so that any other prims in the linkset can also be - // deleted). - if (sceneObjectPart.UUID != groupID && groupID != UUID.Zero) - { - _Log.WarnFormat( - "[REGION DB]: Found root prim {0} {1} at {2} where group was actually {3}. Forcing UUID to group UUID", - sceneObjectPart.Name, sceneObjectPart.UUID, sceneObjectPart.GroupPosition, groupID); - - sceneObjectPart.UUID = groupID; - } - - grp = new SceneObjectGroup(sceneObjectPart); - } - else - { - // Black magic to preserve link numbers - // Why is this needed, fix this in AddPart method. - int link = sceneObjectPart.LinkNum; - - grp.AddPart(sceneObjectPart); - - if (link != 0) - sceneObjectPart.LinkNum = link; - } - } - } - } - - if (grp != null) - objects[grp.UUID] = grp; - - // Instead of attempting to LoadItems on every prim, - // most of which probably have no items... get a - // list from DB of all prims which have items and - // LoadItems only on those - List primsWithInventory = new List(); - string qry = "select distinct primID from primitems"; - using (SqlConnection conn = new SqlConnection(m_connectionString)) - using (SqlCommand command = new SqlCommand(qry, conn)) - { - conn.Open(); - using (SqlDataReader itemReader = command.ExecuteReader()) - { - while (itemReader.Read()) - { - if (!(itemReader["primID"] is DBNull)) - { - UUID primID = new UUID(itemReader["primID"].ToString()); - if (prims.ContainsKey(primID)) - { - primsWithInventory.Add(prims[primID]); - } - } - } - } - } - - LoadItems(primsWithInventory); - - _Log.DebugFormat("[REGION DB]: Loaded {0} objects using {1} prims", objects.Count, prims.Count); - - return new List(objects.Values); - } - - /// - /// Load in the prim's persisted inventory. - /// - /// all prims with inventory on a region - private void LoadItems(List allPrimsWithInventory) - { - string sql = "SELECT * FROM primitems WHERE PrimID = @PrimID"; - using (SqlConnection conn = new SqlConnection(m_connectionString)) - using (SqlCommand command = new SqlCommand(sql, conn)) - { - conn.Open(); - foreach (SceneObjectPart objectPart in allPrimsWithInventory) - { - command.Parameters.Clear(); - command.Parameters.Add(_Database.CreateParameter("@PrimID", objectPart.UUID)); - - List inventory = new List(); - - using (SqlDataReader reader = command.ExecuteReader()) - { - while (reader.Read()) - { - TaskInventoryItem item = BuildItem(reader); - - item.ParentID = objectPart.UUID; // Values in database are - // often wrong - inventory.Add(item); - } - } - - objectPart.Inventory.RestoreInventoryItems(inventory); - } - } - } - - /// - /// Stores all object's details apart from inventory - /// - /// - /// - public void StoreObject(SceneObjectGroup obj, UUID regionUUID) - { - _Log.DebugFormat("[MSSQL]: Adding/Changing SceneObjectGroup: {0} to region: {1}, object has {2} prims.", obj.UUID, regionUUID, obj.Children.Count); - - using (SqlConnection conn = new SqlConnection(m_connectionString)) - { - conn.Open(); - SqlTransaction transaction = conn.BeginTransaction(); - - try - { - foreach (SceneObjectPart sceneObjectPart in obj.Children.Values) - { - //Update prim - using (SqlCommand sqlCommand = conn.CreateCommand()) - { - sqlCommand.Transaction = transaction; - try - { - StoreSceneObjectPrim(sceneObjectPart, sqlCommand, obj.UUID, regionUUID); - } - catch (SqlException sqlEx) - { - _Log.ErrorFormat("[REGION DB]: Store SceneObjectPrim SQL error: {0} at line {1}", sqlEx.Message, sqlEx.LineNumber); - throw; - } - } - - //Update primshapes - using (SqlCommand sqlCommand = conn.CreateCommand()) - { - sqlCommand.Transaction = transaction; - try - { - StoreSceneObjectPrimShapes(sceneObjectPart, sqlCommand, obj.UUID, regionUUID); - } - catch (SqlException sqlEx) - { - _Log.ErrorFormat("[REGION DB]: Store SceneObjectPrimShapes SQL error: {0} at line {1}", sqlEx.Message, sqlEx.LineNumber); - throw; - } - } - } - - transaction.Commit(); - } - catch (Exception ex) - { - _Log.ErrorFormat("[REGION DB]: Store SceneObjectGroup error: {0}, Rolling back...", ex.Message); - try - { - transaction.Rollback(); - } - catch (Exception ex2) - { - //Show error - _Log.InfoFormat("[REGION DB]: Rollback of SceneObjectGroup store transaction failed with error: {0}", ex2.Message); - - } - } - } - } - - /// - /// Stores the prim of the sceneobjectpart. - /// - /// The sceneobjectpart or prim. - /// The SQL command with the transaction. - /// The scenegroup UUID. - /// The region UUID. - private void StoreSceneObjectPrim(SceneObjectPart sceneObjectPart, SqlCommand sqlCommand, UUID sceneGroupID, UUID regionUUID) - { - //Big query to update or insert a new prim. - //Note for SQL Server 2008 this could be simplified - string queryPrims = @" -IF EXISTS (SELECT UUID FROM prims WHERE UUID = @UUID) - BEGIN - UPDATE prims SET - CreationDate = @CreationDate, Name = @Name, Text = @Text, Description = @Description, SitName = @SitName, - TouchName = @TouchName, ObjectFlags = @ObjectFlags, OwnerMask = @OwnerMask, NextOwnerMask = @NextOwnerMask, GroupMask = @GroupMask, - EveryoneMask = @EveryoneMask, BaseMask = @BaseMask, PositionX = @PositionX, PositionY = @PositionY, PositionZ = @PositionZ, - GroupPositionX = @GroupPositionX, GroupPositionY = @GroupPositionY, GroupPositionZ = @GroupPositionZ, VelocityX = @VelocityX, - VelocityY = @VelocityY, VelocityZ = @VelocityZ, AngularVelocityX = @AngularVelocityX, AngularVelocityY = @AngularVelocityY, - AngularVelocityZ = @AngularVelocityZ, AccelerationX = @AccelerationX, AccelerationY = @AccelerationY, - AccelerationZ = @AccelerationZ, RotationX = @RotationX, RotationY = @RotationY, RotationZ = @RotationZ, RotationW = @RotationW, - SitTargetOffsetX = @SitTargetOffsetX, SitTargetOffsetY = @SitTargetOffsetY, SitTargetOffsetZ = @SitTargetOffsetZ, - SitTargetOrientW = @SitTargetOrientW, SitTargetOrientX = @SitTargetOrientX, SitTargetOrientY = @SitTargetOrientY, - SitTargetOrientZ = @SitTargetOrientZ, RegionUUID = @RegionUUID, CreatorID = @CreatorID, OwnerID = @OwnerID, GroupID = @GroupID, - LastOwnerID = @LastOwnerID, SceneGroupID = @SceneGroupID, PayPrice = @PayPrice, PayButton1 = @PayButton1, PayButton2 = @PayButton2, - PayButton3 = @PayButton3, PayButton4 = @PayButton4, LoopedSound = @LoopedSound, LoopedSoundGain = @LoopedSoundGain, - TextureAnimation = @TextureAnimation, OmegaX = @OmegaX, OmegaY = @OmegaY, OmegaZ = @OmegaZ, CameraEyeOffsetX = @CameraEyeOffsetX, - CameraEyeOffsetY = @CameraEyeOffsetY, CameraEyeOffsetZ = @CameraEyeOffsetZ, CameraAtOffsetX = @CameraAtOffsetX, - CameraAtOffsetY = @CameraAtOffsetY, CameraAtOffsetZ = @CameraAtOffsetZ, ForceMouselook = @ForceMouselook, - ScriptAccessPin = @ScriptAccessPin, AllowedDrop = @AllowedDrop, DieAtEdge = @DieAtEdge, SalePrice = @SalePrice, - SaleType = @SaleType, ColorR = @ColorR, ColorG = @ColorG, ColorB = @ColorB, ColorA = @ColorA, ParticleSystem = @ParticleSystem, - ClickAction = @ClickAction, Material = @Material, CollisionSound = @CollisionSound, CollisionSoundVolume = @CollisionSoundVolume, PassTouches = @PassTouches, - LinkNumber = @LinkNumber, MediaURL = @MediaURL - WHERE UUID = @UUID - END -ELSE - BEGIN - INSERT INTO - prims ( - UUID, CreationDate, Name, Text, Description, SitName, TouchName, ObjectFlags, OwnerMask, NextOwnerMask, GroupMask, - EveryoneMask, BaseMask, PositionX, PositionY, PositionZ, GroupPositionX, GroupPositionY, GroupPositionZ, VelocityX, - VelocityY, VelocityZ, AngularVelocityX, AngularVelocityY, AngularVelocityZ, AccelerationX, AccelerationY, AccelerationZ, - RotationX, RotationY, RotationZ, RotationW, SitTargetOffsetX, SitTargetOffsetY, SitTargetOffsetZ, SitTargetOrientW, - SitTargetOrientX, SitTargetOrientY, SitTargetOrientZ, RegionUUID, CreatorID, OwnerID, GroupID, LastOwnerID, SceneGroupID, - PayPrice, PayButton1, PayButton2, PayButton3, PayButton4, LoopedSound, LoopedSoundGain, TextureAnimation, OmegaX, - OmegaY, OmegaZ, CameraEyeOffsetX, CameraEyeOffsetY, CameraEyeOffsetZ, CameraAtOffsetX, CameraAtOffsetY, CameraAtOffsetZ, - ForceMouselook, ScriptAccessPin, AllowedDrop, DieAtEdge, SalePrice, SaleType, ColorR, ColorG, ColorB, ColorA, - ParticleSystem, ClickAction, Material, CollisionSound, CollisionSoundVolume, PassTouches, LinkNumber, MediaURL - ) VALUES ( - @UUID, @CreationDate, @Name, @Text, @Description, @SitName, @TouchName, @ObjectFlags, @OwnerMask, @NextOwnerMask, @GroupMask, - @EveryoneMask, @BaseMask, @PositionX, @PositionY, @PositionZ, @GroupPositionX, @GroupPositionY, @GroupPositionZ, @VelocityX, - @VelocityY, @VelocityZ, @AngularVelocityX, @AngularVelocityY, @AngularVelocityZ, @AccelerationX, @AccelerationY, @AccelerationZ, - @RotationX, @RotationY, @RotationZ, @RotationW, @SitTargetOffsetX, @SitTargetOffsetY, @SitTargetOffsetZ, @SitTargetOrientW, - @SitTargetOrientX, @SitTargetOrientY, @SitTargetOrientZ, @RegionUUID, @CreatorID, @OwnerID, @GroupID, @LastOwnerID, @SceneGroupID, - @PayPrice, @PayButton1, @PayButton2, @PayButton3, @PayButton4, @LoopedSound, @LoopedSoundGain, @TextureAnimation, @OmegaX, - @OmegaY, @OmegaZ, @CameraEyeOffsetX, @CameraEyeOffsetY, @CameraEyeOffsetZ, @CameraAtOffsetX, @CameraAtOffsetY, @CameraAtOffsetZ, - @ForceMouselook, @ScriptAccessPin, @AllowedDrop, @DieAtEdge, @SalePrice, @SaleType, @ColorR, @ColorG, @ColorB, @ColorA, - @ParticleSystem, @ClickAction, @Material, @CollisionSound, @CollisionSoundVolume, @PassTouches, @LinkNumber, @MediaURL - ) - END"; - - //Set commandtext. - sqlCommand.CommandText = queryPrims; - //Add parameters - sqlCommand.Parameters.AddRange(CreatePrimParameters(sceneObjectPart, sceneGroupID, regionUUID)); - - //Execute the query. If it fails then error is trapped in calling function - sqlCommand.ExecuteNonQuery(); - } - - /// - /// Stores the scene object prim shapes. - /// - /// The sceneobjectpart containing prim shape. - /// The SQL command with the transaction. - /// The scenegroup UUID. - /// The region UUID. - private void StoreSceneObjectPrimShapes(SceneObjectPart sceneObjectPart, SqlCommand sqlCommand, UUID sceneGroupID, UUID regionUUID) - { - //Big query to or insert or update primshapes - //Note for SQL Server 2008 this can be simplified - string queryPrimShapes = @" -IF EXISTS (SELECT UUID FROM primshapes WHERE UUID = @UUID) - BEGIN - UPDATE primshapes SET - Shape = @Shape, ScaleX = @ScaleX, ScaleY = @ScaleY, ScaleZ = @ScaleZ, PCode = @PCode, PathBegin = @PathBegin, - PathEnd = @PathEnd, PathScaleX = @PathScaleX, PathScaleY = @PathScaleY, PathShearX = @PathShearX, PathShearY = @PathShearY, - PathSkew = @PathSkew, PathCurve = @PathCurve, PathRadiusOffset = @PathRadiusOffset, PathRevolutions = @PathRevolutions, - PathTaperX = @PathTaperX, PathTaperY = @PathTaperY, PathTwist = @PathTwist, PathTwistBegin = @PathTwistBegin, - ProfileBegin = @ProfileBegin, ProfileEnd = @ProfileEnd, ProfileCurve = @ProfileCurve, ProfileHollow = @ProfileHollow, - Texture = @Texture, ExtraParams = @ExtraParams, State = @State, Media = @Media - WHERE UUID = @UUID - END -ELSE - BEGIN - INSERT INTO - primshapes ( - UUID, Shape, ScaleX, ScaleY, ScaleZ, PCode, PathBegin, PathEnd, PathScaleX, PathScaleY, PathShearX, PathShearY, - PathSkew, PathCurve, PathRadiusOffset, PathRevolutions, PathTaperX, PathTaperY, PathTwist, PathTwistBegin, ProfileBegin, - ProfileEnd, ProfileCurve, ProfileHollow, Texture, ExtraParams, State, Media - ) VALUES ( - @UUID, @Shape, @ScaleX, @ScaleY, @ScaleZ, @PCode, @PathBegin, @PathEnd, @PathScaleX, @PathScaleY, @PathShearX, @PathShearY, - @PathSkew, @PathCurve, @PathRadiusOffset, @PathRevolutions, @PathTaperX, @PathTaperY, @PathTwist, @PathTwistBegin, @ProfileBegin, - @ProfileEnd, @ProfileCurve, @ProfileHollow, @Texture, @ExtraParams, @State, @Media - ) - END"; - - //Set commandtext. - sqlCommand.CommandText = queryPrimShapes; - - //Add parameters - sqlCommand.Parameters.AddRange(CreatePrimShapeParameters(sceneObjectPart, sceneGroupID, regionUUID)); - - //Execute the query. If it fails then error is trapped in calling function - sqlCommand.ExecuteNonQuery(); - - } - - /// - /// Removes a object from the database. - /// Meaning removing it from tables Prims, PrimShapes and PrimItems - /// - /// id of scenegroup - /// regionUUID (is this used anyway - public void RemoveObject(UUID objectID, UUID regionUUID) - { - _Log.InfoFormat("[MSSQL]: Removing obj: {0} from region: {1}", objectID, regionUUID); - - //Remove from prims and primsitem table - string sqlPrims = "DELETE FROM PRIMS WHERE SceneGroupID = @objectID"; - string sqlPrimItems = "DELETE FROM PRIMITEMS WHERE primID in (SELECT UUID FROM PRIMS WHERE SceneGroupID = @objectID)"; - string sqlPrimShapes = "DELETE FROM PRIMSHAPES WHERE uuid in (SELECT UUID FROM PRIMS WHERE SceneGroupID = @objectID)"; - - lock (_Database) - { - //Using the non transaction mode. - using (SqlConnection conn = new SqlConnection(m_connectionString)) - using (SqlCommand cmd = new SqlCommand()) - { - cmd.Connection = conn; - cmd.CommandText = sqlPrimShapes; - conn.Open(); - cmd.Parameters.Add(_Database.CreateParameter("objectID", objectID)); - cmd.ExecuteNonQuery(); - - cmd.CommandText = sqlPrimItems; - cmd.ExecuteNonQuery(); - - cmd.CommandText = sqlPrims; - cmd.ExecuteNonQuery(); - } - } - } - - /// - /// Store the inventory of a prim. Warning deletes everything first and then adds all again. - /// - /// - /// - public void StorePrimInventory(UUID primID, ICollection items) - { - //_Log.InfoFormat("[REGION DB: Persisting Prim Inventory with prim ID {0}", primID); - - //Statement from MySQL section! - // For now, we're just going to crudely remove all the previous inventory items - // no matter whether they have changed or not, and replace them with the current set. - - //Delete everything from PrimID - //TODO add index on PrimID in DB, if not already exist - - string sql = "DELETE PRIMITEMS WHERE primID = @primID"; - using (SqlConnection conn = new SqlConnection(m_connectionString)) - using (SqlCommand cmd = new SqlCommand(sql, conn)) - { - cmd.Parameters.Add(_Database.CreateParameter("@primID", primID)); - conn.Open(); - cmd.ExecuteNonQuery(); - } - - sql = - @"INSERT INTO primitems ( - itemID,primID,assetID,parentFolderID,invType,assetType,name,description,creationDate,creatorID,ownerID,lastOwnerID,groupID, - nextPermissions,currentPermissions,basePermissions,everyonePermissions,groupPermissions,flags) - VALUES (@itemID,@primID,@assetID,@parentFolderID,@invType,@assetType,@name,@description,@creationDate,@creatorID,@ownerID, - @lastOwnerID,@groupID,@nextPermissions,@currentPermissions,@basePermissions,@everyonePermissions,@groupPermissions,@flags)"; - - using (SqlConnection conn = new SqlConnection(m_connectionString)) - using (SqlCommand cmd = new SqlCommand(sql, conn)) - { - foreach (TaskInventoryItem taskItem in items) - { - cmd.Parameters.AddRange(CreatePrimInventoryParameters(taskItem)); - conn.Open(); - cmd.ExecuteNonQuery(); - - cmd.Parameters.Clear(); - } - } - } - - #endregion - - /// - /// Loads the terrain map. - /// - /// regionID. - /// - public double[,] LoadTerrain(UUID regionID) - { - double[,] terrain = new double[(int)Constants.RegionSize, (int)Constants.RegionSize]; - terrain.Initialize(); - - string sql = "select top 1 RegionUUID, Revision, Heightfield from terrain where RegionUUID = @RegionUUID order by Revision desc"; - - using (SqlConnection conn = new SqlConnection(m_connectionString)) - using (SqlCommand cmd = new SqlCommand(sql, conn)) - { - // MySqlParameter param = new MySqlParameter(); - cmd.Parameters.Add(_Database.CreateParameter("@RegionUUID", regionID)); - conn.Open(); - using (SqlDataReader reader = cmd.ExecuteReader()) - { - int rev; - if (reader.Read()) - { - MemoryStream str = new MemoryStream((byte[])reader["Heightfield"]); - BinaryReader br = new BinaryReader(str); - for (int x = 0; x < (int)Constants.RegionSize; x++) - { - for (int y = 0; y < (int)Constants.RegionSize; y++) - { - terrain[x, y] = br.ReadDouble(); - } - } - rev = (int)reader["Revision"]; - } - else - { - _Log.Info("[REGION DB]: No terrain found for region"); - return null; - } - _Log.Info("[REGION DB]: Loaded terrain revision r" + rev); - } - } - - return terrain; - } - - /// - /// Stores the terrain map to DB. - /// - /// terrain map data. - /// regionID. - public void StoreTerrain(double[,] terrain, UUID regionID) - { - int revision = Util.UnixTimeSinceEpoch(); - - //Delete old terrain map - string sql = "delete from terrain where RegionUUID=@RegionUUID"; - using (SqlConnection conn = new SqlConnection(m_connectionString)) - using (SqlCommand cmd = new SqlCommand(sql, conn)) - { - cmd.Parameters.Add(_Database.CreateParameter("@RegionUUID", regionID)); - conn.Open(); - cmd.ExecuteNonQuery(); - } - - sql = "insert into terrain(RegionUUID, Revision, Heightfield) values(@RegionUUID, @Revision, @Heightfield)"; - - using (SqlConnection conn = new SqlConnection(m_connectionString)) - using (SqlCommand cmd = new SqlCommand(sql, conn)) - { - cmd.Parameters.Add(_Database.CreateParameter("@RegionUUID", regionID)); - cmd.Parameters.Add(_Database.CreateParameter("@Revision", revision)); - cmd.Parameters.Add(_Database.CreateParameter("@Heightfield", serializeTerrain(terrain))); - conn.Open(); - cmd.ExecuteNonQuery(); - } - - _Log.Info("[REGION DB]: Stored terrain revision r " + revision); - } - - /// - /// Loads all the land objects of a region. - /// - /// The region UUID. - /// - public List LoadLandObjects(UUID regionUUID) - { - List LandDataForRegion = new List(); - - string sql = "select * from land where RegionUUID = @RegionUUID"; - - //Retrieve all land data from region - using (SqlConnection conn = new SqlConnection(m_connectionString)) - using (SqlCommand cmd = new SqlCommand(sql, conn)) - { - cmd.Parameters.Add(_Database.CreateParameter("@RegionUUID", regionUUID)); - conn.Open(); - using (SqlDataReader readerLandData = cmd.ExecuteReader()) - { - while (readerLandData.Read()) - { - LandDataForRegion.Add(BuildLandData(readerLandData)); - } - } - } - - //Retrieve all accesslist data for all landdata - foreach (LandData LandData in LandDataForRegion) - { - sql = "select * from landaccesslist where LandUUID = @LandUUID"; - using (SqlConnection conn = new SqlConnection(m_connectionString)) - using (SqlCommand cmd = new SqlCommand(sql, conn)) - { - cmd.Parameters.Add(_Database.CreateParameter("@LandUUID", LandData.GlobalID)); - conn.Open(); - using (SqlDataReader readerAccessList = cmd.ExecuteReader()) - { - while (readerAccessList.Read()) - { - LandData.ParcelAccessList.Add(BuildLandAccessData(readerAccessList)); - } - } - } - } - - //Return data - return LandDataForRegion; - } - - /// - /// Stores land object with landaccess list. - /// - /// parcel data. - public void StoreLandObject(ILandObject parcel) - { - //As this is only one record in land table I just delete all and then add a new record. - //As the delete landaccess is already in the mysql code - - //Delete old values - RemoveLandObject(parcel.LandData.GlobalID); - - //Insert new values - string sql = @"INSERT INTO [land] -([UUID],[RegionUUID],[LocalLandID],[Bitmap],[Name],[Description],[OwnerUUID],[IsGroupOwned],[Area],[AuctionID],[Category],[ClaimDate],[ClaimPrice],[GroupUUID],[SalePrice],[LandStatus],[LandFlags],[LandingType],[MediaAutoScale],[MediaTextureUUID],[MediaURL],[MusicURL],[PassHours],[PassPrice],[SnapshotUUID],[UserLocationX],[UserLocationY],[UserLocationZ],[UserLookAtX],[UserLookAtY],[UserLookAtZ],[AuthbuyerID],[OtherCleanTime]) -VALUES -(@UUID,@RegionUUID,@LocalLandID,@Bitmap,@Name,@Description,@OwnerUUID,@IsGroupOwned,@Area,@AuctionID,@Category,@ClaimDate,@ClaimPrice,@GroupUUID,@SalePrice,@LandStatus,@LandFlags,@LandingType,@MediaAutoScale,@MediaTextureUUID,@MediaURL,@MusicURL,@PassHours,@PassPrice,@SnapshotUUID,@UserLocationX,@UserLocationY,@UserLocationZ,@UserLookAtX,@UserLookAtY,@UserLookAtZ,@AuthbuyerID,@OtherCleanTime)"; - - using (SqlConnection conn = new SqlConnection(m_connectionString)) - using (SqlCommand cmd = new SqlCommand(sql, conn)) - { - cmd.Parameters.AddRange(CreateLandParameters(parcel.LandData, parcel.RegionUUID)); - conn.Open(); - cmd.ExecuteNonQuery(); - } - - sql = "INSERT INTO [landaccesslist] ([LandUUID],[AccessUUID],[Flags]) VALUES (@LandUUID,@AccessUUID,@Flags)"; - - using (SqlConnection conn = new SqlConnection(m_connectionString)) - using (SqlCommand cmd = new SqlCommand(sql, conn)) - { - conn.Open(); - foreach (ParcelManager.ParcelAccessEntry parcelAccessEntry in parcel.LandData.ParcelAccessList) - { - cmd.Parameters.AddRange(CreateLandAccessParameters(parcelAccessEntry, parcel.RegionUUID)); - - cmd.ExecuteNonQuery(); - cmd.Parameters.Clear(); - } - } - } - - /// - /// Removes a land object from DB. - /// - /// UUID of landobject - public void RemoveLandObject(UUID globalID) - { - string sql = "delete from land where UUID=@UUID"; - using (SqlConnection conn = new SqlConnection(m_connectionString)) - using (SqlCommand cmd = new SqlCommand(sql, conn)) - { - cmd.Parameters.Add(_Database.CreateParameter("@UUID", globalID)); - conn.Open(); - cmd.ExecuteNonQuery(); - } - sql = "delete from landaccesslist where LandUUID=@UUID"; - using (SqlConnection conn = new SqlConnection(m_connectionString)) - using (SqlCommand cmd = new SqlCommand(sql, conn)) - { - cmd.Parameters.Add(_Database.CreateParameter("@UUID", globalID)); - conn.Open(); - cmd.ExecuteNonQuery(); - } - } - public RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID) - { - //This connector doesn't support the windlight module yet - //Return default LL windlight settings - return new RegionLightShareData(); - } - public void StoreRegionWindlightSettings(RegionLightShareData wl) - { - //This connector doesn't support the windlight module yet - } - /// - /// Loads the settings of a region. - /// - /// The region UUID. - /// - public RegionSettings LoadRegionSettings(UUID regionUUID) - { - string sql = "select * from regionsettings where regionUUID = @regionUUID"; - RegionSettings regionSettings; - using (SqlConnection conn = new SqlConnection(m_connectionString)) - using (SqlCommand cmd = new SqlCommand(sql, conn)) - { - cmd.Parameters.Add(_Database.CreateParameter("@regionUUID", regionUUID)); - conn.Open(); - using (SqlDataReader reader = cmd.ExecuteReader()) - { - if (reader.Read()) - { - regionSettings = BuildRegionSettings(reader); - regionSettings.OnSave += StoreRegionSettings; - - return regionSettings; - } - } - } - - //If we reach this point then there are new region settings for that region - regionSettings = new RegionSettings(); - regionSettings.RegionUUID = regionUUID; - regionSettings.OnSave += StoreRegionSettings; - - //Store new values - StoreNewRegionSettings(regionSettings); - - return regionSettings; - } - - /// - /// Store region settings, need to check if the check is really necesary. If we can make something for creating new region. - /// - /// region settings. - public void StoreRegionSettings(RegionSettings regionSettings) - { - //Little check if regionUUID already exist in DB - string regionUUID; - string sql = "SELECT regionUUID FROM regionsettings WHERE regionUUID = @regionUUID"; - using (SqlConnection conn = new SqlConnection(m_connectionString)) - using (SqlCommand cmd = new SqlCommand(sql, conn)) - { - cmd.Parameters.Add(_Database.CreateParameter("@regionUUID", regionSettings.RegionUUID)); - conn.Open(); - regionUUID = cmd.ExecuteScalar().ToString(); - } - - if (string.IsNullOrEmpty(regionUUID)) - { - StoreNewRegionSettings(regionSettings); - } - else - { - //This method only updates region settings!!! First call LoadRegionSettings to create new region settings in DB - sql = - @"UPDATE [regionsettings] SET [block_terraform] = @block_terraform ,[block_fly] = @block_fly ,[allow_damage] = @allow_damage -,[restrict_pushing] = @restrict_pushing ,[allow_land_resell] = @allow_land_resell ,[allow_land_join_divide] = @allow_land_join_divide -,[block_show_in_search] = @block_show_in_search ,[agent_limit] = @agent_limit ,[object_bonus] = @object_bonus ,[maturity] = @maturity -,[disable_scripts] = @disable_scripts ,[disable_collisions] = @disable_collisions ,[disable_physics] = @disable_physics -,[terrain_texture_1] = @terrain_texture_1 ,[terrain_texture_2] = @terrain_texture_2 ,[terrain_texture_3] = @terrain_texture_3 -,[terrain_texture_4] = @terrain_texture_4 ,[elevation_1_nw] = @elevation_1_nw ,[elevation_2_nw] = @elevation_2_nw -,[elevation_1_ne] = @elevation_1_ne ,[elevation_2_ne] = @elevation_2_ne ,[elevation_1_se] = @elevation_1_se ,[elevation_2_se] = @elevation_2_se -,[elevation_1_sw] = @elevation_1_sw ,[elevation_2_sw] = @elevation_2_sw ,[water_height] = @water_height ,[terrain_raise_limit] = @terrain_raise_limit -,[terrain_lower_limit] = @terrain_lower_limit ,[use_estate_sun] = @use_estate_sun ,[fixed_sun] = @fixed_sun ,[sun_position] = @sun_position -,[covenant] = @covenant , [sunvectorx] = @sunvectorx, [sunvectory] = @sunvectory, [sunvectorz] = @sunvectorz, [Sandbox] = @Sandbox, [loaded_creation_datetime] = @loaded_creation_datetime, [loaded_creation_id] = @loaded_creation_id - WHERE [regionUUID] = @regionUUID"; - - using (SqlConnection conn = new SqlConnection(m_connectionString)) - using (SqlCommand cmd = new SqlCommand(sql, conn)) - { - cmd.Parameters.AddRange(CreateRegionSettingParameters(regionSettings)); - conn.Open(); - cmd.ExecuteNonQuery(); - } - } - } - - public void Shutdown() - { - //Not used?? - } - - #region Private Methods - - /// - /// Serializes the terrain data for storage in DB. - /// - /// terrain data - /// - private static Array serializeTerrain(double[,] val) - { - MemoryStream str = new MemoryStream(((int)Constants.RegionSize * (int)Constants.RegionSize) * sizeof(double)); - BinaryWriter bw = new BinaryWriter(str); - - // TODO: COMPATIBILITY - Add byte-order conversions - for (int x = 0; x < (int)Constants.RegionSize; x++) - for (int y = 0; y < (int)Constants.RegionSize; y++) - { - double height = val[x, y]; - if (height == 0.0) - height = double.Epsilon; - - bw.Write(height); - } - - return str.ToArray(); - } - - /// - /// Stores new regionsettings. - /// - /// The region settings. - private void StoreNewRegionSettings(RegionSettings regionSettings) - { - string sql = @"INSERT INTO [regionsettings] - ([regionUUID],[block_terraform],[block_fly],[allow_damage],[restrict_pushing],[allow_land_resell],[allow_land_join_divide], - [block_show_in_search],[agent_limit],[object_bonus],[maturity],[disable_scripts],[disable_collisions],[disable_physics], - [terrain_texture_1],[terrain_texture_2],[terrain_texture_3],[terrain_texture_4],[elevation_1_nw],[elevation_2_nw],[elevation_1_ne], - [elevation_2_ne],[elevation_1_se],[elevation_2_se],[elevation_1_sw],[elevation_2_sw],[water_height],[terrain_raise_limit], - [terrain_lower_limit],[use_estate_sun],[fixed_sun],[sun_position],[covenant],[sunvectorx], [sunvectory], [sunvectorz],[Sandbox], [loaded_creation_datetime], [loaded_creation_id] - ) - VALUES - (@regionUUID,@block_terraform,@block_fly,@allow_damage,@restrict_pushing,@allow_land_resell,@allow_land_join_divide, - @block_show_in_search,@agent_limit,@object_bonus,@maturity,@disable_scripts,@disable_collisions,@disable_physics, - @terrain_texture_1,@terrain_texture_2,@terrain_texture_3,@terrain_texture_4,@elevation_1_nw,@elevation_2_nw,@elevation_1_ne, - @elevation_2_ne,@elevation_1_se,@elevation_2_se,@elevation_1_sw,@elevation_2_sw,@water_height,@terrain_raise_limit, - @terrain_lower_limit,@use_estate_sun,@fixed_sun,@sun_position,@covenant,@sunvectorx,@sunvectory, @sunvectorz, @Sandbox, @loaded_creation_datetime, @loaded_creation_id)"; - - using (SqlConnection conn = new SqlConnection(m_connectionString)) - using (SqlCommand cmd = new SqlCommand(sql, conn)) - { - cmd.Parameters.AddRange(CreateRegionSettingParameters(regionSettings)); - conn.Open(); - cmd.ExecuteNonQuery(); - } - } - - #region Private DataRecord conversion methods - - /// - /// Builds the region settings from a datarecod. - /// - /// datarecord with regionsettings. - /// - private static RegionSettings BuildRegionSettings(IDataRecord row) - { - //TODO change this is some more generic code so we doesnt have to change it every time a new field is added? - RegionSettings newSettings = new RegionSettings(); - - newSettings.RegionUUID = new UUID((Guid)row["regionUUID"]); - newSettings.BlockTerraform = Convert.ToBoolean(row["block_terraform"]); - newSettings.AllowDamage = Convert.ToBoolean(row["allow_damage"]); - newSettings.BlockFly = Convert.ToBoolean(row["block_fly"]); - newSettings.RestrictPushing = Convert.ToBoolean(row["restrict_pushing"]); - newSettings.AllowLandResell = Convert.ToBoolean(row["allow_land_resell"]); - newSettings.AllowLandJoinDivide = Convert.ToBoolean(row["allow_land_join_divide"]); - newSettings.BlockShowInSearch = Convert.ToBoolean(row["block_show_in_search"]); - newSettings.AgentLimit = Convert.ToInt32(row["agent_limit"]); - newSettings.ObjectBonus = Convert.ToDouble(row["object_bonus"]); - newSettings.Maturity = Convert.ToInt32(row["maturity"]); - newSettings.DisableScripts = Convert.ToBoolean(row["disable_scripts"]); - newSettings.DisableCollisions = Convert.ToBoolean(row["disable_collisions"]); - newSettings.DisablePhysics = Convert.ToBoolean(row["disable_physics"]); - newSettings.TerrainTexture1 = new UUID((Guid)row["terrain_texture_1"]); - newSettings.TerrainTexture2 = new UUID((Guid)row["terrain_texture_2"]); - newSettings.TerrainTexture3 = new UUID((Guid)row["terrain_texture_3"]); - newSettings.TerrainTexture4 = new UUID((Guid)row["terrain_texture_4"]); - newSettings.Elevation1NW = Convert.ToDouble(row["elevation_1_nw"]); - newSettings.Elevation2NW = Convert.ToDouble(row["elevation_2_nw"]); - newSettings.Elevation1NE = Convert.ToDouble(row["elevation_1_ne"]); - newSettings.Elevation2NE = Convert.ToDouble(row["elevation_2_ne"]); - newSettings.Elevation1SE = Convert.ToDouble(row["elevation_1_se"]); - newSettings.Elevation2SE = Convert.ToDouble(row["elevation_2_se"]); - newSettings.Elevation1SW = Convert.ToDouble(row["elevation_1_sw"]); - newSettings.Elevation2SW = Convert.ToDouble(row["elevation_2_sw"]); - newSettings.WaterHeight = Convert.ToDouble(row["water_height"]); - newSettings.TerrainRaiseLimit = Convert.ToDouble(row["terrain_raise_limit"]); - newSettings.TerrainLowerLimit = Convert.ToDouble(row["terrain_lower_limit"]); - newSettings.UseEstateSun = Convert.ToBoolean(row["use_estate_sun"]); - newSettings.Sandbox = Convert.ToBoolean(row["sandbox"]); - newSettings.FixedSun = Convert.ToBoolean(row["fixed_sun"]); - newSettings.SunPosition = Convert.ToDouble(row["sun_position"]); - newSettings.SunVector = new Vector3( - Convert.ToSingle(row["sunvectorx"]), - Convert.ToSingle(row["sunvectory"]), - Convert.ToSingle(row["sunvectorz"]) - ); - newSettings.Covenant = new UUID((Guid)row["covenant"]); - - newSettings.LoadedCreationDateTime = Convert.ToInt32(row["loaded_creation_datetime"]); - - if (row["loaded_creation_id"] is DBNull) - newSettings.LoadedCreationID = ""; - else - newSettings.LoadedCreationID = (String)row["loaded_creation_id"]; - return newSettings; - } - - /// - /// Builds the land data from a datarecord. - /// - /// datarecord with land data - /// - private static LandData BuildLandData(IDataRecord row) - { - LandData newData = new LandData(); - - newData.GlobalID = new UUID((Guid)row["UUID"]); - newData.LocalID = Convert.ToInt32(row["LocalLandID"]); - - // Bitmap is a byte[512] - newData.Bitmap = (Byte[])row["Bitmap"]; - - newData.Name = (string)row["Name"]; - newData.Description = (string)row["Description"]; - newData.OwnerID = new UUID((Guid)row["OwnerUUID"]); - newData.IsGroupOwned = Convert.ToBoolean(row["IsGroupOwned"]); - newData.Area = Convert.ToInt32(row["Area"]); - newData.AuctionID = Convert.ToUInt32(row["AuctionID"]); //Unemplemented - newData.Category = (ParcelCategory)Convert.ToInt32(row["Category"]); - //Enum libsecondlife.Parcel.ParcelCategory - newData.ClaimDate = Convert.ToInt32(row["ClaimDate"]); - newData.ClaimPrice = Convert.ToInt32(row["ClaimPrice"]); - newData.GroupID = new UUID((Guid)row["GroupUUID"]); - newData.SalePrice = Convert.ToInt32(row["SalePrice"]); - newData.Status = (ParcelStatus)Convert.ToInt32(row["LandStatus"]); - //Enum. libsecondlife.Parcel.ParcelStatus - newData.Flags = Convert.ToUInt32(row["LandFlags"]); - newData.LandingType = Convert.ToByte(row["LandingType"]); - newData.MediaAutoScale = Convert.ToByte(row["MediaAutoScale"]); - newData.MediaID = new UUID((Guid)row["MediaTextureUUID"]); - newData.MediaURL = (string)row["MediaURL"]; - newData.MusicURL = (string)row["MusicURL"]; - newData.PassHours = Convert.ToSingle(row["PassHours"]); - newData.PassPrice = Convert.ToInt32(row["PassPrice"]); - - // UUID authedbuyer; - // UUID snapshotID; - // - // if (UUID.TryParse((string)row["AuthBuyerID"], out authedbuyer)) - // newData.AuthBuyerID = authedbuyer; - // - // if (UUID.TryParse((string)row["SnapshotUUID"], out snapshotID)) - // newData.SnapshotID = snapshotID; - newData.AuthBuyerID = new UUID((Guid)row["AuthBuyerID"]); - newData.SnapshotID = new UUID((Guid)row["SnapshotUUID"]); - - newData.OtherCleanTime = Convert.ToInt32(row["OtherCleanTime"]); - - try - { - newData.UserLocation = - new Vector3(Convert.ToSingle(row["UserLocationX"]), Convert.ToSingle(row["UserLocationY"]), - Convert.ToSingle(row["UserLocationZ"])); - newData.UserLookAt = - new Vector3(Convert.ToSingle(row["UserLookAtX"]), Convert.ToSingle(row["UserLookAtY"]), - Convert.ToSingle(row["UserLookAtZ"])); - } - catch (InvalidCastException) - { - newData.UserLocation = Vector3.Zero; - newData.UserLookAt = Vector3.Zero; - _Log.ErrorFormat("[PARCEL]: unable to get parcel telehub settings for {1}", newData.Name); - } - - newData.ParcelAccessList = new List(); - - return newData; - } - - /// - /// Builds the landaccess data from a data record. - /// - /// datarecord with landaccess data - /// - private static ParcelManager.ParcelAccessEntry BuildLandAccessData(IDataRecord row) - { - ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); - entry.AgentID = new UUID((Guid)row["AccessUUID"]); - entry.Flags = (AccessList)Convert.ToInt32(row["Flags"]); - entry.Time = new DateTime(); - return entry; - } - - /// - /// Builds the prim from a datarecord. - /// - /// datarecord - /// - private static SceneObjectPart BuildPrim(IDataRecord primRow) - { - SceneObjectPart prim = new SceneObjectPart(); - - prim.UUID = new UUID((Guid)primRow["UUID"]); - // explicit conversion of integers is required, which sort - // of sucks. No idea if there is a shortcut here or not. - prim.CreationDate = Convert.ToInt32(primRow["CreationDate"]); - prim.Name = (string)primRow["Name"]; - // various text fields - prim.Text = (string)primRow["Text"]; - prim.Color = Color.FromArgb(Convert.ToInt32(primRow["ColorA"]), - Convert.ToInt32(primRow["ColorR"]), - Convert.ToInt32(primRow["ColorG"]), - Convert.ToInt32(primRow["ColorB"])); - prim.Description = (string)primRow["Description"]; - prim.SitName = (string)primRow["SitName"]; - prim.TouchName = (string)primRow["TouchName"]; - // permissions - prim.Flags = (PrimFlags)Convert.ToUInt32(primRow["ObjectFlags"]); - prim.CreatorID = new UUID((Guid)primRow["CreatorID"]); - prim.OwnerID = new UUID((Guid)primRow["OwnerID"]); - prim.GroupID = new UUID((Guid)primRow["GroupID"]); - prim.LastOwnerID = new UUID((Guid)primRow["LastOwnerID"]); - prim.OwnerMask = Convert.ToUInt32(primRow["OwnerMask"]); - prim.NextOwnerMask = Convert.ToUInt32(primRow["NextOwnerMask"]); - prim.GroupMask = Convert.ToUInt32(primRow["GroupMask"]); - prim.EveryoneMask = Convert.ToUInt32(primRow["EveryoneMask"]); - prim.BaseMask = Convert.ToUInt32(primRow["BaseMask"]); - // vectors - prim.OffsetPosition = new Vector3( - Convert.ToSingle(primRow["PositionX"]), - Convert.ToSingle(primRow["PositionY"]), - Convert.ToSingle(primRow["PositionZ"])); - - prim.GroupPosition = new Vector3( - Convert.ToSingle(primRow["GroupPositionX"]), - Convert.ToSingle(primRow["GroupPositionY"]), - Convert.ToSingle(primRow["GroupPositionZ"])); - - prim.Velocity = new Vector3( - Convert.ToSingle(primRow["VelocityX"]), - Convert.ToSingle(primRow["VelocityY"]), - Convert.ToSingle(primRow["VelocityZ"])); - - prim.AngularVelocity = new Vector3( - Convert.ToSingle(primRow["AngularVelocityX"]), - Convert.ToSingle(primRow["AngularVelocityY"]), - Convert.ToSingle(primRow["AngularVelocityZ"])); - - prim.Acceleration = new Vector3( - Convert.ToSingle(primRow["AccelerationX"]), - Convert.ToSingle(primRow["AccelerationY"]), - Convert.ToSingle(primRow["AccelerationZ"])); - - // quaternions - prim.RotationOffset = new Quaternion( - Convert.ToSingle(primRow["RotationX"]), - Convert.ToSingle(primRow["RotationY"]), - Convert.ToSingle(primRow["RotationZ"]), - Convert.ToSingle(primRow["RotationW"])); - - prim.SitTargetPositionLL = new Vector3( - Convert.ToSingle(primRow["SitTargetOffsetX"]), - Convert.ToSingle(primRow["SitTargetOffsetY"]), - Convert.ToSingle(primRow["SitTargetOffsetZ"])); - - prim.SitTargetOrientationLL = new Quaternion( - Convert.ToSingle(primRow["SitTargetOrientX"]), - Convert.ToSingle(primRow["SitTargetOrientY"]), - Convert.ToSingle(primRow["SitTargetOrientZ"]), - Convert.ToSingle(primRow["SitTargetOrientW"])); - - prim.PayPrice[0] = Convert.ToInt32(primRow["PayPrice"]); - prim.PayPrice[1] = Convert.ToInt32(primRow["PayButton1"]); - prim.PayPrice[2] = Convert.ToInt32(primRow["PayButton2"]); - prim.PayPrice[3] = Convert.ToInt32(primRow["PayButton3"]); - prim.PayPrice[4] = Convert.ToInt32(primRow["PayButton4"]); - - prim.Sound = new UUID((Guid)primRow["LoopedSound"]); - prim.SoundGain = Convert.ToSingle(primRow["LoopedSoundGain"]); - prim.SoundFlags = 1; // If it's persisted at all, it's looped - - if (!(primRow["TextureAnimation"] is DBNull)) - prim.TextureAnimation = (Byte[])primRow["TextureAnimation"]; - if (!(primRow["ParticleSystem"] is DBNull)) - prim.ParticleSystem = (Byte[])primRow["ParticleSystem"]; - - prim.AngularVelocity = new Vector3( - Convert.ToSingle(primRow["OmegaX"]), - Convert.ToSingle(primRow["OmegaY"]), - Convert.ToSingle(primRow["OmegaZ"])); - - prim.SetCameraEyeOffset(new Vector3( - Convert.ToSingle(primRow["CameraEyeOffsetX"]), - Convert.ToSingle(primRow["CameraEyeOffsetY"]), - Convert.ToSingle(primRow["CameraEyeOffsetZ"]) - )); - - prim.SetCameraAtOffset(new Vector3( - Convert.ToSingle(primRow["CameraAtOffsetX"]), - Convert.ToSingle(primRow["CameraAtOffsetY"]), - Convert.ToSingle(primRow["CameraAtOffsetZ"]) - )); - - if (Convert.ToInt16(primRow["ForceMouselook"]) != 0) - prim.SetForceMouselook(true); - - prim.ScriptAccessPin = Convert.ToInt32(primRow["ScriptAccessPin"]); - - if (Convert.ToInt16(primRow["AllowedDrop"]) != 0) - prim.AllowedDrop = true; - - if (Convert.ToInt16(primRow["DieAtEdge"]) != 0) - prim.DIE_AT_EDGE = true; - - prim.SalePrice = Convert.ToInt32(primRow["SalePrice"]); - prim.ObjectSaleType = Convert.ToByte(primRow["SaleType"]); - - prim.Material = Convert.ToByte(primRow["Material"]); - - if (!(primRow["ClickAction"] is DBNull)) - prim.ClickAction = Convert.ToByte(primRow["ClickAction"]); - - prim.CollisionSound = new UUID((Guid)primRow["CollisionSound"]); - prim.CollisionSoundVolume = Convert.ToSingle(primRow["CollisionSoundVolume"]); - if (Convert.ToInt16(primRow["PassTouches"]) != 0) - prim.PassTouches = true; - prim.LinkNum = Convert.ToInt32(primRow["LinkNumber"]); - - if (!(primRow["MediaURL"] is System.DBNull)) - prim.MediaUrl = (string)primRow["MediaURL"]; - - return prim; - } - - /// - /// Builds the prim shape from a datarecord. - /// - /// The row. - /// - private static PrimitiveBaseShape BuildShape(IDataRecord shapeRow) - { - PrimitiveBaseShape baseShape = new PrimitiveBaseShape(); - - baseShape.Scale = new Vector3( - Convert.ToSingle(shapeRow["ScaleX"]), - Convert.ToSingle(shapeRow["ScaleY"]), - Convert.ToSingle(shapeRow["ScaleZ"])); - - // paths - baseShape.PCode = Convert.ToByte(shapeRow["PCode"]); - baseShape.PathBegin = Convert.ToUInt16(shapeRow["PathBegin"]); - baseShape.PathEnd = Convert.ToUInt16(shapeRow["PathEnd"]); - baseShape.PathScaleX = Convert.ToByte(shapeRow["PathScaleX"]); - baseShape.PathScaleY = Convert.ToByte(shapeRow["PathScaleY"]); - baseShape.PathShearX = Convert.ToByte(shapeRow["PathShearX"]); - baseShape.PathShearY = Convert.ToByte(shapeRow["PathShearY"]); - baseShape.PathSkew = Convert.ToSByte(shapeRow["PathSkew"]); - baseShape.PathCurve = Convert.ToByte(shapeRow["PathCurve"]); - baseShape.PathRadiusOffset = Convert.ToSByte(shapeRow["PathRadiusOffset"]); - baseShape.PathRevolutions = Convert.ToByte(shapeRow["PathRevolutions"]); - baseShape.PathTaperX = Convert.ToSByte(shapeRow["PathTaperX"]); - baseShape.PathTaperY = Convert.ToSByte(shapeRow["PathTaperY"]); - baseShape.PathTwist = Convert.ToSByte(shapeRow["PathTwist"]); - baseShape.PathTwistBegin = Convert.ToSByte(shapeRow["PathTwistBegin"]); - // profile - baseShape.ProfileBegin = Convert.ToUInt16(shapeRow["ProfileBegin"]); - baseShape.ProfileEnd = Convert.ToUInt16(shapeRow["ProfileEnd"]); - baseShape.ProfileCurve = Convert.ToByte(shapeRow["ProfileCurve"]); - baseShape.ProfileHollow = Convert.ToUInt16(shapeRow["ProfileHollow"]); - - byte[] textureEntry = (byte[])shapeRow["Texture"]; - baseShape.TextureEntry = textureEntry; - - baseShape.ExtraParams = (byte[])shapeRow["ExtraParams"]; - - try - { - baseShape.State = Convert.ToByte(shapeRow["State"]); - } - catch (InvalidCastException) - { - } - - if (!(shapeRow["Media"] is System.DBNull)) - baseShape.Media = PrimitiveBaseShape.MediaList.FromXml((string)shapeRow["Media"]); - - return baseShape; - } - - /// - /// Build a prim inventory item from the persisted data. - /// - /// - /// - private static TaskInventoryItem BuildItem(IDataRecord inventoryRow) - { - TaskInventoryItem taskItem = new TaskInventoryItem(); - - taskItem.ItemID = new UUID((Guid)inventoryRow["itemID"]); - taskItem.ParentPartID = new UUID((Guid)inventoryRow["primID"]); - taskItem.AssetID = new UUID((Guid)inventoryRow["assetID"]); - taskItem.ParentID = new UUID((Guid)inventoryRow["parentFolderID"]); - - taskItem.InvType = Convert.ToInt32(inventoryRow["invType"]); - taskItem.Type = Convert.ToInt32(inventoryRow["assetType"]); - - taskItem.Name = (string)inventoryRow["name"]; - taskItem.Description = (string)inventoryRow["description"]; - taskItem.CreationDate = Convert.ToUInt32(inventoryRow["creationDate"]); - taskItem.CreatorID = new UUID((Guid)inventoryRow["creatorID"]); - taskItem.OwnerID = new UUID((Guid)inventoryRow["ownerID"]); - taskItem.LastOwnerID = new UUID((Guid)inventoryRow["lastOwnerID"]); - taskItem.GroupID = new UUID((Guid)inventoryRow["groupID"]); - - taskItem.NextPermissions = Convert.ToUInt32(inventoryRow["nextPermissions"]); - taskItem.CurrentPermissions = Convert.ToUInt32(inventoryRow["currentPermissions"]); - taskItem.BasePermissions = Convert.ToUInt32(inventoryRow["basePermissions"]); - taskItem.EveryonePermissions = Convert.ToUInt32(inventoryRow["everyonePermissions"]); - taskItem.GroupPermissions = Convert.ToUInt32(inventoryRow["groupPermissions"]); - taskItem.Flags = Convert.ToUInt32(inventoryRow["flags"]); - - return taskItem; - } - - #endregion - - #region Create parameters methods - - /// - /// Creates the prim inventory parameters. - /// - /// item in inventory. - /// - private SqlParameter[] CreatePrimInventoryParameters(TaskInventoryItem taskItem) - { - List parameters = new List(); - - parameters.Add(_Database.CreateParameter("itemID", taskItem.ItemID)); - parameters.Add(_Database.CreateParameter("primID", taskItem.ParentPartID)); - parameters.Add(_Database.CreateParameter("assetID", taskItem.AssetID)); - parameters.Add(_Database.CreateParameter("parentFolderID", taskItem.ParentID)); - parameters.Add(_Database.CreateParameter("invType", taskItem.InvType)); - parameters.Add(_Database.CreateParameter("assetType", taskItem.Type)); - - parameters.Add(_Database.CreateParameter("name", taskItem.Name)); - parameters.Add(_Database.CreateParameter("description", taskItem.Description)); - parameters.Add(_Database.CreateParameter("creationDate", taskItem.CreationDate)); - parameters.Add(_Database.CreateParameter("creatorID", taskItem.CreatorID)); - parameters.Add(_Database.CreateParameter("ownerID", taskItem.OwnerID)); - parameters.Add(_Database.CreateParameter("lastOwnerID", taskItem.LastOwnerID)); - parameters.Add(_Database.CreateParameter("groupID", taskItem.GroupID)); - parameters.Add(_Database.CreateParameter("nextPermissions", taskItem.NextPermissions)); - parameters.Add(_Database.CreateParameter("currentPermissions", taskItem.CurrentPermissions)); - parameters.Add(_Database.CreateParameter("basePermissions", taskItem.BasePermissions)); - parameters.Add(_Database.CreateParameter("everyonePermissions", taskItem.EveryonePermissions)); - parameters.Add(_Database.CreateParameter("groupPermissions", taskItem.GroupPermissions)); - parameters.Add(_Database.CreateParameter("flags", taskItem.Flags)); - - return parameters.ToArray(); - } - - /// - /// Creates the region setting parameters. - /// - /// regionsettings. - /// - private SqlParameter[] CreateRegionSettingParameters(RegionSettings settings) - { - List parameters = new List(); - - parameters.Add(_Database.CreateParameter("regionUUID", settings.RegionUUID)); - parameters.Add(_Database.CreateParameter("block_terraform", settings.BlockTerraform)); - parameters.Add(_Database.CreateParameter("block_fly", settings.BlockFly)); - parameters.Add(_Database.CreateParameter("allow_damage", settings.AllowDamage)); - parameters.Add(_Database.CreateParameter("restrict_pushing", settings.RestrictPushing)); - parameters.Add(_Database.CreateParameter("allow_land_resell", settings.AllowLandResell)); - parameters.Add(_Database.CreateParameter("allow_land_join_divide", settings.AllowLandJoinDivide)); - parameters.Add(_Database.CreateParameter("block_show_in_search", settings.BlockShowInSearch)); - parameters.Add(_Database.CreateParameter("agent_limit", settings.AgentLimit)); - parameters.Add(_Database.CreateParameter("object_bonus", settings.ObjectBonus)); - parameters.Add(_Database.CreateParameter("maturity", settings.Maturity)); - parameters.Add(_Database.CreateParameter("disable_scripts", settings.DisableScripts)); - parameters.Add(_Database.CreateParameter("disable_collisions", settings.DisableCollisions)); - parameters.Add(_Database.CreateParameter("disable_physics", settings.DisablePhysics)); - parameters.Add(_Database.CreateParameter("terrain_texture_1", settings.TerrainTexture1)); - parameters.Add(_Database.CreateParameter("terrain_texture_2", settings.TerrainTexture2)); - parameters.Add(_Database.CreateParameter("terrain_texture_3", settings.TerrainTexture3)); - parameters.Add(_Database.CreateParameter("terrain_texture_4", settings.TerrainTexture4)); - parameters.Add(_Database.CreateParameter("elevation_1_nw", settings.Elevation1NW)); - parameters.Add(_Database.CreateParameter("elevation_2_nw", settings.Elevation2NW)); - parameters.Add(_Database.CreateParameter("elevation_1_ne", settings.Elevation1NE)); - parameters.Add(_Database.CreateParameter("elevation_2_ne", settings.Elevation2NE)); - parameters.Add(_Database.CreateParameter("elevation_1_se", settings.Elevation1SE)); - parameters.Add(_Database.CreateParameter("elevation_2_se", settings.Elevation2SE)); - parameters.Add(_Database.CreateParameter("elevation_1_sw", settings.Elevation1SW)); - parameters.Add(_Database.CreateParameter("elevation_2_sw", settings.Elevation2SW)); - parameters.Add(_Database.CreateParameter("water_height", settings.WaterHeight)); - parameters.Add(_Database.CreateParameter("terrain_raise_limit", settings.TerrainRaiseLimit)); - parameters.Add(_Database.CreateParameter("terrain_lower_limit", settings.TerrainLowerLimit)); - parameters.Add(_Database.CreateParameter("use_estate_sun", settings.UseEstateSun)); - parameters.Add(_Database.CreateParameter("sandbox", settings.Sandbox)); - parameters.Add(_Database.CreateParameter("fixed_sun", settings.FixedSun)); - parameters.Add(_Database.CreateParameter("sun_position", settings.SunPosition)); - parameters.Add(_Database.CreateParameter("sunvectorx", settings.SunVector.X)); - parameters.Add(_Database.CreateParameter("sunvectory", settings.SunVector.Y)); - parameters.Add(_Database.CreateParameter("sunvectorz", settings.SunVector.Z)); - parameters.Add(_Database.CreateParameter("covenant", settings.Covenant)); - parameters.Add(_Database.CreateParameter("Loaded_Creation_DateTime", settings.LoadedCreationDateTime)); - parameters.Add(_Database.CreateParameter("Loaded_Creation_ID", settings.LoadedCreationID)); - - return parameters.ToArray(); - } - - /// - /// Creates the land parameters. - /// - /// land parameters. - /// region UUID. - /// - private SqlParameter[] CreateLandParameters(LandData land, UUID regionUUID) - { - List parameters = new List(); - - parameters.Add(_Database.CreateParameter("UUID", land.GlobalID)); - parameters.Add(_Database.CreateParameter("RegionUUID", regionUUID)); - parameters.Add(_Database.CreateParameter("LocalLandID", land.LocalID)); - - // Bitmap is a byte[512] - parameters.Add(_Database.CreateParameter("Bitmap", land.Bitmap)); - - parameters.Add(_Database.CreateParameter("Name", land.Name)); - parameters.Add(_Database.CreateParameter("Description", land.Description)); - parameters.Add(_Database.CreateParameter("OwnerUUID", land.OwnerID)); - parameters.Add(_Database.CreateParameter("IsGroupOwned", land.IsGroupOwned)); - parameters.Add(_Database.CreateParameter("Area", land.Area)); - parameters.Add(_Database.CreateParameter("AuctionID", land.AuctionID)); //Unemplemented - parameters.Add(_Database.CreateParameter("Category", (int)land.Category)); //Enum libsecondlife.Parcel.ParcelCategory - parameters.Add(_Database.CreateParameter("ClaimDate", land.ClaimDate)); - parameters.Add(_Database.CreateParameter("ClaimPrice", land.ClaimPrice)); - parameters.Add(_Database.CreateParameter("GroupUUID", land.GroupID)); - parameters.Add(_Database.CreateParameter("SalePrice", land.SalePrice)); - parameters.Add(_Database.CreateParameter("LandStatus", (int)land.Status)); //Enum. libsecondlife.Parcel.ParcelStatus - parameters.Add(_Database.CreateParameter("LandFlags", land.Flags)); - parameters.Add(_Database.CreateParameter("LandingType", land.LandingType)); - parameters.Add(_Database.CreateParameter("MediaAutoScale", land.MediaAutoScale)); - parameters.Add(_Database.CreateParameter("MediaTextureUUID", land.MediaID)); - parameters.Add(_Database.CreateParameter("MediaURL", land.MediaURL)); - parameters.Add(_Database.CreateParameter("MusicURL", land.MusicURL)); - parameters.Add(_Database.CreateParameter("PassHours", land.PassHours)); - parameters.Add(_Database.CreateParameter("PassPrice", land.PassPrice)); - parameters.Add(_Database.CreateParameter("SnapshotUUID", land.SnapshotID)); - parameters.Add(_Database.CreateParameter("UserLocationX", land.UserLocation.X)); - parameters.Add(_Database.CreateParameter("UserLocationY", land.UserLocation.Y)); - parameters.Add(_Database.CreateParameter("UserLocationZ", land.UserLocation.Z)); - parameters.Add(_Database.CreateParameter("UserLookAtX", land.UserLookAt.X)); - parameters.Add(_Database.CreateParameter("UserLookAtY", land.UserLookAt.Y)); - parameters.Add(_Database.CreateParameter("UserLookAtZ", land.UserLookAt.Z)); - parameters.Add(_Database.CreateParameter("AuthBuyerID", land.AuthBuyerID)); - parameters.Add(_Database.CreateParameter("OtherCleanTime", land.OtherCleanTime)); - - return parameters.ToArray(); - } - - /// - /// Creates the land access parameters. - /// - /// parcel access entry. - /// parcel ID. - /// - private SqlParameter[] CreateLandAccessParameters(ParcelManager.ParcelAccessEntry parcelAccessEntry, UUID parcelID) - { - List parameters = new List(); - - parameters.Add(_Database.CreateParameter("LandUUID", parcelID)); - parameters.Add(_Database.CreateParameter("AccessUUID", parcelAccessEntry.AgentID)); - parameters.Add(_Database.CreateParameter("Flags", parcelAccessEntry.Flags)); - - return parameters.ToArray(); - } - - /// - /// Creates the prim parameters for storing in DB. - /// - /// Basic data of SceneObjectpart prim. - /// The scenegroup ID. - /// The region ID. - /// - private SqlParameter[] CreatePrimParameters(SceneObjectPart prim, UUID sceneGroupID, UUID regionUUID) - { - List parameters = new List(); - - parameters.Add(_Database.CreateParameter("UUID", prim.UUID)); - parameters.Add(_Database.CreateParameter("RegionUUID", regionUUID)); - parameters.Add(_Database.CreateParameter("CreationDate", prim.CreationDate)); - parameters.Add(_Database.CreateParameter("Name", prim.Name)); - parameters.Add(_Database.CreateParameter("SceneGroupID", sceneGroupID)); - // the UUID of the root part for this SceneObjectGroup - // various text fields - parameters.Add(_Database.CreateParameter("Text", prim.Text)); - parameters.Add(_Database.CreateParameter("ColorR", prim.Color.R)); - parameters.Add(_Database.CreateParameter("ColorG", prim.Color.G)); - parameters.Add(_Database.CreateParameter("ColorB", prim.Color.B)); - parameters.Add(_Database.CreateParameter("ColorA", prim.Color.A)); - parameters.Add(_Database.CreateParameter("Description", prim.Description)); - parameters.Add(_Database.CreateParameter("SitName", prim.SitName)); - parameters.Add(_Database.CreateParameter("TouchName", prim.TouchName)); - // permissions - parameters.Add(_Database.CreateParameter("ObjectFlags", (uint)prim.Flags)); - parameters.Add(_Database.CreateParameter("CreatorID", prim.CreatorID)); - parameters.Add(_Database.CreateParameter("OwnerID", prim.OwnerID)); - parameters.Add(_Database.CreateParameter("GroupID", prim.GroupID)); - parameters.Add(_Database.CreateParameter("LastOwnerID", prim.LastOwnerID)); - parameters.Add(_Database.CreateParameter("OwnerMask", prim.OwnerMask)); - parameters.Add(_Database.CreateParameter("NextOwnerMask", prim.NextOwnerMask)); - parameters.Add(_Database.CreateParameter("GroupMask", prim.GroupMask)); - parameters.Add(_Database.CreateParameter("EveryoneMask", prim.EveryoneMask)); - parameters.Add(_Database.CreateParameter("BaseMask", prim.BaseMask)); - // vectors - parameters.Add(_Database.CreateParameter("PositionX", prim.OffsetPosition.X)); - parameters.Add(_Database.CreateParameter("PositionY", prim.OffsetPosition.Y)); - parameters.Add(_Database.CreateParameter("PositionZ", prim.OffsetPosition.Z)); - parameters.Add(_Database.CreateParameter("GroupPositionX", prim.GroupPosition.X)); - parameters.Add(_Database.CreateParameter("GroupPositionY", prim.GroupPosition.Y)); - parameters.Add(_Database.CreateParameter("GroupPositionZ", prim.GroupPosition.Z)); - parameters.Add(_Database.CreateParameter("VelocityX", prim.Velocity.X)); - parameters.Add(_Database.CreateParameter("VelocityY", prim.Velocity.Y)); - parameters.Add(_Database.CreateParameter("VelocityZ", prim.Velocity.Z)); - parameters.Add(_Database.CreateParameter("AngularVelocityX", prim.AngularVelocity.X)); - parameters.Add(_Database.CreateParameter("AngularVelocityY", prim.AngularVelocity.Y)); - parameters.Add(_Database.CreateParameter("AngularVelocityZ", prim.AngularVelocity.Z)); - parameters.Add(_Database.CreateParameter("AccelerationX", prim.Acceleration.X)); - parameters.Add(_Database.CreateParameter("AccelerationY", prim.Acceleration.Y)); - parameters.Add(_Database.CreateParameter("AccelerationZ", prim.Acceleration.Z)); - // quaternions - parameters.Add(_Database.CreateParameter("RotationX", prim.RotationOffset.X)); - parameters.Add(_Database.CreateParameter("RotationY", prim.RotationOffset.Y)); - parameters.Add(_Database.CreateParameter("RotationZ", prim.RotationOffset.Z)); - parameters.Add(_Database.CreateParameter("RotationW", prim.RotationOffset.W)); - - // Sit target - Vector3 sitTargetPos = prim.SitTargetPositionLL; - parameters.Add(_Database.CreateParameter("SitTargetOffsetX", sitTargetPos.X)); - parameters.Add(_Database.CreateParameter("SitTargetOffsetY", sitTargetPos.Y)); - parameters.Add(_Database.CreateParameter("SitTargetOffsetZ", sitTargetPos.Z)); - - Quaternion sitTargetOrient = prim.SitTargetOrientationLL; - parameters.Add(_Database.CreateParameter("SitTargetOrientW", sitTargetOrient.W)); - parameters.Add(_Database.CreateParameter("SitTargetOrientX", sitTargetOrient.X)); - parameters.Add(_Database.CreateParameter("SitTargetOrientY", sitTargetOrient.Y)); - parameters.Add(_Database.CreateParameter("SitTargetOrientZ", sitTargetOrient.Z)); - - parameters.Add(_Database.CreateParameter("PayPrice", prim.PayPrice[0])); - parameters.Add(_Database.CreateParameter("PayButton1", prim.PayPrice[1])); - parameters.Add(_Database.CreateParameter("PayButton2", prim.PayPrice[2])); - parameters.Add(_Database.CreateParameter("PayButton3", prim.PayPrice[3])); - parameters.Add(_Database.CreateParameter("PayButton4", prim.PayPrice[4])); - - if ((prim.SoundFlags & 1) != 0) // Looped - { - parameters.Add(_Database.CreateParameter("LoopedSound", prim.Sound)); - parameters.Add(_Database.CreateParameter("LoopedSoundGain", prim.SoundGain)); - } - else - { - parameters.Add(_Database.CreateParameter("LoopedSound", UUID.Zero)); - parameters.Add(_Database.CreateParameter("LoopedSoundGain", 0.0f)); - } - - parameters.Add(_Database.CreateParameter("TextureAnimation", prim.TextureAnimation)); - parameters.Add(_Database.CreateParameter("ParticleSystem", prim.ParticleSystem)); - - parameters.Add(_Database.CreateParameter("OmegaX", prim.AngularVelocity.X)); - parameters.Add(_Database.CreateParameter("OmegaY", prim.AngularVelocity.Y)); - parameters.Add(_Database.CreateParameter("OmegaZ", prim.AngularVelocity.Z)); - - parameters.Add(_Database.CreateParameter("CameraEyeOffsetX", prim.GetCameraEyeOffset().X)); - parameters.Add(_Database.CreateParameter("CameraEyeOffsetY", prim.GetCameraEyeOffset().Y)); - parameters.Add(_Database.CreateParameter("CameraEyeOffsetZ", prim.GetCameraEyeOffset().Z)); - - parameters.Add(_Database.CreateParameter("CameraAtOffsetX", prim.GetCameraAtOffset().X)); - parameters.Add(_Database.CreateParameter("CameraAtOffsetY", prim.GetCameraAtOffset().Y)); - parameters.Add(_Database.CreateParameter("CameraAtOffsetZ", prim.GetCameraAtOffset().Z)); - - if (prim.GetForceMouselook()) - parameters.Add(_Database.CreateParameter("ForceMouselook", 1)); - else - parameters.Add(_Database.CreateParameter("ForceMouselook", 0)); - - parameters.Add(_Database.CreateParameter("ScriptAccessPin", prim.ScriptAccessPin)); - - if (prim.AllowedDrop) - parameters.Add(_Database.CreateParameter("AllowedDrop", 1)); - else - parameters.Add(_Database.CreateParameter("AllowedDrop", 0)); - - if (prim.DIE_AT_EDGE) - parameters.Add(_Database.CreateParameter("DieAtEdge", 1)); - else - parameters.Add(_Database.CreateParameter("DieAtEdge", 0)); - - parameters.Add(_Database.CreateParameter("SalePrice", prim.SalePrice)); - parameters.Add(_Database.CreateParameter("SaleType", prim.ObjectSaleType)); - - byte clickAction = prim.ClickAction; - parameters.Add(_Database.CreateParameter("ClickAction", clickAction)); - - parameters.Add(_Database.CreateParameter("Material", prim.Material)); - - parameters.Add(_Database.CreateParameter("CollisionSound", prim.CollisionSound)); - parameters.Add(_Database.CreateParameter("CollisionSoundVolume", prim.CollisionSoundVolume)); - if (prim.PassTouches) - parameters.Add(_Database.CreateParameter("PassTouches", 1)); - else - parameters.Add(_Database.CreateParameter("PassTouches", 0)); - parameters.Add(_Database.CreateParameter("LinkNumber", prim.LinkNum)); - parameters.Add(_Database.CreateParameter("MediaURL", prim.MediaUrl)); - - return parameters.ToArray(); - } - - /// - /// Creates the primshape parameters for stroing in DB. - /// - /// Basic data of SceneObjectpart prim. - /// The scene group ID. - /// The region UUID. - /// - private SqlParameter[] CreatePrimShapeParameters(SceneObjectPart prim, UUID sceneGroupID, UUID regionUUID) - { - List parameters = new List(); - - PrimitiveBaseShape s = prim.Shape; - parameters.Add(_Database.CreateParameter("UUID", prim.UUID)); - // shape is an enum - parameters.Add(_Database.CreateParameter("Shape", 0)); - // vectors - parameters.Add(_Database.CreateParameter("ScaleX", s.Scale.X)); - parameters.Add(_Database.CreateParameter("ScaleY", s.Scale.Y)); - parameters.Add(_Database.CreateParameter("ScaleZ", s.Scale.Z)); - // paths - parameters.Add(_Database.CreateParameter("PCode", s.PCode)); - parameters.Add(_Database.CreateParameter("PathBegin", s.PathBegin)); - parameters.Add(_Database.CreateParameter("PathEnd", s.PathEnd)); - parameters.Add(_Database.CreateParameter("PathScaleX", s.PathScaleX)); - parameters.Add(_Database.CreateParameter("PathScaleY", s.PathScaleY)); - parameters.Add(_Database.CreateParameter("PathShearX", s.PathShearX)); - parameters.Add(_Database.CreateParameter("PathShearY", s.PathShearY)); - parameters.Add(_Database.CreateParameter("PathSkew", s.PathSkew)); - parameters.Add(_Database.CreateParameter("PathCurve", s.PathCurve)); - parameters.Add(_Database.CreateParameter("PathRadiusOffset", s.PathRadiusOffset)); - parameters.Add(_Database.CreateParameter("PathRevolutions", s.PathRevolutions)); - parameters.Add(_Database.CreateParameter("PathTaperX", s.PathTaperX)); - parameters.Add(_Database.CreateParameter("PathTaperY", s.PathTaperY)); - parameters.Add(_Database.CreateParameter("PathTwist", s.PathTwist)); - parameters.Add(_Database.CreateParameter("PathTwistBegin", s.PathTwistBegin)); - // profile - parameters.Add(_Database.CreateParameter("ProfileBegin", s.ProfileBegin)); - parameters.Add(_Database.CreateParameter("ProfileEnd", s.ProfileEnd)); - parameters.Add(_Database.CreateParameter("ProfileCurve", s.ProfileCurve)); - parameters.Add(_Database.CreateParameter("ProfileHollow", s.ProfileHollow)); - parameters.Add(_Database.CreateParameter("Texture", s.TextureEntry)); - parameters.Add(_Database.CreateParameter("ExtraParams", s.ExtraParams)); - parameters.Add(_Database.CreateParameter("State", s.State)); - parameters.Add(_Database.CreateParameter("Media", null == s.Media ? null : s.Media.ToXml())); - - return parameters.ToArray(); - } - - #endregion - - #endregion - } -} diff --git a/OpenSim/Data/MSSQL/MSSQLSimulationData.cs b/OpenSim/Data/MSSQL/MSSQLSimulationData.cs new file mode 100644 index 0000000..ae105d5 --- /dev/null +++ b/OpenSim/Data/MSSQL/MSSQLSimulationData.cs @@ -0,0 +1,1572 @@ +/* + * 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.Data; +using System.Data.SqlClient; +using System.Drawing; +using System.IO; +using System.Reflection; +using log4net; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Data.MSSQL +{ + /// + /// A MSSQL Interface for the Region Server. + /// + public class MSSQLSimulationData : ISimulationDataStore + { + private const string _migrationStore = "RegionStore"; + + // private static FileSystemDataStore Instance = new FileSystemDataStore(); + private static readonly ILog _Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// The database manager + /// + private MSSQLManager _Database; + private string m_connectionString; + /// + /// Initialises the region datastore + /// + /// The connection string. + public void Initialise(string connectionString) + { + m_connectionString = connectionString; + _Database = new MSSQLManager(connectionString); + + + //Migration settings + _Database.CheckMigration(_migrationStore); + } + + /// + /// Dispose the database + /// + public void Dispose() { } + + #region SceneObjectGroup region for loading and Store of the scene. + + /// + /// Loads the objects present in the region. + /// + /// The region UUID. + /// + public List LoadObjects(UUID regionUUID) + { + UUID lastGroupID = UUID.Zero; + + Dictionary prims = new Dictionary(); + Dictionary objects = new Dictionary(); + SceneObjectGroup grp = null; + + string sql = "SELECT *, " + + "sort = CASE WHEN prims.UUID = prims.SceneGroupID THEN 0 ELSE 1 END " + + "FROM prims " + + "LEFT JOIN primshapes ON prims.UUID = primshapes.UUID " + + "WHERE RegionUUID = @RegionUUID " + + "ORDER BY SceneGroupID asc, sort asc, LinkNumber asc"; + + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand command = new SqlCommand(sql, conn)) + { + command.Parameters.Add(_Database.CreateParameter("@regionUUID", regionUUID)); + conn.Open(); + using (SqlDataReader reader = command.ExecuteReader()) + { + while (reader.Read()) + { + SceneObjectPart sceneObjectPart = BuildPrim(reader); + if (reader["Shape"] is DBNull) + sceneObjectPart.Shape = PrimitiveBaseShape.Default; + else + sceneObjectPart.Shape = BuildShape(reader); + + prims[sceneObjectPart.UUID] = sceneObjectPart; + + UUID groupID = new UUID((Guid)reader["SceneGroupID"]); + + if (groupID != lastGroupID) // New SOG + { + if (grp != null) + objects[grp.UUID] = grp; + + lastGroupID = groupID; + + // There sometimes exist OpenSim bugs that 'orphan groups' so that none of the prims are + // recorded as the root prim (for which the UUID must equal the persisted group UUID). In + // this case, force the UUID to be the same as the group UUID so that at least these can be + // deleted (we need to change the UUID so that any other prims in the linkset can also be + // deleted). + if (sceneObjectPart.UUID != groupID && groupID != UUID.Zero) + { + _Log.WarnFormat( + "[REGION DB]: Found root prim {0} {1} at {2} where group was actually {3}. Forcing UUID to group UUID", + sceneObjectPart.Name, sceneObjectPart.UUID, sceneObjectPart.GroupPosition, groupID); + + sceneObjectPart.UUID = groupID; + } + + grp = new SceneObjectGroup(sceneObjectPart); + } + else + { + // Black magic to preserve link numbers + // Why is this needed, fix this in AddPart method. + int link = sceneObjectPart.LinkNum; + + grp.AddPart(sceneObjectPart); + + if (link != 0) + sceneObjectPart.LinkNum = link; + } + } + } + } + + if (grp != null) + objects[grp.UUID] = grp; + + // Instead of attempting to LoadItems on every prim, + // most of which probably have no items... get a + // list from DB of all prims which have items and + // LoadItems only on those + List primsWithInventory = new List(); + string qry = "select distinct primID from primitems"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand command = new SqlCommand(qry, conn)) + { + conn.Open(); + using (SqlDataReader itemReader = command.ExecuteReader()) + { + while (itemReader.Read()) + { + if (!(itemReader["primID"] is DBNull)) + { + UUID primID = new UUID(itemReader["primID"].ToString()); + if (prims.ContainsKey(primID)) + { + primsWithInventory.Add(prims[primID]); + } + } + } + } + } + + LoadItems(primsWithInventory); + + _Log.DebugFormat("[REGION DB]: Loaded {0} objects using {1} prims", objects.Count, prims.Count); + + return new List(objects.Values); + } + + /// + /// Load in the prim's persisted inventory. + /// + /// all prims with inventory on a region + private void LoadItems(List allPrimsWithInventory) + { + string sql = "SELECT * FROM primitems WHERE PrimID = @PrimID"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand command = new SqlCommand(sql, conn)) + { + conn.Open(); + foreach (SceneObjectPart objectPart in allPrimsWithInventory) + { + command.Parameters.Clear(); + command.Parameters.Add(_Database.CreateParameter("@PrimID", objectPart.UUID)); + + List inventory = new List(); + + using (SqlDataReader reader = command.ExecuteReader()) + { + while (reader.Read()) + { + TaskInventoryItem item = BuildItem(reader); + + item.ParentID = objectPart.UUID; // Values in database are + // often wrong + inventory.Add(item); + } + } + + objectPart.Inventory.RestoreInventoryItems(inventory); + } + } + } + + /// + /// Stores all object's details apart from inventory + /// + /// + /// + public void StoreObject(SceneObjectGroup obj, UUID regionUUID) + { + _Log.DebugFormat("[MSSQL]: Adding/Changing SceneObjectGroup: {0} to region: {1}, object has {2} prims.", obj.UUID, regionUUID, obj.Children.Count); + + using (SqlConnection conn = new SqlConnection(m_connectionString)) + { + conn.Open(); + SqlTransaction transaction = conn.BeginTransaction(); + + try + { + foreach (SceneObjectPart sceneObjectPart in obj.Children.Values) + { + //Update prim + using (SqlCommand sqlCommand = conn.CreateCommand()) + { + sqlCommand.Transaction = transaction; + try + { + StoreSceneObjectPrim(sceneObjectPart, sqlCommand, obj.UUID, regionUUID); + } + catch (SqlException sqlEx) + { + _Log.ErrorFormat("[REGION DB]: Store SceneObjectPrim SQL error: {0} at line {1}", sqlEx.Message, sqlEx.LineNumber); + throw; + } + } + + //Update primshapes + using (SqlCommand sqlCommand = conn.CreateCommand()) + { + sqlCommand.Transaction = transaction; + try + { + StoreSceneObjectPrimShapes(sceneObjectPart, sqlCommand, obj.UUID, regionUUID); + } + catch (SqlException sqlEx) + { + _Log.ErrorFormat("[REGION DB]: Store SceneObjectPrimShapes SQL error: {0} at line {1}", sqlEx.Message, sqlEx.LineNumber); + throw; + } + } + } + + transaction.Commit(); + } + catch (Exception ex) + { + _Log.ErrorFormat("[REGION DB]: Store SceneObjectGroup error: {0}, Rolling back...", ex.Message); + try + { + transaction.Rollback(); + } + catch (Exception ex2) + { + //Show error + _Log.InfoFormat("[REGION DB]: Rollback of SceneObjectGroup store transaction failed with error: {0}", ex2.Message); + + } + } + } + } + + /// + /// Stores the prim of the sceneobjectpart. + /// + /// The sceneobjectpart or prim. + /// The SQL command with the transaction. + /// The scenegroup UUID. + /// The region UUID. + private void StoreSceneObjectPrim(SceneObjectPart sceneObjectPart, SqlCommand sqlCommand, UUID sceneGroupID, UUID regionUUID) + { + //Big query to update or insert a new prim. + //Note for SQL Server 2008 this could be simplified + string queryPrims = @" +IF EXISTS (SELECT UUID FROM prims WHERE UUID = @UUID) + BEGIN + UPDATE prims SET + CreationDate = @CreationDate, Name = @Name, Text = @Text, Description = @Description, SitName = @SitName, + TouchName = @TouchName, ObjectFlags = @ObjectFlags, OwnerMask = @OwnerMask, NextOwnerMask = @NextOwnerMask, GroupMask = @GroupMask, + EveryoneMask = @EveryoneMask, BaseMask = @BaseMask, PositionX = @PositionX, PositionY = @PositionY, PositionZ = @PositionZ, + GroupPositionX = @GroupPositionX, GroupPositionY = @GroupPositionY, GroupPositionZ = @GroupPositionZ, VelocityX = @VelocityX, + VelocityY = @VelocityY, VelocityZ = @VelocityZ, AngularVelocityX = @AngularVelocityX, AngularVelocityY = @AngularVelocityY, + AngularVelocityZ = @AngularVelocityZ, AccelerationX = @AccelerationX, AccelerationY = @AccelerationY, + AccelerationZ = @AccelerationZ, RotationX = @RotationX, RotationY = @RotationY, RotationZ = @RotationZ, RotationW = @RotationW, + SitTargetOffsetX = @SitTargetOffsetX, SitTargetOffsetY = @SitTargetOffsetY, SitTargetOffsetZ = @SitTargetOffsetZ, + SitTargetOrientW = @SitTargetOrientW, SitTargetOrientX = @SitTargetOrientX, SitTargetOrientY = @SitTargetOrientY, + SitTargetOrientZ = @SitTargetOrientZ, RegionUUID = @RegionUUID, CreatorID = @CreatorID, OwnerID = @OwnerID, GroupID = @GroupID, + LastOwnerID = @LastOwnerID, SceneGroupID = @SceneGroupID, PayPrice = @PayPrice, PayButton1 = @PayButton1, PayButton2 = @PayButton2, + PayButton3 = @PayButton3, PayButton4 = @PayButton4, LoopedSound = @LoopedSound, LoopedSoundGain = @LoopedSoundGain, + TextureAnimation = @TextureAnimation, OmegaX = @OmegaX, OmegaY = @OmegaY, OmegaZ = @OmegaZ, CameraEyeOffsetX = @CameraEyeOffsetX, + CameraEyeOffsetY = @CameraEyeOffsetY, CameraEyeOffsetZ = @CameraEyeOffsetZ, CameraAtOffsetX = @CameraAtOffsetX, + CameraAtOffsetY = @CameraAtOffsetY, CameraAtOffsetZ = @CameraAtOffsetZ, ForceMouselook = @ForceMouselook, + ScriptAccessPin = @ScriptAccessPin, AllowedDrop = @AllowedDrop, DieAtEdge = @DieAtEdge, SalePrice = @SalePrice, + SaleType = @SaleType, ColorR = @ColorR, ColorG = @ColorG, ColorB = @ColorB, ColorA = @ColorA, ParticleSystem = @ParticleSystem, + ClickAction = @ClickAction, Material = @Material, CollisionSound = @CollisionSound, CollisionSoundVolume = @CollisionSoundVolume, PassTouches = @PassTouches, + LinkNumber = @LinkNumber, MediaURL = @MediaURL + WHERE UUID = @UUID + END +ELSE + BEGIN + INSERT INTO + prims ( + UUID, CreationDate, Name, Text, Description, SitName, TouchName, ObjectFlags, OwnerMask, NextOwnerMask, GroupMask, + EveryoneMask, BaseMask, PositionX, PositionY, PositionZ, GroupPositionX, GroupPositionY, GroupPositionZ, VelocityX, + VelocityY, VelocityZ, AngularVelocityX, AngularVelocityY, AngularVelocityZ, AccelerationX, AccelerationY, AccelerationZ, + RotationX, RotationY, RotationZ, RotationW, SitTargetOffsetX, SitTargetOffsetY, SitTargetOffsetZ, SitTargetOrientW, + SitTargetOrientX, SitTargetOrientY, SitTargetOrientZ, RegionUUID, CreatorID, OwnerID, GroupID, LastOwnerID, SceneGroupID, + PayPrice, PayButton1, PayButton2, PayButton3, PayButton4, LoopedSound, LoopedSoundGain, TextureAnimation, OmegaX, + OmegaY, OmegaZ, CameraEyeOffsetX, CameraEyeOffsetY, CameraEyeOffsetZ, CameraAtOffsetX, CameraAtOffsetY, CameraAtOffsetZ, + ForceMouselook, ScriptAccessPin, AllowedDrop, DieAtEdge, SalePrice, SaleType, ColorR, ColorG, ColorB, ColorA, + ParticleSystem, ClickAction, Material, CollisionSound, CollisionSoundVolume, PassTouches, LinkNumber, MediaURL + ) VALUES ( + @UUID, @CreationDate, @Name, @Text, @Description, @SitName, @TouchName, @ObjectFlags, @OwnerMask, @NextOwnerMask, @GroupMask, + @EveryoneMask, @BaseMask, @PositionX, @PositionY, @PositionZ, @GroupPositionX, @GroupPositionY, @GroupPositionZ, @VelocityX, + @VelocityY, @VelocityZ, @AngularVelocityX, @AngularVelocityY, @AngularVelocityZ, @AccelerationX, @AccelerationY, @AccelerationZ, + @RotationX, @RotationY, @RotationZ, @RotationW, @SitTargetOffsetX, @SitTargetOffsetY, @SitTargetOffsetZ, @SitTargetOrientW, + @SitTargetOrientX, @SitTargetOrientY, @SitTargetOrientZ, @RegionUUID, @CreatorID, @OwnerID, @GroupID, @LastOwnerID, @SceneGroupID, + @PayPrice, @PayButton1, @PayButton2, @PayButton3, @PayButton4, @LoopedSound, @LoopedSoundGain, @TextureAnimation, @OmegaX, + @OmegaY, @OmegaZ, @CameraEyeOffsetX, @CameraEyeOffsetY, @CameraEyeOffsetZ, @CameraAtOffsetX, @CameraAtOffsetY, @CameraAtOffsetZ, + @ForceMouselook, @ScriptAccessPin, @AllowedDrop, @DieAtEdge, @SalePrice, @SaleType, @ColorR, @ColorG, @ColorB, @ColorA, + @ParticleSystem, @ClickAction, @Material, @CollisionSound, @CollisionSoundVolume, @PassTouches, @LinkNumber, @MediaURL + ) + END"; + + //Set commandtext. + sqlCommand.CommandText = queryPrims; + //Add parameters + sqlCommand.Parameters.AddRange(CreatePrimParameters(sceneObjectPart, sceneGroupID, regionUUID)); + + //Execute the query. If it fails then error is trapped in calling function + sqlCommand.ExecuteNonQuery(); + } + + /// + /// Stores the scene object prim shapes. + /// + /// The sceneobjectpart containing prim shape. + /// The SQL command with the transaction. + /// The scenegroup UUID. + /// The region UUID. + private void StoreSceneObjectPrimShapes(SceneObjectPart sceneObjectPart, SqlCommand sqlCommand, UUID sceneGroupID, UUID regionUUID) + { + //Big query to or insert or update primshapes + //Note for SQL Server 2008 this can be simplified + string queryPrimShapes = @" +IF EXISTS (SELECT UUID FROM primshapes WHERE UUID = @UUID) + BEGIN + UPDATE primshapes SET + Shape = @Shape, ScaleX = @ScaleX, ScaleY = @ScaleY, ScaleZ = @ScaleZ, PCode = @PCode, PathBegin = @PathBegin, + PathEnd = @PathEnd, PathScaleX = @PathScaleX, PathScaleY = @PathScaleY, PathShearX = @PathShearX, PathShearY = @PathShearY, + PathSkew = @PathSkew, PathCurve = @PathCurve, PathRadiusOffset = @PathRadiusOffset, PathRevolutions = @PathRevolutions, + PathTaperX = @PathTaperX, PathTaperY = @PathTaperY, PathTwist = @PathTwist, PathTwistBegin = @PathTwistBegin, + ProfileBegin = @ProfileBegin, ProfileEnd = @ProfileEnd, ProfileCurve = @ProfileCurve, ProfileHollow = @ProfileHollow, + Texture = @Texture, ExtraParams = @ExtraParams, State = @State, Media = @Media + WHERE UUID = @UUID + END +ELSE + BEGIN + INSERT INTO + primshapes ( + UUID, Shape, ScaleX, ScaleY, ScaleZ, PCode, PathBegin, PathEnd, PathScaleX, PathScaleY, PathShearX, PathShearY, + PathSkew, PathCurve, PathRadiusOffset, PathRevolutions, PathTaperX, PathTaperY, PathTwist, PathTwistBegin, ProfileBegin, + ProfileEnd, ProfileCurve, ProfileHollow, Texture, ExtraParams, State, Media + ) VALUES ( + @UUID, @Shape, @ScaleX, @ScaleY, @ScaleZ, @PCode, @PathBegin, @PathEnd, @PathScaleX, @PathScaleY, @PathShearX, @PathShearY, + @PathSkew, @PathCurve, @PathRadiusOffset, @PathRevolutions, @PathTaperX, @PathTaperY, @PathTwist, @PathTwistBegin, @ProfileBegin, + @ProfileEnd, @ProfileCurve, @ProfileHollow, @Texture, @ExtraParams, @State, @Media + ) + END"; + + //Set commandtext. + sqlCommand.CommandText = queryPrimShapes; + + //Add parameters + sqlCommand.Parameters.AddRange(CreatePrimShapeParameters(sceneObjectPart, sceneGroupID, regionUUID)); + + //Execute the query. If it fails then error is trapped in calling function + sqlCommand.ExecuteNonQuery(); + + } + + /// + /// Removes a object from the database. + /// Meaning removing it from tables Prims, PrimShapes and PrimItems + /// + /// id of scenegroup + /// regionUUID (is this used anyway + public void RemoveObject(UUID objectID, UUID regionUUID) + { + _Log.InfoFormat("[MSSQL]: Removing obj: {0} from region: {1}", objectID, regionUUID); + + //Remove from prims and primsitem table + string sqlPrims = "DELETE FROM PRIMS WHERE SceneGroupID = @objectID"; + string sqlPrimItems = "DELETE FROM PRIMITEMS WHERE primID in (SELECT UUID FROM PRIMS WHERE SceneGroupID = @objectID)"; + string sqlPrimShapes = "DELETE FROM PRIMSHAPES WHERE uuid in (SELECT UUID FROM PRIMS WHERE SceneGroupID = @objectID)"; + + lock (_Database) + { + //Using the non transaction mode. + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand()) + { + cmd.Connection = conn; + cmd.CommandText = sqlPrimShapes; + conn.Open(); + cmd.Parameters.Add(_Database.CreateParameter("objectID", objectID)); + cmd.ExecuteNonQuery(); + + cmd.CommandText = sqlPrimItems; + cmd.ExecuteNonQuery(); + + cmd.CommandText = sqlPrims; + cmd.ExecuteNonQuery(); + } + } + } + + /// + /// Store the inventory of a prim. Warning deletes everything first and then adds all again. + /// + /// + /// + public void StorePrimInventory(UUID primID, ICollection items) + { + //_Log.InfoFormat("[REGION DB: Persisting Prim Inventory with prim ID {0}", primID); + + //Statement from MySQL section! + // For now, we're just going to crudely remove all the previous inventory items + // no matter whether they have changed or not, and replace them with the current set. + + //Delete everything from PrimID + //TODO add index on PrimID in DB, if not already exist + + string sql = "DELETE PRIMITEMS WHERE primID = @primID"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.Add(_Database.CreateParameter("@primID", primID)); + conn.Open(); + cmd.ExecuteNonQuery(); + } + + sql = + @"INSERT INTO primitems ( + itemID,primID,assetID,parentFolderID,invType,assetType,name,description,creationDate,creatorID,ownerID,lastOwnerID,groupID, + nextPermissions,currentPermissions,basePermissions,everyonePermissions,groupPermissions,flags) + VALUES (@itemID,@primID,@assetID,@parentFolderID,@invType,@assetType,@name,@description,@creationDate,@creatorID,@ownerID, + @lastOwnerID,@groupID,@nextPermissions,@currentPermissions,@basePermissions,@everyonePermissions,@groupPermissions,@flags)"; + + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + foreach (TaskInventoryItem taskItem in items) + { + cmd.Parameters.AddRange(CreatePrimInventoryParameters(taskItem)); + conn.Open(); + cmd.ExecuteNonQuery(); + + cmd.Parameters.Clear(); + } + } + } + + #endregion + + /// + /// Loads the terrain map. + /// + /// regionID. + /// + public double[,] LoadTerrain(UUID regionID) + { + double[,] terrain = new double[(int)Constants.RegionSize, (int)Constants.RegionSize]; + terrain.Initialize(); + + string sql = "select top 1 RegionUUID, Revision, Heightfield from terrain where RegionUUID = @RegionUUID order by Revision desc"; + + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + // MySqlParameter param = new MySqlParameter(); + cmd.Parameters.Add(_Database.CreateParameter("@RegionUUID", regionID)); + conn.Open(); + using (SqlDataReader reader = cmd.ExecuteReader()) + { + int rev; + if (reader.Read()) + { + MemoryStream str = new MemoryStream((byte[])reader["Heightfield"]); + BinaryReader br = new BinaryReader(str); + for (int x = 0; x < (int)Constants.RegionSize; x++) + { + for (int y = 0; y < (int)Constants.RegionSize; y++) + { + terrain[x, y] = br.ReadDouble(); + } + } + rev = (int)reader["Revision"]; + } + else + { + _Log.Info("[REGION DB]: No terrain found for region"); + return null; + } + _Log.Info("[REGION DB]: Loaded terrain revision r" + rev); + } + } + + return terrain; + } + + /// + /// Stores the terrain map to DB. + /// + /// terrain map data. + /// regionID. + public void StoreTerrain(double[,] terrain, UUID regionID) + { + int revision = Util.UnixTimeSinceEpoch(); + + //Delete old terrain map + string sql = "delete from terrain where RegionUUID=@RegionUUID"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.Add(_Database.CreateParameter("@RegionUUID", regionID)); + conn.Open(); + cmd.ExecuteNonQuery(); + } + + sql = "insert into terrain(RegionUUID, Revision, Heightfield) values(@RegionUUID, @Revision, @Heightfield)"; + + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.Add(_Database.CreateParameter("@RegionUUID", regionID)); + cmd.Parameters.Add(_Database.CreateParameter("@Revision", revision)); + cmd.Parameters.Add(_Database.CreateParameter("@Heightfield", serializeTerrain(terrain))); + conn.Open(); + cmd.ExecuteNonQuery(); + } + + _Log.Info("[REGION DB]: Stored terrain revision r " + revision); + } + + /// + /// Loads all the land objects of a region. + /// + /// The region UUID. + /// + public List LoadLandObjects(UUID regionUUID) + { + List LandDataForRegion = new List(); + + string sql = "select * from land where RegionUUID = @RegionUUID"; + + //Retrieve all land data from region + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.Add(_Database.CreateParameter("@RegionUUID", regionUUID)); + conn.Open(); + using (SqlDataReader readerLandData = cmd.ExecuteReader()) + { + while (readerLandData.Read()) + { + LandDataForRegion.Add(BuildLandData(readerLandData)); + } + } + } + + //Retrieve all accesslist data for all landdata + foreach (LandData LandData in LandDataForRegion) + { + sql = "select * from landaccesslist where LandUUID = @LandUUID"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.Add(_Database.CreateParameter("@LandUUID", LandData.GlobalID)); + conn.Open(); + using (SqlDataReader readerAccessList = cmd.ExecuteReader()) + { + while (readerAccessList.Read()) + { + LandData.ParcelAccessList.Add(BuildLandAccessData(readerAccessList)); + } + } + } + } + + //Return data + return LandDataForRegion; + } + + /// + /// Stores land object with landaccess list. + /// + /// parcel data. + public void StoreLandObject(ILandObject parcel) + { + //As this is only one record in land table I just delete all and then add a new record. + //As the delete landaccess is already in the mysql code + + //Delete old values + RemoveLandObject(parcel.LandData.GlobalID); + + //Insert new values + string sql = @"INSERT INTO [land] +([UUID],[RegionUUID],[LocalLandID],[Bitmap],[Name],[Description],[OwnerUUID],[IsGroupOwned],[Area],[AuctionID],[Category],[ClaimDate],[ClaimPrice],[GroupUUID],[SalePrice],[LandStatus],[LandFlags],[LandingType],[MediaAutoScale],[MediaTextureUUID],[MediaURL],[MusicURL],[PassHours],[PassPrice],[SnapshotUUID],[UserLocationX],[UserLocationY],[UserLocationZ],[UserLookAtX],[UserLookAtY],[UserLookAtZ],[AuthbuyerID],[OtherCleanTime]) +VALUES +(@UUID,@RegionUUID,@LocalLandID,@Bitmap,@Name,@Description,@OwnerUUID,@IsGroupOwned,@Area,@AuctionID,@Category,@ClaimDate,@ClaimPrice,@GroupUUID,@SalePrice,@LandStatus,@LandFlags,@LandingType,@MediaAutoScale,@MediaTextureUUID,@MediaURL,@MusicURL,@PassHours,@PassPrice,@SnapshotUUID,@UserLocationX,@UserLocationY,@UserLocationZ,@UserLookAtX,@UserLookAtY,@UserLookAtZ,@AuthbuyerID,@OtherCleanTime)"; + + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.AddRange(CreateLandParameters(parcel.LandData, parcel.RegionUUID)); + conn.Open(); + cmd.ExecuteNonQuery(); + } + + sql = "INSERT INTO [landaccesslist] ([LandUUID],[AccessUUID],[Flags]) VALUES (@LandUUID,@AccessUUID,@Flags)"; + + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + conn.Open(); + foreach (ParcelManager.ParcelAccessEntry parcelAccessEntry in parcel.LandData.ParcelAccessList) + { + cmd.Parameters.AddRange(CreateLandAccessParameters(parcelAccessEntry, parcel.RegionUUID)); + + cmd.ExecuteNonQuery(); + cmd.Parameters.Clear(); + } + } + } + + /// + /// Removes a land object from DB. + /// + /// UUID of landobject + public void RemoveLandObject(UUID globalID) + { + string sql = "delete from land where UUID=@UUID"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.Add(_Database.CreateParameter("@UUID", globalID)); + conn.Open(); + cmd.ExecuteNonQuery(); + } + sql = "delete from landaccesslist where LandUUID=@UUID"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.Add(_Database.CreateParameter("@UUID", globalID)); + conn.Open(); + cmd.ExecuteNonQuery(); + } + } + public RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID) + { + //This connector doesn't support the windlight module yet + //Return default LL windlight settings + return new RegionLightShareData(); + } + public void StoreRegionWindlightSettings(RegionLightShareData wl) + { + //This connector doesn't support the windlight module yet + } + /// + /// Loads the settings of a region. + /// + /// The region UUID. + /// + public RegionSettings LoadRegionSettings(UUID regionUUID) + { + string sql = "select * from regionsettings where regionUUID = @regionUUID"; + RegionSettings regionSettings; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.Add(_Database.CreateParameter("@regionUUID", regionUUID)); + conn.Open(); + using (SqlDataReader reader = cmd.ExecuteReader()) + { + if (reader.Read()) + { + regionSettings = BuildRegionSettings(reader); + regionSettings.OnSave += StoreRegionSettings; + + return regionSettings; + } + } + } + + //If we reach this point then there are new region settings for that region + regionSettings = new RegionSettings(); + regionSettings.RegionUUID = regionUUID; + regionSettings.OnSave += StoreRegionSettings; + + //Store new values + StoreNewRegionSettings(regionSettings); + + return regionSettings; + } + + /// + /// Store region settings, need to check if the check is really necesary. If we can make something for creating new region. + /// + /// region settings. + public void StoreRegionSettings(RegionSettings regionSettings) + { + //Little check if regionUUID already exist in DB + string regionUUID; + string sql = "SELECT regionUUID FROM regionsettings WHERE regionUUID = @regionUUID"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.Add(_Database.CreateParameter("@regionUUID", regionSettings.RegionUUID)); + conn.Open(); + regionUUID = cmd.ExecuteScalar().ToString(); + } + + if (string.IsNullOrEmpty(regionUUID)) + { + StoreNewRegionSettings(regionSettings); + } + else + { + //This method only updates region settings!!! First call LoadRegionSettings to create new region settings in DB + sql = + @"UPDATE [regionsettings] SET [block_terraform] = @block_terraform ,[block_fly] = @block_fly ,[allow_damage] = @allow_damage +,[restrict_pushing] = @restrict_pushing ,[allow_land_resell] = @allow_land_resell ,[allow_land_join_divide] = @allow_land_join_divide +,[block_show_in_search] = @block_show_in_search ,[agent_limit] = @agent_limit ,[object_bonus] = @object_bonus ,[maturity] = @maturity +,[disable_scripts] = @disable_scripts ,[disable_collisions] = @disable_collisions ,[disable_physics] = @disable_physics +,[terrain_texture_1] = @terrain_texture_1 ,[terrain_texture_2] = @terrain_texture_2 ,[terrain_texture_3] = @terrain_texture_3 +,[terrain_texture_4] = @terrain_texture_4 ,[elevation_1_nw] = @elevation_1_nw ,[elevation_2_nw] = @elevation_2_nw +,[elevation_1_ne] = @elevation_1_ne ,[elevation_2_ne] = @elevation_2_ne ,[elevation_1_se] = @elevation_1_se ,[elevation_2_se] = @elevation_2_se +,[elevation_1_sw] = @elevation_1_sw ,[elevation_2_sw] = @elevation_2_sw ,[water_height] = @water_height ,[terrain_raise_limit] = @terrain_raise_limit +,[terrain_lower_limit] = @terrain_lower_limit ,[use_estate_sun] = @use_estate_sun ,[fixed_sun] = @fixed_sun ,[sun_position] = @sun_position +,[covenant] = @covenant , [sunvectorx] = @sunvectorx, [sunvectory] = @sunvectory, [sunvectorz] = @sunvectorz, [Sandbox] = @Sandbox, [loaded_creation_datetime] = @loaded_creation_datetime, [loaded_creation_id] = @loaded_creation_id + WHERE [regionUUID] = @regionUUID"; + + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.AddRange(CreateRegionSettingParameters(regionSettings)); + conn.Open(); + cmd.ExecuteNonQuery(); + } + } + } + + public void Shutdown() + { + //Not used?? + } + + #region Private Methods + + /// + /// Serializes the terrain data for storage in DB. + /// + /// terrain data + /// + private static Array serializeTerrain(double[,] val) + { + MemoryStream str = new MemoryStream(((int)Constants.RegionSize * (int)Constants.RegionSize) * sizeof(double)); + BinaryWriter bw = new BinaryWriter(str); + + // TODO: COMPATIBILITY - Add byte-order conversions + for (int x = 0; x < (int)Constants.RegionSize; x++) + for (int y = 0; y < (int)Constants.RegionSize; y++) + { + double height = val[x, y]; + if (height == 0.0) + height = double.Epsilon; + + bw.Write(height); + } + + return str.ToArray(); + } + + /// + /// Stores new regionsettings. + /// + /// The region settings. + private void StoreNewRegionSettings(RegionSettings regionSettings) + { + string sql = @"INSERT INTO [regionsettings] + ([regionUUID],[block_terraform],[block_fly],[allow_damage],[restrict_pushing],[allow_land_resell],[allow_land_join_divide], + [block_show_in_search],[agent_limit],[object_bonus],[maturity],[disable_scripts],[disable_collisions],[disable_physics], + [terrain_texture_1],[terrain_texture_2],[terrain_texture_3],[terrain_texture_4],[elevation_1_nw],[elevation_2_nw],[elevation_1_ne], + [elevation_2_ne],[elevation_1_se],[elevation_2_se],[elevation_1_sw],[elevation_2_sw],[water_height],[terrain_raise_limit], + [terrain_lower_limit],[use_estate_sun],[fixed_sun],[sun_position],[covenant],[sunvectorx], [sunvectory], [sunvectorz],[Sandbox], [loaded_creation_datetime], [loaded_creation_id] + ) + VALUES + (@regionUUID,@block_terraform,@block_fly,@allow_damage,@restrict_pushing,@allow_land_resell,@allow_land_join_divide, + @block_show_in_search,@agent_limit,@object_bonus,@maturity,@disable_scripts,@disable_collisions,@disable_physics, + @terrain_texture_1,@terrain_texture_2,@terrain_texture_3,@terrain_texture_4,@elevation_1_nw,@elevation_2_nw,@elevation_1_ne, + @elevation_2_ne,@elevation_1_se,@elevation_2_se,@elevation_1_sw,@elevation_2_sw,@water_height,@terrain_raise_limit, + @terrain_lower_limit,@use_estate_sun,@fixed_sun,@sun_position,@covenant,@sunvectorx,@sunvectory, @sunvectorz, @Sandbox, @loaded_creation_datetime, @loaded_creation_id)"; + + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.AddRange(CreateRegionSettingParameters(regionSettings)); + conn.Open(); + cmd.ExecuteNonQuery(); + } + } + + #region Private DataRecord conversion methods + + /// + /// Builds the region settings from a datarecod. + /// + /// datarecord with regionsettings. + /// + private static RegionSettings BuildRegionSettings(IDataRecord row) + { + //TODO change this is some more generic code so we doesnt have to change it every time a new field is added? + RegionSettings newSettings = new RegionSettings(); + + newSettings.RegionUUID = new UUID((Guid)row["regionUUID"]); + newSettings.BlockTerraform = Convert.ToBoolean(row["block_terraform"]); + newSettings.AllowDamage = Convert.ToBoolean(row["allow_damage"]); + newSettings.BlockFly = Convert.ToBoolean(row["block_fly"]); + newSettings.RestrictPushing = Convert.ToBoolean(row["restrict_pushing"]); + newSettings.AllowLandResell = Convert.ToBoolean(row["allow_land_resell"]); + newSettings.AllowLandJoinDivide = Convert.ToBoolean(row["allow_land_join_divide"]); + newSettings.BlockShowInSearch = Convert.ToBoolean(row["block_show_in_search"]); + newSettings.AgentLimit = Convert.ToInt32(row["agent_limit"]); + newSettings.ObjectBonus = Convert.ToDouble(row["object_bonus"]); + newSettings.Maturity = Convert.ToInt32(row["maturity"]); + newSettings.DisableScripts = Convert.ToBoolean(row["disable_scripts"]); + newSettings.DisableCollisions = Convert.ToBoolean(row["disable_collisions"]); + newSettings.DisablePhysics = Convert.ToBoolean(row["disable_physics"]); + newSettings.TerrainTexture1 = new UUID((Guid)row["terrain_texture_1"]); + newSettings.TerrainTexture2 = new UUID((Guid)row["terrain_texture_2"]); + newSettings.TerrainTexture3 = new UUID((Guid)row["terrain_texture_3"]); + newSettings.TerrainTexture4 = new UUID((Guid)row["terrain_texture_4"]); + newSettings.Elevation1NW = Convert.ToDouble(row["elevation_1_nw"]); + newSettings.Elevation2NW = Convert.ToDouble(row["elevation_2_nw"]); + newSettings.Elevation1NE = Convert.ToDouble(row["elevation_1_ne"]); + newSettings.Elevation2NE = Convert.ToDouble(row["elevation_2_ne"]); + newSettings.Elevation1SE = Convert.ToDouble(row["elevation_1_se"]); + newSettings.Elevation2SE = Convert.ToDouble(row["elevation_2_se"]); + newSettings.Elevation1SW = Convert.ToDouble(row["elevation_1_sw"]); + newSettings.Elevation2SW = Convert.ToDouble(row["elevation_2_sw"]); + newSettings.WaterHeight = Convert.ToDouble(row["water_height"]); + newSettings.TerrainRaiseLimit = Convert.ToDouble(row["terrain_raise_limit"]); + newSettings.TerrainLowerLimit = Convert.ToDouble(row["terrain_lower_limit"]); + newSettings.UseEstateSun = Convert.ToBoolean(row["use_estate_sun"]); + newSettings.Sandbox = Convert.ToBoolean(row["sandbox"]); + newSettings.FixedSun = Convert.ToBoolean(row["fixed_sun"]); + newSettings.SunPosition = Convert.ToDouble(row["sun_position"]); + newSettings.SunVector = new Vector3( + Convert.ToSingle(row["sunvectorx"]), + Convert.ToSingle(row["sunvectory"]), + Convert.ToSingle(row["sunvectorz"]) + ); + newSettings.Covenant = new UUID((Guid)row["covenant"]); + + newSettings.LoadedCreationDateTime = Convert.ToInt32(row["loaded_creation_datetime"]); + + if (row["loaded_creation_id"] is DBNull) + newSettings.LoadedCreationID = ""; + else + newSettings.LoadedCreationID = (String)row["loaded_creation_id"]; + return newSettings; + } + + /// + /// Builds the land data from a datarecord. + /// + /// datarecord with land data + /// + private static LandData BuildLandData(IDataRecord row) + { + LandData newData = new LandData(); + + newData.GlobalID = new UUID((Guid)row["UUID"]); + newData.LocalID = Convert.ToInt32(row["LocalLandID"]); + + // Bitmap is a byte[512] + newData.Bitmap = (Byte[])row["Bitmap"]; + + newData.Name = (string)row["Name"]; + newData.Description = (string)row["Description"]; + newData.OwnerID = new UUID((Guid)row["OwnerUUID"]); + newData.IsGroupOwned = Convert.ToBoolean(row["IsGroupOwned"]); + newData.Area = Convert.ToInt32(row["Area"]); + newData.AuctionID = Convert.ToUInt32(row["AuctionID"]); //Unemplemented + newData.Category = (ParcelCategory)Convert.ToInt32(row["Category"]); + //Enum libsecondlife.Parcel.ParcelCategory + newData.ClaimDate = Convert.ToInt32(row["ClaimDate"]); + newData.ClaimPrice = Convert.ToInt32(row["ClaimPrice"]); + newData.GroupID = new UUID((Guid)row["GroupUUID"]); + newData.SalePrice = Convert.ToInt32(row["SalePrice"]); + newData.Status = (ParcelStatus)Convert.ToInt32(row["LandStatus"]); + //Enum. libsecondlife.Parcel.ParcelStatus + newData.Flags = Convert.ToUInt32(row["LandFlags"]); + newData.LandingType = Convert.ToByte(row["LandingType"]); + newData.MediaAutoScale = Convert.ToByte(row["MediaAutoScale"]); + newData.MediaID = new UUID((Guid)row["MediaTextureUUID"]); + newData.MediaURL = (string)row["MediaURL"]; + newData.MusicURL = (string)row["MusicURL"]; + newData.PassHours = Convert.ToSingle(row["PassHours"]); + newData.PassPrice = Convert.ToInt32(row["PassPrice"]); + + // UUID authedbuyer; + // UUID snapshotID; + // + // if (UUID.TryParse((string)row["AuthBuyerID"], out authedbuyer)) + // newData.AuthBuyerID = authedbuyer; + // + // if (UUID.TryParse((string)row["SnapshotUUID"], out snapshotID)) + // newData.SnapshotID = snapshotID; + newData.AuthBuyerID = new UUID((Guid)row["AuthBuyerID"]); + newData.SnapshotID = new UUID((Guid)row["SnapshotUUID"]); + + newData.OtherCleanTime = Convert.ToInt32(row["OtherCleanTime"]); + + try + { + newData.UserLocation = + new Vector3(Convert.ToSingle(row["UserLocationX"]), Convert.ToSingle(row["UserLocationY"]), + Convert.ToSingle(row["UserLocationZ"])); + newData.UserLookAt = + new Vector3(Convert.ToSingle(row["UserLookAtX"]), Convert.ToSingle(row["UserLookAtY"]), + Convert.ToSingle(row["UserLookAtZ"])); + } + catch (InvalidCastException) + { + newData.UserLocation = Vector3.Zero; + newData.UserLookAt = Vector3.Zero; + _Log.ErrorFormat("[PARCEL]: unable to get parcel telehub settings for {1}", newData.Name); + } + + newData.ParcelAccessList = new List(); + + return newData; + } + + /// + /// Builds the landaccess data from a data record. + /// + /// datarecord with landaccess data + /// + private static ParcelManager.ParcelAccessEntry BuildLandAccessData(IDataRecord row) + { + ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); + entry.AgentID = new UUID((Guid)row["AccessUUID"]); + entry.Flags = (AccessList)Convert.ToInt32(row["Flags"]); + entry.Time = new DateTime(); + return entry; + } + + /// + /// Builds the prim from a datarecord. + /// + /// datarecord + /// + private static SceneObjectPart BuildPrim(IDataRecord primRow) + { + SceneObjectPart prim = new SceneObjectPart(); + + prim.UUID = new UUID((Guid)primRow["UUID"]); + // explicit conversion of integers is required, which sort + // of sucks. No idea if there is a shortcut here or not. + prim.CreationDate = Convert.ToInt32(primRow["CreationDate"]); + prim.Name = (string)primRow["Name"]; + // various text fields + prim.Text = (string)primRow["Text"]; + prim.Color = Color.FromArgb(Convert.ToInt32(primRow["ColorA"]), + Convert.ToInt32(primRow["ColorR"]), + Convert.ToInt32(primRow["ColorG"]), + Convert.ToInt32(primRow["ColorB"])); + prim.Description = (string)primRow["Description"]; + prim.SitName = (string)primRow["SitName"]; + prim.TouchName = (string)primRow["TouchName"]; + // permissions + prim.Flags = (PrimFlags)Convert.ToUInt32(primRow["ObjectFlags"]); + prim.CreatorID = new UUID((Guid)primRow["CreatorID"]); + prim.OwnerID = new UUID((Guid)primRow["OwnerID"]); + prim.GroupID = new UUID((Guid)primRow["GroupID"]); + prim.LastOwnerID = new UUID((Guid)primRow["LastOwnerID"]); + prim.OwnerMask = Convert.ToUInt32(primRow["OwnerMask"]); + prim.NextOwnerMask = Convert.ToUInt32(primRow["NextOwnerMask"]); + prim.GroupMask = Convert.ToUInt32(primRow["GroupMask"]); + prim.EveryoneMask = Convert.ToUInt32(primRow["EveryoneMask"]); + prim.BaseMask = Convert.ToUInt32(primRow["BaseMask"]); + // vectors + prim.OffsetPosition = new Vector3( + Convert.ToSingle(primRow["PositionX"]), + Convert.ToSingle(primRow["PositionY"]), + Convert.ToSingle(primRow["PositionZ"])); + + prim.GroupPosition = new Vector3( + Convert.ToSingle(primRow["GroupPositionX"]), + Convert.ToSingle(primRow["GroupPositionY"]), + Convert.ToSingle(primRow["GroupPositionZ"])); + + prim.Velocity = new Vector3( + Convert.ToSingle(primRow["VelocityX"]), + Convert.ToSingle(primRow["VelocityY"]), + Convert.ToSingle(primRow["VelocityZ"])); + + prim.AngularVelocity = new Vector3( + Convert.ToSingle(primRow["AngularVelocityX"]), + Convert.ToSingle(primRow["AngularVelocityY"]), + Convert.ToSingle(primRow["AngularVelocityZ"])); + + prim.Acceleration = new Vector3( + Convert.ToSingle(primRow["AccelerationX"]), + Convert.ToSingle(primRow["AccelerationY"]), + Convert.ToSingle(primRow["AccelerationZ"])); + + // quaternions + prim.RotationOffset = new Quaternion( + Convert.ToSingle(primRow["RotationX"]), + Convert.ToSingle(primRow["RotationY"]), + Convert.ToSingle(primRow["RotationZ"]), + Convert.ToSingle(primRow["RotationW"])); + + prim.SitTargetPositionLL = new Vector3( + Convert.ToSingle(primRow["SitTargetOffsetX"]), + Convert.ToSingle(primRow["SitTargetOffsetY"]), + Convert.ToSingle(primRow["SitTargetOffsetZ"])); + + prim.SitTargetOrientationLL = new Quaternion( + Convert.ToSingle(primRow["SitTargetOrientX"]), + Convert.ToSingle(primRow["SitTargetOrientY"]), + Convert.ToSingle(primRow["SitTargetOrientZ"]), + Convert.ToSingle(primRow["SitTargetOrientW"])); + + prim.PayPrice[0] = Convert.ToInt32(primRow["PayPrice"]); + prim.PayPrice[1] = Convert.ToInt32(primRow["PayButton1"]); + prim.PayPrice[2] = Convert.ToInt32(primRow["PayButton2"]); + prim.PayPrice[3] = Convert.ToInt32(primRow["PayButton3"]); + prim.PayPrice[4] = Convert.ToInt32(primRow["PayButton4"]); + + prim.Sound = new UUID((Guid)primRow["LoopedSound"]); + prim.SoundGain = Convert.ToSingle(primRow["LoopedSoundGain"]); + prim.SoundFlags = 1; // If it's persisted at all, it's looped + + if (!(primRow["TextureAnimation"] is DBNull)) + prim.TextureAnimation = (Byte[])primRow["TextureAnimation"]; + if (!(primRow["ParticleSystem"] is DBNull)) + prim.ParticleSystem = (Byte[])primRow["ParticleSystem"]; + + prim.AngularVelocity = new Vector3( + Convert.ToSingle(primRow["OmegaX"]), + Convert.ToSingle(primRow["OmegaY"]), + Convert.ToSingle(primRow["OmegaZ"])); + + prim.SetCameraEyeOffset(new Vector3( + Convert.ToSingle(primRow["CameraEyeOffsetX"]), + Convert.ToSingle(primRow["CameraEyeOffsetY"]), + Convert.ToSingle(primRow["CameraEyeOffsetZ"]) + )); + + prim.SetCameraAtOffset(new Vector3( + Convert.ToSingle(primRow["CameraAtOffsetX"]), + Convert.ToSingle(primRow["CameraAtOffsetY"]), + Convert.ToSingle(primRow["CameraAtOffsetZ"]) + )); + + if (Convert.ToInt16(primRow["ForceMouselook"]) != 0) + prim.SetForceMouselook(true); + + prim.ScriptAccessPin = Convert.ToInt32(primRow["ScriptAccessPin"]); + + if (Convert.ToInt16(primRow["AllowedDrop"]) != 0) + prim.AllowedDrop = true; + + if (Convert.ToInt16(primRow["DieAtEdge"]) != 0) + prim.DIE_AT_EDGE = true; + + prim.SalePrice = Convert.ToInt32(primRow["SalePrice"]); + prim.ObjectSaleType = Convert.ToByte(primRow["SaleType"]); + + prim.Material = Convert.ToByte(primRow["Material"]); + + if (!(primRow["ClickAction"] is DBNull)) + prim.ClickAction = Convert.ToByte(primRow["ClickAction"]); + + prim.CollisionSound = new UUID((Guid)primRow["CollisionSound"]); + prim.CollisionSoundVolume = Convert.ToSingle(primRow["CollisionSoundVolume"]); + if (Convert.ToInt16(primRow["PassTouches"]) != 0) + prim.PassTouches = true; + prim.LinkNum = Convert.ToInt32(primRow["LinkNumber"]); + + if (!(primRow["MediaURL"] is System.DBNull)) + prim.MediaUrl = (string)primRow["MediaURL"]; + + return prim; + } + + /// + /// Builds the prim shape from a datarecord. + /// + /// The row. + /// + private static PrimitiveBaseShape BuildShape(IDataRecord shapeRow) + { + PrimitiveBaseShape baseShape = new PrimitiveBaseShape(); + + baseShape.Scale = new Vector3( + Convert.ToSingle(shapeRow["ScaleX"]), + Convert.ToSingle(shapeRow["ScaleY"]), + Convert.ToSingle(shapeRow["ScaleZ"])); + + // paths + baseShape.PCode = Convert.ToByte(shapeRow["PCode"]); + baseShape.PathBegin = Convert.ToUInt16(shapeRow["PathBegin"]); + baseShape.PathEnd = Convert.ToUInt16(shapeRow["PathEnd"]); + baseShape.PathScaleX = Convert.ToByte(shapeRow["PathScaleX"]); + baseShape.PathScaleY = Convert.ToByte(shapeRow["PathScaleY"]); + baseShape.PathShearX = Convert.ToByte(shapeRow["PathShearX"]); + baseShape.PathShearY = Convert.ToByte(shapeRow["PathShearY"]); + baseShape.PathSkew = Convert.ToSByte(shapeRow["PathSkew"]); + baseShape.PathCurve = Convert.ToByte(shapeRow["PathCurve"]); + baseShape.PathRadiusOffset = Convert.ToSByte(shapeRow["PathRadiusOffset"]); + baseShape.PathRevolutions = Convert.ToByte(shapeRow["PathRevolutions"]); + baseShape.PathTaperX = Convert.ToSByte(shapeRow["PathTaperX"]); + baseShape.PathTaperY = Convert.ToSByte(shapeRow["PathTaperY"]); + baseShape.PathTwist = Convert.ToSByte(shapeRow["PathTwist"]); + baseShape.PathTwistBegin = Convert.ToSByte(shapeRow["PathTwistBegin"]); + // profile + baseShape.ProfileBegin = Convert.ToUInt16(shapeRow["ProfileBegin"]); + baseShape.ProfileEnd = Convert.ToUInt16(shapeRow["ProfileEnd"]); + baseShape.ProfileCurve = Convert.ToByte(shapeRow["ProfileCurve"]); + baseShape.ProfileHollow = Convert.ToUInt16(shapeRow["ProfileHollow"]); + + byte[] textureEntry = (byte[])shapeRow["Texture"]; + baseShape.TextureEntry = textureEntry; + + baseShape.ExtraParams = (byte[])shapeRow["ExtraParams"]; + + try + { + baseShape.State = Convert.ToByte(shapeRow["State"]); + } + catch (InvalidCastException) + { + } + + if (!(shapeRow["Media"] is System.DBNull)) + baseShape.Media = PrimitiveBaseShape.MediaList.FromXml((string)shapeRow["Media"]); + + return baseShape; + } + + /// + /// Build a prim inventory item from the persisted data. + /// + /// + /// + private static TaskInventoryItem BuildItem(IDataRecord inventoryRow) + { + TaskInventoryItem taskItem = new TaskInventoryItem(); + + taskItem.ItemID = new UUID((Guid)inventoryRow["itemID"]); + taskItem.ParentPartID = new UUID((Guid)inventoryRow["primID"]); + taskItem.AssetID = new UUID((Guid)inventoryRow["assetID"]); + taskItem.ParentID = new UUID((Guid)inventoryRow["parentFolderID"]); + + taskItem.InvType = Convert.ToInt32(inventoryRow["invType"]); + taskItem.Type = Convert.ToInt32(inventoryRow["assetType"]); + + taskItem.Name = (string)inventoryRow["name"]; + taskItem.Description = (string)inventoryRow["description"]; + taskItem.CreationDate = Convert.ToUInt32(inventoryRow["creationDate"]); + taskItem.CreatorID = new UUID((Guid)inventoryRow["creatorID"]); + taskItem.OwnerID = new UUID((Guid)inventoryRow["ownerID"]); + taskItem.LastOwnerID = new UUID((Guid)inventoryRow["lastOwnerID"]); + taskItem.GroupID = new UUID((Guid)inventoryRow["groupID"]); + + taskItem.NextPermissions = Convert.ToUInt32(inventoryRow["nextPermissions"]); + taskItem.CurrentPermissions = Convert.ToUInt32(inventoryRow["currentPermissions"]); + taskItem.BasePermissions = Convert.ToUInt32(inventoryRow["basePermissions"]); + taskItem.EveryonePermissions = Convert.ToUInt32(inventoryRow["everyonePermissions"]); + taskItem.GroupPermissions = Convert.ToUInt32(inventoryRow["groupPermissions"]); + taskItem.Flags = Convert.ToUInt32(inventoryRow["flags"]); + + return taskItem; + } + + #endregion + + #region Create parameters methods + + /// + /// Creates the prim inventory parameters. + /// + /// item in inventory. + /// + private SqlParameter[] CreatePrimInventoryParameters(TaskInventoryItem taskItem) + { + List parameters = new List(); + + parameters.Add(_Database.CreateParameter("itemID", taskItem.ItemID)); + parameters.Add(_Database.CreateParameter("primID", taskItem.ParentPartID)); + parameters.Add(_Database.CreateParameter("assetID", taskItem.AssetID)); + parameters.Add(_Database.CreateParameter("parentFolderID", taskItem.ParentID)); + parameters.Add(_Database.CreateParameter("invType", taskItem.InvType)); + parameters.Add(_Database.CreateParameter("assetType", taskItem.Type)); + + parameters.Add(_Database.CreateParameter("name", taskItem.Name)); + parameters.Add(_Database.CreateParameter("description", taskItem.Description)); + parameters.Add(_Database.CreateParameter("creationDate", taskItem.CreationDate)); + parameters.Add(_Database.CreateParameter("creatorID", taskItem.CreatorID)); + parameters.Add(_Database.CreateParameter("ownerID", taskItem.OwnerID)); + parameters.Add(_Database.CreateParameter("lastOwnerID", taskItem.LastOwnerID)); + parameters.Add(_Database.CreateParameter("groupID", taskItem.GroupID)); + parameters.Add(_Database.CreateParameter("nextPermissions", taskItem.NextPermissions)); + parameters.Add(_Database.CreateParameter("currentPermissions", taskItem.CurrentPermissions)); + parameters.Add(_Database.CreateParameter("basePermissions", taskItem.BasePermissions)); + parameters.Add(_Database.CreateParameter("everyonePermissions", taskItem.EveryonePermissions)); + parameters.Add(_Database.CreateParameter("groupPermissions", taskItem.GroupPermissions)); + parameters.Add(_Database.CreateParameter("flags", taskItem.Flags)); + + return parameters.ToArray(); + } + + /// + /// Creates the region setting parameters. + /// + /// regionsettings. + /// + private SqlParameter[] CreateRegionSettingParameters(RegionSettings settings) + { + List parameters = new List(); + + parameters.Add(_Database.CreateParameter("regionUUID", settings.RegionUUID)); + parameters.Add(_Database.CreateParameter("block_terraform", settings.BlockTerraform)); + parameters.Add(_Database.CreateParameter("block_fly", settings.BlockFly)); + parameters.Add(_Database.CreateParameter("allow_damage", settings.AllowDamage)); + parameters.Add(_Database.CreateParameter("restrict_pushing", settings.RestrictPushing)); + parameters.Add(_Database.CreateParameter("allow_land_resell", settings.AllowLandResell)); + parameters.Add(_Database.CreateParameter("allow_land_join_divide", settings.AllowLandJoinDivide)); + parameters.Add(_Database.CreateParameter("block_show_in_search", settings.BlockShowInSearch)); + parameters.Add(_Database.CreateParameter("agent_limit", settings.AgentLimit)); + parameters.Add(_Database.CreateParameter("object_bonus", settings.ObjectBonus)); + parameters.Add(_Database.CreateParameter("maturity", settings.Maturity)); + parameters.Add(_Database.CreateParameter("disable_scripts", settings.DisableScripts)); + parameters.Add(_Database.CreateParameter("disable_collisions", settings.DisableCollisions)); + parameters.Add(_Database.CreateParameter("disable_physics", settings.DisablePhysics)); + parameters.Add(_Database.CreateParameter("terrain_texture_1", settings.TerrainTexture1)); + parameters.Add(_Database.CreateParameter("terrain_texture_2", settings.TerrainTexture2)); + parameters.Add(_Database.CreateParameter("terrain_texture_3", settings.TerrainTexture3)); + parameters.Add(_Database.CreateParameter("terrain_texture_4", settings.TerrainTexture4)); + parameters.Add(_Database.CreateParameter("elevation_1_nw", settings.Elevation1NW)); + parameters.Add(_Database.CreateParameter("elevation_2_nw", settings.Elevation2NW)); + parameters.Add(_Database.CreateParameter("elevation_1_ne", settings.Elevation1NE)); + parameters.Add(_Database.CreateParameter("elevation_2_ne", settings.Elevation2NE)); + parameters.Add(_Database.CreateParameter("elevation_1_se", settings.Elevation1SE)); + parameters.Add(_Database.CreateParameter("elevation_2_se", settings.Elevation2SE)); + parameters.Add(_Database.CreateParameter("elevation_1_sw", settings.Elevation1SW)); + parameters.Add(_Database.CreateParameter("elevation_2_sw", settings.Elevation2SW)); + parameters.Add(_Database.CreateParameter("water_height", settings.WaterHeight)); + parameters.Add(_Database.CreateParameter("terrain_raise_limit", settings.TerrainRaiseLimit)); + parameters.Add(_Database.CreateParameter("terrain_lower_limit", settings.TerrainLowerLimit)); + parameters.Add(_Database.CreateParameter("use_estate_sun", settings.UseEstateSun)); + parameters.Add(_Database.CreateParameter("sandbox", settings.Sandbox)); + parameters.Add(_Database.CreateParameter("fixed_sun", settings.FixedSun)); + parameters.Add(_Database.CreateParameter("sun_position", settings.SunPosition)); + parameters.Add(_Database.CreateParameter("sunvectorx", settings.SunVector.X)); + parameters.Add(_Database.CreateParameter("sunvectory", settings.SunVector.Y)); + parameters.Add(_Database.CreateParameter("sunvectorz", settings.SunVector.Z)); + parameters.Add(_Database.CreateParameter("covenant", settings.Covenant)); + parameters.Add(_Database.CreateParameter("Loaded_Creation_DateTime", settings.LoadedCreationDateTime)); + parameters.Add(_Database.CreateParameter("Loaded_Creation_ID", settings.LoadedCreationID)); + + return parameters.ToArray(); + } + + /// + /// Creates the land parameters. + /// + /// land parameters. + /// region UUID. + /// + private SqlParameter[] CreateLandParameters(LandData land, UUID regionUUID) + { + List parameters = new List(); + + parameters.Add(_Database.CreateParameter("UUID", land.GlobalID)); + parameters.Add(_Database.CreateParameter("RegionUUID", regionUUID)); + parameters.Add(_Database.CreateParameter("LocalLandID", land.LocalID)); + + // Bitmap is a byte[512] + parameters.Add(_Database.CreateParameter("Bitmap", land.Bitmap)); + + parameters.Add(_Database.CreateParameter("Name", land.Name)); + parameters.Add(_Database.CreateParameter("Description", land.Description)); + parameters.Add(_Database.CreateParameter("OwnerUUID", land.OwnerID)); + parameters.Add(_Database.CreateParameter("IsGroupOwned", land.IsGroupOwned)); + parameters.Add(_Database.CreateParameter("Area", land.Area)); + parameters.Add(_Database.CreateParameter("AuctionID", land.AuctionID)); //Unemplemented + parameters.Add(_Database.CreateParameter("Category", (int)land.Category)); //Enum libsecondlife.Parcel.ParcelCategory + parameters.Add(_Database.CreateParameter("ClaimDate", land.ClaimDate)); + parameters.Add(_Database.CreateParameter("ClaimPrice", land.ClaimPrice)); + parameters.Add(_Database.CreateParameter("GroupUUID", land.GroupID)); + parameters.Add(_Database.CreateParameter("SalePrice", land.SalePrice)); + parameters.Add(_Database.CreateParameter("LandStatus", (int)land.Status)); //Enum. libsecondlife.Parcel.ParcelStatus + parameters.Add(_Database.CreateParameter("LandFlags", land.Flags)); + parameters.Add(_Database.CreateParameter("LandingType", land.LandingType)); + parameters.Add(_Database.CreateParameter("MediaAutoScale", land.MediaAutoScale)); + parameters.Add(_Database.CreateParameter("MediaTextureUUID", land.MediaID)); + parameters.Add(_Database.CreateParameter("MediaURL", land.MediaURL)); + parameters.Add(_Database.CreateParameter("MusicURL", land.MusicURL)); + parameters.Add(_Database.CreateParameter("PassHours", land.PassHours)); + parameters.Add(_Database.CreateParameter("PassPrice", land.PassPrice)); + parameters.Add(_Database.CreateParameter("SnapshotUUID", land.SnapshotID)); + parameters.Add(_Database.CreateParameter("UserLocationX", land.UserLocation.X)); + parameters.Add(_Database.CreateParameter("UserLocationY", land.UserLocation.Y)); + parameters.Add(_Database.CreateParameter("UserLocationZ", land.UserLocation.Z)); + parameters.Add(_Database.CreateParameter("UserLookAtX", land.UserLookAt.X)); + parameters.Add(_Database.CreateParameter("UserLookAtY", land.UserLookAt.Y)); + parameters.Add(_Database.CreateParameter("UserLookAtZ", land.UserLookAt.Z)); + parameters.Add(_Database.CreateParameter("AuthBuyerID", land.AuthBuyerID)); + parameters.Add(_Database.CreateParameter("OtherCleanTime", land.OtherCleanTime)); + + return parameters.ToArray(); + } + + /// + /// Creates the land access parameters. + /// + /// parcel access entry. + /// parcel ID. + /// + private SqlParameter[] CreateLandAccessParameters(ParcelManager.ParcelAccessEntry parcelAccessEntry, UUID parcelID) + { + List parameters = new List(); + + parameters.Add(_Database.CreateParameter("LandUUID", parcelID)); + parameters.Add(_Database.CreateParameter("AccessUUID", parcelAccessEntry.AgentID)); + parameters.Add(_Database.CreateParameter("Flags", parcelAccessEntry.Flags)); + + return parameters.ToArray(); + } + + /// + /// Creates the prim parameters for storing in DB. + /// + /// Basic data of SceneObjectpart prim. + /// The scenegroup ID. + /// The region ID. + /// + private SqlParameter[] CreatePrimParameters(SceneObjectPart prim, UUID sceneGroupID, UUID regionUUID) + { + List parameters = new List(); + + parameters.Add(_Database.CreateParameter("UUID", prim.UUID)); + parameters.Add(_Database.CreateParameter("RegionUUID", regionUUID)); + parameters.Add(_Database.CreateParameter("CreationDate", prim.CreationDate)); + parameters.Add(_Database.CreateParameter("Name", prim.Name)); + parameters.Add(_Database.CreateParameter("SceneGroupID", sceneGroupID)); + // the UUID of the root part for this SceneObjectGroup + // various text fields + parameters.Add(_Database.CreateParameter("Text", prim.Text)); + parameters.Add(_Database.CreateParameter("ColorR", prim.Color.R)); + parameters.Add(_Database.CreateParameter("ColorG", prim.Color.G)); + parameters.Add(_Database.CreateParameter("ColorB", prim.Color.B)); + parameters.Add(_Database.CreateParameter("ColorA", prim.Color.A)); + parameters.Add(_Database.CreateParameter("Description", prim.Description)); + parameters.Add(_Database.CreateParameter("SitName", prim.SitName)); + parameters.Add(_Database.CreateParameter("TouchName", prim.TouchName)); + // permissions + parameters.Add(_Database.CreateParameter("ObjectFlags", (uint)prim.Flags)); + parameters.Add(_Database.CreateParameter("CreatorID", prim.CreatorID)); + parameters.Add(_Database.CreateParameter("OwnerID", prim.OwnerID)); + parameters.Add(_Database.CreateParameter("GroupID", prim.GroupID)); + parameters.Add(_Database.CreateParameter("LastOwnerID", prim.LastOwnerID)); + parameters.Add(_Database.CreateParameter("OwnerMask", prim.OwnerMask)); + parameters.Add(_Database.CreateParameter("NextOwnerMask", prim.NextOwnerMask)); + parameters.Add(_Database.CreateParameter("GroupMask", prim.GroupMask)); + parameters.Add(_Database.CreateParameter("EveryoneMask", prim.EveryoneMask)); + parameters.Add(_Database.CreateParameter("BaseMask", prim.BaseMask)); + // vectors + parameters.Add(_Database.CreateParameter("PositionX", prim.OffsetPosition.X)); + parameters.Add(_Database.CreateParameter("PositionY", prim.OffsetPosition.Y)); + parameters.Add(_Database.CreateParameter("PositionZ", prim.OffsetPosition.Z)); + parameters.Add(_Database.CreateParameter("GroupPositionX", prim.GroupPosition.X)); + parameters.Add(_Database.CreateParameter("GroupPositionY", prim.GroupPosition.Y)); + parameters.Add(_Database.CreateParameter("GroupPositionZ", prim.GroupPosition.Z)); + parameters.Add(_Database.CreateParameter("VelocityX", prim.Velocity.X)); + parameters.Add(_Database.CreateParameter("VelocityY", prim.Velocity.Y)); + parameters.Add(_Database.CreateParameter("VelocityZ", prim.Velocity.Z)); + parameters.Add(_Database.CreateParameter("AngularVelocityX", prim.AngularVelocity.X)); + parameters.Add(_Database.CreateParameter("AngularVelocityY", prim.AngularVelocity.Y)); + parameters.Add(_Database.CreateParameter("AngularVelocityZ", prim.AngularVelocity.Z)); + parameters.Add(_Database.CreateParameter("AccelerationX", prim.Acceleration.X)); + parameters.Add(_Database.CreateParameter("AccelerationY", prim.Acceleration.Y)); + parameters.Add(_Database.CreateParameter("AccelerationZ", prim.Acceleration.Z)); + // quaternions + parameters.Add(_Database.CreateParameter("RotationX", prim.RotationOffset.X)); + parameters.Add(_Database.CreateParameter("RotationY", prim.RotationOffset.Y)); + parameters.Add(_Database.CreateParameter("RotationZ", prim.RotationOffset.Z)); + parameters.Add(_Database.CreateParameter("RotationW", prim.RotationOffset.W)); + + // Sit target + Vector3 sitTargetPos = prim.SitTargetPositionLL; + parameters.Add(_Database.CreateParameter("SitTargetOffsetX", sitTargetPos.X)); + parameters.Add(_Database.CreateParameter("SitTargetOffsetY", sitTargetPos.Y)); + parameters.Add(_Database.CreateParameter("SitTargetOffsetZ", sitTargetPos.Z)); + + Quaternion sitTargetOrient = prim.SitTargetOrientationLL; + parameters.Add(_Database.CreateParameter("SitTargetOrientW", sitTargetOrient.W)); + parameters.Add(_Database.CreateParameter("SitTargetOrientX", sitTargetOrient.X)); + parameters.Add(_Database.CreateParameter("SitTargetOrientY", sitTargetOrient.Y)); + parameters.Add(_Database.CreateParameter("SitTargetOrientZ", sitTargetOrient.Z)); + + parameters.Add(_Database.CreateParameter("PayPrice", prim.PayPrice[0])); + parameters.Add(_Database.CreateParameter("PayButton1", prim.PayPrice[1])); + parameters.Add(_Database.CreateParameter("PayButton2", prim.PayPrice[2])); + parameters.Add(_Database.CreateParameter("PayButton3", prim.PayPrice[3])); + parameters.Add(_Database.CreateParameter("PayButton4", prim.PayPrice[4])); + + if ((prim.SoundFlags & 1) != 0) // Looped + { + parameters.Add(_Database.CreateParameter("LoopedSound", prim.Sound)); + parameters.Add(_Database.CreateParameter("LoopedSoundGain", prim.SoundGain)); + } + else + { + parameters.Add(_Database.CreateParameter("LoopedSound", UUID.Zero)); + parameters.Add(_Database.CreateParameter("LoopedSoundGain", 0.0f)); + } + + parameters.Add(_Database.CreateParameter("TextureAnimation", prim.TextureAnimation)); + parameters.Add(_Database.CreateParameter("ParticleSystem", prim.ParticleSystem)); + + parameters.Add(_Database.CreateParameter("OmegaX", prim.AngularVelocity.X)); + parameters.Add(_Database.CreateParameter("OmegaY", prim.AngularVelocity.Y)); + parameters.Add(_Database.CreateParameter("OmegaZ", prim.AngularVelocity.Z)); + + parameters.Add(_Database.CreateParameter("CameraEyeOffsetX", prim.GetCameraEyeOffset().X)); + parameters.Add(_Database.CreateParameter("CameraEyeOffsetY", prim.GetCameraEyeOffset().Y)); + parameters.Add(_Database.CreateParameter("CameraEyeOffsetZ", prim.GetCameraEyeOffset().Z)); + + parameters.Add(_Database.CreateParameter("CameraAtOffsetX", prim.GetCameraAtOffset().X)); + parameters.Add(_Database.CreateParameter("CameraAtOffsetY", prim.GetCameraAtOffset().Y)); + parameters.Add(_Database.CreateParameter("CameraAtOffsetZ", prim.GetCameraAtOffset().Z)); + + if (prim.GetForceMouselook()) + parameters.Add(_Database.CreateParameter("ForceMouselook", 1)); + else + parameters.Add(_Database.CreateParameter("ForceMouselook", 0)); + + parameters.Add(_Database.CreateParameter("ScriptAccessPin", prim.ScriptAccessPin)); + + if (prim.AllowedDrop) + parameters.Add(_Database.CreateParameter("AllowedDrop", 1)); + else + parameters.Add(_Database.CreateParameter("AllowedDrop", 0)); + + if (prim.DIE_AT_EDGE) + parameters.Add(_Database.CreateParameter("DieAtEdge", 1)); + else + parameters.Add(_Database.CreateParameter("DieAtEdge", 0)); + + parameters.Add(_Database.CreateParameter("SalePrice", prim.SalePrice)); + parameters.Add(_Database.CreateParameter("SaleType", prim.ObjectSaleType)); + + byte clickAction = prim.ClickAction; + parameters.Add(_Database.CreateParameter("ClickAction", clickAction)); + + parameters.Add(_Database.CreateParameter("Material", prim.Material)); + + parameters.Add(_Database.CreateParameter("CollisionSound", prim.CollisionSound)); + parameters.Add(_Database.CreateParameter("CollisionSoundVolume", prim.CollisionSoundVolume)); + if (prim.PassTouches) + parameters.Add(_Database.CreateParameter("PassTouches", 1)); + else + parameters.Add(_Database.CreateParameter("PassTouches", 0)); + parameters.Add(_Database.CreateParameter("LinkNumber", prim.LinkNum)); + parameters.Add(_Database.CreateParameter("MediaURL", prim.MediaUrl)); + + return parameters.ToArray(); + } + + /// + /// Creates the primshape parameters for stroing in DB. + /// + /// Basic data of SceneObjectpart prim. + /// The scene group ID. + /// The region UUID. + /// + private SqlParameter[] CreatePrimShapeParameters(SceneObjectPart prim, UUID sceneGroupID, UUID regionUUID) + { + List parameters = new List(); + + PrimitiveBaseShape s = prim.Shape; + parameters.Add(_Database.CreateParameter("UUID", prim.UUID)); + // shape is an enum + parameters.Add(_Database.CreateParameter("Shape", 0)); + // vectors + parameters.Add(_Database.CreateParameter("ScaleX", s.Scale.X)); + parameters.Add(_Database.CreateParameter("ScaleY", s.Scale.Y)); + parameters.Add(_Database.CreateParameter("ScaleZ", s.Scale.Z)); + // paths + parameters.Add(_Database.CreateParameter("PCode", s.PCode)); + parameters.Add(_Database.CreateParameter("PathBegin", s.PathBegin)); + parameters.Add(_Database.CreateParameter("PathEnd", s.PathEnd)); + parameters.Add(_Database.CreateParameter("PathScaleX", s.PathScaleX)); + parameters.Add(_Database.CreateParameter("PathScaleY", s.PathScaleY)); + parameters.Add(_Database.CreateParameter("PathShearX", s.PathShearX)); + parameters.Add(_Database.CreateParameter("PathShearY", s.PathShearY)); + parameters.Add(_Database.CreateParameter("PathSkew", s.PathSkew)); + parameters.Add(_Database.CreateParameter("PathCurve", s.PathCurve)); + parameters.Add(_Database.CreateParameter("PathRadiusOffset", s.PathRadiusOffset)); + parameters.Add(_Database.CreateParameter("PathRevolutions", s.PathRevolutions)); + parameters.Add(_Database.CreateParameter("PathTaperX", s.PathTaperX)); + parameters.Add(_Database.CreateParameter("PathTaperY", s.PathTaperY)); + parameters.Add(_Database.CreateParameter("PathTwist", s.PathTwist)); + parameters.Add(_Database.CreateParameter("PathTwistBegin", s.PathTwistBegin)); + // profile + parameters.Add(_Database.CreateParameter("ProfileBegin", s.ProfileBegin)); + parameters.Add(_Database.CreateParameter("ProfileEnd", s.ProfileEnd)); + parameters.Add(_Database.CreateParameter("ProfileCurve", s.ProfileCurve)); + parameters.Add(_Database.CreateParameter("ProfileHollow", s.ProfileHollow)); + parameters.Add(_Database.CreateParameter("Texture", s.TextureEntry)); + parameters.Add(_Database.CreateParameter("ExtraParams", s.ExtraParams)); + parameters.Add(_Database.CreateParameter("State", s.State)); + parameters.Add(_Database.CreateParameter("Media", null == s.Media ? null : s.Media.ToXml())); + + return parameters.ToArray(); + } + + #endregion + + #endregion + } +} diff --git a/OpenSim/Data/MySQL/MySQLLegacyRegionData.cs b/OpenSim/Data/MySQL/MySQLLegacyRegionData.cs deleted file mode 100644 index a39e68d..0000000 --- a/OpenSim/Data/MySQL/MySQLLegacyRegionData.cs +++ /dev/null @@ -1,1820 +0,0 @@ -/* - * 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.Data; -using System.Drawing; -using System.IO; -using System.Reflection; -using System.Threading; -using log4net; -using MySql.Data.MySqlClient; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Data; - -namespace OpenSim.Data.MySQL -{ - /// - /// A MySQL Interface for the Region Server - /// - public class MySQLDataStore : IRegionDataStore - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private string m_connectionString; - private object m_dbLock = new object(); - - public void Initialise(string connectionString) - { - m_connectionString = connectionString; - - using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) - { - dbcon.Open(); - - // Apply new Migrations - // - Assembly assem = GetType().Assembly; - Migration m = new Migration(dbcon, assem, "RegionStore"); - m.Update(); - - // Clean dropped attachments - // - try - { - using (MySqlCommand cmd = dbcon.CreateCommand()) - { - cmd.CommandText = "delete from prims, primshapes using prims " + - "left join primshapes on prims.uuid = primshapes.uuid " + - "where PCode = 9 and State <> 0"; - ExecuteNonQuery(cmd); - } - } - catch (MySqlException ex) - { - m_log.Error("[REGION DB]: Error cleaning up dropped attachments: " + ex.Message); - } - } - } - - private IDataReader ExecuteReader(MySqlCommand c) - { - IDataReader r = null; - - try - { - r = c.ExecuteReader(); - } - catch (Exception e) - { - m_log.Error("[REGION DB]: MySQL error in ExecuteReader: " + e.Message); - throw; - } - - return r; - } - - private void ExecuteNonQuery(MySqlCommand c) - { - try - { - c.ExecuteNonQuery(); - } - catch (Exception e) - { - m_log.Error("[REGION DB]: MySQL error in ExecuteNonQuery: " + e.Message); - throw; - } - } - - public void Dispose() {} - - public void StoreObject(SceneObjectGroup obj, UUID regionUUID) - { - uint flags = obj.RootPart.GetEffectiveObjectFlags(); - - // Eligibility check - // - if ((flags & (uint)PrimFlags.Temporary) != 0) - return; - if ((flags & (uint)PrimFlags.TemporaryOnRez) != 0) - return; - - lock (m_dbLock) - { - using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) - { - dbcon.Open(); - MySqlCommand cmd = dbcon.CreateCommand(); - - foreach (SceneObjectPart prim in obj.Children.Values) - { - cmd.Parameters.Clear(); - - cmd.CommandText = "replace into prims (" + - "UUID, CreationDate, " + - "Name, Text, Description, " + - "SitName, TouchName, ObjectFlags, " + - "OwnerMask, NextOwnerMask, GroupMask, " + - "EveryoneMask, BaseMask, PositionX, " + - "PositionY, PositionZ, GroupPositionX, " + - "GroupPositionY, GroupPositionZ, VelocityX, " + - "VelocityY, VelocityZ, AngularVelocityX, " + - "AngularVelocityY, AngularVelocityZ, " + - "AccelerationX, AccelerationY, " + - "AccelerationZ, RotationX, " + - "RotationY, RotationZ, " + - "RotationW, SitTargetOffsetX, " + - "SitTargetOffsetY, SitTargetOffsetZ, " + - "SitTargetOrientW, SitTargetOrientX, " + - "SitTargetOrientY, SitTargetOrientZ, " + - "RegionUUID, CreatorID, " + - "OwnerID, GroupID, " + - "LastOwnerID, SceneGroupID, " + - "PayPrice, PayButton1, " + - "PayButton2, PayButton3, " + - "PayButton4, LoopedSound, " + - "LoopedSoundGain, TextureAnimation, " + - "OmegaX, OmegaY, OmegaZ, " + - "CameraEyeOffsetX, CameraEyeOffsetY, " + - "CameraEyeOffsetZ, CameraAtOffsetX, " + - "CameraAtOffsetY, CameraAtOffsetZ, " + - "ForceMouselook, ScriptAccessPin, " + - "AllowedDrop, DieAtEdge, " + - "SalePrice, SaleType, " + - "ColorR, ColorG, ColorB, ColorA, " + - "ParticleSystem, ClickAction, Material, " + - "CollisionSound, CollisionSoundVolume, " + - "PassTouches, " + - "LinkNumber, MediaURL) values (" + "?UUID, " + - "?CreationDate, ?Name, ?Text, " + - "?Description, ?SitName, ?TouchName, " + - "?ObjectFlags, ?OwnerMask, ?NextOwnerMask, " + - "?GroupMask, ?EveryoneMask, ?BaseMask, " + - "?PositionX, ?PositionY, ?PositionZ, " + - "?GroupPositionX, ?GroupPositionY, " + - "?GroupPositionZ, ?VelocityX, " + - "?VelocityY, ?VelocityZ, ?AngularVelocityX, " + - "?AngularVelocityY, ?AngularVelocityZ, " + - "?AccelerationX, ?AccelerationY, " + - "?AccelerationZ, ?RotationX, " + - "?RotationY, ?RotationZ, " + - "?RotationW, ?SitTargetOffsetX, " + - "?SitTargetOffsetY, ?SitTargetOffsetZ, " + - "?SitTargetOrientW, ?SitTargetOrientX, " + - "?SitTargetOrientY, ?SitTargetOrientZ, " + - "?RegionUUID, ?CreatorID, ?OwnerID, " + - "?GroupID, ?LastOwnerID, ?SceneGroupID, " + - "?PayPrice, ?PayButton1, ?PayButton2, " + - "?PayButton3, ?PayButton4, ?LoopedSound, " + - "?LoopedSoundGain, ?TextureAnimation, " + - "?OmegaX, ?OmegaY, ?OmegaZ, " + - "?CameraEyeOffsetX, ?CameraEyeOffsetY, " + - "?CameraEyeOffsetZ, ?CameraAtOffsetX, " + - "?CameraAtOffsetY, ?CameraAtOffsetZ, " + - "?ForceMouselook, ?ScriptAccessPin, " + - "?AllowedDrop, ?DieAtEdge, ?SalePrice, " + - "?SaleType, ?ColorR, ?ColorG, " + - "?ColorB, ?ColorA, ?ParticleSystem, " + - "?ClickAction, ?Material, ?CollisionSound, " + - "?CollisionSoundVolume, ?PassTouches, ?LinkNumber, ?MediaURL)"; - - FillPrimCommand(cmd, prim, obj.UUID, regionUUID); - - ExecuteNonQuery(cmd); - - cmd.Parameters.Clear(); - - cmd.CommandText = "replace into primshapes (" + - "UUID, Shape, ScaleX, ScaleY, " + - "ScaleZ, PCode, PathBegin, PathEnd, " + - "PathScaleX, PathScaleY, PathShearX, " + - "PathShearY, PathSkew, PathCurve, " + - "PathRadiusOffset, PathRevolutions, " + - "PathTaperX, PathTaperY, PathTwist, " + - "PathTwistBegin, ProfileBegin, ProfileEnd, " + - "ProfileCurve, ProfileHollow, Texture, " + - "ExtraParams, State, Media) values (?UUID, " + - "?Shape, ?ScaleX, ?ScaleY, ?ScaleZ, " + - "?PCode, ?PathBegin, ?PathEnd, " + - "?PathScaleX, ?PathScaleY, " + - "?PathShearX, ?PathShearY, " + - "?PathSkew, ?PathCurve, ?PathRadiusOffset, " + - "?PathRevolutions, ?PathTaperX, " + - "?PathTaperY, ?PathTwist, " + - "?PathTwistBegin, ?ProfileBegin, " + - "?ProfileEnd, ?ProfileCurve, " + - "?ProfileHollow, ?Texture, ?ExtraParams, " + - "?State, ?Media)"; - - FillShapeCommand(cmd, prim); - - ExecuteNonQuery(cmd); - } - - cmd.Dispose(); - } - } - } - - public void RemoveObject(UUID obj, UUID regionUUID) - { -// m_log.DebugFormat("[REGION DB]: Deleting scene object {0} from {1} in database", obj, regionUUID); - - List uuids = new List(); - - // Formerly, this used to check the region UUID. - // That makes no sense, as we remove the contents of a prim - // unconditionally, but the prim dependent on the region ID. - // So, we would destroy an object and cause hard to detect - // issues if we delete the contents only. Deleting it all may - // cause the loss of a prim, but is cleaner. - // It's also faster because it uses the primary key. - // - lock (m_dbLock) - { - using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) - { - dbcon.Open(); - - using (MySqlCommand cmd = dbcon.CreateCommand()) - { - cmd.CommandText = "select UUID from prims where SceneGroupID= ?UUID"; - cmd.Parameters.AddWithValue("UUID", obj.ToString()); - - using (IDataReader reader = ExecuteReader(cmd)) - { - while (reader.Read()) - uuids.Add(DBGuid.FromDB(reader["UUID"].ToString())); - } - - // delete the main prims - cmd.CommandText = "delete from prims where SceneGroupID= ?UUID"; - ExecuteNonQuery(cmd); - } - } - } - - // there is no way this should be < 1 unless there is - // a very corrupt database, but in that case be extra - // safe anyway. - if (uuids.Count > 0) - { - RemoveShapes(uuids); - RemoveItems(uuids); - } - } - - /// - /// Remove all persisted items of the given prim. - /// The caller must acquire the necessrary synchronization locks - /// - /// the Item UUID - private void RemoveItems(UUID uuid) - { - lock (m_dbLock) - { - using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) - { - dbcon.Open(); - - using (MySqlCommand cmd = dbcon.CreateCommand()) - { - cmd.CommandText = "delete from primitems where PrimID = ?PrimID"; - cmd.Parameters.AddWithValue("PrimID", uuid.ToString()); - - ExecuteNonQuery(cmd); - } - } - } - } - - /// - /// Remove all persisted shapes for a list of prims - /// The caller must acquire the necessrary synchronization locks - /// - /// the list of UUIDs - private void RemoveShapes(List uuids) - { - lock (m_dbLock) - { - string sql = "delete from primshapes where "; - using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) - { - dbcon.Open(); - - using (MySqlCommand cmd = dbcon.CreateCommand()) - { - for (int i = 0; i < uuids.Count; i++) - { - if ((i + 1) == uuids.Count) - {// end of the list - sql += "(UUID = ?UUID" + i + ")"; - } - else - { - sql += "(UUID = ?UUID" + i + ") or "; - } - } - cmd.CommandText = sql; - - for (int i = 0; i < uuids.Count; i++) - cmd.Parameters.AddWithValue("UUID" + i, uuids[i].ToString()); - - ExecuteNonQuery(cmd); - } - } - } - } - - /// - /// Remove all persisted items for a list of prims - /// The caller must acquire the necessrary synchronization locks - /// - /// the list of UUIDs - private void RemoveItems(List uuids) - { - lock (m_dbLock) - { - string sql = "delete from primitems where "; - using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) - { - dbcon.Open(); - - using (MySqlCommand cmd = dbcon.CreateCommand()) - { - for (int i = 0; i < uuids.Count; i++) - { - if ((i + 1) == uuids.Count) - { - // end of the list - sql += "(PrimID = ?PrimID" + i + ")"; - } - else - { - sql += "(PrimID = ?PrimID" + i + ") or "; - } - } - cmd.CommandText = sql; - - for (int i = 0; i < uuids.Count; i++) - cmd.Parameters.AddWithValue("PrimID" + i, uuids[i].ToString()); - - ExecuteNonQuery(cmd); - } - } - } - } - - public List LoadObjects(UUID regionID) - { - const int ROWS_PER_QUERY = 5000; - - Dictionary prims = new Dictionary(ROWS_PER_QUERY); - Dictionary objects = new Dictionary(); - int count = 0; - - #region Prim Loading - - lock (m_dbLock) - { - using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) - { - dbcon.Open(); - - using (MySqlCommand cmd = dbcon.CreateCommand()) - { - cmd.CommandText = - "SELECT * FROM prims LEFT JOIN primshapes ON prims.UUID = primshapes.UUID WHERE RegionUUID = ?RegionUUID"; - cmd.Parameters.AddWithValue("RegionUUID", regionID.ToString()); - - using (IDataReader reader = ExecuteReader(cmd)) - { - while (reader.Read()) - { - SceneObjectPart prim = BuildPrim(reader); - if (reader["Shape"] is DBNull) - prim.Shape = PrimitiveBaseShape.Default; - else - prim.Shape = BuildShape(reader); - - UUID parentID = DBGuid.FromDB(reader["SceneGroupID"].ToString()); - if (parentID != prim.UUID) - prim.ParentUUID = parentID; - - prims[prim.UUID] = prim; - - ++count; - if (count % ROWS_PER_QUERY == 0) - m_log.Debug("[REGION DB]: Loaded " + count + " prims..."); - } - } - } - } - } - - #endregion Prim Loading - - #region SceneObjectGroup Creation - - // Create all of the SOGs from the root prims first - foreach (SceneObjectPart prim in prims.Values) - { - if (prim.ParentUUID == UUID.Zero) - objects[prim.UUID] = new SceneObjectGroup(prim); - } - - // Add all of the children objects to the SOGs - foreach (SceneObjectPart prim in prims.Values) - { - SceneObjectGroup sog; - if (prim.UUID != prim.ParentUUID) - { - if (objects.TryGetValue(prim.ParentUUID, out sog)) - { - int originalLinkNum = prim.LinkNum; - - sog.AddPart(prim); - - // SceneObjectGroup.AddPart() tries to be smart and automatically set the LinkNum. - // We override that here - if (originalLinkNum != 0) - prim.LinkNum = originalLinkNum; - } - else - { - m_log.WarnFormat( - "[REGION DB]: Database contains an orphan child prim {0} {1} in region {2} pointing to missing parent {3}. This prim will not be loaded.", - prim.Name, prim.UUID, regionID, prim.ParentUUID); - } - } - } - - #endregion SceneObjectGroup Creation - - m_log.DebugFormat("[REGION DB]: Loaded {0} objects using {1} prims", objects.Count, prims.Count); - - #region Prim Inventory Loading - - // Instead of attempting to LoadItems on every prim, - // most of which probably have no items... get a - // list from DB of all prims which have items and - // LoadItems only on those - List primsWithInventory = new List(); - lock (m_dbLock) - { - using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) - { - dbcon.Open(); - - using (MySqlCommand itemCmd = dbcon.CreateCommand()) - { - itemCmd.CommandText = "SELECT DISTINCT primID FROM primitems"; - using (IDataReader itemReader = ExecuteReader(itemCmd)) - { - while (itemReader.Read()) - { - if (!(itemReader["primID"] is DBNull)) - { - UUID primID = DBGuid.FromDB(itemReader["primID"].ToString()); - if (prims.ContainsKey(primID)) - primsWithInventory.Add(prims[primID]); - } - } - } - } - } - } - - foreach (SceneObjectPart prim in primsWithInventory) - { - LoadItems(prim); - } - - #endregion Prim Inventory Loading - - m_log.DebugFormat("[REGION DB]: Loaded inventory from {0} objects", primsWithInventory.Count); - - return new List(objects.Values); - } - - /// - /// Load in a prim's persisted inventory. - /// - /// The prim - private void LoadItems(SceneObjectPart prim) - { - lock (m_dbLock) - { - List inventory = new List(); - - using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) - { - dbcon.Open(); - - using (MySqlCommand cmd = dbcon.CreateCommand()) - { - cmd.CommandText = "select * from primitems where PrimID = ?PrimID"; - cmd.Parameters.AddWithValue("PrimID", prim.UUID.ToString()); - - using (IDataReader reader = ExecuteReader(cmd)) - { - while (reader.Read()) - { - TaskInventoryItem item = BuildItem(reader); - - item.ParentID = prim.UUID; // Values in database are often wrong - inventory.Add(item); - } - } - } - } - - prim.Inventory.RestoreInventoryItems(inventory); - } - } - - public void StoreTerrain(double[,] ter, UUID regionID) - { - m_log.Info("[REGION DB]: Storing terrain"); - - lock (m_dbLock) - { - using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) - { - dbcon.Open(); - - using (MySqlCommand cmd = dbcon.CreateCommand()) - { - cmd.CommandText = "delete from terrain where RegionUUID = ?RegionUUID"; - cmd.Parameters.AddWithValue("RegionUUID", regionID.ToString()); - - ExecuteNonQuery(cmd); - - cmd.CommandText = "insert into terrain (RegionUUID, " + - "Revision, Heightfield) values (?RegionUUID, " + - "1, ?Heightfield)"; - - cmd.Parameters.AddWithValue("Heightfield", SerializeTerrain(ter)); - - ExecuteNonQuery(cmd); - } - } - } - } - - public double[,] LoadTerrain(UUID regionID) - { - double[,] terrain = null; - - lock (m_dbLock) - { - using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) - { - dbcon.Open(); - - using (MySqlCommand cmd = dbcon.CreateCommand()) - { - cmd.CommandText = "select RegionUUID, Revision, Heightfield " + - "from terrain where RegionUUID = ?RegionUUID " + - "order by Revision desc limit 1"; - cmd.Parameters.AddWithValue("RegionUUID", regionID.ToString()); - - using (IDataReader reader = ExecuteReader(cmd)) - { - while (reader.Read()) - { - int rev = Convert.ToInt32(reader["Revision"]); - - terrain = new double[(int)Constants.RegionSize, (int)Constants.RegionSize]; - terrain.Initialize(); - - using (MemoryStream mstr = new MemoryStream((byte[])reader["Heightfield"])) - { - using (BinaryReader br = new BinaryReader(mstr)) - { - for (int x = 0; x < (int)Constants.RegionSize; x++) - { - for (int y = 0; y < (int)Constants.RegionSize; y++) - { - terrain[x, y] = br.ReadDouble(); - } - } - } - - m_log.InfoFormat("[REGION DB]: Loaded terrain revision r{0}", rev); - } - } - } - } - } - } - - return terrain; - } - - public void RemoveLandObject(UUID globalID) - { - lock (m_dbLock) - { - using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) - { - dbcon.Open(); - - using (MySqlCommand cmd = dbcon.CreateCommand()) - { - cmd.CommandText = "delete from land where UUID = ?UUID"; - cmd.Parameters.AddWithValue("UUID", globalID.ToString()); - - ExecuteNonQuery(cmd); - } - } - } - } - - public void StoreLandObject(ILandObject parcel) - { - lock (m_dbLock) - { - using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) - { - dbcon.Open(); - - using (MySqlCommand cmd = dbcon.CreateCommand()) - { - cmd.CommandText = "replace into land (UUID, RegionUUID, " + - "LocalLandID, Bitmap, Name, Description, " + - "OwnerUUID, IsGroupOwned, Area, AuctionID, " + - "Category, ClaimDate, ClaimPrice, GroupUUID, " + - "SalePrice, LandStatus, LandFlags, LandingType, " + - "MediaAutoScale, MediaTextureUUID, MediaURL, " + - "MusicURL, PassHours, PassPrice, SnapshotUUID, " + - "UserLocationX, UserLocationY, UserLocationZ, " + - "UserLookAtX, UserLookAtY, UserLookAtZ, " + - "AuthbuyerID, OtherCleanTime, MediaType, MediaDescription, " + - "MediaSize, MediaLoop, ObscureMusic, ObscureMedia) values (" + - "?UUID, ?RegionUUID, " + - "?LocalLandID, ?Bitmap, ?Name, ?Description, " + - "?OwnerUUID, ?IsGroupOwned, ?Area, ?AuctionID, " + - "?Category, ?ClaimDate, ?ClaimPrice, ?GroupUUID, " + - "?SalePrice, ?LandStatus, ?LandFlags, ?LandingType, " + - "?MediaAutoScale, ?MediaTextureUUID, ?MediaURL, " + - "?MusicURL, ?PassHours, ?PassPrice, ?SnapshotUUID, " + - "?UserLocationX, ?UserLocationY, ?UserLocationZ, " + - "?UserLookAtX, ?UserLookAtY, ?UserLookAtZ, " + - "?AuthbuyerID, ?OtherCleanTime, ?MediaType, ?MediaDescription, "+ - "CONCAT(?MediaWidth, ',', ?MediaHeight), ?MediaLoop, ?ObscureMusic, ?ObscureMedia)"; - - FillLandCommand(cmd, parcel.LandData, parcel.RegionUUID); - - ExecuteNonQuery(cmd); - - cmd.CommandText = "delete from landaccesslist where LandUUID = ?UUID"; - - ExecuteNonQuery(cmd); - - cmd.Parameters.Clear(); - cmd.CommandText = "insert into landaccesslist (LandUUID, " + - "AccessUUID, Flags) values (?LandUUID, ?AccessUUID, " + - "?Flags)"; - - foreach (ParcelManager.ParcelAccessEntry entry in parcel.LandData.ParcelAccessList) - { - FillLandAccessCommand(cmd, entry, parcel.LandData.GlobalID); - ExecuteNonQuery(cmd); - cmd.Parameters.Clear(); - } - } - } - } - } - - public RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID) - { - RegionLightShareData nWP = new RegionLightShareData(); - nWP.OnSave += StoreRegionWindlightSettings; - - using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) - { - dbcon.Open(); - - string command = "select * from `regionwindlight` where region_id = ?regionID"; - - using(MySqlCommand cmd = new MySqlCommand(command)) - { - cmd.Connection = dbcon; - - cmd.Parameters.AddWithValue("?regionID", regionUUID.ToString()); - - IDataReader result = ExecuteReader(cmd); - if (!result.Read()) - { - //No result, so store our default windlight profile and return it - nWP.regionID = regionUUID; - StoreRegionWindlightSettings(nWP); - return nWP; - } - else - { - nWP.regionID = DBGuid.FromDB(result["region_id"]); - nWP.waterColor.X = Convert.ToSingle(result["water_color_r"]); - nWP.waterColor.Y = Convert.ToSingle(result["water_color_g"]); - nWP.waterColor.Z = Convert.ToSingle(result["water_color_b"]); - nWP.waterFogDensityExponent = Convert.ToSingle(result["water_fog_density_exponent"]); - nWP.underwaterFogModifier = Convert.ToSingle(result["underwater_fog_modifier"]); - nWP.reflectionWaveletScale.X = Convert.ToSingle(result["reflection_wavelet_scale_1"]); - nWP.reflectionWaveletScale.Y = Convert.ToSingle(result["reflection_wavelet_scale_2"]); - nWP.reflectionWaveletScale.Z = Convert.ToSingle(result["reflection_wavelet_scale_3"]); - nWP.fresnelScale = Convert.ToSingle(result["fresnel_scale"]); - nWP.fresnelOffset = Convert.ToSingle(result["fresnel_offset"]); - nWP.refractScaleAbove = Convert.ToSingle(result["refract_scale_above"]); - nWP.refractScaleBelow = Convert.ToSingle(result["refract_scale_below"]); - nWP.blurMultiplier = Convert.ToSingle(result["blur_multiplier"]); - nWP.bigWaveDirection.X = Convert.ToSingle(result["big_wave_direction_x"]); - nWP.bigWaveDirection.Y = Convert.ToSingle(result["big_wave_direction_y"]); - nWP.littleWaveDirection.X = Convert.ToSingle(result["little_wave_direction_x"]); - nWP.littleWaveDirection.Y = Convert.ToSingle(result["little_wave_direction_y"]); - UUID.TryParse(result["normal_map_texture"].ToString(), out nWP.normalMapTexture); - nWP.horizon.X = Convert.ToSingle(result["horizon_r"]); - nWP.horizon.Y = Convert.ToSingle(result["horizon_g"]); - nWP.horizon.Z = Convert.ToSingle(result["horizon_b"]); - nWP.horizon.W = Convert.ToSingle(result["horizon_i"]); - nWP.hazeHorizon = Convert.ToSingle(result["haze_horizon"]); - nWP.blueDensity.X = Convert.ToSingle(result["blue_density_r"]); - nWP.blueDensity.Y = Convert.ToSingle(result["blue_density_g"]); - nWP.blueDensity.Z = Convert.ToSingle(result["blue_density_b"]); - nWP.blueDensity.W = Convert.ToSingle(result["blue_density_i"]); - nWP.hazeDensity = Convert.ToSingle(result["haze_density"]); - nWP.densityMultiplier = Convert.ToSingle(result["density_multiplier"]); - nWP.distanceMultiplier = Convert.ToSingle(result["distance_multiplier"]); - nWP.maxAltitude = Convert.ToUInt16(result["max_altitude"]); - nWP.sunMoonColor.X = Convert.ToSingle(result["sun_moon_color_r"]); - nWP.sunMoonColor.Y = Convert.ToSingle(result["sun_moon_color_g"]); - nWP.sunMoonColor.Z = Convert.ToSingle(result["sun_moon_color_b"]); - nWP.sunMoonColor.W = Convert.ToSingle(result["sun_moon_color_i"]); - nWP.sunMoonPosition = Convert.ToSingle(result["sun_moon_position"]); - nWP.ambient.X = Convert.ToSingle(result["ambient_r"]); - nWP.ambient.Y = Convert.ToSingle(result["ambient_g"]); - nWP.ambient.Z = Convert.ToSingle(result["ambient_b"]); - nWP.ambient.W = Convert.ToSingle(result["ambient_i"]); - nWP.eastAngle = Convert.ToSingle(result["east_angle"]); - nWP.sunGlowFocus = Convert.ToSingle(result["sun_glow_focus"]); - nWP.sunGlowSize = Convert.ToSingle(result["sun_glow_size"]); - nWP.sceneGamma = Convert.ToSingle(result["scene_gamma"]); - nWP.starBrightness = Convert.ToSingle(result["star_brightness"]); - nWP.cloudColor.X = Convert.ToSingle(result["cloud_color_r"]); - nWP.cloudColor.Y = Convert.ToSingle(result["cloud_color_g"]); - nWP.cloudColor.Z = Convert.ToSingle(result["cloud_color_b"]); - nWP.cloudColor.W = Convert.ToSingle(result["cloud_color_i"]); - nWP.cloudXYDensity.X = Convert.ToSingle(result["cloud_x"]); - nWP.cloudXYDensity.Y = Convert.ToSingle(result["cloud_y"]); - nWP.cloudXYDensity.Z = Convert.ToSingle(result["cloud_density"]); - nWP.cloudCoverage = Convert.ToSingle(result["cloud_coverage"]); - nWP.cloudScale = Convert.ToSingle(result["cloud_scale"]); - nWP.cloudDetailXYDensity.X = Convert.ToSingle(result["cloud_detail_x"]); - nWP.cloudDetailXYDensity.Y = Convert.ToSingle(result["cloud_detail_y"]); - nWP.cloudDetailXYDensity.Z = Convert.ToSingle(result["cloud_detail_density"]); - nWP.cloudScrollX = Convert.ToSingle(result["cloud_scroll_x"]); - nWP.cloudScrollXLock = Convert.ToBoolean(result["cloud_scroll_x_lock"]); - nWP.cloudScrollY = Convert.ToSingle(result["cloud_scroll_y"]); - nWP.cloudScrollYLock = Convert.ToBoolean(result["cloud_scroll_y_lock"]); - nWP.drawClassicClouds = Convert.ToBoolean(result["draw_classic_clouds"]); - } - } - } - return nWP; - } - - public RegionSettings LoadRegionSettings(UUID regionUUID) - { - RegionSettings rs = null; - - lock (m_dbLock) - { - using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) - { - dbcon.Open(); - - using (MySqlCommand cmd = dbcon.CreateCommand()) - { - cmd.CommandText = "select * from regionsettings where regionUUID = ?RegionUUID"; - cmd.Parameters.AddWithValue("regionUUID", regionUUID); - - using (IDataReader reader = ExecuteReader(cmd)) - { - if (reader.Read()) - { - rs = BuildRegionSettings(reader); - rs.OnSave += StoreRegionSettings; - } - else - { - rs = new RegionSettings(); - rs.RegionUUID = regionUUID; - rs.OnSave += StoreRegionSettings; - - StoreRegionSettings(rs); - } - } - } - } - } - - return rs; - } - - public void StoreRegionWindlightSettings(RegionLightShareData wl) - { - using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) - { - dbcon.Open(); - - using (MySqlCommand cmd = dbcon.CreateCommand()) - { - cmd.CommandText = "REPLACE INTO `regionwindlight` (`region_id`, `water_color_r`, `water_color_g`, "; - cmd.CommandText += "`water_color_b`, `water_fog_density_exponent`, `underwater_fog_modifier`, "; - cmd.CommandText += "`reflection_wavelet_scale_1`, `reflection_wavelet_scale_2`, `reflection_wavelet_scale_3`, "; - cmd.CommandText += "`fresnel_scale`, `fresnel_offset`, `refract_scale_above`, `refract_scale_below`, "; - cmd.CommandText += "`blur_multiplier`, `big_wave_direction_x`, `big_wave_direction_y`, `little_wave_direction_x`, "; - cmd.CommandText += "`little_wave_direction_y`, `normal_map_texture`, `horizon_r`, `horizon_g`, `horizon_b`, "; - cmd.CommandText += "`horizon_i`, `haze_horizon`, `blue_density_r`, `blue_density_g`, `blue_density_b`, "; - cmd.CommandText += "`blue_density_i`, `haze_density`, `density_multiplier`, `distance_multiplier`, `max_altitude`, "; - cmd.CommandText += "`sun_moon_color_r`, `sun_moon_color_g`, `sun_moon_color_b`, `sun_moon_color_i`, `sun_moon_position`, "; - cmd.CommandText += "`ambient_r`, `ambient_g`, `ambient_b`, `ambient_i`, `east_angle`, `sun_glow_focus`, `sun_glow_size`, "; - cmd.CommandText += "`scene_gamma`, `star_brightness`, `cloud_color_r`, `cloud_color_g`, `cloud_color_b`, `cloud_color_i`, "; - cmd.CommandText += "`cloud_x`, `cloud_y`, `cloud_density`, `cloud_coverage`, `cloud_scale`, `cloud_detail_x`, "; - cmd.CommandText += "`cloud_detail_y`, `cloud_detail_density`, `cloud_scroll_x`, `cloud_scroll_x_lock`, `cloud_scroll_y`, "; - cmd.CommandText += "`cloud_scroll_y_lock`, `draw_classic_clouds`) VALUES (?region_id, ?water_color_r, "; - cmd.CommandText += "?water_color_g, ?water_color_b, ?water_fog_density_exponent, ?underwater_fog_modifier, ?reflection_wavelet_scale_1, "; - cmd.CommandText += "?reflection_wavelet_scale_2, ?reflection_wavelet_scale_3, ?fresnel_scale, ?fresnel_offset, ?refract_scale_above, "; - cmd.CommandText += "?refract_scale_below, ?blur_multiplier, ?big_wave_direction_x, ?big_wave_direction_y, ?little_wave_direction_x, "; - cmd.CommandText += "?little_wave_direction_y, ?normal_map_texture, ?horizon_r, ?horizon_g, ?horizon_b, ?horizon_i, ?haze_horizon, "; - cmd.CommandText += "?blue_density_r, ?blue_density_g, ?blue_density_b, ?blue_density_i, ?haze_density, ?density_multiplier, "; - cmd.CommandText += "?distance_multiplier, ?max_altitude, ?sun_moon_color_r, ?sun_moon_color_g, ?sun_moon_color_b, "; - cmd.CommandText += "?sun_moon_color_i, ?sun_moon_position, ?ambient_r, ?ambient_g, ?ambient_b, ?ambient_i, ?east_angle, "; - cmd.CommandText += "?sun_glow_focus, ?sun_glow_size, ?scene_gamma, ?star_brightness, ?cloud_color_r, ?cloud_color_g, "; - cmd.CommandText += "?cloud_color_b, ?cloud_color_i, ?cloud_x, ?cloud_y, ?cloud_density, ?cloud_coverage, ?cloud_scale, "; - cmd.CommandText += "?cloud_detail_x, ?cloud_detail_y, ?cloud_detail_density, ?cloud_scroll_x, ?cloud_scroll_x_lock, "; - cmd.CommandText += "?cloud_scroll_y, ?cloud_scroll_y_lock, ?draw_classic_clouds)"; - - cmd.Parameters.AddWithValue("region_id", wl.regionID); - cmd.Parameters.AddWithValue("water_color_r", wl.waterColor.X); - cmd.Parameters.AddWithValue("water_color_g", wl.waterColor.Y); - cmd.Parameters.AddWithValue("water_color_b", wl.waterColor.Z); - cmd.Parameters.AddWithValue("water_fog_density_exponent", wl.waterFogDensityExponent); - cmd.Parameters.AddWithValue("underwater_fog_modifier", wl.underwaterFogModifier); - cmd.Parameters.AddWithValue("reflection_wavelet_scale_1", wl.reflectionWaveletScale.X); - cmd.Parameters.AddWithValue("reflection_wavelet_scale_2", wl.reflectionWaveletScale.Y); - cmd.Parameters.AddWithValue("reflection_wavelet_scale_3", wl.reflectionWaveletScale.Z); - cmd.Parameters.AddWithValue("fresnel_scale", wl.fresnelScale); - cmd.Parameters.AddWithValue("fresnel_offset", wl.fresnelOffset); - cmd.Parameters.AddWithValue("refract_scale_above", wl.refractScaleAbove); - cmd.Parameters.AddWithValue("refract_scale_below", wl.refractScaleBelow); - cmd.Parameters.AddWithValue("blur_multiplier", wl.blurMultiplier); - cmd.Parameters.AddWithValue("big_wave_direction_x", wl.bigWaveDirection.X); - cmd.Parameters.AddWithValue("big_wave_direction_y", wl.bigWaveDirection.Y); - cmd.Parameters.AddWithValue("little_wave_direction_x", wl.littleWaveDirection.X); - cmd.Parameters.AddWithValue("little_wave_direction_y", wl.littleWaveDirection.Y); - cmd.Parameters.AddWithValue("normal_map_texture", wl.normalMapTexture); - cmd.Parameters.AddWithValue("horizon_r", wl.horizon.X); - cmd.Parameters.AddWithValue("horizon_g", wl.horizon.Y); - cmd.Parameters.AddWithValue("horizon_b", wl.horizon.Z); - cmd.Parameters.AddWithValue("horizon_i", wl.horizon.W); - cmd.Parameters.AddWithValue("haze_horizon", wl.hazeHorizon); - cmd.Parameters.AddWithValue("blue_density_r", wl.blueDensity.X); - cmd.Parameters.AddWithValue("blue_density_g", wl.blueDensity.Y); - cmd.Parameters.AddWithValue("blue_density_b", wl.blueDensity.Z); - cmd.Parameters.AddWithValue("blue_density_i", wl.blueDensity.W); - cmd.Parameters.AddWithValue("haze_density", wl.hazeDensity); - cmd.Parameters.AddWithValue("density_multiplier", wl.densityMultiplier); - cmd.Parameters.AddWithValue("distance_multiplier", wl.distanceMultiplier); - cmd.Parameters.AddWithValue("max_altitude", wl.maxAltitude); - cmd.Parameters.AddWithValue("sun_moon_color_r", wl.sunMoonColor.X); - cmd.Parameters.AddWithValue("sun_moon_color_g", wl.sunMoonColor.Y); - cmd.Parameters.AddWithValue("sun_moon_color_b", wl.sunMoonColor.Z); - cmd.Parameters.AddWithValue("sun_moon_color_i", wl.sunMoonColor.W); - cmd.Parameters.AddWithValue("sun_moon_position", wl.sunMoonPosition); - cmd.Parameters.AddWithValue("ambient_r", wl.ambient.X); - cmd.Parameters.AddWithValue("ambient_g", wl.ambient.Y); - cmd.Parameters.AddWithValue("ambient_b", wl.ambient.Z); - cmd.Parameters.AddWithValue("ambient_i", wl.ambient.W); - cmd.Parameters.AddWithValue("east_angle", wl.eastAngle); - cmd.Parameters.AddWithValue("sun_glow_focus", wl.sunGlowFocus); - cmd.Parameters.AddWithValue("sun_glow_size", wl.sunGlowSize); - cmd.Parameters.AddWithValue("scene_gamma", wl.sceneGamma); - cmd.Parameters.AddWithValue("star_brightness", wl.starBrightness); - cmd.Parameters.AddWithValue("cloud_color_r", wl.cloudColor.X); - cmd.Parameters.AddWithValue("cloud_color_g", wl.cloudColor.Y); - cmd.Parameters.AddWithValue("cloud_color_b", wl.cloudColor.Z); - cmd.Parameters.AddWithValue("cloud_color_i", wl.cloudColor.W); - cmd.Parameters.AddWithValue("cloud_x", wl.cloudXYDensity.X); - cmd.Parameters.AddWithValue("cloud_y", wl.cloudXYDensity.Y); - cmd.Parameters.AddWithValue("cloud_density", wl.cloudXYDensity.Z); - cmd.Parameters.AddWithValue("cloud_coverage", wl.cloudCoverage); - cmd.Parameters.AddWithValue("cloud_scale", wl.cloudScale); - cmd.Parameters.AddWithValue("cloud_detail_x", wl.cloudDetailXYDensity.X); - cmd.Parameters.AddWithValue("cloud_detail_y", wl.cloudDetailXYDensity.Y); - cmd.Parameters.AddWithValue("cloud_detail_density", wl.cloudDetailXYDensity.Z); - cmd.Parameters.AddWithValue("cloud_scroll_x", wl.cloudScrollX); - cmd.Parameters.AddWithValue("cloud_scroll_x_lock", wl.cloudScrollXLock); - cmd.Parameters.AddWithValue("cloud_scroll_y", wl.cloudScrollY); - cmd.Parameters.AddWithValue("cloud_scroll_y_lock", wl.cloudScrollYLock); - cmd.Parameters.AddWithValue("draw_classic_clouds", wl.drawClassicClouds); - - ExecuteNonQuery(cmd); - } - } - } - - public void StoreRegionSettings(RegionSettings rs) - { - lock (m_dbLock) - { - using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) - { - dbcon.Open(); - - using (MySqlCommand cmd = dbcon.CreateCommand()) - { - cmd.CommandText = "replace into regionsettings (regionUUID, " + - "block_terraform, block_fly, allow_damage, " + - "restrict_pushing, allow_land_resell, " + - "allow_land_join_divide, block_show_in_search, " + - "agent_limit, object_bonus, maturity, " + - "disable_scripts, disable_collisions, " + - "disable_physics, terrain_texture_1, " + - "terrain_texture_2, terrain_texture_3, " + - "terrain_texture_4, elevation_1_nw, " + - "elevation_2_nw, elevation_1_ne, " + - "elevation_2_ne, elevation_1_se, " + - "elevation_2_se, elevation_1_sw, " + - "elevation_2_sw, water_height, " + - "terrain_raise_limit, terrain_lower_limit, " + - "use_estate_sun, fixed_sun, sun_position, " + - "covenant, Sandbox, sunvectorx, sunvectory, " + - "sunvectorz, loaded_creation_datetime, " + - "loaded_creation_id, map_tile_ID) values (?RegionUUID, ?BlockTerraform, " + - "?BlockFly, ?AllowDamage, ?RestrictPushing, " + - "?AllowLandResell, ?AllowLandJoinDivide, " + - "?BlockShowInSearch, ?AgentLimit, ?ObjectBonus, " + - "?Maturity, ?DisableScripts, ?DisableCollisions, " + - "?DisablePhysics, ?TerrainTexture1, " + - "?TerrainTexture2, ?TerrainTexture3, " + - "?TerrainTexture4, ?Elevation1NW, ?Elevation2NW, " + - "?Elevation1NE, ?Elevation2NE, ?Elevation1SE, " + - "?Elevation2SE, ?Elevation1SW, ?Elevation2SW, " + - "?WaterHeight, ?TerrainRaiseLimit, " + - "?TerrainLowerLimit, ?UseEstateSun, ?FixedSun, " + - "?SunPosition, ?Covenant, ?Sandbox, " + - "?SunVectorX, ?SunVectorY, ?SunVectorZ, " + - "?LoadedCreationDateTime, ?LoadedCreationID, " + - "?TerrainImageID)"; - - FillRegionSettingsCommand(cmd, rs); - - ExecuteNonQuery(cmd); - } - } - } - } - - public List LoadLandObjects(UUID regionUUID) - { - List landData = new List(); - - lock (m_dbLock) - { - using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) - { - dbcon.Open(); - - using (MySqlCommand cmd = dbcon.CreateCommand()) - { - cmd.CommandText = "select * from land where RegionUUID = ?RegionUUID"; - cmd.Parameters.AddWithValue("RegionUUID", regionUUID.ToString()); - - using (IDataReader reader = ExecuteReader(cmd)) - { - while (reader.Read()) - { - LandData newLand = BuildLandData(reader); - landData.Add(newLand); - } - } - } - - using (MySqlCommand cmd = dbcon.CreateCommand()) - { - foreach (LandData land in landData) - { - cmd.Parameters.Clear(); - cmd.CommandText = "select * from landaccesslist where LandUUID = ?LandUUID"; - cmd.Parameters.AddWithValue("LandUUID", land.GlobalID.ToString()); - - using (IDataReader reader = ExecuteReader(cmd)) - { - while (reader.Read()) - { - land.ParcelAccessList.Add(BuildLandAccessData(reader)); - } - } - } - } - } - } - - return landData; - } - - public void Shutdown() - { - } - - private SceneObjectPart BuildPrim(IDataReader row) - { - SceneObjectPart prim = new SceneObjectPart(); - - // depending on the MySQL connector version, CHAR(36) may be already converted to Guid! - prim.UUID = DBGuid.FromDB(row["UUID"]); - prim.CreatorID = DBGuid.FromDB(row["CreatorID"]); - prim.OwnerID = DBGuid.FromDB(row["OwnerID"]); - prim.GroupID = DBGuid.FromDB(row["GroupID"]); - prim.LastOwnerID = DBGuid.FromDB(row["LastOwnerID"]); - - // explicit conversion of integers is required, which sort - // of sucks. No idea if there is a shortcut here or not. - prim.CreationDate = (int)row["CreationDate"]; - if (row["Name"] != DBNull.Value) - prim.Name = (string)row["Name"]; - else - prim.Name = String.Empty; - // Various text fields - prim.Text = (string)row["Text"]; - prim.Color = Color.FromArgb((int)row["ColorA"], - (int)row["ColorR"], - (int)row["ColorG"], - (int)row["ColorB"]); - prim.Description = (string)row["Description"]; - prim.SitName = (string)row["SitName"]; - prim.TouchName = (string)row["TouchName"]; - // Permissions - prim.Flags = (PrimFlags)(int)row["ObjectFlags"]; - prim.OwnerMask = (uint)(int)row["OwnerMask"]; - prim.NextOwnerMask = (uint)(int)row["NextOwnerMask"]; - prim.GroupMask = (uint)(int)row["GroupMask"]; - prim.EveryoneMask = (uint)(int)row["EveryoneMask"]; - prim.BaseMask = (uint)(int)row["BaseMask"]; - - // Vectors - prim.OffsetPosition = new Vector3( - (float)(double)row["PositionX"], - (float)(double)row["PositionY"], - (float)(double)row["PositionZ"] - ); - prim.GroupPosition = new Vector3( - (float)(double)row["GroupPositionX"], - (float)(double)row["GroupPositionY"], - (float)(double)row["GroupPositionZ"] - ); - prim.Velocity = new Vector3( - (float)(double)row["VelocityX"], - (float)(double)row["VelocityY"], - (float)(double)row["VelocityZ"] - ); - prim.AngularVelocity = new Vector3( - (float)(double)row["AngularVelocityX"], - (float)(double)row["AngularVelocityY"], - (float)(double)row["AngularVelocityZ"] - ); - prim.Acceleration = new Vector3( - (float)(double)row["AccelerationX"], - (float)(double)row["AccelerationY"], - (float)(double)row["AccelerationZ"] - ); - // quaternions - prim.RotationOffset = new Quaternion( - (float)(double)row["RotationX"], - (float)(double)row["RotationY"], - (float)(double)row["RotationZ"], - (float)(double)row["RotationW"] - ); - prim.SitTargetPositionLL = new Vector3( - (float)(double)row["SitTargetOffsetX"], - (float)(double)row["SitTargetOffsetY"], - (float)(double)row["SitTargetOffsetZ"] - ); - prim.SitTargetOrientationLL = new Quaternion( - (float)(double)row["SitTargetOrientX"], - (float)(double)row["SitTargetOrientY"], - (float)(double)row["SitTargetOrientZ"], - (float)(double)row["SitTargetOrientW"] - ); - - prim.PayPrice[0] = (int)row["PayPrice"]; - prim.PayPrice[1] = (int)row["PayButton1"]; - prim.PayPrice[2] = (int)row["PayButton2"]; - prim.PayPrice[3] = (int)row["PayButton3"]; - prim.PayPrice[4] = (int)row["PayButton4"]; - - prim.Sound = DBGuid.FromDB(row["LoopedSound"].ToString()); - prim.SoundGain = (float)(double)row["LoopedSoundGain"]; - prim.SoundFlags = 1; // If it's persisted at all, it's looped - - if (!(row["TextureAnimation"] is DBNull)) - prim.TextureAnimation = (byte[])row["TextureAnimation"]; - if (!(row["ParticleSystem"] is DBNull)) - prim.ParticleSystem = (byte[])row["ParticleSystem"]; - - prim.AngularVelocity = new Vector3( - (float)(double)row["OmegaX"], - (float)(double)row["OmegaY"], - (float)(double)row["OmegaZ"] - ); - - prim.SetCameraEyeOffset(new Vector3( - (float)(double)row["CameraEyeOffsetX"], - (float)(double)row["CameraEyeOffsetY"], - (float)(double)row["CameraEyeOffsetZ"] - )); - - prim.SetCameraAtOffset(new Vector3( - (float)(double)row["CameraAtOffsetX"], - (float)(double)row["CameraAtOffsetY"], - (float)(double)row["CameraAtOffsetZ"] - )); - - prim.SetForceMouselook((sbyte)row["ForceMouselook"] != 0); - prim.ScriptAccessPin = (int)row["ScriptAccessPin"]; - prim.AllowedDrop = ((sbyte)row["AllowedDrop"] != 0); - prim.DIE_AT_EDGE = ((sbyte)row["DieAtEdge"] != 0); - - prim.SalePrice = (int)row["SalePrice"]; - prim.ObjectSaleType = unchecked((byte)(sbyte)row["SaleType"]); - - prim.Material = unchecked((byte)(sbyte)row["Material"]); - - if (!(row["ClickAction"] is DBNull)) - prim.ClickAction = unchecked((byte)(sbyte)row["ClickAction"]); - - prim.CollisionSound = DBGuid.FromDB(row["CollisionSound"]); - prim.CollisionSoundVolume = (float)(double)row["CollisionSoundVolume"]; - - prim.PassTouches = ((sbyte)row["PassTouches"] != 0); - prim.LinkNum = (int)row["LinkNumber"]; - - if (!(row["MediaURL"] is System.DBNull)) - prim.MediaUrl = (string)row["MediaURL"]; - - return prim; - } - - - /// - /// Build a prim inventory item from the persisted data. - /// - /// - /// - private static TaskInventoryItem BuildItem(IDataReader row) - { - TaskInventoryItem taskItem = new TaskInventoryItem(); - - taskItem.ItemID = DBGuid.FromDB(row["itemID"]); - taskItem.ParentPartID = DBGuid.FromDB(row["primID"]); - taskItem.AssetID = DBGuid.FromDB(row["assetID"]); - taskItem.ParentID = DBGuid.FromDB(row["parentFolderID"]); - - taskItem.InvType = Convert.ToInt32(row["invType"]); - taskItem.Type = Convert.ToInt32(row["assetType"]); - - taskItem.Name = (String)row["name"]; - taskItem.Description = (String)row["description"]; - taskItem.CreationDate = Convert.ToUInt32(row["creationDate"]); - taskItem.CreatorID = DBGuid.FromDB(row["creatorID"]); - taskItem.OwnerID = DBGuid.FromDB(row["ownerID"]); - taskItem.LastOwnerID = DBGuid.FromDB(row["lastOwnerID"]); - taskItem.GroupID = DBGuid.FromDB(row["groupID"]); - - taskItem.NextPermissions = Convert.ToUInt32(row["nextPermissions"]); - taskItem.CurrentPermissions = Convert.ToUInt32(row["currentPermissions"]); - taskItem.BasePermissions = Convert.ToUInt32(row["basePermissions"]); - taskItem.EveryonePermissions = Convert.ToUInt32(row["everyonePermissions"]); - taskItem.GroupPermissions = Convert.ToUInt32(row["groupPermissions"]); - taskItem.Flags = Convert.ToUInt32(row["flags"]); - - return taskItem; - } - - private static RegionSettings BuildRegionSettings(IDataReader row) - { - RegionSettings newSettings = new RegionSettings(); - - newSettings.RegionUUID = DBGuid.FromDB(row["regionUUID"]); - newSettings.BlockTerraform = Convert.ToBoolean(row["block_terraform"]); - newSettings.AllowDamage = Convert.ToBoolean(row["allow_damage"]); - newSettings.BlockFly = Convert.ToBoolean(row["block_fly"]); - newSettings.RestrictPushing = Convert.ToBoolean(row["restrict_pushing"]); - newSettings.AllowLandResell = Convert.ToBoolean(row["allow_land_resell"]); - newSettings.AllowLandJoinDivide = Convert.ToBoolean(row["allow_land_join_divide"]); - newSettings.BlockShowInSearch = Convert.ToBoolean(row["block_show_in_search"]); - newSettings.AgentLimit = Convert.ToInt32(row["agent_limit"]); - newSettings.ObjectBonus = Convert.ToDouble(row["object_bonus"]); - newSettings.Maturity = Convert.ToInt32(row["maturity"]); - newSettings.DisableScripts = Convert.ToBoolean(row["disable_scripts"]); - newSettings.DisableCollisions = Convert.ToBoolean(row["disable_collisions"]); - newSettings.DisablePhysics = Convert.ToBoolean(row["disable_physics"]); - newSettings.TerrainTexture1 = DBGuid.FromDB(row["terrain_texture_1"]); - newSettings.TerrainTexture2 = DBGuid.FromDB(row["terrain_texture_2"]); - newSettings.TerrainTexture3 = DBGuid.FromDB(row["terrain_texture_3"]); - newSettings.TerrainTexture4 = DBGuid.FromDB(row["terrain_texture_4"]); - newSettings.Elevation1NW = Convert.ToDouble(row["elevation_1_nw"]); - newSettings.Elevation2NW = Convert.ToDouble(row["elevation_2_nw"]); - newSettings.Elevation1NE = Convert.ToDouble(row["elevation_1_ne"]); - newSettings.Elevation2NE = Convert.ToDouble(row["elevation_2_ne"]); - newSettings.Elevation1SE = Convert.ToDouble(row["elevation_1_se"]); - newSettings.Elevation2SE = Convert.ToDouble(row["elevation_2_se"]); - newSettings.Elevation1SW = Convert.ToDouble(row["elevation_1_sw"]); - newSettings.Elevation2SW = Convert.ToDouble(row["elevation_2_sw"]); - newSettings.WaterHeight = Convert.ToDouble(row["water_height"]); - newSettings.TerrainRaiseLimit = Convert.ToDouble(row["terrain_raise_limit"]); - newSettings.TerrainLowerLimit = Convert.ToDouble(row["terrain_lower_limit"]); - newSettings.UseEstateSun = Convert.ToBoolean(row["use_estate_sun"]); - newSettings.Sandbox = Convert.ToBoolean(row["sandbox"]); - newSettings.SunVector = new Vector3 ( - Convert.ToSingle(row["sunvectorx"]), - Convert.ToSingle(row["sunvectory"]), - Convert.ToSingle(row["sunvectorz"]) - ); - newSettings.FixedSun = Convert.ToBoolean(row["fixed_sun"]); - newSettings.SunPosition = Convert.ToDouble(row["sun_position"]); - newSettings.Covenant = DBGuid.FromDB(row["covenant"]); - - newSettings.LoadedCreationDateTime = Convert.ToInt32(row["loaded_creation_datetime"]); - - if (row["loaded_creation_id"] is DBNull) - newSettings.LoadedCreationID = ""; - else - newSettings.LoadedCreationID = (String) row["loaded_creation_id"]; - - newSettings.TerrainImageID = DBGuid.FromDB(row["map_tile_ID"]); - - return newSettings; - } - - /// - /// - /// - /// - /// - private static LandData BuildLandData(IDataReader row) - { - LandData newData = new LandData(); - - newData.GlobalID = DBGuid.FromDB(row["UUID"]); - newData.LocalID = Convert.ToInt32(row["LocalLandID"]); - - // Bitmap is a byte[512] - newData.Bitmap = (Byte[]) row["Bitmap"]; - - newData.Name = (String) row["Name"]; - newData.Description = (String) row["Description"]; - newData.OwnerID = DBGuid.FromDB(row["OwnerUUID"]); - newData.IsGroupOwned = Convert.ToBoolean(row["IsGroupOwned"]); - newData.Area = Convert.ToInt32(row["Area"]); - newData.AuctionID = Convert.ToUInt32(row["AuctionID"]); //Unimplemented - newData.Category = (ParcelCategory) Convert.ToInt32(row["Category"]); - //Enum libsecondlife.Parcel.ParcelCategory - newData.ClaimDate = Convert.ToInt32(row["ClaimDate"]); - newData.ClaimPrice = Convert.ToInt32(row["ClaimPrice"]); - newData.GroupID = DBGuid.FromDB(row["GroupUUID"]); - newData.SalePrice = Convert.ToInt32(row["SalePrice"]); - newData.Status = (ParcelStatus) Convert.ToInt32(row["LandStatus"]); - //Enum. libsecondlife.Parcel.ParcelStatus - newData.Flags = Convert.ToUInt32(row["LandFlags"]); - newData.LandingType = Convert.ToByte(row["LandingType"]); - newData.MediaAutoScale = Convert.ToByte(row["MediaAutoScale"]); - newData.MediaID = DBGuid.FromDB(row["MediaTextureUUID"]); - newData.MediaURL = (String) row["MediaURL"]; - newData.MusicURL = (String) row["MusicURL"]; - newData.PassHours = Convert.ToSingle(row["PassHours"]); - newData.PassPrice = Convert.ToInt32(row["PassPrice"]); - UUID authedbuyer = UUID.Zero; - UUID snapshotID = UUID.Zero; - - UUID.TryParse((string)row["AuthBuyerID"], out authedbuyer); - UUID.TryParse((string)row["SnapshotUUID"], out snapshotID); - newData.OtherCleanTime = Convert.ToInt32(row["OtherCleanTime"]); - - newData.AuthBuyerID = authedbuyer; - newData.SnapshotID = snapshotID; - try - { - newData.UserLocation = - new Vector3(Convert.ToSingle(row["UserLocationX"]), Convert.ToSingle(row["UserLocationY"]), - Convert.ToSingle(row["UserLocationZ"])); - newData.UserLookAt = - new Vector3(Convert.ToSingle(row["UserLookAtX"]), Convert.ToSingle(row["UserLookAtY"]), - Convert.ToSingle(row["UserLookAtZ"])); - } - catch (InvalidCastException) - { - newData.UserLocation = Vector3.Zero; - newData.UserLookAt = Vector3.Zero; - m_log.ErrorFormat("[PARCEL]: unable to get parcel telehub settings for {1}", newData.Name); - } - - newData.MediaDescription = (string) row["MediaDescription"]; - newData.MediaType = (string) row["MediaType"]; - newData.MediaWidth = Convert.ToInt32((((string) row["MediaSize"]).Split(','))[0]); - newData.MediaHeight = Convert.ToInt32((((string) row["MediaSize"]).Split(','))[1]); - newData.MediaLoop = Convert.ToBoolean(row["MediaLoop"]); - newData.ObscureMusic = Convert.ToBoolean(row["ObscureMusic"]); - newData.ObscureMedia = Convert.ToBoolean(row["ObscureMedia"]); - - newData.ParcelAccessList = new List(); - - return newData; - } - - /// - /// - /// - /// - /// - private static ParcelManager.ParcelAccessEntry BuildLandAccessData(IDataReader row) - { - ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); - entry.AgentID = DBGuid.FromDB(row["AccessUUID"]); - entry.Flags = (AccessList) Convert.ToInt32(row["Flags"]); - entry.Time = new DateTime(); - return entry; - } - - /// - /// - /// - /// - /// - private static Array SerializeTerrain(double[,] val) - { - MemoryStream str = new MemoryStream(((int)Constants.RegionSize * (int)Constants.RegionSize) *sizeof (double)); - BinaryWriter bw = new BinaryWriter(str); - - // TODO: COMPATIBILITY - Add byte-order conversions - for (int x = 0; x < (int)Constants.RegionSize; x++) - for (int y = 0; y < (int)Constants.RegionSize; y++) - { - double height = val[x, y]; - if (height == 0.0) - height = double.Epsilon; - - bw.Write(height); - } - - return str.ToArray(); - } - - /// - /// Fill the prim command with prim values - /// - /// - /// - /// - /// - private void FillPrimCommand(MySqlCommand cmd, SceneObjectPart prim, UUID sceneGroupID, UUID regionUUID) - { - cmd.Parameters.AddWithValue("UUID", prim.UUID.ToString()); - cmd.Parameters.AddWithValue("RegionUUID", regionUUID.ToString()); - cmd.Parameters.AddWithValue("CreationDate", prim.CreationDate); - cmd.Parameters.AddWithValue("Name", prim.Name); - cmd.Parameters.AddWithValue("SceneGroupID", sceneGroupID.ToString()); - // the UUID of the root part for this SceneObjectGroup - // various text fields - cmd.Parameters.AddWithValue("Text", prim.Text); - cmd.Parameters.AddWithValue("ColorR", prim.Color.R); - cmd.Parameters.AddWithValue("ColorG", prim.Color.G); - cmd.Parameters.AddWithValue("ColorB", prim.Color.B); - cmd.Parameters.AddWithValue("ColorA", prim.Color.A); - cmd.Parameters.AddWithValue("Description", prim.Description); - cmd.Parameters.AddWithValue("SitName", prim.SitName); - cmd.Parameters.AddWithValue("TouchName", prim.TouchName); - // permissions - cmd.Parameters.AddWithValue("ObjectFlags", (uint)prim.Flags); - cmd.Parameters.AddWithValue("CreatorID", prim.CreatorID.ToString()); - cmd.Parameters.AddWithValue("OwnerID", prim.OwnerID.ToString()); - cmd.Parameters.AddWithValue("GroupID", prim.GroupID.ToString()); - cmd.Parameters.AddWithValue("LastOwnerID", prim.LastOwnerID.ToString()); - cmd.Parameters.AddWithValue("OwnerMask", prim.OwnerMask); - cmd.Parameters.AddWithValue("NextOwnerMask", prim.NextOwnerMask); - cmd.Parameters.AddWithValue("GroupMask", prim.GroupMask); - cmd.Parameters.AddWithValue("EveryoneMask", prim.EveryoneMask); - cmd.Parameters.AddWithValue("BaseMask", prim.BaseMask); - // vectors - cmd.Parameters.AddWithValue("PositionX", (double)prim.OffsetPosition.X); - cmd.Parameters.AddWithValue("PositionY", (double)prim.OffsetPosition.Y); - cmd.Parameters.AddWithValue("PositionZ", (double)prim.OffsetPosition.Z); - cmd.Parameters.AddWithValue("GroupPositionX", (double)prim.GroupPosition.X); - cmd.Parameters.AddWithValue("GroupPositionY", (double)prim.GroupPosition.Y); - cmd.Parameters.AddWithValue("GroupPositionZ", (double)prim.GroupPosition.Z); - cmd.Parameters.AddWithValue("VelocityX", (double)prim.Velocity.X); - cmd.Parameters.AddWithValue("VelocityY", (double)prim.Velocity.Y); - cmd.Parameters.AddWithValue("VelocityZ", (double)prim.Velocity.Z); - cmd.Parameters.AddWithValue("AngularVelocityX", (double)prim.AngularVelocity.X); - cmd.Parameters.AddWithValue("AngularVelocityY", (double)prim.AngularVelocity.Y); - cmd.Parameters.AddWithValue("AngularVelocityZ", (double)prim.AngularVelocity.Z); - cmd.Parameters.AddWithValue("AccelerationX", (double)prim.Acceleration.X); - cmd.Parameters.AddWithValue("AccelerationY", (double)prim.Acceleration.Y); - cmd.Parameters.AddWithValue("AccelerationZ", (double)prim.Acceleration.Z); - // quaternions - cmd.Parameters.AddWithValue("RotationX", (double)prim.RotationOffset.X); - cmd.Parameters.AddWithValue("RotationY", (double)prim.RotationOffset.Y); - cmd.Parameters.AddWithValue("RotationZ", (double)prim.RotationOffset.Z); - cmd.Parameters.AddWithValue("RotationW", (double)prim.RotationOffset.W); - - // Sit target - Vector3 sitTargetPos = prim.SitTargetPositionLL; - cmd.Parameters.AddWithValue("SitTargetOffsetX", (double)sitTargetPos.X); - cmd.Parameters.AddWithValue("SitTargetOffsetY", (double)sitTargetPos.Y); - cmd.Parameters.AddWithValue("SitTargetOffsetZ", (double)sitTargetPos.Z); - - Quaternion sitTargetOrient = prim.SitTargetOrientationLL; - cmd.Parameters.AddWithValue("SitTargetOrientW", (double)sitTargetOrient.W); - cmd.Parameters.AddWithValue("SitTargetOrientX", (double)sitTargetOrient.X); - cmd.Parameters.AddWithValue("SitTargetOrientY", (double)sitTargetOrient.Y); - cmd.Parameters.AddWithValue("SitTargetOrientZ", (double)sitTargetOrient.Z); - - cmd.Parameters.AddWithValue("PayPrice", prim.PayPrice[0]); - cmd.Parameters.AddWithValue("PayButton1", prim.PayPrice[1]); - cmd.Parameters.AddWithValue("PayButton2", prim.PayPrice[2]); - cmd.Parameters.AddWithValue("PayButton3", prim.PayPrice[3]); - cmd.Parameters.AddWithValue("PayButton4", prim.PayPrice[4]); - - if ((prim.SoundFlags & 1) != 0) // Looped - { - cmd.Parameters.AddWithValue("LoopedSound", prim.Sound.ToString()); - cmd.Parameters.AddWithValue("LoopedSoundGain", prim.SoundGain); - } - else - { - cmd.Parameters.AddWithValue("LoopedSound", UUID.Zero); - cmd.Parameters.AddWithValue("LoopedSoundGain", 0.0f); - } - - cmd.Parameters.AddWithValue("TextureAnimation", prim.TextureAnimation); - cmd.Parameters.AddWithValue("ParticleSystem", prim.ParticleSystem); - - cmd.Parameters.AddWithValue("OmegaX", (double)prim.AngularVelocity.X); - cmd.Parameters.AddWithValue("OmegaY", (double)prim.AngularVelocity.Y); - cmd.Parameters.AddWithValue("OmegaZ", (double)prim.AngularVelocity.Z); - - cmd.Parameters.AddWithValue("CameraEyeOffsetX", (double)prim.GetCameraEyeOffset().X); - cmd.Parameters.AddWithValue("CameraEyeOffsetY", (double)prim.GetCameraEyeOffset().Y); - cmd.Parameters.AddWithValue("CameraEyeOffsetZ", (double)prim.GetCameraEyeOffset().Z); - - cmd.Parameters.AddWithValue("CameraAtOffsetX", (double)prim.GetCameraAtOffset().X); - cmd.Parameters.AddWithValue("CameraAtOffsetY", (double)prim.GetCameraAtOffset().Y); - cmd.Parameters.AddWithValue("CameraAtOffsetZ", (double)prim.GetCameraAtOffset().Z); - - if (prim.GetForceMouselook()) - cmd.Parameters.AddWithValue("ForceMouselook", 1); - else - cmd.Parameters.AddWithValue("ForceMouselook", 0); - - cmd.Parameters.AddWithValue("ScriptAccessPin", prim.ScriptAccessPin); - - if (prim.AllowedDrop) - cmd.Parameters.AddWithValue("AllowedDrop", 1); - else - cmd.Parameters.AddWithValue("AllowedDrop", 0); - - if (prim.DIE_AT_EDGE) - cmd.Parameters.AddWithValue("DieAtEdge", 1); - else - cmd.Parameters.AddWithValue("DieAtEdge", 0); - - cmd.Parameters.AddWithValue("SalePrice", prim.SalePrice); - cmd.Parameters.AddWithValue("SaleType", unchecked((sbyte)(prim.ObjectSaleType))); - - byte clickAction = prim.ClickAction; - cmd.Parameters.AddWithValue("ClickAction", unchecked((sbyte)(clickAction))); - - cmd.Parameters.AddWithValue("Material", unchecked((sbyte)(prim.Material))); - - cmd.Parameters.AddWithValue("CollisionSound", prim.CollisionSound.ToString()); - cmd.Parameters.AddWithValue("CollisionSoundVolume", prim.CollisionSoundVolume); - - if (prim.PassTouches) - cmd.Parameters.AddWithValue("PassTouches", 1); - else - cmd.Parameters.AddWithValue("PassTouches", 0); - - cmd.Parameters.AddWithValue("LinkNumber", prim.LinkNum); - cmd.Parameters.AddWithValue("MediaURL", prim.MediaUrl); - } - - /// - /// - /// - /// - /// - private static void FillItemCommand(MySqlCommand cmd, TaskInventoryItem taskItem) - { - cmd.Parameters.AddWithValue("itemID", taskItem.ItemID); - cmd.Parameters.AddWithValue("primID", taskItem.ParentPartID); - cmd.Parameters.AddWithValue("assetID", taskItem.AssetID); - cmd.Parameters.AddWithValue("parentFolderID", taskItem.ParentID); - - cmd.Parameters.AddWithValue("invType", taskItem.InvType); - cmd.Parameters.AddWithValue("assetType", taskItem.Type); - - cmd.Parameters.AddWithValue("name", taskItem.Name); - cmd.Parameters.AddWithValue("description", taskItem.Description); - cmd.Parameters.AddWithValue("creationDate", taskItem.CreationDate); - cmd.Parameters.AddWithValue("creatorID", taskItem.CreatorID); - cmd.Parameters.AddWithValue("ownerID", taskItem.OwnerID); - cmd.Parameters.AddWithValue("lastOwnerID", taskItem.LastOwnerID); - cmd.Parameters.AddWithValue("groupID", taskItem.GroupID); - cmd.Parameters.AddWithValue("nextPermissions", taskItem.NextPermissions); - cmd.Parameters.AddWithValue("currentPermissions", taskItem.CurrentPermissions); - cmd.Parameters.AddWithValue("basePermissions", taskItem.BasePermissions); - cmd.Parameters.AddWithValue("everyonePermissions", taskItem.EveryonePermissions); - cmd.Parameters.AddWithValue("groupPermissions", taskItem.GroupPermissions); - cmd.Parameters.AddWithValue("flags", taskItem.Flags); - } - - /// - /// - /// - private static void FillRegionSettingsCommand(MySqlCommand cmd, RegionSettings settings) - { - cmd.Parameters.AddWithValue("RegionUUID", settings.RegionUUID.ToString()); - cmd.Parameters.AddWithValue("BlockTerraform", settings.BlockTerraform); - cmd.Parameters.AddWithValue("BlockFly", settings.BlockFly); - cmd.Parameters.AddWithValue("AllowDamage", settings.AllowDamage); - cmd.Parameters.AddWithValue("RestrictPushing", settings.RestrictPushing); - cmd.Parameters.AddWithValue("AllowLandResell", settings.AllowLandResell); - cmd.Parameters.AddWithValue("AllowLandJoinDivide", settings.AllowLandJoinDivide); - cmd.Parameters.AddWithValue("BlockShowInSearch", settings.BlockShowInSearch); - cmd.Parameters.AddWithValue("AgentLimit", settings.AgentLimit); - cmd.Parameters.AddWithValue("ObjectBonus", settings.ObjectBonus); - cmd.Parameters.AddWithValue("Maturity", settings.Maturity); - cmd.Parameters.AddWithValue("DisableScripts", settings.DisableScripts); - cmd.Parameters.AddWithValue("DisableCollisions", settings.DisableCollisions); - cmd.Parameters.AddWithValue("DisablePhysics", settings.DisablePhysics); - cmd.Parameters.AddWithValue("TerrainTexture1", settings.TerrainTexture1.ToString()); - cmd.Parameters.AddWithValue("TerrainTexture2", settings.TerrainTexture2.ToString()); - cmd.Parameters.AddWithValue("TerrainTexture3", settings.TerrainTexture3.ToString()); - cmd.Parameters.AddWithValue("TerrainTexture4", settings.TerrainTexture4.ToString()); - cmd.Parameters.AddWithValue("Elevation1NW", settings.Elevation1NW); - cmd.Parameters.AddWithValue("Elevation2NW", settings.Elevation2NW); - cmd.Parameters.AddWithValue("Elevation1NE", settings.Elevation1NE); - cmd.Parameters.AddWithValue("Elevation2NE", settings.Elevation2NE); - cmd.Parameters.AddWithValue("Elevation1SE", settings.Elevation1SE); - cmd.Parameters.AddWithValue("Elevation2SE", settings.Elevation2SE); - cmd.Parameters.AddWithValue("Elevation1SW", settings.Elevation1SW); - cmd.Parameters.AddWithValue("Elevation2SW", settings.Elevation2SW); - cmd.Parameters.AddWithValue("WaterHeight", settings.WaterHeight); - cmd.Parameters.AddWithValue("TerrainRaiseLimit", settings.TerrainRaiseLimit); - cmd.Parameters.AddWithValue("TerrainLowerLimit", settings.TerrainLowerLimit); - cmd.Parameters.AddWithValue("UseEstateSun", settings.UseEstateSun); - cmd.Parameters.AddWithValue("Sandbox", settings.Sandbox); - cmd.Parameters.AddWithValue("SunVectorX", settings.SunVector.X); - cmd.Parameters.AddWithValue("SunVectorY", settings.SunVector.Y); - cmd.Parameters.AddWithValue("SunVectorZ", settings.SunVector.Z); - cmd.Parameters.AddWithValue("FixedSun", settings.FixedSun); - cmd.Parameters.AddWithValue("SunPosition", settings.SunPosition); - cmd.Parameters.AddWithValue("Covenant", settings.Covenant.ToString()); - cmd.Parameters.AddWithValue("LoadedCreationDateTime", settings.LoadedCreationDateTime); - cmd.Parameters.AddWithValue("LoadedCreationID", settings.LoadedCreationID); - cmd.Parameters.AddWithValue("TerrainImageID", settings.TerrainImageID); - - } - - /// - /// - /// - /// - /// - /// - private static void FillLandCommand(MySqlCommand cmd, LandData land, UUID regionUUID) - { - cmd.Parameters.AddWithValue("UUID", land.GlobalID.ToString()); - cmd.Parameters.AddWithValue("RegionUUID", regionUUID.ToString()); - cmd.Parameters.AddWithValue("LocalLandID", land.LocalID); - - // Bitmap is a byte[512] - cmd.Parameters.AddWithValue("Bitmap", land.Bitmap); - - cmd.Parameters.AddWithValue("Name", land.Name); - cmd.Parameters.AddWithValue("Description", land.Description); - cmd.Parameters.AddWithValue("OwnerUUID", land.OwnerID.ToString()); - cmd.Parameters.AddWithValue("IsGroupOwned", land.IsGroupOwned); - cmd.Parameters.AddWithValue("Area", land.Area); - cmd.Parameters.AddWithValue("AuctionID", land.AuctionID); //Unemplemented - cmd.Parameters.AddWithValue("Category", land.Category); //Enum libsecondlife.Parcel.ParcelCategory - cmd.Parameters.AddWithValue("ClaimDate", land.ClaimDate); - cmd.Parameters.AddWithValue("ClaimPrice", land.ClaimPrice); - cmd.Parameters.AddWithValue("GroupUUID", land.GroupID.ToString()); - cmd.Parameters.AddWithValue("SalePrice", land.SalePrice); - cmd.Parameters.AddWithValue("LandStatus", land.Status); //Enum. libsecondlife.Parcel.ParcelStatus - cmd.Parameters.AddWithValue("LandFlags", land.Flags); - cmd.Parameters.AddWithValue("LandingType", land.LandingType); - cmd.Parameters.AddWithValue("MediaAutoScale", land.MediaAutoScale); - cmd.Parameters.AddWithValue("MediaTextureUUID", land.MediaID.ToString()); - cmd.Parameters.AddWithValue("MediaURL", land.MediaURL); - cmd.Parameters.AddWithValue("MusicURL", land.MusicURL); - cmd.Parameters.AddWithValue("PassHours", land.PassHours); - cmd.Parameters.AddWithValue("PassPrice", land.PassPrice); - cmd.Parameters.AddWithValue("SnapshotUUID", land.SnapshotID.ToString()); - cmd.Parameters.AddWithValue("UserLocationX", land.UserLocation.X); - cmd.Parameters.AddWithValue("UserLocationY", land.UserLocation.Y); - cmd.Parameters.AddWithValue("UserLocationZ", land.UserLocation.Z); - cmd.Parameters.AddWithValue("UserLookAtX", land.UserLookAt.X); - cmd.Parameters.AddWithValue("UserLookAtY", land.UserLookAt.Y); - cmd.Parameters.AddWithValue("UserLookAtZ", land.UserLookAt.Z); - cmd.Parameters.AddWithValue("AuthBuyerID", land.AuthBuyerID); - cmd.Parameters.AddWithValue("OtherCleanTime", land.OtherCleanTime); - cmd.Parameters.AddWithValue("MediaDescription", land.MediaDescription); - cmd.Parameters.AddWithValue("MediaType", land.MediaType); - cmd.Parameters.AddWithValue("MediaWidth", land.MediaWidth); - cmd.Parameters.AddWithValue("MediaHeight", land.MediaHeight); - cmd.Parameters.AddWithValue("MediaLoop", land.MediaLoop); - cmd.Parameters.AddWithValue("ObscureMusic", land.ObscureMusic); - cmd.Parameters.AddWithValue("ObscureMedia", land.ObscureMedia); - - } - - /// - /// - /// - /// - /// - /// - private static void FillLandAccessCommand(MySqlCommand cmd, ParcelManager.ParcelAccessEntry entry, UUID parcelID) - { - cmd.Parameters.AddWithValue("LandUUID", parcelID.ToString()); - cmd.Parameters.AddWithValue("AccessUUID", entry.AgentID.ToString()); - cmd.Parameters.AddWithValue("Flags", entry.Flags); - } - - /// - /// - /// - /// - /// - private PrimitiveBaseShape BuildShape(IDataReader row) - { - PrimitiveBaseShape s = new PrimitiveBaseShape(); - s.Scale = new Vector3( - (float)(double)row["ScaleX"], - (float)(double)row["ScaleY"], - (float)(double)row["ScaleZ"] - ); - // paths - s.PCode = (byte)(int)row["PCode"]; - s.PathBegin = (ushort)(int)row["PathBegin"]; - s.PathEnd = (ushort)(int)row["PathEnd"]; - s.PathScaleX = (byte)(int)row["PathScaleX"]; - s.PathScaleY = (byte)(int)row["PathScaleY"]; - s.PathShearX = (byte)(int)row["PathShearX"]; - s.PathShearY = (byte)(int)row["PathShearY"]; - s.PathSkew = (sbyte)(int)row["PathSkew"]; - s.PathCurve = (byte)(int)row["PathCurve"]; - s.PathRadiusOffset = (sbyte)(int)row["PathRadiusOffset"]; - s.PathRevolutions = (byte)(int)row["PathRevolutions"]; - s.PathTaperX = (sbyte)(int)row["PathTaperX"]; - s.PathTaperY = (sbyte)(int)row["PathTaperY"]; - s.PathTwist = (sbyte)(int)row["PathTwist"]; - s.PathTwistBegin = (sbyte)(int)row["PathTwistBegin"]; - // profile - s.ProfileBegin = (ushort)(int)row["ProfileBegin"]; - s.ProfileEnd = (ushort)(int)row["ProfileEnd"]; - s.ProfileCurve = (byte)(int)row["ProfileCurve"]; - s.ProfileHollow = (ushort)(int)row["ProfileHollow"]; - s.TextureEntry = (byte[])row["Texture"]; - - s.ExtraParams = (byte[])row["ExtraParams"]; - - s.State = (byte)(int)row["State"]; - - if (!(row["Media"] is System.DBNull)) - s.Media = PrimitiveBaseShape.MediaList.FromXml((string)row["Media"]); - - return s; - } - - /// - /// - /// - /// - /// - private void FillShapeCommand(MySqlCommand cmd, SceneObjectPart prim) - { - PrimitiveBaseShape s = prim.Shape; - cmd.Parameters.AddWithValue("UUID", prim.UUID.ToString()); - // shape is an enum - cmd.Parameters.AddWithValue("Shape", 0); - // vectors - cmd.Parameters.AddWithValue("ScaleX", (double)s.Scale.X); - cmd.Parameters.AddWithValue("ScaleY", (double)s.Scale.Y); - cmd.Parameters.AddWithValue("ScaleZ", (double)s.Scale.Z); - // paths - cmd.Parameters.AddWithValue("PCode", s.PCode); - cmd.Parameters.AddWithValue("PathBegin", s.PathBegin); - cmd.Parameters.AddWithValue("PathEnd", s.PathEnd); - cmd.Parameters.AddWithValue("PathScaleX", s.PathScaleX); - cmd.Parameters.AddWithValue("PathScaleY", s.PathScaleY); - cmd.Parameters.AddWithValue("PathShearX", s.PathShearX); - cmd.Parameters.AddWithValue("PathShearY", s.PathShearY); - cmd.Parameters.AddWithValue("PathSkew", s.PathSkew); - cmd.Parameters.AddWithValue("PathCurve", s.PathCurve); - cmd.Parameters.AddWithValue("PathRadiusOffset", s.PathRadiusOffset); - cmd.Parameters.AddWithValue("PathRevolutions", s.PathRevolutions); - cmd.Parameters.AddWithValue("PathTaperX", s.PathTaperX); - cmd.Parameters.AddWithValue("PathTaperY", s.PathTaperY); - cmd.Parameters.AddWithValue("PathTwist", s.PathTwist); - cmd.Parameters.AddWithValue("PathTwistBegin", s.PathTwistBegin); - // profile - cmd.Parameters.AddWithValue("ProfileBegin", s.ProfileBegin); - cmd.Parameters.AddWithValue("ProfileEnd", s.ProfileEnd); - cmd.Parameters.AddWithValue("ProfileCurve", s.ProfileCurve); - cmd.Parameters.AddWithValue("ProfileHollow", s.ProfileHollow); - cmd.Parameters.AddWithValue("Texture", s.TextureEntry); - cmd.Parameters.AddWithValue("ExtraParams", s.ExtraParams); - cmd.Parameters.AddWithValue("State", s.State); - cmd.Parameters.AddWithValue("Media", null == s.Media ? null : s.Media.ToXml()); - } - - public void StorePrimInventory(UUID primID, ICollection items) - { - lock (m_dbLock) - { - RemoveItems(primID); - - using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) - { - dbcon.Open(); - - MySqlCommand cmd = dbcon.CreateCommand(); - - if (items.Count == 0) - return; - - cmd.CommandText = "insert into primitems (" + - "invType, assetType, name, " + - "description, creationDate, nextPermissions, " + - "currentPermissions, basePermissions, " + - "everyonePermissions, groupPermissions, " + - "flags, itemID, primID, assetID, " + - "parentFolderID, creatorID, ownerID, " + - "groupID, lastOwnerID) values (?invType, " + - "?assetType, ?name, ?description, " + - "?creationDate, ?nextPermissions, " + - "?currentPermissions, ?basePermissions, " + - "?everyonePermissions, ?groupPermissions, " + - "?flags, ?itemID, ?primID, ?assetID, " + - "?parentFolderID, ?creatorID, ?ownerID, " + - "?groupID, ?lastOwnerID)"; - - foreach (TaskInventoryItem item in items) - { - cmd.Parameters.Clear(); - - FillItemCommand(cmd, item); - - ExecuteNonQuery(cmd); - } - - cmd.Dispose(); - } - } - } - } -} diff --git a/OpenSim/Data/MySQL/MySQLSimulationData.cs b/OpenSim/Data/MySQL/MySQLSimulationData.cs new file mode 100644 index 0000000..36f73ef --- /dev/null +++ b/OpenSim/Data/MySQL/MySQLSimulationData.cs @@ -0,0 +1,1820 @@ +/* + * 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.Data; +using System.Drawing; +using System.IO; +using System.Reflection; +using System.Threading; +using log4net; +using MySql.Data.MySqlClient; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Data; + +namespace OpenSim.Data.MySQL +{ + /// + /// A MySQL Interface for the Region Server + /// + public class MySQLSimulationData : ISimulationDataStore + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private string m_connectionString; + private object m_dbLock = new object(); + + public void Initialise(string connectionString) + { + m_connectionString = connectionString; + + using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) + { + dbcon.Open(); + + // Apply new Migrations + // + Assembly assem = GetType().Assembly; + Migration m = new Migration(dbcon, assem, "RegionStore"); + m.Update(); + + // Clean dropped attachments + // + try + { + using (MySqlCommand cmd = dbcon.CreateCommand()) + { + cmd.CommandText = "delete from prims, primshapes using prims " + + "left join primshapes on prims.uuid = primshapes.uuid " + + "where PCode = 9 and State <> 0"; + ExecuteNonQuery(cmd); + } + } + catch (MySqlException ex) + { + m_log.Error("[REGION DB]: Error cleaning up dropped attachments: " + ex.Message); + } + } + } + + private IDataReader ExecuteReader(MySqlCommand c) + { + IDataReader r = null; + + try + { + r = c.ExecuteReader(); + } + catch (Exception e) + { + m_log.Error("[REGION DB]: MySQL error in ExecuteReader: " + e.Message); + throw; + } + + return r; + } + + private void ExecuteNonQuery(MySqlCommand c) + { + try + { + c.ExecuteNonQuery(); + } + catch (Exception e) + { + m_log.Error("[REGION DB]: MySQL error in ExecuteNonQuery: " + e.Message); + throw; + } + } + + public void Dispose() {} + + public void StoreObject(SceneObjectGroup obj, UUID regionUUID) + { + uint flags = obj.RootPart.GetEffectiveObjectFlags(); + + // Eligibility check + // + if ((flags & (uint)PrimFlags.Temporary) != 0) + return; + if ((flags & (uint)PrimFlags.TemporaryOnRez) != 0) + return; + + lock (m_dbLock) + { + using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) + { + dbcon.Open(); + MySqlCommand cmd = dbcon.CreateCommand(); + + foreach (SceneObjectPart prim in obj.Children.Values) + { + cmd.Parameters.Clear(); + + cmd.CommandText = "replace into prims (" + + "UUID, CreationDate, " + + "Name, Text, Description, " + + "SitName, TouchName, ObjectFlags, " + + "OwnerMask, NextOwnerMask, GroupMask, " + + "EveryoneMask, BaseMask, PositionX, " + + "PositionY, PositionZ, GroupPositionX, " + + "GroupPositionY, GroupPositionZ, VelocityX, " + + "VelocityY, VelocityZ, AngularVelocityX, " + + "AngularVelocityY, AngularVelocityZ, " + + "AccelerationX, AccelerationY, " + + "AccelerationZ, RotationX, " + + "RotationY, RotationZ, " + + "RotationW, SitTargetOffsetX, " + + "SitTargetOffsetY, SitTargetOffsetZ, " + + "SitTargetOrientW, SitTargetOrientX, " + + "SitTargetOrientY, SitTargetOrientZ, " + + "RegionUUID, CreatorID, " + + "OwnerID, GroupID, " + + "LastOwnerID, SceneGroupID, " + + "PayPrice, PayButton1, " + + "PayButton2, PayButton3, " + + "PayButton4, LoopedSound, " + + "LoopedSoundGain, TextureAnimation, " + + "OmegaX, OmegaY, OmegaZ, " + + "CameraEyeOffsetX, CameraEyeOffsetY, " + + "CameraEyeOffsetZ, CameraAtOffsetX, " + + "CameraAtOffsetY, CameraAtOffsetZ, " + + "ForceMouselook, ScriptAccessPin, " + + "AllowedDrop, DieAtEdge, " + + "SalePrice, SaleType, " + + "ColorR, ColorG, ColorB, ColorA, " + + "ParticleSystem, ClickAction, Material, " + + "CollisionSound, CollisionSoundVolume, " + + "PassTouches, " + + "LinkNumber, MediaURL) values (" + "?UUID, " + + "?CreationDate, ?Name, ?Text, " + + "?Description, ?SitName, ?TouchName, " + + "?ObjectFlags, ?OwnerMask, ?NextOwnerMask, " + + "?GroupMask, ?EveryoneMask, ?BaseMask, " + + "?PositionX, ?PositionY, ?PositionZ, " + + "?GroupPositionX, ?GroupPositionY, " + + "?GroupPositionZ, ?VelocityX, " + + "?VelocityY, ?VelocityZ, ?AngularVelocityX, " + + "?AngularVelocityY, ?AngularVelocityZ, " + + "?AccelerationX, ?AccelerationY, " + + "?AccelerationZ, ?RotationX, " + + "?RotationY, ?RotationZ, " + + "?RotationW, ?SitTargetOffsetX, " + + "?SitTargetOffsetY, ?SitTargetOffsetZ, " + + "?SitTargetOrientW, ?SitTargetOrientX, " + + "?SitTargetOrientY, ?SitTargetOrientZ, " + + "?RegionUUID, ?CreatorID, ?OwnerID, " + + "?GroupID, ?LastOwnerID, ?SceneGroupID, " + + "?PayPrice, ?PayButton1, ?PayButton2, " + + "?PayButton3, ?PayButton4, ?LoopedSound, " + + "?LoopedSoundGain, ?TextureAnimation, " + + "?OmegaX, ?OmegaY, ?OmegaZ, " + + "?CameraEyeOffsetX, ?CameraEyeOffsetY, " + + "?CameraEyeOffsetZ, ?CameraAtOffsetX, " + + "?CameraAtOffsetY, ?CameraAtOffsetZ, " + + "?ForceMouselook, ?ScriptAccessPin, " + + "?AllowedDrop, ?DieAtEdge, ?SalePrice, " + + "?SaleType, ?ColorR, ?ColorG, " + + "?ColorB, ?ColorA, ?ParticleSystem, " + + "?ClickAction, ?Material, ?CollisionSound, " + + "?CollisionSoundVolume, ?PassTouches, ?LinkNumber, ?MediaURL)"; + + FillPrimCommand(cmd, prim, obj.UUID, regionUUID); + + ExecuteNonQuery(cmd); + + cmd.Parameters.Clear(); + + cmd.CommandText = "replace into primshapes (" + + "UUID, Shape, ScaleX, ScaleY, " + + "ScaleZ, PCode, PathBegin, PathEnd, " + + "PathScaleX, PathScaleY, PathShearX, " + + "PathShearY, PathSkew, PathCurve, " + + "PathRadiusOffset, PathRevolutions, " + + "PathTaperX, PathTaperY, PathTwist, " + + "PathTwistBegin, ProfileBegin, ProfileEnd, " + + "ProfileCurve, ProfileHollow, Texture, " + + "ExtraParams, State, Media) values (?UUID, " + + "?Shape, ?ScaleX, ?ScaleY, ?ScaleZ, " + + "?PCode, ?PathBegin, ?PathEnd, " + + "?PathScaleX, ?PathScaleY, " + + "?PathShearX, ?PathShearY, " + + "?PathSkew, ?PathCurve, ?PathRadiusOffset, " + + "?PathRevolutions, ?PathTaperX, " + + "?PathTaperY, ?PathTwist, " + + "?PathTwistBegin, ?ProfileBegin, " + + "?ProfileEnd, ?ProfileCurve, " + + "?ProfileHollow, ?Texture, ?ExtraParams, " + + "?State, ?Media)"; + + FillShapeCommand(cmd, prim); + + ExecuteNonQuery(cmd); + } + + cmd.Dispose(); + } + } + } + + public void RemoveObject(UUID obj, UUID regionUUID) + { +// m_log.DebugFormat("[REGION DB]: Deleting scene object {0} from {1} in database", obj, regionUUID); + + List uuids = new List(); + + // Formerly, this used to check the region UUID. + // That makes no sense, as we remove the contents of a prim + // unconditionally, but the prim dependent on the region ID. + // So, we would destroy an object and cause hard to detect + // issues if we delete the contents only. Deleting it all may + // cause the loss of a prim, but is cleaner. + // It's also faster because it uses the primary key. + // + lock (m_dbLock) + { + using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) + { + dbcon.Open(); + + using (MySqlCommand cmd = dbcon.CreateCommand()) + { + cmd.CommandText = "select UUID from prims where SceneGroupID= ?UUID"; + cmd.Parameters.AddWithValue("UUID", obj.ToString()); + + using (IDataReader reader = ExecuteReader(cmd)) + { + while (reader.Read()) + uuids.Add(DBGuid.FromDB(reader["UUID"].ToString())); + } + + // delete the main prims + cmd.CommandText = "delete from prims where SceneGroupID= ?UUID"; + ExecuteNonQuery(cmd); + } + } + } + + // there is no way this should be < 1 unless there is + // a very corrupt database, but in that case be extra + // safe anyway. + if (uuids.Count > 0) + { + RemoveShapes(uuids); + RemoveItems(uuids); + } + } + + /// + /// Remove all persisted items of the given prim. + /// The caller must acquire the necessrary synchronization locks + /// + /// the Item UUID + private void RemoveItems(UUID uuid) + { + lock (m_dbLock) + { + using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) + { + dbcon.Open(); + + using (MySqlCommand cmd = dbcon.CreateCommand()) + { + cmd.CommandText = "delete from primitems where PrimID = ?PrimID"; + cmd.Parameters.AddWithValue("PrimID", uuid.ToString()); + + ExecuteNonQuery(cmd); + } + } + } + } + + /// + /// Remove all persisted shapes for a list of prims + /// The caller must acquire the necessrary synchronization locks + /// + /// the list of UUIDs + private void RemoveShapes(List uuids) + { + lock (m_dbLock) + { + string sql = "delete from primshapes where "; + using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) + { + dbcon.Open(); + + using (MySqlCommand cmd = dbcon.CreateCommand()) + { + for (int i = 0; i < uuids.Count; i++) + { + if ((i + 1) == uuids.Count) + {// end of the list + sql += "(UUID = ?UUID" + i + ")"; + } + else + { + sql += "(UUID = ?UUID" + i + ") or "; + } + } + cmd.CommandText = sql; + + for (int i = 0; i < uuids.Count; i++) + cmd.Parameters.AddWithValue("UUID" + i, uuids[i].ToString()); + + ExecuteNonQuery(cmd); + } + } + } + } + + /// + /// Remove all persisted items for a list of prims + /// The caller must acquire the necessrary synchronization locks + /// + /// the list of UUIDs + private void RemoveItems(List uuids) + { + lock (m_dbLock) + { + string sql = "delete from primitems where "; + using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) + { + dbcon.Open(); + + using (MySqlCommand cmd = dbcon.CreateCommand()) + { + for (int i = 0; i < uuids.Count; i++) + { + if ((i + 1) == uuids.Count) + { + // end of the list + sql += "(PrimID = ?PrimID" + i + ")"; + } + else + { + sql += "(PrimID = ?PrimID" + i + ") or "; + } + } + cmd.CommandText = sql; + + for (int i = 0; i < uuids.Count; i++) + cmd.Parameters.AddWithValue("PrimID" + i, uuids[i].ToString()); + + ExecuteNonQuery(cmd); + } + } + } + } + + public List LoadObjects(UUID regionID) + { + const int ROWS_PER_QUERY = 5000; + + Dictionary prims = new Dictionary(ROWS_PER_QUERY); + Dictionary objects = new Dictionary(); + int count = 0; + + #region Prim Loading + + lock (m_dbLock) + { + using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) + { + dbcon.Open(); + + using (MySqlCommand cmd = dbcon.CreateCommand()) + { + cmd.CommandText = + "SELECT * FROM prims LEFT JOIN primshapes ON prims.UUID = primshapes.UUID WHERE RegionUUID = ?RegionUUID"; + cmd.Parameters.AddWithValue("RegionUUID", regionID.ToString()); + + using (IDataReader reader = ExecuteReader(cmd)) + { + while (reader.Read()) + { + SceneObjectPart prim = BuildPrim(reader); + if (reader["Shape"] is DBNull) + prim.Shape = PrimitiveBaseShape.Default; + else + prim.Shape = BuildShape(reader); + + UUID parentID = DBGuid.FromDB(reader["SceneGroupID"].ToString()); + if (parentID != prim.UUID) + prim.ParentUUID = parentID; + + prims[prim.UUID] = prim; + + ++count; + if (count % ROWS_PER_QUERY == 0) + m_log.Debug("[REGION DB]: Loaded " + count + " prims..."); + } + } + } + } + } + + #endregion Prim Loading + + #region SceneObjectGroup Creation + + // Create all of the SOGs from the root prims first + foreach (SceneObjectPart prim in prims.Values) + { + if (prim.ParentUUID == UUID.Zero) + objects[prim.UUID] = new SceneObjectGroup(prim); + } + + // Add all of the children objects to the SOGs + foreach (SceneObjectPart prim in prims.Values) + { + SceneObjectGroup sog; + if (prim.UUID != prim.ParentUUID) + { + if (objects.TryGetValue(prim.ParentUUID, out sog)) + { + int originalLinkNum = prim.LinkNum; + + sog.AddPart(prim); + + // SceneObjectGroup.AddPart() tries to be smart and automatically set the LinkNum. + // We override that here + if (originalLinkNum != 0) + prim.LinkNum = originalLinkNum; + } + else + { + m_log.WarnFormat( + "[REGION DB]: Database contains an orphan child prim {0} {1} in region {2} pointing to missing parent {3}. This prim will not be loaded.", + prim.Name, prim.UUID, regionID, prim.ParentUUID); + } + } + } + + #endregion SceneObjectGroup Creation + + m_log.DebugFormat("[REGION DB]: Loaded {0} objects using {1} prims", objects.Count, prims.Count); + + #region Prim Inventory Loading + + // Instead of attempting to LoadItems on every prim, + // most of which probably have no items... get a + // list from DB of all prims which have items and + // LoadItems only on those + List primsWithInventory = new List(); + lock (m_dbLock) + { + using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) + { + dbcon.Open(); + + using (MySqlCommand itemCmd = dbcon.CreateCommand()) + { + itemCmd.CommandText = "SELECT DISTINCT primID FROM primitems"; + using (IDataReader itemReader = ExecuteReader(itemCmd)) + { + while (itemReader.Read()) + { + if (!(itemReader["primID"] is DBNull)) + { + UUID primID = DBGuid.FromDB(itemReader["primID"].ToString()); + if (prims.ContainsKey(primID)) + primsWithInventory.Add(prims[primID]); + } + } + } + } + } + } + + foreach (SceneObjectPart prim in primsWithInventory) + { + LoadItems(prim); + } + + #endregion Prim Inventory Loading + + m_log.DebugFormat("[REGION DB]: Loaded inventory from {0} objects", primsWithInventory.Count); + + return new List(objects.Values); + } + + /// + /// Load in a prim's persisted inventory. + /// + /// The prim + private void LoadItems(SceneObjectPart prim) + { + lock (m_dbLock) + { + List inventory = new List(); + + using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) + { + dbcon.Open(); + + using (MySqlCommand cmd = dbcon.CreateCommand()) + { + cmd.CommandText = "select * from primitems where PrimID = ?PrimID"; + cmd.Parameters.AddWithValue("PrimID", prim.UUID.ToString()); + + using (IDataReader reader = ExecuteReader(cmd)) + { + while (reader.Read()) + { + TaskInventoryItem item = BuildItem(reader); + + item.ParentID = prim.UUID; // Values in database are often wrong + inventory.Add(item); + } + } + } + } + + prim.Inventory.RestoreInventoryItems(inventory); + } + } + + public void StoreTerrain(double[,] ter, UUID regionID) + { + m_log.Info("[REGION DB]: Storing terrain"); + + lock (m_dbLock) + { + using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) + { + dbcon.Open(); + + using (MySqlCommand cmd = dbcon.CreateCommand()) + { + cmd.CommandText = "delete from terrain where RegionUUID = ?RegionUUID"; + cmd.Parameters.AddWithValue("RegionUUID", regionID.ToString()); + + ExecuteNonQuery(cmd); + + cmd.CommandText = "insert into terrain (RegionUUID, " + + "Revision, Heightfield) values (?RegionUUID, " + + "1, ?Heightfield)"; + + cmd.Parameters.AddWithValue("Heightfield", SerializeTerrain(ter)); + + ExecuteNonQuery(cmd); + } + } + } + } + + public double[,] LoadTerrain(UUID regionID) + { + double[,] terrain = null; + + lock (m_dbLock) + { + using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) + { + dbcon.Open(); + + using (MySqlCommand cmd = dbcon.CreateCommand()) + { + cmd.CommandText = "select RegionUUID, Revision, Heightfield " + + "from terrain where RegionUUID = ?RegionUUID " + + "order by Revision desc limit 1"; + cmd.Parameters.AddWithValue("RegionUUID", regionID.ToString()); + + using (IDataReader reader = ExecuteReader(cmd)) + { + while (reader.Read()) + { + int rev = Convert.ToInt32(reader["Revision"]); + + terrain = new double[(int)Constants.RegionSize, (int)Constants.RegionSize]; + terrain.Initialize(); + + using (MemoryStream mstr = new MemoryStream((byte[])reader["Heightfield"])) + { + using (BinaryReader br = new BinaryReader(mstr)) + { + for (int x = 0; x < (int)Constants.RegionSize; x++) + { + for (int y = 0; y < (int)Constants.RegionSize; y++) + { + terrain[x, y] = br.ReadDouble(); + } + } + } + + m_log.InfoFormat("[REGION DB]: Loaded terrain revision r{0}", rev); + } + } + } + } + } + } + + return terrain; + } + + public void RemoveLandObject(UUID globalID) + { + lock (m_dbLock) + { + using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) + { + dbcon.Open(); + + using (MySqlCommand cmd = dbcon.CreateCommand()) + { + cmd.CommandText = "delete from land where UUID = ?UUID"; + cmd.Parameters.AddWithValue("UUID", globalID.ToString()); + + ExecuteNonQuery(cmd); + } + } + } + } + + public void StoreLandObject(ILandObject parcel) + { + lock (m_dbLock) + { + using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) + { + dbcon.Open(); + + using (MySqlCommand cmd = dbcon.CreateCommand()) + { + cmd.CommandText = "replace into land (UUID, RegionUUID, " + + "LocalLandID, Bitmap, Name, Description, " + + "OwnerUUID, IsGroupOwned, Area, AuctionID, " + + "Category, ClaimDate, ClaimPrice, GroupUUID, " + + "SalePrice, LandStatus, LandFlags, LandingType, " + + "MediaAutoScale, MediaTextureUUID, MediaURL, " + + "MusicURL, PassHours, PassPrice, SnapshotUUID, " + + "UserLocationX, UserLocationY, UserLocationZ, " + + "UserLookAtX, UserLookAtY, UserLookAtZ, " + + "AuthbuyerID, OtherCleanTime, MediaType, MediaDescription, " + + "MediaSize, MediaLoop, ObscureMusic, ObscureMedia) values (" + + "?UUID, ?RegionUUID, " + + "?LocalLandID, ?Bitmap, ?Name, ?Description, " + + "?OwnerUUID, ?IsGroupOwned, ?Area, ?AuctionID, " + + "?Category, ?ClaimDate, ?ClaimPrice, ?GroupUUID, " + + "?SalePrice, ?LandStatus, ?LandFlags, ?LandingType, " + + "?MediaAutoScale, ?MediaTextureUUID, ?MediaURL, " + + "?MusicURL, ?PassHours, ?PassPrice, ?SnapshotUUID, " + + "?UserLocationX, ?UserLocationY, ?UserLocationZ, " + + "?UserLookAtX, ?UserLookAtY, ?UserLookAtZ, " + + "?AuthbuyerID, ?OtherCleanTime, ?MediaType, ?MediaDescription, "+ + "CONCAT(?MediaWidth, ',', ?MediaHeight), ?MediaLoop, ?ObscureMusic, ?ObscureMedia)"; + + FillLandCommand(cmd, parcel.LandData, parcel.RegionUUID); + + ExecuteNonQuery(cmd); + + cmd.CommandText = "delete from landaccesslist where LandUUID = ?UUID"; + + ExecuteNonQuery(cmd); + + cmd.Parameters.Clear(); + cmd.CommandText = "insert into landaccesslist (LandUUID, " + + "AccessUUID, Flags) values (?LandUUID, ?AccessUUID, " + + "?Flags)"; + + foreach (ParcelManager.ParcelAccessEntry entry in parcel.LandData.ParcelAccessList) + { + FillLandAccessCommand(cmd, entry, parcel.LandData.GlobalID); + ExecuteNonQuery(cmd); + cmd.Parameters.Clear(); + } + } + } + } + } + + public RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID) + { + RegionLightShareData nWP = new RegionLightShareData(); + nWP.OnSave += StoreRegionWindlightSettings; + + using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) + { + dbcon.Open(); + + string command = "select * from `regionwindlight` where region_id = ?regionID"; + + using(MySqlCommand cmd = new MySqlCommand(command)) + { + cmd.Connection = dbcon; + + cmd.Parameters.AddWithValue("?regionID", regionUUID.ToString()); + + IDataReader result = ExecuteReader(cmd); + if (!result.Read()) + { + //No result, so store our default windlight profile and return it + nWP.regionID = regionUUID; + StoreRegionWindlightSettings(nWP); + return nWP; + } + else + { + nWP.regionID = DBGuid.FromDB(result["region_id"]); + nWP.waterColor.X = Convert.ToSingle(result["water_color_r"]); + nWP.waterColor.Y = Convert.ToSingle(result["water_color_g"]); + nWP.waterColor.Z = Convert.ToSingle(result["water_color_b"]); + nWP.waterFogDensityExponent = Convert.ToSingle(result["water_fog_density_exponent"]); + nWP.underwaterFogModifier = Convert.ToSingle(result["underwater_fog_modifier"]); + nWP.reflectionWaveletScale.X = Convert.ToSingle(result["reflection_wavelet_scale_1"]); + nWP.reflectionWaveletScale.Y = Convert.ToSingle(result["reflection_wavelet_scale_2"]); + nWP.reflectionWaveletScale.Z = Convert.ToSingle(result["reflection_wavelet_scale_3"]); + nWP.fresnelScale = Convert.ToSingle(result["fresnel_scale"]); + nWP.fresnelOffset = Convert.ToSingle(result["fresnel_offset"]); + nWP.refractScaleAbove = Convert.ToSingle(result["refract_scale_above"]); + nWP.refractScaleBelow = Convert.ToSingle(result["refract_scale_below"]); + nWP.blurMultiplier = Convert.ToSingle(result["blur_multiplier"]); + nWP.bigWaveDirection.X = Convert.ToSingle(result["big_wave_direction_x"]); + nWP.bigWaveDirection.Y = Convert.ToSingle(result["big_wave_direction_y"]); + nWP.littleWaveDirection.X = Convert.ToSingle(result["little_wave_direction_x"]); + nWP.littleWaveDirection.Y = Convert.ToSingle(result["little_wave_direction_y"]); + UUID.TryParse(result["normal_map_texture"].ToString(), out nWP.normalMapTexture); + nWP.horizon.X = Convert.ToSingle(result["horizon_r"]); + nWP.horizon.Y = Convert.ToSingle(result["horizon_g"]); + nWP.horizon.Z = Convert.ToSingle(result["horizon_b"]); + nWP.horizon.W = Convert.ToSingle(result["horizon_i"]); + nWP.hazeHorizon = Convert.ToSingle(result["haze_horizon"]); + nWP.blueDensity.X = Convert.ToSingle(result["blue_density_r"]); + nWP.blueDensity.Y = Convert.ToSingle(result["blue_density_g"]); + nWP.blueDensity.Z = Convert.ToSingle(result["blue_density_b"]); + nWP.blueDensity.W = Convert.ToSingle(result["blue_density_i"]); + nWP.hazeDensity = Convert.ToSingle(result["haze_density"]); + nWP.densityMultiplier = Convert.ToSingle(result["density_multiplier"]); + nWP.distanceMultiplier = Convert.ToSingle(result["distance_multiplier"]); + nWP.maxAltitude = Convert.ToUInt16(result["max_altitude"]); + nWP.sunMoonColor.X = Convert.ToSingle(result["sun_moon_color_r"]); + nWP.sunMoonColor.Y = Convert.ToSingle(result["sun_moon_color_g"]); + nWP.sunMoonColor.Z = Convert.ToSingle(result["sun_moon_color_b"]); + nWP.sunMoonColor.W = Convert.ToSingle(result["sun_moon_color_i"]); + nWP.sunMoonPosition = Convert.ToSingle(result["sun_moon_position"]); + nWP.ambient.X = Convert.ToSingle(result["ambient_r"]); + nWP.ambient.Y = Convert.ToSingle(result["ambient_g"]); + nWP.ambient.Z = Convert.ToSingle(result["ambient_b"]); + nWP.ambient.W = Convert.ToSingle(result["ambient_i"]); + nWP.eastAngle = Convert.ToSingle(result["east_angle"]); + nWP.sunGlowFocus = Convert.ToSingle(result["sun_glow_focus"]); + nWP.sunGlowSize = Convert.ToSingle(result["sun_glow_size"]); + nWP.sceneGamma = Convert.ToSingle(result["scene_gamma"]); + nWP.starBrightness = Convert.ToSingle(result["star_brightness"]); + nWP.cloudColor.X = Convert.ToSingle(result["cloud_color_r"]); + nWP.cloudColor.Y = Convert.ToSingle(result["cloud_color_g"]); + nWP.cloudColor.Z = Convert.ToSingle(result["cloud_color_b"]); + nWP.cloudColor.W = Convert.ToSingle(result["cloud_color_i"]); + nWP.cloudXYDensity.X = Convert.ToSingle(result["cloud_x"]); + nWP.cloudXYDensity.Y = Convert.ToSingle(result["cloud_y"]); + nWP.cloudXYDensity.Z = Convert.ToSingle(result["cloud_density"]); + nWP.cloudCoverage = Convert.ToSingle(result["cloud_coverage"]); + nWP.cloudScale = Convert.ToSingle(result["cloud_scale"]); + nWP.cloudDetailXYDensity.X = Convert.ToSingle(result["cloud_detail_x"]); + nWP.cloudDetailXYDensity.Y = Convert.ToSingle(result["cloud_detail_y"]); + nWP.cloudDetailXYDensity.Z = Convert.ToSingle(result["cloud_detail_density"]); + nWP.cloudScrollX = Convert.ToSingle(result["cloud_scroll_x"]); + nWP.cloudScrollXLock = Convert.ToBoolean(result["cloud_scroll_x_lock"]); + nWP.cloudScrollY = Convert.ToSingle(result["cloud_scroll_y"]); + nWP.cloudScrollYLock = Convert.ToBoolean(result["cloud_scroll_y_lock"]); + nWP.drawClassicClouds = Convert.ToBoolean(result["draw_classic_clouds"]); + } + } + } + return nWP; + } + + public RegionSettings LoadRegionSettings(UUID regionUUID) + { + RegionSettings rs = null; + + lock (m_dbLock) + { + using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) + { + dbcon.Open(); + + using (MySqlCommand cmd = dbcon.CreateCommand()) + { + cmd.CommandText = "select * from regionsettings where regionUUID = ?RegionUUID"; + cmd.Parameters.AddWithValue("regionUUID", regionUUID); + + using (IDataReader reader = ExecuteReader(cmd)) + { + if (reader.Read()) + { + rs = BuildRegionSettings(reader); + rs.OnSave += StoreRegionSettings; + } + else + { + rs = new RegionSettings(); + rs.RegionUUID = regionUUID; + rs.OnSave += StoreRegionSettings; + + StoreRegionSettings(rs); + } + } + } + } + } + + return rs; + } + + public void StoreRegionWindlightSettings(RegionLightShareData wl) + { + using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) + { + dbcon.Open(); + + using (MySqlCommand cmd = dbcon.CreateCommand()) + { + cmd.CommandText = "REPLACE INTO `regionwindlight` (`region_id`, `water_color_r`, `water_color_g`, "; + cmd.CommandText += "`water_color_b`, `water_fog_density_exponent`, `underwater_fog_modifier`, "; + cmd.CommandText += "`reflection_wavelet_scale_1`, `reflection_wavelet_scale_2`, `reflection_wavelet_scale_3`, "; + cmd.CommandText += "`fresnel_scale`, `fresnel_offset`, `refract_scale_above`, `refract_scale_below`, "; + cmd.CommandText += "`blur_multiplier`, `big_wave_direction_x`, `big_wave_direction_y`, `little_wave_direction_x`, "; + cmd.CommandText += "`little_wave_direction_y`, `normal_map_texture`, `horizon_r`, `horizon_g`, `horizon_b`, "; + cmd.CommandText += "`horizon_i`, `haze_horizon`, `blue_density_r`, `blue_density_g`, `blue_density_b`, "; + cmd.CommandText += "`blue_density_i`, `haze_density`, `density_multiplier`, `distance_multiplier`, `max_altitude`, "; + cmd.CommandText += "`sun_moon_color_r`, `sun_moon_color_g`, `sun_moon_color_b`, `sun_moon_color_i`, `sun_moon_position`, "; + cmd.CommandText += "`ambient_r`, `ambient_g`, `ambient_b`, `ambient_i`, `east_angle`, `sun_glow_focus`, `sun_glow_size`, "; + cmd.CommandText += "`scene_gamma`, `star_brightness`, `cloud_color_r`, `cloud_color_g`, `cloud_color_b`, `cloud_color_i`, "; + cmd.CommandText += "`cloud_x`, `cloud_y`, `cloud_density`, `cloud_coverage`, `cloud_scale`, `cloud_detail_x`, "; + cmd.CommandText += "`cloud_detail_y`, `cloud_detail_density`, `cloud_scroll_x`, `cloud_scroll_x_lock`, `cloud_scroll_y`, "; + cmd.CommandText += "`cloud_scroll_y_lock`, `draw_classic_clouds`) VALUES (?region_id, ?water_color_r, "; + cmd.CommandText += "?water_color_g, ?water_color_b, ?water_fog_density_exponent, ?underwater_fog_modifier, ?reflection_wavelet_scale_1, "; + cmd.CommandText += "?reflection_wavelet_scale_2, ?reflection_wavelet_scale_3, ?fresnel_scale, ?fresnel_offset, ?refract_scale_above, "; + cmd.CommandText += "?refract_scale_below, ?blur_multiplier, ?big_wave_direction_x, ?big_wave_direction_y, ?little_wave_direction_x, "; + cmd.CommandText += "?little_wave_direction_y, ?normal_map_texture, ?horizon_r, ?horizon_g, ?horizon_b, ?horizon_i, ?haze_horizon, "; + cmd.CommandText += "?blue_density_r, ?blue_density_g, ?blue_density_b, ?blue_density_i, ?haze_density, ?density_multiplier, "; + cmd.CommandText += "?distance_multiplier, ?max_altitude, ?sun_moon_color_r, ?sun_moon_color_g, ?sun_moon_color_b, "; + cmd.CommandText += "?sun_moon_color_i, ?sun_moon_position, ?ambient_r, ?ambient_g, ?ambient_b, ?ambient_i, ?east_angle, "; + cmd.CommandText += "?sun_glow_focus, ?sun_glow_size, ?scene_gamma, ?star_brightness, ?cloud_color_r, ?cloud_color_g, "; + cmd.CommandText += "?cloud_color_b, ?cloud_color_i, ?cloud_x, ?cloud_y, ?cloud_density, ?cloud_coverage, ?cloud_scale, "; + cmd.CommandText += "?cloud_detail_x, ?cloud_detail_y, ?cloud_detail_density, ?cloud_scroll_x, ?cloud_scroll_x_lock, "; + cmd.CommandText += "?cloud_scroll_y, ?cloud_scroll_y_lock, ?draw_classic_clouds)"; + + cmd.Parameters.AddWithValue("region_id", wl.regionID); + cmd.Parameters.AddWithValue("water_color_r", wl.waterColor.X); + cmd.Parameters.AddWithValue("water_color_g", wl.waterColor.Y); + cmd.Parameters.AddWithValue("water_color_b", wl.waterColor.Z); + cmd.Parameters.AddWithValue("water_fog_density_exponent", wl.waterFogDensityExponent); + cmd.Parameters.AddWithValue("underwater_fog_modifier", wl.underwaterFogModifier); + cmd.Parameters.AddWithValue("reflection_wavelet_scale_1", wl.reflectionWaveletScale.X); + cmd.Parameters.AddWithValue("reflection_wavelet_scale_2", wl.reflectionWaveletScale.Y); + cmd.Parameters.AddWithValue("reflection_wavelet_scale_3", wl.reflectionWaveletScale.Z); + cmd.Parameters.AddWithValue("fresnel_scale", wl.fresnelScale); + cmd.Parameters.AddWithValue("fresnel_offset", wl.fresnelOffset); + cmd.Parameters.AddWithValue("refract_scale_above", wl.refractScaleAbove); + cmd.Parameters.AddWithValue("refract_scale_below", wl.refractScaleBelow); + cmd.Parameters.AddWithValue("blur_multiplier", wl.blurMultiplier); + cmd.Parameters.AddWithValue("big_wave_direction_x", wl.bigWaveDirection.X); + cmd.Parameters.AddWithValue("big_wave_direction_y", wl.bigWaveDirection.Y); + cmd.Parameters.AddWithValue("little_wave_direction_x", wl.littleWaveDirection.X); + cmd.Parameters.AddWithValue("little_wave_direction_y", wl.littleWaveDirection.Y); + cmd.Parameters.AddWithValue("normal_map_texture", wl.normalMapTexture); + cmd.Parameters.AddWithValue("horizon_r", wl.horizon.X); + cmd.Parameters.AddWithValue("horizon_g", wl.horizon.Y); + cmd.Parameters.AddWithValue("horizon_b", wl.horizon.Z); + cmd.Parameters.AddWithValue("horizon_i", wl.horizon.W); + cmd.Parameters.AddWithValue("haze_horizon", wl.hazeHorizon); + cmd.Parameters.AddWithValue("blue_density_r", wl.blueDensity.X); + cmd.Parameters.AddWithValue("blue_density_g", wl.blueDensity.Y); + cmd.Parameters.AddWithValue("blue_density_b", wl.blueDensity.Z); + cmd.Parameters.AddWithValue("blue_density_i", wl.blueDensity.W); + cmd.Parameters.AddWithValue("haze_density", wl.hazeDensity); + cmd.Parameters.AddWithValue("density_multiplier", wl.densityMultiplier); + cmd.Parameters.AddWithValue("distance_multiplier", wl.distanceMultiplier); + cmd.Parameters.AddWithValue("max_altitude", wl.maxAltitude); + cmd.Parameters.AddWithValue("sun_moon_color_r", wl.sunMoonColor.X); + cmd.Parameters.AddWithValue("sun_moon_color_g", wl.sunMoonColor.Y); + cmd.Parameters.AddWithValue("sun_moon_color_b", wl.sunMoonColor.Z); + cmd.Parameters.AddWithValue("sun_moon_color_i", wl.sunMoonColor.W); + cmd.Parameters.AddWithValue("sun_moon_position", wl.sunMoonPosition); + cmd.Parameters.AddWithValue("ambient_r", wl.ambient.X); + cmd.Parameters.AddWithValue("ambient_g", wl.ambient.Y); + cmd.Parameters.AddWithValue("ambient_b", wl.ambient.Z); + cmd.Parameters.AddWithValue("ambient_i", wl.ambient.W); + cmd.Parameters.AddWithValue("east_angle", wl.eastAngle); + cmd.Parameters.AddWithValue("sun_glow_focus", wl.sunGlowFocus); + cmd.Parameters.AddWithValue("sun_glow_size", wl.sunGlowSize); + cmd.Parameters.AddWithValue("scene_gamma", wl.sceneGamma); + cmd.Parameters.AddWithValue("star_brightness", wl.starBrightness); + cmd.Parameters.AddWithValue("cloud_color_r", wl.cloudColor.X); + cmd.Parameters.AddWithValue("cloud_color_g", wl.cloudColor.Y); + cmd.Parameters.AddWithValue("cloud_color_b", wl.cloudColor.Z); + cmd.Parameters.AddWithValue("cloud_color_i", wl.cloudColor.W); + cmd.Parameters.AddWithValue("cloud_x", wl.cloudXYDensity.X); + cmd.Parameters.AddWithValue("cloud_y", wl.cloudXYDensity.Y); + cmd.Parameters.AddWithValue("cloud_density", wl.cloudXYDensity.Z); + cmd.Parameters.AddWithValue("cloud_coverage", wl.cloudCoverage); + cmd.Parameters.AddWithValue("cloud_scale", wl.cloudScale); + cmd.Parameters.AddWithValue("cloud_detail_x", wl.cloudDetailXYDensity.X); + cmd.Parameters.AddWithValue("cloud_detail_y", wl.cloudDetailXYDensity.Y); + cmd.Parameters.AddWithValue("cloud_detail_density", wl.cloudDetailXYDensity.Z); + cmd.Parameters.AddWithValue("cloud_scroll_x", wl.cloudScrollX); + cmd.Parameters.AddWithValue("cloud_scroll_x_lock", wl.cloudScrollXLock); + cmd.Parameters.AddWithValue("cloud_scroll_y", wl.cloudScrollY); + cmd.Parameters.AddWithValue("cloud_scroll_y_lock", wl.cloudScrollYLock); + cmd.Parameters.AddWithValue("draw_classic_clouds", wl.drawClassicClouds); + + ExecuteNonQuery(cmd); + } + } + } + + public void StoreRegionSettings(RegionSettings rs) + { + lock (m_dbLock) + { + using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) + { + dbcon.Open(); + + using (MySqlCommand cmd = dbcon.CreateCommand()) + { + cmd.CommandText = "replace into regionsettings (regionUUID, " + + "block_terraform, block_fly, allow_damage, " + + "restrict_pushing, allow_land_resell, " + + "allow_land_join_divide, block_show_in_search, " + + "agent_limit, object_bonus, maturity, " + + "disable_scripts, disable_collisions, " + + "disable_physics, terrain_texture_1, " + + "terrain_texture_2, terrain_texture_3, " + + "terrain_texture_4, elevation_1_nw, " + + "elevation_2_nw, elevation_1_ne, " + + "elevation_2_ne, elevation_1_se, " + + "elevation_2_se, elevation_1_sw, " + + "elevation_2_sw, water_height, " + + "terrain_raise_limit, terrain_lower_limit, " + + "use_estate_sun, fixed_sun, sun_position, " + + "covenant, Sandbox, sunvectorx, sunvectory, " + + "sunvectorz, loaded_creation_datetime, " + + "loaded_creation_id, map_tile_ID) values (?RegionUUID, ?BlockTerraform, " + + "?BlockFly, ?AllowDamage, ?RestrictPushing, " + + "?AllowLandResell, ?AllowLandJoinDivide, " + + "?BlockShowInSearch, ?AgentLimit, ?ObjectBonus, " + + "?Maturity, ?DisableScripts, ?DisableCollisions, " + + "?DisablePhysics, ?TerrainTexture1, " + + "?TerrainTexture2, ?TerrainTexture3, " + + "?TerrainTexture4, ?Elevation1NW, ?Elevation2NW, " + + "?Elevation1NE, ?Elevation2NE, ?Elevation1SE, " + + "?Elevation2SE, ?Elevation1SW, ?Elevation2SW, " + + "?WaterHeight, ?TerrainRaiseLimit, " + + "?TerrainLowerLimit, ?UseEstateSun, ?FixedSun, " + + "?SunPosition, ?Covenant, ?Sandbox, " + + "?SunVectorX, ?SunVectorY, ?SunVectorZ, " + + "?LoadedCreationDateTime, ?LoadedCreationID, " + + "?TerrainImageID)"; + + FillRegionSettingsCommand(cmd, rs); + + ExecuteNonQuery(cmd); + } + } + } + } + + public List LoadLandObjects(UUID regionUUID) + { + List landData = new List(); + + lock (m_dbLock) + { + using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) + { + dbcon.Open(); + + using (MySqlCommand cmd = dbcon.CreateCommand()) + { + cmd.CommandText = "select * from land where RegionUUID = ?RegionUUID"; + cmd.Parameters.AddWithValue("RegionUUID", regionUUID.ToString()); + + using (IDataReader reader = ExecuteReader(cmd)) + { + while (reader.Read()) + { + LandData newLand = BuildLandData(reader); + landData.Add(newLand); + } + } + } + + using (MySqlCommand cmd = dbcon.CreateCommand()) + { + foreach (LandData land in landData) + { + cmd.Parameters.Clear(); + cmd.CommandText = "select * from landaccesslist where LandUUID = ?LandUUID"; + cmd.Parameters.AddWithValue("LandUUID", land.GlobalID.ToString()); + + using (IDataReader reader = ExecuteReader(cmd)) + { + while (reader.Read()) + { + land.ParcelAccessList.Add(BuildLandAccessData(reader)); + } + } + } + } + } + } + + return landData; + } + + public void Shutdown() + { + } + + private SceneObjectPart BuildPrim(IDataReader row) + { + SceneObjectPart prim = new SceneObjectPart(); + + // depending on the MySQL connector version, CHAR(36) may be already converted to Guid! + prim.UUID = DBGuid.FromDB(row["UUID"]); + prim.CreatorID = DBGuid.FromDB(row["CreatorID"]); + prim.OwnerID = DBGuid.FromDB(row["OwnerID"]); + prim.GroupID = DBGuid.FromDB(row["GroupID"]); + prim.LastOwnerID = DBGuid.FromDB(row["LastOwnerID"]); + + // explicit conversion of integers is required, which sort + // of sucks. No idea if there is a shortcut here or not. + prim.CreationDate = (int)row["CreationDate"]; + if (row["Name"] != DBNull.Value) + prim.Name = (string)row["Name"]; + else + prim.Name = String.Empty; + // Various text fields + prim.Text = (string)row["Text"]; + prim.Color = Color.FromArgb((int)row["ColorA"], + (int)row["ColorR"], + (int)row["ColorG"], + (int)row["ColorB"]); + prim.Description = (string)row["Description"]; + prim.SitName = (string)row["SitName"]; + prim.TouchName = (string)row["TouchName"]; + // Permissions + prim.Flags = (PrimFlags)(int)row["ObjectFlags"]; + prim.OwnerMask = (uint)(int)row["OwnerMask"]; + prim.NextOwnerMask = (uint)(int)row["NextOwnerMask"]; + prim.GroupMask = (uint)(int)row["GroupMask"]; + prim.EveryoneMask = (uint)(int)row["EveryoneMask"]; + prim.BaseMask = (uint)(int)row["BaseMask"]; + + // Vectors + prim.OffsetPosition = new Vector3( + (float)(double)row["PositionX"], + (float)(double)row["PositionY"], + (float)(double)row["PositionZ"] + ); + prim.GroupPosition = new Vector3( + (float)(double)row["GroupPositionX"], + (float)(double)row["GroupPositionY"], + (float)(double)row["GroupPositionZ"] + ); + prim.Velocity = new Vector3( + (float)(double)row["VelocityX"], + (float)(double)row["VelocityY"], + (float)(double)row["VelocityZ"] + ); + prim.AngularVelocity = new Vector3( + (float)(double)row["AngularVelocityX"], + (float)(double)row["AngularVelocityY"], + (float)(double)row["AngularVelocityZ"] + ); + prim.Acceleration = new Vector3( + (float)(double)row["AccelerationX"], + (float)(double)row["AccelerationY"], + (float)(double)row["AccelerationZ"] + ); + // quaternions + prim.RotationOffset = new Quaternion( + (float)(double)row["RotationX"], + (float)(double)row["RotationY"], + (float)(double)row["RotationZ"], + (float)(double)row["RotationW"] + ); + prim.SitTargetPositionLL = new Vector3( + (float)(double)row["SitTargetOffsetX"], + (float)(double)row["SitTargetOffsetY"], + (float)(double)row["SitTargetOffsetZ"] + ); + prim.SitTargetOrientationLL = new Quaternion( + (float)(double)row["SitTargetOrientX"], + (float)(double)row["SitTargetOrientY"], + (float)(double)row["SitTargetOrientZ"], + (float)(double)row["SitTargetOrientW"] + ); + + prim.PayPrice[0] = (int)row["PayPrice"]; + prim.PayPrice[1] = (int)row["PayButton1"]; + prim.PayPrice[2] = (int)row["PayButton2"]; + prim.PayPrice[3] = (int)row["PayButton3"]; + prim.PayPrice[4] = (int)row["PayButton4"]; + + prim.Sound = DBGuid.FromDB(row["LoopedSound"].ToString()); + prim.SoundGain = (float)(double)row["LoopedSoundGain"]; + prim.SoundFlags = 1; // If it's persisted at all, it's looped + + if (!(row["TextureAnimation"] is DBNull)) + prim.TextureAnimation = (byte[])row["TextureAnimation"]; + if (!(row["ParticleSystem"] is DBNull)) + prim.ParticleSystem = (byte[])row["ParticleSystem"]; + + prim.AngularVelocity = new Vector3( + (float)(double)row["OmegaX"], + (float)(double)row["OmegaY"], + (float)(double)row["OmegaZ"] + ); + + prim.SetCameraEyeOffset(new Vector3( + (float)(double)row["CameraEyeOffsetX"], + (float)(double)row["CameraEyeOffsetY"], + (float)(double)row["CameraEyeOffsetZ"] + )); + + prim.SetCameraAtOffset(new Vector3( + (float)(double)row["CameraAtOffsetX"], + (float)(double)row["CameraAtOffsetY"], + (float)(double)row["CameraAtOffsetZ"] + )); + + prim.SetForceMouselook((sbyte)row["ForceMouselook"] != 0); + prim.ScriptAccessPin = (int)row["ScriptAccessPin"]; + prim.AllowedDrop = ((sbyte)row["AllowedDrop"] != 0); + prim.DIE_AT_EDGE = ((sbyte)row["DieAtEdge"] != 0); + + prim.SalePrice = (int)row["SalePrice"]; + prim.ObjectSaleType = unchecked((byte)(sbyte)row["SaleType"]); + + prim.Material = unchecked((byte)(sbyte)row["Material"]); + + if (!(row["ClickAction"] is DBNull)) + prim.ClickAction = unchecked((byte)(sbyte)row["ClickAction"]); + + prim.CollisionSound = DBGuid.FromDB(row["CollisionSound"]); + prim.CollisionSoundVolume = (float)(double)row["CollisionSoundVolume"]; + + prim.PassTouches = ((sbyte)row["PassTouches"] != 0); + prim.LinkNum = (int)row["LinkNumber"]; + + if (!(row["MediaURL"] is System.DBNull)) + prim.MediaUrl = (string)row["MediaURL"]; + + return prim; + } + + + /// + /// Build a prim inventory item from the persisted data. + /// + /// + /// + private static TaskInventoryItem BuildItem(IDataReader row) + { + TaskInventoryItem taskItem = new TaskInventoryItem(); + + taskItem.ItemID = DBGuid.FromDB(row["itemID"]); + taskItem.ParentPartID = DBGuid.FromDB(row["primID"]); + taskItem.AssetID = DBGuid.FromDB(row["assetID"]); + taskItem.ParentID = DBGuid.FromDB(row["parentFolderID"]); + + taskItem.InvType = Convert.ToInt32(row["invType"]); + taskItem.Type = Convert.ToInt32(row["assetType"]); + + taskItem.Name = (String)row["name"]; + taskItem.Description = (String)row["description"]; + taskItem.CreationDate = Convert.ToUInt32(row["creationDate"]); + taskItem.CreatorID = DBGuid.FromDB(row["creatorID"]); + taskItem.OwnerID = DBGuid.FromDB(row["ownerID"]); + taskItem.LastOwnerID = DBGuid.FromDB(row["lastOwnerID"]); + taskItem.GroupID = DBGuid.FromDB(row["groupID"]); + + taskItem.NextPermissions = Convert.ToUInt32(row["nextPermissions"]); + taskItem.CurrentPermissions = Convert.ToUInt32(row["currentPermissions"]); + taskItem.BasePermissions = Convert.ToUInt32(row["basePermissions"]); + taskItem.EveryonePermissions = Convert.ToUInt32(row["everyonePermissions"]); + taskItem.GroupPermissions = Convert.ToUInt32(row["groupPermissions"]); + taskItem.Flags = Convert.ToUInt32(row["flags"]); + + return taskItem; + } + + private static RegionSettings BuildRegionSettings(IDataReader row) + { + RegionSettings newSettings = new RegionSettings(); + + newSettings.RegionUUID = DBGuid.FromDB(row["regionUUID"]); + newSettings.BlockTerraform = Convert.ToBoolean(row["block_terraform"]); + newSettings.AllowDamage = Convert.ToBoolean(row["allow_damage"]); + newSettings.BlockFly = Convert.ToBoolean(row["block_fly"]); + newSettings.RestrictPushing = Convert.ToBoolean(row["restrict_pushing"]); + newSettings.AllowLandResell = Convert.ToBoolean(row["allow_land_resell"]); + newSettings.AllowLandJoinDivide = Convert.ToBoolean(row["allow_land_join_divide"]); + newSettings.BlockShowInSearch = Convert.ToBoolean(row["block_show_in_search"]); + newSettings.AgentLimit = Convert.ToInt32(row["agent_limit"]); + newSettings.ObjectBonus = Convert.ToDouble(row["object_bonus"]); + newSettings.Maturity = Convert.ToInt32(row["maturity"]); + newSettings.DisableScripts = Convert.ToBoolean(row["disable_scripts"]); + newSettings.DisableCollisions = Convert.ToBoolean(row["disable_collisions"]); + newSettings.DisablePhysics = Convert.ToBoolean(row["disable_physics"]); + newSettings.TerrainTexture1 = DBGuid.FromDB(row["terrain_texture_1"]); + newSettings.TerrainTexture2 = DBGuid.FromDB(row["terrain_texture_2"]); + newSettings.TerrainTexture3 = DBGuid.FromDB(row["terrain_texture_3"]); + newSettings.TerrainTexture4 = DBGuid.FromDB(row["terrain_texture_4"]); + newSettings.Elevation1NW = Convert.ToDouble(row["elevation_1_nw"]); + newSettings.Elevation2NW = Convert.ToDouble(row["elevation_2_nw"]); + newSettings.Elevation1NE = Convert.ToDouble(row["elevation_1_ne"]); + newSettings.Elevation2NE = Convert.ToDouble(row["elevation_2_ne"]); + newSettings.Elevation1SE = Convert.ToDouble(row["elevation_1_se"]); + newSettings.Elevation2SE = Convert.ToDouble(row["elevation_2_se"]); + newSettings.Elevation1SW = Convert.ToDouble(row["elevation_1_sw"]); + newSettings.Elevation2SW = Convert.ToDouble(row["elevation_2_sw"]); + newSettings.WaterHeight = Convert.ToDouble(row["water_height"]); + newSettings.TerrainRaiseLimit = Convert.ToDouble(row["terrain_raise_limit"]); + newSettings.TerrainLowerLimit = Convert.ToDouble(row["terrain_lower_limit"]); + newSettings.UseEstateSun = Convert.ToBoolean(row["use_estate_sun"]); + newSettings.Sandbox = Convert.ToBoolean(row["sandbox"]); + newSettings.SunVector = new Vector3 ( + Convert.ToSingle(row["sunvectorx"]), + Convert.ToSingle(row["sunvectory"]), + Convert.ToSingle(row["sunvectorz"]) + ); + newSettings.FixedSun = Convert.ToBoolean(row["fixed_sun"]); + newSettings.SunPosition = Convert.ToDouble(row["sun_position"]); + newSettings.Covenant = DBGuid.FromDB(row["covenant"]); + + newSettings.LoadedCreationDateTime = Convert.ToInt32(row["loaded_creation_datetime"]); + + if (row["loaded_creation_id"] is DBNull) + newSettings.LoadedCreationID = ""; + else + newSettings.LoadedCreationID = (String) row["loaded_creation_id"]; + + newSettings.TerrainImageID = DBGuid.FromDB(row["map_tile_ID"]); + + return newSettings; + } + + /// + /// + /// + /// + /// + private static LandData BuildLandData(IDataReader row) + { + LandData newData = new LandData(); + + newData.GlobalID = DBGuid.FromDB(row["UUID"]); + newData.LocalID = Convert.ToInt32(row["LocalLandID"]); + + // Bitmap is a byte[512] + newData.Bitmap = (Byte[]) row["Bitmap"]; + + newData.Name = (String) row["Name"]; + newData.Description = (String) row["Description"]; + newData.OwnerID = DBGuid.FromDB(row["OwnerUUID"]); + newData.IsGroupOwned = Convert.ToBoolean(row["IsGroupOwned"]); + newData.Area = Convert.ToInt32(row["Area"]); + newData.AuctionID = Convert.ToUInt32(row["AuctionID"]); //Unimplemented + newData.Category = (ParcelCategory) Convert.ToInt32(row["Category"]); + //Enum libsecondlife.Parcel.ParcelCategory + newData.ClaimDate = Convert.ToInt32(row["ClaimDate"]); + newData.ClaimPrice = Convert.ToInt32(row["ClaimPrice"]); + newData.GroupID = DBGuid.FromDB(row["GroupUUID"]); + newData.SalePrice = Convert.ToInt32(row["SalePrice"]); + newData.Status = (ParcelStatus) Convert.ToInt32(row["LandStatus"]); + //Enum. libsecondlife.Parcel.ParcelStatus + newData.Flags = Convert.ToUInt32(row["LandFlags"]); + newData.LandingType = Convert.ToByte(row["LandingType"]); + newData.MediaAutoScale = Convert.ToByte(row["MediaAutoScale"]); + newData.MediaID = DBGuid.FromDB(row["MediaTextureUUID"]); + newData.MediaURL = (String) row["MediaURL"]; + newData.MusicURL = (String) row["MusicURL"]; + newData.PassHours = Convert.ToSingle(row["PassHours"]); + newData.PassPrice = Convert.ToInt32(row["PassPrice"]); + UUID authedbuyer = UUID.Zero; + UUID snapshotID = UUID.Zero; + + UUID.TryParse((string)row["AuthBuyerID"], out authedbuyer); + UUID.TryParse((string)row["SnapshotUUID"], out snapshotID); + newData.OtherCleanTime = Convert.ToInt32(row["OtherCleanTime"]); + + newData.AuthBuyerID = authedbuyer; + newData.SnapshotID = snapshotID; + try + { + newData.UserLocation = + new Vector3(Convert.ToSingle(row["UserLocationX"]), Convert.ToSingle(row["UserLocationY"]), + Convert.ToSingle(row["UserLocationZ"])); + newData.UserLookAt = + new Vector3(Convert.ToSingle(row["UserLookAtX"]), Convert.ToSingle(row["UserLookAtY"]), + Convert.ToSingle(row["UserLookAtZ"])); + } + catch (InvalidCastException) + { + newData.UserLocation = Vector3.Zero; + newData.UserLookAt = Vector3.Zero; + m_log.ErrorFormat("[PARCEL]: unable to get parcel telehub settings for {1}", newData.Name); + } + + newData.MediaDescription = (string) row["MediaDescription"]; + newData.MediaType = (string) row["MediaType"]; + newData.MediaWidth = Convert.ToInt32((((string) row["MediaSize"]).Split(','))[0]); + newData.MediaHeight = Convert.ToInt32((((string) row["MediaSize"]).Split(','))[1]); + newData.MediaLoop = Convert.ToBoolean(row["MediaLoop"]); + newData.ObscureMusic = Convert.ToBoolean(row["ObscureMusic"]); + newData.ObscureMedia = Convert.ToBoolean(row["ObscureMedia"]); + + newData.ParcelAccessList = new List(); + + return newData; + } + + /// + /// + /// + /// + /// + private static ParcelManager.ParcelAccessEntry BuildLandAccessData(IDataReader row) + { + ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); + entry.AgentID = DBGuid.FromDB(row["AccessUUID"]); + entry.Flags = (AccessList) Convert.ToInt32(row["Flags"]); + entry.Time = new DateTime(); + return entry; + } + + /// + /// + /// + /// + /// + private static Array SerializeTerrain(double[,] val) + { + MemoryStream str = new MemoryStream(((int)Constants.RegionSize * (int)Constants.RegionSize) *sizeof (double)); + BinaryWriter bw = new BinaryWriter(str); + + // TODO: COMPATIBILITY - Add byte-order conversions + for (int x = 0; x < (int)Constants.RegionSize; x++) + for (int y = 0; y < (int)Constants.RegionSize; y++) + { + double height = val[x, y]; + if (height == 0.0) + height = double.Epsilon; + + bw.Write(height); + } + + return str.ToArray(); + } + + /// + /// Fill the prim command with prim values + /// + /// + /// + /// + /// + private void FillPrimCommand(MySqlCommand cmd, SceneObjectPart prim, UUID sceneGroupID, UUID regionUUID) + { + cmd.Parameters.AddWithValue("UUID", prim.UUID.ToString()); + cmd.Parameters.AddWithValue("RegionUUID", regionUUID.ToString()); + cmd.Parameters.AddWithValue("CreationDate", prim.CreationDate); + cmd.Parameters.AddWithValue("Name", prim.Name); + cmd.Parameters.AddWithValue("SceneGroupID", sceneGroupID.ToString()); + // the UUID of the root part for this SceneObjectGroup + // various text fields + cmd.Parameters.AddWithValue("Text", prim.Text); + cmd.Parameters.AddWithValue("ColorR", prim.Color.R); + cmd.Parameters.AddWithValue("ColorG", prim.Color.G); + cmd.Parameters.AddWithValue("ColorB", prim.Color.B); + cmd.Parameters.AddWithValue("ColorA", prim.Color.A); + cmd.Parameters.AddWithValue("Description", prim.Description); + cmd.Parameters.AddWithValue("SitName", prim.SitName); + cmd.Parameters.AddWithValue("TouchName", prim.TouchName); + // permissions + cmd.Parameters.AddWithValue("ObjectFlags", (uint)prim.Flags); + cmd.Parameters.AddWithValue("CreatorID", prim.CreatorID.ToString()); + cmd.Parameters.AddWithValue("OwnerID", prim.OwnerID.ToString()); + cmd.Parameters.AddWithValue("GroupID", prim.GroupID.ToString()); + cmd.Parameters.AddWithValue("LastOwnerID", prim.LastOwnerID.ToString()); + cmd.Parameters.AddWithValue("OwnerMask", prim.OwnerMask); + cmd.Parameters.AddWithValue("NextOwnerMask", prim.NextOwnerMask); + cmd.Parameters.AddWithValue("GroupMask", prim.GroupMask); + cmd.Parameters.AddWithValue("EveryoneMask", prim.EveryoneMask); + cmd.Parameters.AddWithValue("BaseMask", prim.BaseMask); + // vectors + cmd.Parameters.AddWithValue("PositionX", (double)prim.OffsetPosition.X); + cmd.Parameters.AddWithValue("PositionY", (double)prim.OffsetPosition.Y); + cmd.Parameters.AddWithValue("PositionZ", (double)prim.OffsetPosition.Z); + cmd.Parameters.AddWithValue("GroupPositionX", (double)prim.GroupPosition.X); + cmd.Parameters.AddWithValue("GroupPositionY", (double)prim.GroupPosition.Y); + cmd.Parameters.AddWithValue("GroupPositionZ", (double)prim.GroupPosition.Z); + cmd.Parameters.AddWithValue("VelocityX", (double)prim.Velocity.X); + cmd.Parameters.AddWithValue("VelocityY", (double)prim.Velocity.Y); + cmd.Parameters.AddWithValue("VelocityZ", (double)prim.Velocity.Z); + cmd.Parameters.AddWithValue("AngularVelocityX", (double)prim.AngularVelocity.X); + cmd.Parameters.AddWithValue("AngularVelocityY", (double)prim.AngularVelocity.Y); + cmd.Parameters.AddWithValue("AngularVelocityZ", (double)prim.AngularVelocity.Z); + cmd.Parameters.AddWithValue("AccelerationX", (double)prim.Acceleration.X); + cmd.Parameters.AddWithValue("AccelerationY", (double)prim.Acceleration.Y); + cmd.Parameters.AddWithValue("AccelerationZ", (double)prim.Acceleration.Z); + // quaternions + cmd.Parameters.AddWithValue("RotationX", (double)prim.RotationOffset.X); + cmd.Parameters.AddWithValue("RotationY", (double)prim.RotationOffset.Y); + cmd.Parameters.AddWithValue("RotationZ", (double)prim.RotationOffset.Z); + cmd.Parameters.AddWithValue("RotationW", (double)prim.RotationOffset.W); + + // Sit target + Vector3 sitTargetPos = prim.SitTargetPositionLL; + cmd.Parameters.AddWithValue("SitTargetOffsetX", (double)sitTargetPos.X); + cmd.Parameters.AddWithValue("SitTargetOffsetY", (double)sitTargetPos.Y); + cmd.Parameters.AddWithValue("SitTargetOffsetZ", (double)sitTargetPos.Z); + + Quaternion sitTargetOrient = prim.SitTargetOrientationLL; + cmd.Parameters.AddWithValue("SitTargetOrientW", (double)sitTargetOrient.W); + cmd.Parameters.AddWithValue("SitTargetOrientX", (double)sitTargetOrient.X); + cmd.Parameters.AddWithValue("SitTargetOrientY", (double)sitTargetOrient.Y); + cmd.Parameters.AddWithValue("SitTargetOrientZ", (double)sitTargetOrient.Z); + + cmd.Parameters.AddWithValue("PayPrice", prim.PayPrice[0]); + cmd.Parameters.AddWithValue("PayButton1", prim.PayPrice[1]); + cmd.Parameters.AddWithValue("PayButton2", prim.PayPrice[2]); + cmd.Parameters.AddWithValue("PayButton3", prim.PayPrice[3]); + cmd.Parameters.AddWithValue("PayButton4", prim.PayPrice[4]); + + if ((prim.SoundFlags & 1) != 0) // Looped + { + cmd.Parameters.AddWithValue("LoopedSound", prim.Sound.ToString()); + cmd.Parameters.AddWithValue("LoopedSoundGain", prim.SoundGain); + } + else + { + cmd.Parameters.AddWithValue("LoopedSound", UUID.Zero); + cmd.Parameters.AddWithValue("LoopedSoundGain", 0.0f); + } + + cmd.Parameters.AddWithValue("TextureAnimation", prim.TextureAnimation); + cmd.Parameters.AddWithValue("ParticleSystem", prim.ParticleSystem); + + cmd.Parameters.AddWithValue("OmegaX", (double)prim.AngularVelocity.X); + cmd.Parameters.AddWithValue("OmegaY", (double)prim.AngularVelocity.Y); + cmd.Parameters.AddWithValue("OmegaZ", (double)prim.AngularVelocity.Z); + + cmd.Parameters.AddWithValue("CameraEyeOffsetX", (double)prim.GetCameraEyeOffset().X); + cmd.Parameters.AddWithValue("CameraEyeOffsetY", (double)prim.GetCameraEyeOffset().Y); + cmd.Parameters.AddWithValue("CameraEyeOffsetZ", (double)prim.GetCameraEyeOffset().Z); + + cmd.Parameters.AddWithValue("CameraAtOffsetX", (double)prim.GetCameraAtOffset().X); + cmd.Parameters.AddWithValue("CameraAtOffsetY", (double)prim.GetCameraAtOffset().Y); + cmd.Parameters.AddWithValue("CameraAtOffsetZ", (double)prim.GetCameraAtOffset().Z); + + if (prim.GetForceMouselook()) + cmd.Parameters.AddWithValue("ForceMouselook", 1); + else + cmd.Parameters.AddWithValue("ForceMouselook", 0); + + cmd.Parameters.AddWithValue("ScriptAccessPin", prim.ScriptAccessPin); + + if (prim.AllowedDrop) + cmd.Parameters.AddWithValue("AllowedDrop", 1); + else + cmd.Parameters.AddWithValue("AllowedDrop", 0); + + if (prim.DIE_AT_EDGE) + cmd.Parameters.AddWithValue("DieAtEdge", 1); + else + cmd.Parameters.AddWithValue("DieAtEdge", 0); + + cmd.Parameters.AddWithValue("SalePrice", prim.SalePrice); + cmd.Parameters.AddWithValue("SaleType", unchecked((sbyte)(prim.ObjectSaleType))); + + byte clickAction = prim.ClickAction; + cmd.Parameters.AddWithValue("ClickAction", unchecked((sbyte)(clickAction))); + + cmd.Parameters.AddWithValue("Material", unchecked((sbyte)(prim.Material))); + + cmd.Parameters.AddWithValue("CollisionSound", prim.CollisionSound.ToString()); + cmd.Parameters.AddWithValue("CollisionSoundVolume", prim.CollisionSoundVolume); + + if (prim.PassTouches) + cmd.Parameters.AddWithValue("PassTouches", 1); + else + cmd.Parameters.AddWithValue("PassTouches", 0); + + cmd.Parameters.AddWithValue("LinkNumber", prim.LinkNum); + cmd.Parameters.AddWithValue("MediaURL", prim.MediaUrl); + } + + /// + /// + /// + /// + /// + private static void FillItemCommand(MySqlCommand cmd, TaskInventoryItem taskItem) + { + cmd.Parameters.AddWithValue("itemID", taskItem.ItemID); + cmd.Parameters.AddWithValue("primID", taskItem.ParentPartID); + cmd.Parameters.AddWithValue("assetID", taskItem.AssetID); + cmd.Parameters.AddWithValue("parentFolderID", taskItem.ParentID); + + cmd.Parameters.AddWithValue("invType", taskItem.InvType); + cmd.Parameters.AddWithValue("assetType", taskItem.Type); + + cmd.Parameters.AddWithValue("name", taskItem.Name); + cmd.Parameters.AddWithValue("description", taskItem.Description); + cmd.Parameters.AddWithValue("creationDate", taskItem.CreationDate); + cmd.Parameters.AddWithValue("creatorID", taskItem.CreatorID); + cmd.Parameters.AddWithValue("ownerID", taskItem.OwnerID); + cmd.Parameters.AddWithValue("lastOwnerID", taskItem.LastOwnerID); + cmd.Parameters.AddWithValue("groupID", taskItem.GroupID); + cmd.Parameters.AddWithValue("nextPermissions", taskItem.NextPermissions); + cmd.Parameters.AddWithValue("currentPermissions", taskItem.CurrentPermissions); + cmd.Parameters.AddWithValue("basePermissions", taskItem.BasePermissions); + cmd.Parameters.AddWithValue("everyonePermissions", taskItem.EveryonePermissions); + cmd.Parameters.AddWithValue("groupPermissions", taskItem.GroupPermissions); + cmd.Parameters.AddWithValue("flags", taskItem.Flags); + } + + /// + /// + /// + private static void FillRegionSettingsCommand(MySqlCommand cmd, RegionSettings settings) + { + cmd.Parameters.AddWithValue("RegionUUID", settings.RegionUUID.ToString()); + cmd.Parameters.AddWithValue("BlockTerraform", settings.BlockTerraform); + cmd.Parameters.AddWithValue("BlockFly", settings.BlockFly); + cmd.Parameters.AddWithValue("AllowDamage", settings.AllowDamage); + cmd.Parameters.AddWithValue("RestrictPushing", settings.RestrictPushing); + cmd.Parameters.AddWithValue("AllowLandResell", settings.AllowLandResell); + cmd.Parameters.AddWithValue("AllowLandJoinDivide", settings.AllowLandJoinDivide); + cmd.Parameters.AddWithValue("BlockShowInSearch", settings.BlockShowInSearch); + cmd.Parameters.AddWithValue("AgentLimit", settings.AgentLimit); + cmd.Parameters.AddWithValue("ObjectBonus", settings.ObjectBonus); + cmd.Parameters.AddWithValue("Maturity", settings.Maturity); + cmd.Parameters.AddWithValue("DisableScripts", settings.DisableScripts); + cmd.Parameters.AddWithValue("DisableCollisions", settings.DisableCollisions); + cmd.Parameters.AddWithValue("DisablePhysics", settings.DisablePhysics); + cmd.Parameters.AddWithValue("TerrainTexture1", settings.TerrainTexture1.ToString()); + cmd.Parameters.AddWithValue("TerrainTexture2", settings.TerrainTexture2.ToString()); + cmd.Parameters.AddWithValue("TerrainTexture3", settings.TerrainTexture3.ToString()); + cmd.Parameters.AddWithValue("TerrainTexture4", settings.TerrainTexture4.ToString()); + cmd.Parameters.AddWithValue("Elevation1NW", settings.Elevation1NW); + cmd.Parameters.AddWithValue("Elevation2NW", settings.Elevation2NW); + cmd.Parameters.AddWithValue("Elevation1NE", settings.Elevation1NE); + cmd.Parameters.AddWithValue("Elevation2NE", settings.Elevation2NE); + cmd.Parameters.AddWithValue("Elevation1SE", settings.Elevation1SE); + cmd.Parameters.AddWithValue("Elevation2SE", settings.Elevation2SE); + cmd.Parameters.AddWithValue("Elevation1SW", settings.Elevation1SW); + cmd.Parameters.AddWithValue("Elevation2SW", settings.Elevation2SW); + cmd.Parameters.AddWithValue("WaterHeight", settings.WaterHeight); + cmd.Parameters.AddWithValue("TerrainRaiseLimit", settings.TerrainRaiseLimit); + cmd.Parameters.AddWithValue("TerrainLowerLimit", settings.TerrainLowerLimit); + cmd.Parameters.AddWithValue("UseEstateSun", settings.UseEstateSun); + cmd.Parameters.AddWithValue("Sandbox", settings.Sandbox); + cmd.Parameters.AddWithValue("SunVectorX", settings.SunVector.X); + cmd.Parameters.AddWithValue("SunVectorY", settings.SunVector.Y); + cmd.Parameters.AddWithValue("SunVectorZ", settings.SunVector.Z); + cmd.Parameters.AddWithValue("FixedSun", settings.FixedSun); + cmd.Parameters.AddWithValue("SunPosition", settings.SunPosition); + cmd.Parameters.AddWithValue("Covenant", settings.Covenant.ToString()); + cmd.Parameters.AddWithValue("LoadedCreationDateTime", settings.LoadedCreationDateTime); + cmd.Parameters.AddWithValue("LoadedCreationID", settings.LoadedCreationID); + cmd.Parameters.AddWithValue("TerrainImageID", settings.TerrainImageID); + + } + + /// + /// + /// + /// + /// + /// + private static void FillLandCommand(MySqlCommand cmd, LandData land, UUID regionUUID) + { + cmd.Parameters.AddWithValue("UUID", land.GlobalID.ToString()); + cmd.Parameters.AddWithValue("RegionUUID", regionUUID.ToString()); + cmd.Parameters.AddWithValue("LocalLandID", land.LocalID); + + // Bitmap is a byte[512] + cmd.Parameters.AddWithValue("Bitmap", land.Bitmap); + + cmd.Parameters.AddWithValue("Name", land.Name); + cmd.Parameters.AddWithValue("Description", land.Description); + cmd.Parameters.AddWithValue("OwnerUUID", land.OwnerID.ToString()); + cmd.Parameters.AddWithValue("IsGroupOwned", land.IsGroupOwned); + cmd.Parameters.AddWithValue("Area", land.Area); + cmd.Parameters.AddWithValue("AuctionID", land.AuctionID); //Unemplemented + cmd.Parameters.AddWithValue("Category", land.Category); //Enum libsecondlife.Parcel.ParcelCategory + cmd.Parameters.AddWithValue("ClaimDate", land.ClaimDate); + cmd.Parameters.AddWithValue("ClaimPrice", land.ClaimPrice); + cmd.Parameters.AddWithValue("GroupUUID", land.GroupID.ToString()); + cmd.Parameters.AddWithValue("SalePrice", land.SalePrice); + cmd.Parameters.AddWithValue("LandStatus", land.Status); //Enum. libsecondlife.Parcel.ParcelStatus + cmd.Parameters.AddWithValue("LandFlags", land.Flags); + cmd.Parameters.AddWithValue("LandingType", land.LandingType); + cmd.Parameters.AddWithValue("MediaAutoScale", land.MediaAutoScale); + cmd.Parameters.AddWithValue("MediaTextureUUID", land.MediaID.ToString()); + cmd.Parameters.AddWithValue("MediaURL", land.MediaURL); + cmd.Parameters.AddWithValue("MusicURL", land.MusicURL); + cmd.Parameters.AddWithValue("PassHours", land.PassHours); + cmd.Parameters.AddWithValue("PassPrice", land.PassPrice); + cmd.Parameters.AddWithValue("SnapshotUUID", land.SnapshotID.ToString()); + cmd.Parameters.AddWithValue("UserLocationX", land.UserLocation.X); + cmd.Parameters.AddWithValue("UserLocationY", land.UserLocation.Y); + cmd.Parameters.AddWithValue("UserLocationZ", land.UserLocation.Z); + cmd.Parameters.AddWithValue("UserLookAtX", land.UserLookAt.X); + cmd.Parameters.AddWithValue("UserLookAtY", land.UserLookAt.Y); + cmd.Parameters.AddWithValue("UserLookAtZ", land.UserLookAt.Z); + cmd.Parameters.AddWithValue("AuthBuyerID", land.AuthBuyerID); + cmd.Parameters.AddWithValue("OtherCleanTime", land.OtherCleanTime); + cmd.Parameters.AddWithValue("MediaDescription", land.MediaDescription); + cmd.Parameters.AddWithValue("MediaType", land.MediaType); + cmd.Parameters.AddWithValue("MediaWidth", land.MediaWidth); + cmd.Parameters.AddWithValue("MediaHeight", land.MediaHeight); + cmd.Parameters.AddWithValue("MediaLoop", land.MediaLoop); + cmd.Parameters.AddWithValue("ObscureMusic", land.ObscureMusic); + cmd.Parameters.AddWithValue("ObscureMedia", land.ObscureMedia); + + } + + /// + /// + /// + /// + /// + /// + private static void FillLandAccessCommand(MySqlCommand cmd, ParcelManager.ParcelAccessEntry entry, UUID parcelID) + { + cmd.Parameters.AddWithValue("LandUUID", parcelID.ToString()); + cmd.Parameters.AddWithValue("AccessUUID", entry.AgentID.ToString()); + cmd.Parameters.AddWithValue("Flags", entry.Flags); + } + + /// + /// + /// + /// + /// + private PrimitiveBaseShape BuildShape(IDataReader row) + { + PrimitiveBaseShape s = new PrimitiveBaseShape(); + s.Scale = new Vector3( + (float)(double)row["ScaleX"], + (float)(double)row["ScaleY"], + (float)(double)row["ScaleZ"] + ); + // paths + s.PCode = (byte)(int)row["PCode"]; + s.PathBegin = (ushort)(int)row["PathBegin"]; + s.PathEnd = (ushort)(int)row["PathEnd"]; + s.PathScaleX = (byte)(int)row["PathScaleX"]; + s.PathScaleY = (byte)(int)row["PathScaleY"]; + s.PathShearX = (byte)(int)row["PathShearX"]; + s.PathShearY = (byte)(int)row["PathShearY"]; + s.PathSkew = (sbyte)(int)row["PathSkew"]; + s.PathCurve = (byte)(int)row["PathCurve"]; + s.PathRadiusOffset = (sbyte)(int)row["PathRadiusOffset"]; + s.PathRevolutions = (byte)(int)row["PathRevolutions"]; + s.PathTaperX = (sbyte)(int)row["PathTaperX"]; + s.PathTaperY = (sbyte)(int)row["PathTaperY"]; + s.PathTwist = (sbyte)(int)row["PathTwist"]; + s.PathTwistBegin = (sbyte)(int)row["PathTwistBegin"]; + // profile + s.ProfileBegin = (ushort)(int)row["ProfileBegin"]; + s.ProfileEnd = (ushort)(int)row["ProfileEnd"]; + s.ProfileCurve = (byte)(int)row["ProfileCurve"]; + s.ProfileHollow = (ushort)(int)row["ProfileHollow"]; + s.TextureEntry = (byte[])row["Texture"]; + + s.ExtraParams = (byte[])row["ExtraParams"]; + + s.State = (byte)(int)row["State"]; + + if (!(row["Media"] is System.DBNull)) + s.Media = PrimitiveBaseShape.MediaList.FromXml((string)row["Media"]); + + return s; + } + + /// + /// + /// + /// + /// + private void FillShapeCommand(MySqlCommand cmd, SceneObjectPart prim) + { + PrimitiveBaseShape s = prim.Shape; + cmd.Parameters.AddWithValue("UUID", prim.UUID.ToString()); + // shape is an enum + cmd.Parameters.AddWithValue("Shape", 0); + // vectors + cmd.Parameters.AddWithValue("ScaleX", (double)s.Scale.X); + cmd.Parameters.AddWithValue("ScaleY", (double)s.Scale.Y); + cmd.Parameters.AddWithValue("ScaleZ", (double)s.Scale.Z); + // paths + cmd.Parameters.AddWithValue("PCode", s.PCode); + cmd.Parameters.AddWithValue("PathBegin", s.PathBegin); + cmd.Parameters.AddWithValue("PathEnd", s.PathEnd); + cmd.Parameters.AddWithValue("PathScaleX", s.PathScaleX); + cmd.Parameters.AddWithValue("PathScaleY", s.PathScaleY); + cmd.Parameters.AddWithValue("PathShearX", s.PathShearX); + cmd.Parameters.AddWithValue("PathShearY", s.PathShearY); + cmd.Parameters.AddWithValue("PathSkew", s.PathSkew); + cmd.Parameters.AddWithValue("PathCurve", s.PathCurve); + cmd.Parameters.AddWithValue("PathRadiusOffset", s.PathRadiusOffset); + cmd.Parameters.AddWithValue("PathRevolutions", s.PathRevolutions); + cmd.Parameters.AddWithValue("PathTaperX", s.PathTaperX); + cmd.Parameters.AddWithValue("PathTaperY", s.PathTaperY); + cmd.Parameters.AddWithValue("PathTwist", s.PathTwist); + cmd.Parameters.AddWithValue("PathTwistBegin", s.PathTwistBegin); + // profile + cmd.Parameters.AddWithValue("ProfileBegin", s.ProfileBegin); + cmd.Parameters.AddWithValue("ProfileEnd", s.ProfileEnd); + cmd.Parameters.AddWithValue("ProfileCurve", s.ProfileCurve); + cmd.Parameters.AddWithValue("ProfileHollow", s.ProfileHollow); + cmd.Parameters.AddWithValue("Texture", s.TextureEntry); + cmd.Parameters.AddWithValue("ExtraParams", s.ExtraParams); + cmd.Parameters.AddWithValue("State", s.State); + cmd.Parameters.AddWithValue("Media", null == s.Media ? null : s.Media.ToXml()); + } + + public void StorePrimInventory(UUID primID, ICollection items) + { + lock (m_dbLock) + { + RemoveItems(primID); + + using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) + { + dbcon.Open(); + + MySqlCommand cmd = dbcon.CreateCommand(); + + if (items.Count == 0) + return; + + cmd.CommandText = "insert into primitems (" + + "invType, assetType, name, " + + "description, creationDate, nextPermissions, " + + "currentPermissions, basePermissions, " + + "everyonePermissions, groupPermissions, " + + "flags, itemID, primID, assetID, " + + "parentFolderID, creatorID, ownerID, " + + "groupID, lastOwnerID) values (?invType, " + + "?assetType, ?name, ?description, " + + "?creationDate, ?nextPermissions, " + + "?currentPermissions, ?basePermissions, " + + "?everyonePermissions, ?groupPermissions, " + + "?flags, ?itemID, ?primID, ?assetID, " + + "?parentFolderID, ?creatorID, ?ownerID, " + + "?groupID, ?lastOwnerID)"; + + foreach (TaskInventoryItem item in items) + { + cmd.Parameters.Clear(); + + FillItemCommand(cmd, item); + + ExecuteNonQuery(cmd); + } + + cmd.Dispose(); + } + } + } + } +} diff --git a/OpenSim/Data/Null/NullDataStore.cs b/OpenSim/Data/Null/NullDataStore.cs deleted file mode 100644 index 3ba44bb..0000000 --- a/OpenSim/Data/Null/NullDataStore.cs +++ /dev/null @@ -1,112 +0,0 @@ -/* - * 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.Collections.Generic; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Data.Null -{ - /// - /// NULL DataStore, do not store anything - /// - public class NullDataStore : IRegionDataStore - { - public void Initialise(string dbfile) - { - return; - } - - public void Dispose() - { - } - - public void StoreRegionSettings(RegionSettings rs) - { - } - public RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID) - { - //This connector doesn't support the windlight module yet - //Return default LL windlight settings - return new RegionLightShareData(); - } - public void StoreRegionWindlightSettings(RegionLightShareData wl) - { - //This connector doesn't support the windlight module yet - } - public RegionSettings LoadRegionSettings(UUID regionUUID) - { - return null; - } - - public void StoreObject(SceneObjectGroup obj, UUID regionUUID) - { - } - - public void RemoveObject(UUID obj, UUID regionUUID) - { - } - - // see IRegionDatastore - public void StorePrimInventory(UUID primID, ICollection items) - { - } - - public List LoadObjects(UUID regionUUID) - { - return new List(); - } - - public void StoreTerrain(double[,] ter, UUID regionID) - { - } - - public double[,] LoadTerrain(UUID regionID) - { - return null; - } - - public void RemoveLandObject(UUID globalID) - { - } - - public void StoreLandObject(ILandObject land) - { - } - - public List LoadLandObjects(UUID regionUUID) - { - return new List(); - } - - public void Shutdown() - { - } - } -} diff --git a/OpenSim/Data/Null/NullSimulationData.cs b/OpenSim/Data/Null/NullSimulationData.cs new file mode 100644 index 0000000..9c7da8e --- /dev/null +++ b/OpenSim/Data/Null/NullSimulationData.cs @@ -0,0 +1,112 @@ +/* + * 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.Collections.Generic; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Data.Null +{ + /// + /// NULL DataStore, do not store anything + /// + public class NullSimulationData : ISimulationDataStore + { + public void Initialise(string dbfile) + { + return; + } + + public void Dispose() + { + } + + public void StoreRegionSettings(RegionSettings rs) + { + } + public RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID) + { + //This connector doesn't support the windlight module yet + //Return default LL windlight settings + return new RegionLightShareData(); + } + public void StoreRegionWindlightSettings(RegionLightShareData wl) + { + //This connector doesn't support the windlight module yet + } + public RegionSettings LoadRegionSettings(UUID regionUUID) + { + return null; + } + + public void StoreObject(SceneObjectGroup obj, UUID regionUUID) + { + } + + public void RemoveObject(UUID obj, UUID regionUUID) + { + } + + // see IRegionDatastore + public void StorePrimInventory(UUID primID, ICollection items) + { + } + + public List LoadObjects(UUID regionUUID) + { + return new List(); + } + + public void StoreTerrain(double[,] ter, UUID regionID) + { + } + + public double[,] LoadTerrain(UUID regionID) + { + return null; + } + + public void RemoveLandObject(UUID globalID) + { + } + + public void StoreLandObject(ILandObject land) + { + } + + public List LoadLandObjects(UUID regionUUID) + { + return new List(); + } + + public void Shutdown() + { + } + } +} diff --git a/OpenSim/Data/SQLite/SQLiteRegionData.cs b/OpenSim/Data/SQLite/SQLiteRegionData.cs deleted file mode 100644 index 88699a7..0000000 --- a/OpenSim/Data/SQLite/SQLiteRegionData.cs +++ /dev/null @@ -1,2355 +0,0 @@ -/* - * 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.Data; -using System.Drawing; -using System.IO; -using System.Reflection; -using log4net; -using Mono.Data.Sqlite; -using OpenMetaverse; -using OpenMetaverse.StructuredData; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Data.SQLite -{ - /// - /// A RegionData Interface to the SQLite database - /// - public class SQLiteRegionData : IRegionDataStore - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private const string primSelect = "select * from prims"; - private const string shapeSelect = "select * from primshapes"; - private const string itemsSelect = "select * from primitems"; - private const string terrainSelect = "select * from terrain limit 1"; - private const string landSelect = "select * from land"; - private const string landAccessListSelect = "select distinct * from landaccesslist"; - private const string regionbanListSelect = "select * from regionban"; - private const string regionSettingsSelect = "select * from regionsettings"; - - private DataSet ds; - private SqliteDataAdapter primDa; - private SqliteDataAdapter shapeDa; - private SqliteDataAdapter itemsDa; - private SqliteDataAdapter terrainDa; - private SqliteDataAdapter landDa; - private SqliteDataAdapter landAccessListDa; - private SqliteDataAdapter regionSettingsDa; - - private SqliteConnection m_conn; - - private String m_connectionString; - - // Temporary attribute while this is experimental - - /*********************************************************************** - * - * Public Interface Functions - * - **********************************************************************/ - - /// - /// See IRegionDataStore - /// - /// Initialises RegionData Interface - /// Loads and initialises a new SQLite connection and maintains it. - /// - /// - /// the connection string - public void Initialise(string connectionString) - { - try - { - m_connectionString = connectionString; - - ds = new DataSet("Region"); - - m_log.Info("[SQLITE REGION DB]: Sqlite - connecting: " + connectionString); - m_conn = new SqliteConnection(m_connectionString); - m_conn.Open(); - - SqliteCommand primSelectCmd = new SqliteCommand(primSelect, m_conn); - primDa = new SqliteDataAdapter(primSelectCmd); - - SqliteCommand shapeSelectCmd = new SqliteCommand(shapeSelect, m_conn); - shapeDa = new SqliteDataAdapter(shapeSelectCmd); - // SqliteCommandBuilder shapeCb = new SqliteCommandBuilder(shapeDa); - - SqliteCommand itemsSelectCmd = new SqliteCommand(itemsSelect, m_conn); - itemsDa = new SqliteDataAdapter(itemsSelectCmd); - - SqliteCommand terrainSelectCmd = new SqliteCommand(terrainSelect, m_conn); - terrainDa = new SqliteDataAdapter(terrainSelectCmd); - - SqliteCommand landSelectCmd = new SqliteCommand(landSelect, m_conn); - landDa = new SqliteDataAdapter(landSelectCmd); - - SqliteCommand landAccessListSelectCmd = new SqliteCommand(landAccessListSelect, m_conn); - landAccessListDa = new SqliteDataAdapter(landAccessListSelectCmd); - - SqliteCommand regionSettingsSelectCmd = new SqliteCommand(regionSettingsSelect, m_conn); - regionSettingsDa = new SqliteDataAdapter(regionSettingsSelectCmd); - // This actually does the roll forward assembly stuff - Assembly assem = GetType().Assembly; - Migration m = new Migration(m_conn, assem, "RegionStore"); - m.Update(); - - lock (ds) - { - ds.Tables.Add(createPrimTable()); - setupPrimCommands(primDa, m_conn); - - ds.Tables.Add(createShapeTable()); - setupShapeCommands(shapeDa, m_conn); - - ds.Tables.Add(createItemsTable()); - setupItemsCommands(itemsDa, m_conn); - - ds.Tables.Add(createTerrainTable()); - setupTerrainCommands(terrainDa, m_conn); - - ds.Tables.Add(createLandTable()); - setupLandCommands(landDa, m_conn); - - ds.Tables.Add(createLandAccessListTable()); - setupLandAccessCommands(landAccessListDa, m_conn); - - ds.Tables.Add(createRegionSettingsTable()); - setupRegionSettingsCommands(regionSettingsDa, m_conn); - - // WORKAROUND: This is a work around for sqlite on - // windows, which gets really unhappy with blob columns - // that have no sample data in them. At some point we - // need to actually find a proper way to handle this. - try - { - primDa.Fill(ds.Tables["prims"]); - } - catch (Exception) - { - m_log.Info("[SQLITE REGION DB]: Caught fill error on prims table"); - } - - try - { - shapeDa.Fill(ds.Tables["primshapes"]); - } - catch (Exception) - { - m_log.Info("[SQLITE REGION DB]: Caught fill error on primshapes table"); - } - - try - { - itemsDa.Fill(ds.Tables["primitems"]); - } - catch (Exception) - { - m_log.Info("[SQLITE REGION DB]: Caught fill error on primitems table"); - } - - try - { - terrainDa.Fill(ds.Tables["terrain"]); - } - catch (Exception) - { - m_log.Info("[SQLITE REGION DB]: Caught fill error on terrain table"); - } - - try - { - landDa.Fill(ds.Tables["land"]); - } - catch (Exception) - { - m_log.Info("[SQLITE REGION DB]: Caught fill error on land table"); - } - - try - { - landAccessListDa.Fill(ds.Tables["landaccesslist"]); - } - catch (Exception) - { - m_log.Info("[SQLITE REGION DB]: Caught fill error on landaccesslist table"); - } - - try - { - regionSettingsDa.Fill(ds.Tables["regionsettings"]); - } - catch (Exception) - { - m_log.Info("[SQLITE REGION DB]: Caught fill error on regionsettings table"); - } - - // We have to create a data set mapping for every table, otherwise the IDataAdaptor.Update() will not populate rows with values! - // Not sure exactly why this is - this kind of thing was not necessary before - justincc 20100409 - // Possibly because we manually set up our own DataTables before connecting to the database - CreateDataSetMapping(primDa, "prims"); - CreateDataSetMapping(shapeDa, "primshapes"); - CreateDataSetMapping(itemsDa, "primitems"); - CreateDataSetMapping(terrainDa, "terrain"); - CreateDataSetMapping(landDa, "land"); - CreateDataSetMapping(landAccessListDa, "landaccesslist"); - CreateDataSetMapping(regionSettingsDa, "regionsettings"); - } - } - catch (Exception e) - { - m_log.Error(e); - Environment.Exit(23); - } - - return; - } - - public void Dispose() - { - if (m_conn != null) - { - m_conn.Close(); - m_conn = null; - } - if (ds != null) - { - ds.Dispose(); - ds = null; - } - if (primDa != null) - { - primDa.Dispose(); - primDa = null; - } - if (shapeDa != null) - { - shapeDa.Dispose(); - shapeDa = null; - } - if (itemsDa != null) - { - itemsDa.Dispose(); - itemsDa = null; - } - if (terrainDa != null) - { - terrainDa.Dispose(); - terrainDa = null; - } - if (landDa != null) - { - landDa.Dispose(); - landDa = null; - } - if (landAccessListDa != null) - { - landAccessListDa.Dispose(); - landAccessListDa = null; - } - if (regionSettingsDa != null) - { - regionSettingsDa.Dispose(); - regionSettingsDa = null; - } - } - - public void StoreRegionSettings(RegionSettings rs) - { - lock (ds) - { - DataTable regionsettings = ds.Tables["regionsettings"]; - - DataRow settingsRow = regionsettings.Rows.Find(rs.RegionUUID.ToString()); - if (settingsRow == null) - { - settingsRow = regionsettings.NewRow(); - fillRegionSettingsRow(settingsRow, rs); - regionsettings.Rows.Add(settingsRow); - } - else - { - fillRegionSettingsRow(settingsRow, rs); - } - - Commit(); - } - } - public RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID) - { - //This connector doesn't support the windlight module yet - //Return default LL windlight settings - return new RegionLightShareData(); - } - public void StoreRegionWindlightSettings(RegionLightShareData wl) - { - //This connector doesn't support the windlight module yet - } - public RegionSettings LoadRegionSettings(UUID regionUUID) - { - lock (ds) - { - DataTable regionsettings = ds.Tables["regionsettings"]; - - string searchExp = "regionUUID = '" + regionUUID.ToString() + "'"; - DataRow[] rawsettings = regionsettings.Select(searchExp); - if (rawsettings.Length == 0) - { - RegionSettings rs = new RegionSettings(); - rs.RegionUUID = regionUUID; - rs.OnSave += StoreRegionSettings; - - StoreRegionSettings(rs); - - return rs; - } - DataRow row = rawsettings[0]; - - RegionSettings newSettings = buildRegionSettings(row); - newSettings.OnSave += StoreRegionSettings; - - return newSettings; - } - } - - /// - /// Adds an object into region storage - /// - /// the object - /// the region UUID - public void StoreObject(SceneObjectGroup obj, UUID regionUUID) - { - uint flags = obj.RootPart.GetEffectiveObjectFlags(); - - // Eligibility check - // - if ((flags & (uint)PrimFlags.Temporary) != 0) - return; - if ((flags & (uint)PrimFlags.TemporaryOnRez) != 0) - return; - - lock (ds) - { - foreach (SceneObjectPart prim in obj.Children.Values) - { -// m_log.Info("[REGION DB]: Adding obj: " + obj.UUID + " to region: " + regionUUID); - addPrim(prim, obj.UUID, regionUUID); - } - } - - Commit(); - // m_log.Info("[Dump of prims]: " + ds.GetXml()); - } - - /// - /// Removes an object from region storage - /// - /// the object - /// the region UUID - public void RemoveObject(UUID obj, UUID regionUUID) - { - // m_log.InfoFormat("[REGION DB]: Removing obj: {0} from region: {1}", obj.Guid, regionUUID); - - DataTable prims = ds.Tables["prims"]; - DataTable shapes = ds.Tables["primshapes"]; - - string selectExp = "SceneGroupID = '" + obj + "' and RegionUUID = '" + regionUUID + "'"; - lock (ds) - { - DataRow[] primRows = prims.Select(selectExp); - foreach (DataRow row in primRows) - { - // Remove shape rows - UUID uuid = new UUID((string) row["UUID"]); - DataRow shapeRow = shapes.Rows.Find(uuid.ToString()); - if (shapeRow != null) - { - shapeRow.Delete(); - } - - RemoveItems(uuid); - - // Remove prim row - row.Delete(); - } - } - - Commit(); - } - - /// - /// Remove all persisted items of the given prim. - /// The caller must acquire the necessrary synchronization locks and commit or rollback changes. - /// - /// The item UUID - private void RemoveItems(UUID uuid) - { - DataTable items = ds.Tables["primitems"]; - - String sql = String.Format("primID = '{0}'", uuid); - DataRow[] itemRows = items.Select(sql); - - foreach (DataRow itemRow in itemRows) - { - itemRow.Delete(); - } - } - - /// - /// Load persisted objects from region storage. - /// - /// The region UUID - /// List of loaded groups - public List LoadObjects(UUID regionUUID) - { - Dictionary createdObjects = new Dictionary(); - - List retvals = new List(); - - DataTable prims = ds.Tables["prims"]; - DataTable shapes = ds.Tables["primshapes"]; - - string byRegion = "RegionUUID = '" + regionUUID + "'"; - - lock (ds) - { - DataRow[] primsForRegion = prims.Select(byRegion); -// m_log.Info("[SQLITE REGION DB]: Loaded " + primsForRegion.Length + " prims for region: " + regionUUID); - - // First, create all groups - foreach (DataRow primRow in primsForRegion) - { - try - { - SceneObjectPart prim = null; - - string uuid = (string) primRow["UUID"]; - string objID = (string) primRow["SceneGroupID"]; - - if (uuid == objID) //is new SceneObjectGroup ? - { - prim = buildPrim(primRow); - DataRow shapeRow = shapes.Rows.Find(prim.UUID.ToString()); - if (shapeRow != null) - { - prim.Shape = buildShape(shapeRow); - } - else - { - m_log.Warn( - "[SQLITE REGION DB]: No shape found for prim in storage, so setting default box shape"); - prim.Shape = PrimitiveBaseShape.Default; - } - - SceneObjectGroup group = new SceneObjectGroup(prim); - createdObjects.Add(group.UUID, group); - retvals.Add(group); - LoadItems(prim); - } - } - catch (Exception e) - { - m_log.Error("[SQLITE REGION DB]: Failed create prim object in new group, exception and data follows"); - m_log.Error("[SQLITE REGION DB]: ", e); - foreach (DataColumn col in prims.Columns) - { - m_log.Error("[SQLITE REGION DB]: Col: " + col.ColumnName + " => " + primRow[col]); - } - } - } - - // Now fill the groups with part data - foreach (DataRow primRow in primsForRegion) - { - try - { - SceneObjectPart prim = null; - - string uuid = (string) primRow["UUID"]; - string objID = (string) primRow["SceneGroupID"]; - if (uuid != objID) //is new SceneObjectGroup ? - { - prim = buildPrim(primRow); - DataRow shapeRow = shapes.Rows.Find(prim.UUID.ToString()); - if (shapeRow != null) - { - prim.Shape = buildShape(shapeRow); - } - else - { - m_log.Warn( - "[SQLITE REGION DB]: No shape found for prim in storage, so setting default box shape"); - prim.Shape = PrimitiveBaseShape.Default; - } - - createdObjects[new UUID(objID)].AddPart(prim); - LoadItems(prim); - } - } - catch (Exception e) - { - m_log.Error("[SQLITE REGION DB]: Failed create prim object in group, exception and data follows"); - m_log.Error("[SQLITE REGION DB]: ", e); - foreach (DataColumn col in prims.Columns) - { - m_log.Error("[SQLITE REGION DB]: Col: " + col.ColumnName + " => " + primRow[col]); - } - } - } - } - return retvals; - } - - /// - /// Load in a prim's persisted inventory. - /// - /// the prim - private void LoadItems(SceneObjectPart prim) - { -// m_log.DebugFormat("[SQLITE REGION DB]: Loading inventory for {0} {1}", prim.Name, prim.UUID); - - DataTable dbItems = ds.Tables["primitems"]; - String sql = String.Format("primID = '{0}'", prim.UUID.ToString()); - DataRow[] dbItemRows = dbItems.Select(sql); - IList inventory = new List(); - -// m_log.DebugFormat( -// "[SQLITE REGION DB]: Found {0} items for {1} {2}", dbItemRows.Length, prim.Name, prim.UUID); - - foreach (DataRow row in dbItemRows) - { - TaskInventoryItem item = buildItem(row); - inventory.Add(item); - -// m_log.DebugFormat("[SQLITE REGION DB]: Restored item {0} {1}", item.Name, item.ItemID); - } - - prim.Inventory.RestoreInventoryItems(inventory); - } - - /// - /// Store a terrain revision in region storage - /// - /// terrain heightfield - /// region UUID - public void StoreTerrain(double[,] ter, UUID regionID) - { - lock (ds) - { - int revision = Util.UnixTimeSinceEpoch(); - - // This is added to get rid of the infinitely growing - // terrain databases which negatively impact on SQLite - // over time. Before reenabling this feature there - // needs to be a limitter put on the number of - // revisions in the database, as this old - // implementation is a DOS attack waiting to happen. - - using ( - SqliteCommand cmd = - new SqliteCommand("delete from terrain where RegionUUID=:RegionUUID and Revision <= :Revision", - m_conn)) - { - cmd.Parameters.Add(new SqliteParameter(":RegionUUID", regionID.ToString())); - cmd.Parameters.Add(new SqliteParameter(":Revision", revision)); - cmd.ExecuteNonQuery(); - } - - // the following is an work around for .NET. The perf - // issues associated with it aren't as bad as you think. - m_log.Debug("[SQLITE REGION DB]: Storing terrain revision r" + revision.ToString()); - String sql = "insert into terrain(RegionUUID, Revision, Heightfield)" + - " values(:RegionUUID, :Revision, :Heightfield)"; - - using (SqliteCommand cmd = new SqliteCommand(sql, m_conn)) - { - cmd.Parameters.Add(new SqliteParameter(":RegionUUID", regionID.ToString())); - cmd.Parameters.Add(new SqliteParameter(":Revision", revision)); - cmd.Parameters.Add(new SqliteParameter(":Heightfield", serializeTerrain(ter))); - cmd.ExecuteNonQuery(); - } - } - } - - /// - /// Load the latest terrain revision from region storage - /// - /// the region UUID - /// Heightfield data - public double[,] LoadTerrain(UUID regionID) - { - lock (ds) - { - double[,] terret = new double[(int)Constants.RegionSize, (int)Constants.RegionSize]; - terret.Initialize(); - - String sql = "select RegionUUID, Revision, Heightfield from terrain" + - " where RegionUUID=:RegionUUID order by Revision desc"; - - using (SqliteCommand cmd = new SqliteCommand(sql, m_conn)) - { - cmd.Parameters.Add(new SqliteParameter(":RegionUUID", regionID.ToString())); - - using (IDataReader row = cmd.ExecuteReader()) - { - int rev = 0; - if (row.Read()) - { - // TODO: put this into a function - using (MemoryStream str = new MemoryStream((byte[])row["Heightfield"])) - { - using (BinaryReader br = new BinaryReader(str)) - { - for (int x = 0; x < (int)Constants.RegionSize; x++) - { - for (int y = 0; y < (int)Constants.RegionSize; y++) - { - terret[x, y] = br.ReadDouble(); - } - } - } - } - rev = Convert.ToInt32(row["Revision"]); - } - else - { - m_log.Warn("[SQLITE REGION DB]: No terrain found for region"); - return null; - } - - m_log.Debug("[SQLITE REGION DB]: Loaded terrain revision r" + rev.ToString()); - } - } - return terret; - } - } - - /// - /// - /// - /// - public void RemoveLandObject(UUID globalID) - { - lock (ds) - { - // Can't use blanket SQL statements when using SqlAdapters unless you re-read the data into the adapter - // after you're done. - // replaced below code with the SqliteAdapter version. - //using (SqliteCommand cmd = new SqliteCommand("delete from land where UUID=:UUID", m_conn)) - //{ - // cmd.Parameters.Add(new SqliteParameter(":UUID", globalID.ToString())); - // cmd.ExecuteNonQuery(); - //} - - //using (SqliteCommand cmd = new SqliteCommand("delete from landaccesslist where LandUUID=:UUID", m_conn)) - //{ - // cmd.Parameters.Add(new SqliteParameter(":UUID", globalID.ToString())); - // cmd.ExecuteNonQuery(); - //} - - DataTable land = ds.Tables["land"]; - DataTable landaccesslist = ds.Tables["landaccesslist"]; - DataRow landRow = land.Rows.Find(globalID.ToString()); - if (landRow != null) - { - land.Rows.Remove(landRow); - } - List rowsToDelete = new List(); - foreach (DataRow rowToCheck in landaccesslist.Rows) - { - if (rowToCheck["LandUUID"].ToString() == globalID.ToString()) - rowsToDelete.Add(rowToCheck); - } - for (int iter = 0; iter < rowsToDelete.Count; iter++) - { - landaccesslist.Rows.Remove(rowsToDelete[iter]); - } - - - } - Commit(); - } - - /// - /// - /// - /// - public void StoreLandObject(ILandObject parcel) - { - lock (ds) - { - DataTable land = ds.Tables["land"]; - DataTable landaccesslist = ds.Tables["landaccesslist"]; - - DataRow landRow = land.Rows.Find(parcel.LandData.GlobalID.ToString()); - if (landRow == null) - { - landRow = land.NewRow(); - fillLandRow(landRow, parcel.LandData, parcel.RegionUUID); - land.Rows.Add(landRow); - } - else - { - fillLandRow(landRow, parcel.LandData, parcel.RegionUUID); - } - - // I know this caused someone issues before, but OpenSim is unusable if we leave this stuff around - //using (SqliteCommand cmd = new SqliteCommand("delete from landaccesslist where LandUUID=:LandUUID", m_conn)) - //{ - // cmd.Parameters.Add(new SqliteParameter(":LandUUID", parcel.LandData.GlobalID.ToString())); - // cmd.ExecuteNonQuery(); - -// } - - // This is the slower.. but more appropriate thing to do - - // We can't modify the table with direct queries before calling Commit() and re-filling them. - List rowsToDelete = new List(); - foreach (DataRow rowToCheck in landaccesslist.Rows) - { - if (rowToCheck["LandUUID"].ToString() == parcel.LandData.GlobalID.ToString()) - rowsToDelete.Add(rowToCheck); - } - for (int iter = 0; iter < rowsToDelete.Count; iter++) - { - landaccesslist.Rows.Remove(rowsToDelete[iter]); - } - rowsToDelete.Clear(); - foreach (ParcelManager.ParcelAccessEntry entry in parcel.LandData.ParcelAccessList) - { - DataRow newAccessRow = landaccesslist.NewRow(); - fillLandAccessRow(newAccessRow, entry, parcel.LandData.GlobalID); - landaccesslist.Rows.Add(newAccessRow); - } - } - - Commit(); - } - - /// - /// - /// - /// - /// - public List LoadLandObjects(UUID regionUUID) - { - List landDataForRegion = new List(); - lock (ds) - { - DataTable land = ds.Tables["land"]; - DataTable landaccesslist = ds.Tables["landaccesslist"]; - string searchExp = "RegionUUID = '" + regionUUID + "'"; - DataRow[] rawDataForRegion = land.Select(searchExp); - foreach (DataRow rawDataLand in rawDataForRegion) - { - LandData newLand = buildLandData(rawDataLand); - string accessListSearchExp = "LandUUID = '" + newLand.GlobalID + "'"; - DataRow[] rawDataForLandAccessList = landaccesslist.Select(accessListSearchExp); - foreach (DataRow rawDataLandAccess in rawDataForLandAccessList) - { - newLand.ParcelAccessList.Add(buildLandAccessData(rawDataLandAccess)); - } - - landDataForRegion.Add(newLand); - } - } - return landDataForRegion; - } - - /// - /// - /// - public void Commit() - { - //m_log.Debug("[SQLITE]: Starting commit"); - lock (ds) - { - primDa.Update(ds, "prims"); - shapeDa.Update(ds, "primshapes"); - - itemsDa.Update(ds, "primitems"); - - terrainDa.Update(ds, "terrain"); - landDa.Update(ds, "land"); - landAccessListDa.Update(ds, "landaccesslist"); - try - { - regionSettingsDa.Update(ds, "regionsettings"); - } - catch (SqliteException SqlEx) - { - throw new Exception( - "There was a SQL error or connection string configuration error when saving the region settings. This could be a bug, it could also happen if ConnectionString is defined in the [DatabaseService] section of StandaloneCommon.ini in the config_include folder. This could also happen if the config_include folder doesn't exist or if the OpenSim.ini [Architecture] section isn't set. If this is your first time running OpenSimulator, please restart the simulator and bug a developer to fix this!", - SqlEx); - } - ds.AcceptChanges(); - } - } - - /// - /// See - /// - public void Shutdown() - { - Commit(); - } - - /*********************************************************************** - * - * Database Definition Functions - * - * This should be db agnostic as we define them in ADO.NET terms - * - **********************************************************************/ - - protected void CreateDataSetMapping(IDataAdapter da, string tableName) - { - ITableMapping dbMapping = da.TableMappings.Add(tableName, tableName); - foreach (DataColumn col in ds.Tables[tableName].Columns) - { - dbMapping.ColumnMappings.Add(col.ColumnName, col.ColumnName); - } - } - - /// - /// - /// - /// - /// - /// - private static void createCol(DataTable dt, string name, Type type) - { - DataColumn col = new DataColumn(name, type); - dt.Columns.Add(col); - } - - /// - /// Creates the "terrain" table - /// - /// terrain table DataTable - private static DataTable createTerrainTable() - { - DataTable terrain = new DataTable("terrain"); - - createCol(terrain, "RegionUUID", typeof (String)); - createCol(terrain, "Revision", typeof (Int32)); - createCol(terrain, "Heightfield", typeof (Byte[])); - - return terrain; - } - - /// - /// Creates the "prims" table - /// - /// prim table DataTable - private static DataTable createPrimTable() - { - DataTable prims = new DataTable("prims"); - - createCol(prims, "UUID", typeof (String)); - createCol(prims, "RegionUUID", typeof (String)); - createCol(prims, "CreationDate", typeof (Int32)); - createCol(prims, "Name", typeof (String)); - createCol(prims, "SceneGroupID", typeof (String)); - // various text fields - createCol(prims, "Text", typeof (String)); - createCol(prims, "ColorR", typeof (Int32)); - createCol(prims, "ColorG", typeof (Int32)); - createCol(prims, "ColorB", typeof (Int32)); - createCol(prims, "ColorA", typeof (Int32)); - createCol(prims, "Description", typeof (String)); - createCol(prims, "SitName", typeof (String)); - createCol(prims, "TouchName", typeof (String)); - // permissions - createCol(prims, "ObjectFlags", typeof (Int32)); - createCol(prims, "CreatorID", typeof (String)); - createCol(prims, "OwnerID", typeof (String)); - createCol(prims, "GroupID", typeof (String)); - createCol(prims, "LastOwnerID", typeof (String)); - createCol(prims, "OwnerMask", typeof (Int32)); - createCol(prims, "NextOwnerMask", typeof (Int32)); - createCol(prims, "GroupMask", typeof (Int32)); - createCol(prims, "EveryoneMask", typeof (Int32)); - createCol(prims, "BaseMask", typeof (Int32)); - // vectors - createCol(prims, "PositionX", typeof (Double)); - createCol(prims, "PositionY", typeof (Double)); - createCol(prims, "PositionZ", typeof (Double)); - createCol(prims, "GroupPositionX", typeof (Double)); - createCol(prims, "GroupPositionY", typeof (Double)); - createCol(prims, "GroupPositionZ", typeof (Double)); - createCol(prims, "VelocityX", typeof (Double)); - createCol(prims, "VelocityY", typeof (Double)); - createCol(prims, "VelocityZ", typeof (Double)); - createCol(prims, "AngularVelocityX", typeof (Double)); - createCol(prims, "AngularVelocityY", typeof (Double)); - createCol(prims, "AngularVelocityZ", typeof (Double)); - createCol(prims, "AccelerationX", typeof (Double)); - createCol(prims, "AccelerationY", typeof (Double)); - createCol(prims, "AccelerationZ", typeof (Double)); - // quaternions - createCol(prims, "RotationX", typeof (Double)); - createCol(prims, "RotationY", typeof (Double)); - createCol(prims, "RotationZ", typeof (Double)); - createCol(prims, "RotationW", typeof (Double)); - - // sit target - createCol(prims, "SitTargetOffsetX", typeof (Double)); - createCol(prims, "SitTargetOffsetY", typeof (Double)); - createCol(prims, "SitTargetOffsetZ", typeof (Double)); - - createCol(prims, "SitTargetOrientW", typeof (Double)); - createCol(prims, "SitTargetOrientX", typeof (Double)); - createCol(prims, "SitTargetOrientY", typeof (Double)); - createCol(prims, "SitTargetOrientZ", typeof (Double)); - - createCol(prims, "PayPrice", typeof(Int32)); - createCol(prims, "PayButton1", typeof(Int32)); - createCol(prims, "PayButton2", typeof(Int32)); - createCol(prims, "PayButton3", typeof(Int32)); - createCol(prims, "PayButton4", typeof(Int32)); - - createCol(prims, "LoopedSound", typeof(String)); - createCol(prims, "LoopedSoundGain", typeof(Double)); - createCol(prims, "TextureAnimation", typeof(String)); - createCol(prims, "ParticleSystem", typeof(String)); - - createCol(prims, "OmegaX", typeof(Double)); - createCol(prims, "OmegaY", typeof(Double)); - createCol(prims, "OmegaZ", typeof(Double)); - - createCol(prims, "CameraEyeOffsetX", typeof(Double)); - createCol(prims, "CameraEyeOffsetY", typeof(Double)); - createCol(prims, "CameraEyeOffsetZ", typeof(Double)); - - createCol(prims, "CameraAtOffsetX", typeof(Double)); - createCol(prims, "CameraAtOffsetY", typeof(Double)); - createCol(prims, "CameraAtOffsetZ", typeof(Double)); - - createCol(prims, "ForceMouselook", typeof(Int16)); - - createCol(prims, "ScriptAccessPin", typeof(Int32)); - - createCol(prims, "AllowedDrop", typeof(Int16)); - createCol(prims, "DieAtEdge", typeof(Int16)); - - createCol(prims, "SalePrice", typeof(Int32)); - createCol(prims, "SaleType", typeof(Int16)); - - // click action - createCol(prims, "ClickAction", typeof (Byte)); - - createCol(prims, "Material", typeof(Byte)); - - createCol(prims, "CollisionSound", typeof(String)); - createCol(prims, "CollisionSoundVolume", typeof(Double)); - - createCol(prims, "VolumeDetect", typeof(Int16)); - - createCol(prims, "MediaURL", typeof(String)); - - // Add in contraints - prims.PrimaryKey = new DataColumn[] {prims.Columns["UUID"]}; - - return prims; - } - - /// - /// Creates "primshapes" table - /// - /// shape table DataTable - private static DataTable createShapeTable() - { - DataTable shapes = new DataTable("primshapes"); - createCol(shapes, "UUID", typeof (String)); - // shape is an enum - createCol(shapes, "Shape", typeof (Int32)); - // vectors - createCol(shapes, "ScaleX", typeof (Double)); - createCol(shapes, "ScaleY", typeof (Double)); - createCol(shapes, "ScaleZ", typeof (Double)); - // paths - createCol(shapes, "PCode", typeof (Int32)); - createCol(shapes, "PathBegin", typeof (Int32)); - createCol(shapes, "PathEnd", typeof (Int32)); - createCol(shapes, "PathScaleX", typeof (Int32)); - createCol(shapes, "PathScaleY", typeof (Int32)); - createCol(shapes, "PathShearX", typeof (Int32)); - createCol(shapes, "PathShearY", typeof (Int32)); - createCol(shapes, "PathSkew", typeof (Int32)); - createCol(shapes, "PathCurve", typeof (Int32)); - createCol(shapes, "PathRadiusOffset", typeof (Int32)); - createCol(shapes, "PathRevolutions", typeof (Int32)); - createCol(shapes, "PathTaperX", typeof (Int32)); - createCol(shapes, "PathTaperY", typeof (Int32)); - createCol(shapes, "PathTwist", typeof (Int32)); - createCol(shapes, "PathTwistBegin", typeof (Int32)); - // profile - createCol(shapes, "ProfileBegin", typeof (Int32)); - createCol(shapes, "ProfileEnd", typeof (Int32)); - createCol(shapes, "ProfileCurve", typeof (Int32)); - createCol(shapes, "ProfileHollow", typeof (Int32)); - createCol(shapes, "State", typeof(Int32)); - // text TODO: this isn't right, but I'm not sure the right - // way to specify this as a blob atm - createCol(shapes, "Texture", typeof (Byte[])); - createCol(shapes, "ExtraParams", typeof (Byte[])); - createCol(shapes, "Media", typeof(String)); - - shapes.PrimaryKey = new DataColumn[] {shapes.Columns["UUID"]}; - - return shapes; - } - - /// - /// creates "primitems" table - /// - /// item table DataTable - private static DataTable createItemsTable() - { - DataTable items = new DataTable("primitems"); - - createCol(items, "itemID", typeof (String)); - createCol(items, "primID", typeof (String)); - createCol(items, "assetID", typeof (String)); - createCol(items, "parentFolderID", typeof (String)); - - createCol(items, "invType", typeof (Int32)); - createCol(items, "assetType", typeof (Int32)); - - createCol(items, "name", typeof (String)); - createCol(items, "description", typeof (String)); - - createCol(items, "creationDate", typeof (Int64)); - createCol(items, "creatorID", typeof (String)); - createCol(items, "ownerID", typeof (String)); - createCol(items, "lastOwnerID", typeof (String)); - createCol(items, "groupID", typeof (String)); - - createCol(items, "nextPermissions", typeof (UInt32)); - createCol(items, "currentPermissions", typeof (UInt32)); - createCol(items, "basePermissions", typeof (UInt32)); - createCol(items, "everyonePermissions", typeof (UInt32)); - createCol(items, "groupPermissions", typeof (UInt32)); - createCol(items, "flags", typeof (UInt32)); - - items.PrimaryKey = new DataColumn[] { items.Columns["itemID"] }; - - return items; - } - - /// - /// Creates "land" table - /// - /// land table DataTable - private static DataTable createLandTable() - { - DataTable land = new DataTable("land"); - createCol(land, "UUID", typeof (String)); - createCol(land, "RegionUUID", typeof (String)); - createCol(land, "LocalLandID", typeof (UInt32)); - - // Bitmap is a byte[512] - createCol(land, "Bitmap", typeof (Byte[])); - - createCol(land, "Name", typeof (String)); - createCol(land, "Desc", typeof (String)); - createCol(land, "OwnerUUID", typeof (String)); - createCol(land, "IsGroupOwned", typeof (Boolean)); - createCol(land, "Area", typeof (Int32)); - createCol(land, "AuctionID", typeof (Int32)); //Unemplemented - createCol(land, "Category", typeof (Int32)); //Enum OpenMetaverse.Parcel.ParcelCategory - createCol(land, "ClaimDate", typeof (Int32)); - createCol(land, "ClaimPrice", typeof (Int32)); - createCol(land, "GroupUUID", typeof (string)); - createCol(land, "SalePrice", typeof (Int32)); - createCol(land, "LandStatus", typeof (Int32)); //Enum. OpenMetaverse.Parcel.ParcelStatus - createCol(land, "LandFlags", typeof (UInt32)); - createCol(land, "LandingType", typeof (Byte)); - createCol(land, "MediaAutoScale", typeof (Byte)); - createCol(land, "MediaTextureUUID", typeof (String)); - createCol(land, "MediaURL", typeof (String)); - createCol(land, "MusicURL", typeof (String)); - createCol(land, "PassHours", typeof (Double)); - createCol(land, "PassPrice", typeof (UInt32)); - createCol(land, "SnapshotUUID", typeof (String)); - createCol(land, "UserLocationX", typeof (Double)); - createCol(land, "UserLocationY", typeof (Double)); - createCol(land, "UserLocationZ", typeof (Double)); - createCol(land, "UserLookAtX", typeof (Double)); - createCol(land, "UserLookAtY", typeof (Double)); - createCol(land, "UserLookAtZ", typeof (Double)); - createCol(land, "AuthbuyerID", typeof(String)); - createCol(land, "OtherCleanTime", typeof(Int32)); - - land.PrimaryKey = new DataColumn[] {land.Columns["UUID"]}; - - return land; - } - - /// - /// create "landaccesslist" table - /// - /// Landacceslist DataTable - private static DataTable createLandAccessListTable() - { - DataTable landaccess = new DataTable("landaccesslist"); - createCol(landaccess, "LandUUID", typeof (String)); - createCol(landaccess, "AccessUUID", typeof (String)); - createCol(landaccess, "Flags", typeof (UInt32)); - - return landaccess; - } - - private static DataTable createRegionSettingsTable() - { - DataTable regionsettings = new DataTable("regionsettings"); - createCol(regionsettings, "regionUUID", typeof(String)); - createCol(regionsettings, "block_terraform", typeof (Int32)); - createCol(regionsettings, "block_fly", typeof (Int32)); - createCol(regionsettings, "allow_damage", typeof (Int32)); - createCol(regionsettings, "restrict_pushing", typeof (Int32)); - createCol(regionsettings, "allow_land_resell", typeof (Int32)); - createCol(regionsettings, "allow_land_join_divide", typeof (Int32)); - createCol(regionsettings, "block_show_in_search", typeof (Int32)); - createCol(regionsettings, "agent_limit", typeof (Int32)); - createCol(regionsettings, "object_bonus", typeof (Double)); - createCol(regionsettings, "maturity", typeof (Int32)); - createCol(regionsettings, "disable_scripts", typeof (Int32)); - createCol(regionsettings, "disable_collisions", typeof (Int32)); - createCol(regionsettings, "disable_physics", typeof (Int32)); - createCol(regionsettings, "terrain_texture_1", typeof(String)); - createCol(regionsettings, "terrain_texture_2", typeof(String)); - createCol(regionsettings, "terrain_texture_3", typeof(String)); - createCol(regionsettings, "terrain_texture_4", typeof(String)); - createCol(regionsettings, "elevation_1_nw", typeof (Double)); - createCol(regionsettings, "elevation_2_nw", typeof (Double)); - createCol(regionsettings, "elevation_1_ne", typeof (Double)); - createCol(regionsettings, "elevation_2_ne", typeof (Double)); - createCol(regionsettings, "elevation_1_se", typeof (Double)); - createCol(regionsettings, "elevation_2_se", typeof (Double)); - createCol(regionsettings, "elevation_1_sw", typeof (Double)); - createCol(regionsettings, "elevation_2_sw", typeof (Double)); - createCol(regionsettings, "water_height", typeof (Double)); - createCol(regionsettings, "terrain_raise_limit", typeof (Double)); - createCol(regionsettings, "terrain_lower_limit", typeof (Double)); - createCol(regionsettings, "use_estate_sun", typeof (Int32)); - createCol(regionsettings, "sandbox", typeof (Int32)); - createCol(regionsettings, "sunvectorx",typeof (Double)); - createCol(regionsettings, "sunvectory",typeof (Double)); - createCol(regionsettings, "sunvectorz",typeof (Double)); - createCol(regionsettings, "fixed_sun", typeof (Int32)); - createCol(regionsettings, "sun_position", typeof (Double)); - createCol(regionsettings, "covenant", typeof(String)); - createCol(regionsettings, "map_tile_ID", typeof(String)); - regionsettings.PrimaryKey = new DataColumn[] { regionsettings.Columns["regionUUID"] }; - return regionsettings; - } - - /*********************************************************************** - * - * Convert between ADO.NET <=> OpenSim Objects - * - * These should be database independant - * - **********************************************************************/ - - /// - /// - /// - /// - /// - private SceneObjectPart buildPrim(DataRow row) - { - // Code commented. Uncomment to test the unit test inline. - - // The unit test mentions this commented code for the purposes - // of debugging a unit test failure - - // SceneObjectGroup sog = new SceneObjectGroup(); - // SceneObjectPart sop = new SceneObjectPart(); - // sop.LocalId = 1; - // sop.Name = "object1"; - // sop.Description = "object1"; - // sop.Text = ""; - // sop.SitName = ""; - // sop.TouchName = ""; - // sop.UUID = UUID.Random(); - // sop.Shape = PrimitiveBaseShape.Default; - // sog.SetRootPart(sop); - // Add breakpoint in above line. Check sop fields. - - // TODO: this doesn't work yet because something more - // interesting has to be done to actually get these values - // back out. Not enough time to figure it out yet. - - SceneObjectPart prim = new SceneObjectPart(); - prim.UUID = new UUID((String) row["UUID"]); - // explicit conversion of integers is required, which sort - // of sucks. No idea if there is a shortcut here or not. - prim.CreationDate = Convert.ToInt32(row["CreationDate"]); - prim.Name = row["Name"] == DBNull.Value ? string.Empty : (string)row["Name"]; - // various text fields - prim.Text = (String) row["Text"]; - prim.Color = Color.FromArgb(Convert.ToInt32(row["ColorA"]), - Convert.ToInt32(row["ColorR"]), - Convert.ToInt32(row["ColorG"]), - Convert.ToInt32(row["ColorB"])); - prim.Description = (String) row["Description"]; - prim.SitName = (String) row["SitName"]; - prim.TouchName = (String) row["TouchName"]; - // permissions - prim.ObjectFlags = Convert.ToUInt32(row["ObjectFlags"]); - prim.CreatorID = new UUID((String) row["CreatorID"]); - prim.OwnerID = new UUID((String) row["OwnerID"]); - prim.GroupID = new UUID((String) row["GroupID"]); - prim.LastOwnerID = new UUID((String) row["LastOwnerID"]); - prim.OwnerMask = Convert.ToUInt32(row["OwnerMask"]); - prim.NextOwnerMask = Convert.ToUInt32(row["NextOwnerMask"]); - prim.GroupMask = Convert.ToUInt32(row["GroupMask"]); - prim.EveryoneMask = Convert.ToUInt32(row["EveryoneMask"]); - prim.BaseMask = Convert.ToUInt32(row["BaseMask"]); - // vectors - prim.OffsetPosition = new Vector3( - Convert.ToSingle(row["PositionX"]), - Convert.ToSingle(row["PositionY"]), - Convert.ToSingle(row["PositionZ"]) - ); - prim.GroupPosition = new Vector3( - Convert.ToSingle(row["GroupPositionX"]), - Convert.ToSingle(row["GroupPositionY"]), - Convert.ToSingle(row["GroupPositionZ"]) - ); - prim.Velocity = new Vector3( - Convert.ToSingle(row["VelocityX"]), - Convert.ToSingle(row["VelocityY"]), - Convert.ToSingle(row["VelocityZ"]) - ); - prim.AngularVelocity = new Vector3( - Convert.ToSingle(row["AngularVelocityX"]), - Convert.ToSingle(row["AngularVelocityY"]), - Convert.ToSingle(row["AngularVelocityZ"]) - ); - prim.Acceleration = new Vector3( - Convert.ToSingle(row["AccelerationX"]), - Convert.ToSingle(row["AccelerationY"]), - Convert.ToSingle(row["AccelerationZ"]) - ); - // quaternions - prim.RotationOffset = new Quaternion( - Convert.ToSingle(row["RotationX"]), - Convert.ToSingle(row["RotationY"]), - Convert.ToSingle(row["RotationZ"]), - Convert.ToSingle(row["RotationW"]) - ); - - prim.SitTargetPositionLL = new Vector3( - Convert.ToSingle(row["SitTargetOffsetX"]), - Convert.ToSingle(row["SitTargetOffsetY"]), - Convert.ToSingle(row["SitTargetOffsetZ"])); - prim.SitTargetOrientationLL = new Quaternion( - Convert.ToSingle( - row["SitTargetOrientX"]), - Convert.ToSingle( - row["SitTargetOrientY"]), - Convert.ToSingle( - row["SitTargetOrientZ"]), - Convert.ToSingle( - row["SitTargetOrientW"])); - - prim.ClickAction = Convert.ToByte(row["ClickAction"]); - prim.PayPrice[0] = Convert.ToInt32(row["PayPrice"]); - prim.PayPrice[1] = Convert.ToInt32(row["PayButton1"]); - prim.PayPrice[2] = Convert.ToInt32(row["PayButton2"]); - prim.PayPrice[3] = Convert.ToInt32(row["PayButton3"]); - prim.PayPrice[4] = Convert.ToInt32(row["PayButton4"]); - - prim.Sound = new UUID(row["LoopedSound"].ToString()); - prim.SoundGain = Convert.ToSingle(row["LoopedSoundGain"]); - prim.SoundFlags = 1; // If it's persisted at all, it's looped - - if (!row.IsNull("TextureAnimation")) - prim.TextureAnimation = Convert.FromBase64String(row["TextureAnimation"].ToString()); - if (!row.IsNull("ParticleSystem")) - prim.ParticleSystem = Convert.FromBase64String(row["ParticleSystem"].ToString()); - - prim.AngularVelocity = new Vector3( - Convert.ToSingle(row["OmegaX"]), - Convert.ToSingle(row["OmegaY"]), - Convert.ToSingle(row["OmegaZ"]) - ); - - prim.SetCameraEyeOffset(new Vector3( - Convert.ToSingle(row["CameraEyeOffsetX"]), - Convert.ToSingle(row["CameraEyeOffsetY"]), - Convert.ToSingle(row["CameraEyeOffsetZ"]) - )); - - prim.SetCameraAtOffset(new Vector3( - Convert.ToSingle(row["CameraAtOffsetX"]), - Convert.ToSingle(row["CameraAtOffsetY"]), - Convert.ToSingle(row["CameraAtOffsetZ"]) - )); - - if (Convert.ToInt16(row["ForceMouselook"]) != 0) - prim.SetForceMouselook(true); - - prim.ScriptAccessPin = Convert.ToInt32(row["ScriptAccessPin"]); - - if (Convert.ToInt16(row["AllowedDrop"]) != 0) - prim.AllowedDrop = true; - - if (Convert.ToInt16(row["DieAtEdge"]) != 0) - prim.DIE_AT_EDGE = true; - - prim.SalePrice = Convert.ToInt32(row["SalePrice"]); - prim.ObjectSaleType = Convert.ToByte(row["SaleType"]); - - prim.Material = Convert.ToByte(row["Material"]); - - prim.CollisionSound = new UUID(row["CollisionSound"].ToString()); - prim.CollisionSoundVolume = Convert.ToSingle(row["CollisionSoundVolume"]); - - if (Convert.ToInt16(row["VolumeDetect"]) != 0) - prim.VolumeDetectActive = true; - - if (!(row["MediaURL"] is System.DBNull)) - { - //m_log.DebugFormat("[SQLITE]: MediaUrl type [{0}]", row["MediaURL"].GetType()); - prim.MediaUrl = (string)row["MediaURL"]; - } - - return prim; - } - - /// - /// Build a prim inventory item from the persisted data. - /// - /// - /// - private static TaskInventoryItem buildItem(DataRow row) - { - TaskInventoryItem taskItem = new TaskInventoryItem(); - - taskItem.ItemID = new UUID((String)row["itemID"]); - taskItem.ParentPartID = new UUID((String)row["primID"]); - taskItem.AssetID = new UUID((String)row["assetID"]); - taskItem.ParentID = new UUID((String)row["parentFolderID"]); - - taskItem.InvType = Convert.ToInt32(row["invType"]); - taskItem.Type = Convert.ToInt32(row["assetType"]); - - taskItem.Name = (String)row["name"]; - taskItem.Description = (String)row["description"]; - taskItem.CreationDate = Convert.ToUInt32(row["creationDate"]); - taskItem.CreatorID = new UUID((String)row["creatorID"]); - taskItem.OwnerID = new UUID((String)row["ownerID"]); - taskItem.LastOwnerID = new UUID((String)row["lastOwnerID"]); - taskItem.GroupID = new UUID((String)row["groupID"]); - - taskItem.NextPermissions = Convert.ToUInt32(row["nextPermissions"]); - taskItem.CurrentPermissions = Convert.ToUInt32(row["currentPermissions"]); - taskItem.BasePermissions = Convert.ToUInt32(row["basePermissions"]); - taskItem.EveryonePermissions = Convert.ToUInt32(row["everyonePermissions"]); - taskItem.GroupPermissions = Convert.ToUInt32(row["groupPermissions"]); - taskItem.Flags = Convert.ToUInt32(row["flags"]); - - return taskItem; - } - - /// - /// Build a Land Data from the persisted data. - /// - /// - /// - private LandData buildLandData(DataRow row) - { - LandData newData = new LandData(); - - newData.GlobalID = new UUID((String) row["UUID"]); - newData.LocalID = Convert.ToInt32(row["LocalLandID"]); - - // Bitmap is a byte[512] - newData.Bitmap = (Byte[]) row["Bitmap"]; - - newData.Name = (String) row["Name"]; - newData.Description = (String) row["Desc"]; - newData.OwnerID = (UUID)(String) row["OwnerUUID"]; - newData.IsGroupOwned = (Boolean) row["IsGroupOwned"]; - newData.Area = Convert.ToInt32(row["Area"]); - newData.AuctionID = Convert.ToUInt32(row["AuctionID"]); //Unemplemented - newData.Category = (ParcelCategory) Convert.ToInt32(row["Category"]); - //Enum OpenMetaverse.Parcel.ParcelCategory - newData.ClaimDate = Convert.ToInt32(row["ClaimDate"]); - newData.ClaimPrice = Convert.ToInt32(row["ClaimPrice"]); - newData.GroupID = new UUID((String) row["GroupUUID"]); - newData.SalePrice = Convert.ToInt32(row["SalePrice"]); - newData.Status = (ParcelStatus) Convert.ToInt32(row["LandStatus"]); - //Enum. OpenMetaverse.Parcel.ParcelStatus - newData.Flags = Convert.ToUInt32(row["LandFlags"]); - newData.LandingType = (Byte) row["LandingType"]; - newData.MediaAutoScale = (Byte) row["MediaAutoScale"]; - newData.MediaID = new UUID((String) row["MediaTextureUUID"]); - newData.MediaURL = (String) row["MediaURL"]; - newData.MusicURL = (String) row["MusicURL"]; - newData.PassHours = Convert.ToSingle(row["PassHours"]); - newData.PassPrice = Convert.ToInt32(row["PassPrice"]); - newData.SnapshotID = (UUID)(String) row["SnapshotUUID"]; - try - { - - newData.UserLocation = - new Vector3(Convert.ToSingle(row["UserLocationX"]), Convert.ToSingle(row["UserLocationY"]), - Convert.ToSingle(row["UserLocationZ"])); - newData.UserLookAt = - new Vector3(Convert.ToSingle(row["UserLookAtX"]), Convert.ToSingle(row["UserLookAtY"]), - Convert.ToSingle(row["UserLookAtZ"])); - - } - catch (InvalidCastException) - { - m_log.ErrorFormat("[SQLITE REGION DB]: unable to get parcel telehub settings for {1}", newData.Name); - newData.UserLocation = Vector3.Zero; - newData.UserLookAt = Vector3.Zero; - } - newData.ParcelAccessList = new List(); - UUID authBuyerID = UUID.Zero; - - UUID.TryParse((string)row["AuthbuyerID"], out authBuyerID); - - newData.OtherCleanTime = Convert.ToInt32(row["OtherCleanTime"]); - - return newData; - } - - private RegionSettings buildRegionSettings(DataRow row) - { - RegionSettings newSettings = new RegionSettings(); - - newSettings.RegionUUID = new UUID((string) row["regionUUID"]); - newSettings.BlockTerraform = Convert.ToBoolean(row["block_terraform"]); - newSettings.AllowDamage = Convert.ToBoolean(row["allow_damage"]); - newSettings.BlockFly = Convert.ToBoolean(row["block_fly"]); - newSettings.RestrictPushing = Convert.ToBoolean(row["restrict_pushing"]); - newSettings.AllowLandResell = Convert.ToBoolean(row["allow_land_resell"]); - newSettings.AllowLandJoinDivide = Convert.ToBoolean(row["allow_land_join_divide"]); - newSettings.BlockShowInSearch = Convert.ToBoolean(row["block_show_in_search"]); - newSettings.AgentLimit = Convert.ToInt32(row["agent_limit"]); - newSettings.ObjectBonus = Convert.ToDouble(row["object_bonus"]); - newSettings.Maturity = Convert.ToInt32(row["maturity"]); - newSettings.DisableScripts = Convert.ToBoolean(row["disable_scripts"]); - newSettings.DisableCollisions = Convert.ToBoolean(row["disable_collisions"]); - newSettings.DisablePhysics = Convert.ToBoolean(row["disable_physics"]); - newSettings.TerrainTexture1 = new UUID((String) row["terrain_texture_1"]); - newSettings.TerrainTexture2 = new UUID((String) row["terrain_texture_2"]); - newSettings.TerrainTexture3 = new UUID((String) row["terrain_texture_3"]); - newSettings.TerrainTexture4 = new UUID((String) row["terrain_texture_4"]); - newSettings.Elevation1NW = Convert.ToDouble(row["elevation_1_nw"]); - newSettings.Elevation2NW = Convert.ToDouble(row["elevation_2_nw"]); - newSettings.Elevation1NE = Convert.ToDouble(row["elevation_1_ne"]); - newSettings.Elevation2NE = Convert.ToDouble(row["elevation_2_ne"]); - newSettings.Elevation1SE = Convert.ToDouble(row["elevation_1_se"]); - newSettings.Elevation2SE = Convert.ToDouble(row["elevation_2_se"]); - newSettings.Elevation1SW = Convert.ToDouble(row["elevation_1_sw"]); - newSettings.Elevation2SW = Convert.ToDouble(row["elevation_2_sw"]); - newSettings.WaterHeight = Convert.ToDouble(row["water_height"]); - newSettings.TerrainRaiseLimit = Convert.ToDouble(row["terrain_raise_limit"]); - newSettings.TerrainLowerLimit = Convert.ToDouble(row["terrain_lower_limit"]); - newSettings.UseEstateSun = Convert.ToBoolean(row["use_estate_sun"]); - newSettings.Sandbox = Convert.ToBoolean(row["sandbox"]); - newSettings.SunVector = new Vector3 ( - Convert.ToSingle(row["sunvectorx"]), - Convert.ToSingle(row["sunvectory"]), - Convert.ToSingle(row["sunvectorz"]) - ); - newSettings.FixedSun = Convert.ToBoolean(row["fixed_sun"]); - newSettings.SunPosition = Convert.ToDouble(row["sun_position"]); - newSettings.Covenant = new UUID((String) row["covenant"]); - newSettings.TerrainImageID = new UUID((String)row["map_tile_ID"]); - - return newSettings; - } - - /// - /// Build a land access entry from the persisted data. - /// - /// - /// - private static ParcelManager.ParcelAccessEntry buildLandAccessData(DataRow row) - { - ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); - entry.AgentID = new UUID((string) row["AccessUUID"]); - entry.Flags = (AccessList) row["Flags"]; - entry.Time = new DateTime(); - return entry; - } - - /// - /// - /// - /// - /// - private static Array serializeTerrain(double[,] val) - { - MemoryStream str = new MemoryStream(((int)Constants.RegionSize * (int)Constants.RegionSize) *sizeof (double)); - BinaryWriter bw = new BinaryWriter(str); - - // TODO: COMPATIBILITY - Add byte-order conversions - for (int x = 0; x < (int)Constants.RegionSize; x++) - for (int y = 0; y < (int)Constants.RegionSize; y++) - bw.Write(val[x, y]); - - return str.ToArray(); - } - -// private void fillTerrainRow(DataRow row, UUID regionUUID, int rev, double[,] val) -// { -// row["RegionUUID"] = regionUUID; -// row["Revision"] = rev; - - // MemoryStream str = new MemoryStream(((int)Constants.RegionSize * (int)Constants.RegionSize)*sizeof (double)); -// BinaryWriter bw = new BinaryWriter(str); - -// // TODO: COMPATIBILITY - Add byte-order conversions - // for (int x = 0; x < (int)Constants.RegionSize; x++) - // for (int y = 0; y < (int)Constants.RegionSize; y++) -// bw.Write(val[x, y]); - -// row["Heightfield"] = str.ToArray(); -// } - - /// - /// - /// - /// - /// - /// - /// - private static void fillPrimRow(DataRow row, SceneObjectPart prim, UUID sceneGroupID, UUID regionUUID) - { - row["UUID"] = prim.UUID.ToString(); - row["RegionUUID"] = regionUUID.ToString(); - row["CreationDate"] = prim.CreationDate; - row["Name"] = prim.Name; - row["SceneGroupID"] = sceneGroupID.ToString(); - // the UUID of the root part for this SceneObjectGroup - // various text fields - row["Text"] = prim.Text; - row["Description"] = prim.Description; - row["SitName"] = prim.SitName; - row["TouchName"] = prim.TouchName; - // permissions - row["ObjectFlags"] = prim.ObjectFlags; - row["CreatorID"] = prim.CreatorID.ToString(); - row["OwnerID"] = prim.OwnerID.ToString(); - row["GroupID"] = prim.GroupID.ToString(); - row["LastOwnerID"] = prim.LastOwnerID.ToString(); - row["OwnerMask"] = prim.OwnerMask; - row["NextOwnerMask"] = prim.NextOwnerMask; - row["GroupMask"] = prim.GroupMask; - row["EveryoneMask"] = prim.EveryoneMask; - row["BaseMask"] = prim.BaseMask; - // vectors - row["PositionX"] = prim.OffsetPosition.X; - row["PositionY"] = prim.OffsetPosition.Y; - row["PositionZ"] = prim.OffsetPosition.Z; - row["GroupPositionX"] = prim.GroupPosition.X; - row["GroupPositionY"] = prim.GroupPosition.Y; - row["GroupPositionZ"] = prim.GroupPosition.Z; - row["VelocityX"] = prim.Velocity.X; - row["VelocityY"] = prim.Velocity.Y; - row["VelocityZ"] = prim.Velocity.Z; - row["AngularVelocityX"] = prim.AngularVelocity.X; - row["AngularVelocityY"] = prim.AngularVelocity.Y; - row["AngularVelocityZ"] = prim.AngularVelocity.Z; - row["AccelerationX"] = prim.Acceleration.X; - row["AccelerationY"] = prim.Acceleration.Y; - row["AccelerationZ"] = prim.Acceleration.Z; - // quaternions - row["RotationX"] = prim.RotationOffset.X; - row["RotationY"] = prim.RotationOffset.Y; - row["RotationZ"] = prim.RotationOffset.Z; - row["RotationW"] = prim.RotationOffset.W; - - // Sit target - Vector3 sitTargetPos = prim.SitTargetPositionLL; - row["SitTargetOffsetX"] = sitTargetPos.X; - row["SitTargetOffsetY"] = sitTargetPos.Y; - row["SitTargetOffsetZ"] = sitTargetPos.Z; - - Quaternion sitTargetOrient = prim.SitTargetOrientationLL; - row["SitTargetOrientW"] = sitTargetOrient.W; - row["SitTargetOrientX"] = sitTargetOrient.X; - row["SitTargetOrientY"] = sitTargetOrient.Y; - row["SitTargetOrientZ"] = sitTargetOrient.Z; - row["ColorR"] = Convert.ToInt32(prim.Color.R); - row["ColorG"] = Convert.ToInt32(prim.Color.G); - row["ColorB"] = Convert.ToInt32(prim.Color.B); - row["ColorA"] = Convert.ToInt32(prim.Color.A); - row["PayPrice"] = prim.PayPrice[0]; - row["PayButton1"] = prim.PayPrice[1]; - row["PayButton2"] = prim.PayPrice[2]; - row["PayButton3"] = prim.PayPrice[3]; - row["PayButton4"] = prim.PayPrice[4]; - - row["TextureAnimation"] = Convert.ToBase64String(prim.TextureAnimation); - row["ParticleSystem"] = Convert.ToBase64String(prim.ParticleSystem); - - row["OmegaX"] = prim.AngularVelocity.X; - row["OmegaY"] = prim.AngularVelocity.Y; - row["OmegaZ"] = prim.AngularVelocity.Z; - - row["CameraEyeOffsetX"] = prim.GetCameraEyeOffset().X; - row["CameraEyeOffsetY"] = prim.GetCameraEyeOffset().Y; - row["CameraEyeOffsetZ"] = prim.GetCameraEyeOffset().Z; - - row["CameraAtOffsetX"] = prim.GetCameraAtOffset().X; - row["CameraAtOffsetY"] = prim.GetCameraAtOffset().Y; - row["CameraAtOffsetZ"] = prim.GetCameraAtOffset().Z; - - - if ((prim.SoundFlags & 1) != 0) // Looped - { - row["LoopedSound"] = prim.Sound.ToString(); - row["LoopedSoundGain"] = prim.SoundGain; - } - else - { - row["LoopedSound"] = UUID.Zero.ToString(); - row["LoopedSoundGain"] = 0.0f; - } - - if (prim.GetForceMouselook()) - row["ForceMouselook"] = 1; - else - row["ForceMouselook"] = 0; - - row["ScriptAccessPin"] = prim.ScriptAccessPin; - - if (prim.AllowedDrop) - row["AllowedDrop"] = 1; - else - row["AllowedDrop"] = 0; - - if (prim.DIE_AT_EDGE) - row["DieAtEdge"] = 1; - else - row["DieAtEdge"] = 0; - - row["SalePrice"] = prim.SalePrice; - row["SaleType"] = Convert.ToInt16(prim.ObjectSaleType); - - // click action - row["ClickAction"] = prim.ClickAction; - - row["SalePrice"] = prim.SalePrice; - row["Material"] = prim.Material; - - row["CollisionSound"] = prim.CollisionSound.ToString(); - row["CollisionSoundVolume"] = prim.CollisionSoundVolume; - if (prim.VolumeDetectActive) - row["VolumeDetect"] = 1; - else - row["VolumeDetect"] = 0; - - row["MediaURL"] = prim.MediaUrl; - } - - /// - /// - /// - /// - /// - private static void fillItemRow(DataRow row, TaskInventoryItem taskItem) - { - row["itemID"] = taskItem.ItemID.ToString(); - row["primID"] = taskItem.ParentPartID.ToString(); - row["assetID"] = taskItem.AssetID.ToString(); - row["parentFolderID"] = taskItem.ParentID.ToString(); - - row["invType"] = taskItem.InvType; - row["assetType"] = taskItem.Type; - - row["name"] = taskItem.Name; - row["description"] = taskItem.Description; - row["creationDate"] = taskItem.CreationDate; - row["creatorID"] = taskItem.CreatorID.ToString(); - row["ownerID"] = taskItem.OwnerID.ToString(); - row["lastOwnerID"] = taskItem.LastOwnerID.ToString(); - row["groupID"] = taskItem.GroupID.ToString(); - row["nextPermissions"] = taskItem.NextPermissions; - row["currentPermissions"] = taskItem.CurrentPermissions; - row["basePermissions"] = taskItem.BasePermissions; - row["everyonePermissions"] = taskItem.EveryonePermissions; - row["groupPermissions"] = taskItem.GroupPermissions; - row["flags"] = taskItem.Flags; - } - - /// - /// - /// - /// - /// - /// - private static void fillLandRow(DataRow row, LandData land, UUID regionUUID) - { - row["UUID"] = land.GlobalID.ToString(); - row["RegionUUID"] = regionUUID.ToString(); - row["LocalLandID"] = land.LocalID; - - // Bitmap is a byte[512] - row["Bitmap"] = land.Bitmap; - - row["Name"] = land.Name; - row["Desc"] = land.Description; - row["OwnerUUID"] = land.OwnerID.ToString(); - row["IsGroupOwned"] = land.IsGroupOwned; - row["Area"] = land.Area; - row["AuctionID"] = land.AuctionID; //Unemplemented - row["Category"] = land.Category; //Enum OpenMetaverse.Parcel.ParcelCategory - row["ClaimDate"] = land.ClaimDate; - row["ClaimPrice"] = land.ClaimPrice; - row["GroupUUID"] = land.GroupID.ToString(); - row["SalePrice"] = land.SalePrice; - row["LandStatus"] = land.Status; //Enum. OpenMetaverse.Parcel.ParcelStatus - row["LandFlags"] = land.Flags; - row["LandingType"] = land.LandingType; - row["MediaAutoScale"] = land.MediaAutoScale; - row["MediaTextureUUID"] = land.MediaID.ToString(); - row["MediaURL"] = land.MediaURL; - row["MusicURL"] = land.MusicURL; - row["PassHours"] = land.PassHours; - row["PassPrice"] = land.PassPrice; - row["SnapshotUUID"] = land.SnapshotID.ToString(); - row["UserLocationX"] = land.UserLocation.X; - row["UserLocationY"] = land.UserLocation.Y; - row["UserLocationZ"] = land.UserLocation.Z; - row["UserLookAtX"] = land.UserLookAt.X; - row["UserLookAtY"] = land.UserLookAt.Y; - row["UserLookAtZ"] = land.UserLookAt.Z; - row["AuthbuyerID"] = land.AuthBuyerID.ToString(); - row["OtherCleanTime"] = land.OtherCleanTime; - row["MediaType"] = land.MediaType; - row["MediaDescription"] = land.MediaDescription; - row["MediaSize"] = land.MediaWidth.ToString() + "," + land.MediaHeight.ToString(); - row["MediaLoop"] = land.MediaLoop.ToString(); - row["ObscureMusic"] = land.ObscureMusic.ToString(); - row["ObscureMedia"] = land.ObscureMedia.ToString(); - } - - /// - /// - /// - /// - /// - /// - private static void fillLandAccessRow(DataRow row, ParcelManager.ParcelAccessEntry entry, UUID parcelID) - { - row["LandUUID"] = parcelID.ToString(); - row["AccessUUID"] = entry.AgentID.ToString(); - row["Flags"] = entry.Flags; - } - - private static void fillRegionSettingsRow(DataRow row, RegionSettings settings) - { - row["regionUUID"] = settings.RegionUUID.ToString(); - row["block_terraform"] = settings.BlockTerraform; - row["block_fly"] = settings.BlockFly; - row["allow_damage"] = settings.AllowDamage; - row["restrict_pushing"] = settings.RestrictPushing; - row["allow_land_resell"] = settings.AllowLandResell; - row["allow_land_join_divide"] = settings.AllowLandJoinDivide; - row["block_show_in_search"] = settings.BlockShowInSearch; - row["agent_limit"] = settings.AgentLimit; - row["object_bonus"] = settings.ObjectBonus; - row["maturity"] = settings.Maturity; - row["disable_scripts"] = settings.DisableScripts; - row["disable_collisions"] = settings.DisableCollisions; - row["disable_physics"] = settings.DisablePhysics; - row["terrain_texture_1"] = settings.TerrainTexture1.ToString(); - row["terrain_texture_2"] = settings.TerrainTexture2.ToString(); - row["terrain_texture_3"] = settings.TerrainTexture3.ToString(); - row["terrain_texture_4"] = settings.TerrainTexture4.ToString(); - row["elevation_1_nw"] = settings.Elevation1NW; - row["elevation_2_nw"] = settings.Elevation2NW; - row["elevation_1_ne"] = settings.Elevation1NE; - row["elevation_2_ne"] = settings.Elevation2NE; - row["elevation_1_se"] = settings.Elevation1SE; - row["elevation_2_se"] = settings.Elevation2SE; - row["elevation_1_sw"] = settings.Elevation1SW; - row["elevation_2_sw"] = settings.Elevation2SW; - row["water_height"] = settings.WaterHeight; - row["terrain_raise_limit"] = settings.TerrainRaiseLimit; - row["terrain_lower_limit"] = settings.TerrainLowerLimit; - row["use_estate_sun"] = settings.UseEstateSun; - row["Sandbox"] = settings.Sandbox; // database uses upper case S for sandbox - row["sunvectorx"] = settings.SunVector.X; - row["sunvectory"] = settings.SunVector.Y; - row["sunvectorz"] = settings.SunVector.Z; - row["fixed_sun"] = settings.FixedSun; - row["sun_position"] = settings.SunPosition; - row["covenant"] = settings.Covenant.ToString(); - row["map_tile_ID"] = settings.TerrainImageID.ToString(); - } - - /// - /// - /// - /// - /// - private PrimitiveBaseShape buildShape(DataRow row) - { - PrimitiveBaseShape s = new PrimitiveBaseShape(); - s.Scale = new Vector3( - Convert.ToSingle(row["ScaleX"]), - Convert.ToSingle(row["ScaleY"]), - Convert.ToSingle(row["ScaleZ"]) - ); - // paths - s.PCode = Convert.ToByte(row["PCode"]); - s.PathBegin = Convert.ToUInt16(row["PathBegin"]); - s.PathEnd = Convert.ToUInt16(row["PathEnd"]); - s.PathScaleX = Convert.ToByte(row["PathScaleX"]); - s.PathScaleY = Convert.ToByte(row["PathScaleY"]); - s.PathShearX = Convert.ToByte(row["PathShearX"]); - s.PathShearY = Convert.ToByte(row["PathShearY"]); - s.PathSkew = Convert.ToSByte(row["PathSkew"]); - s.PathCurve = Convert.ToByte(row["PathCurve"]); - s.PathRadiusOffset = Convert.ToSByte(row["PathRadiusOffset"]); - s.PathRevolutions = Convert.ToByte(row["PathRevolutions"]); - s.PathTaperX = Convert.ToSByte(row["PathTaperX"]); - s.PathTaperY = Convert.ToSByte(row["PathTaperY"]); - s.PathTwist = Convert.ToSByte(row["PathTwist"]); - s.PathTwistBegin = Convert.ToSByte(row["PathTwistBegin"]); - // profile - s.ProfileBegin = Convert.ToUInt16(row["ProfileBegin"]); - s.ProfileEnd = Convert.ToUInt16(row["ProfileEnd"]); - s.ProfileCurve = Convert.ToByte(row["ProfileCurve"]); - s.ProfileHollow = Convert.ToUInt16(row["ProfileHollow"]); - s.State = Convert.ToByte(row["State"]); - - byte[] textureEntry = (byte[])row["Texture"]; - s.TextureEntry = textureEntry; - - s.ExtraParams = (byte[]) row["ExtraParams"]; - - if (!(row["Media"] is System.DBNull)) - s.Media = PrimitiveBaseShape.MediaList.FromXml((string)row["Media"]); - - return s; - } - - /// - /// - /// - /// - /// - private static void fillShapeRow(DataRow row, SceneObjectPart prim) - { - PrimitiveBaseShape s = prim.Shape; - row["UUID"] = prim.UUID.ToString(); - // shape is an enum - row["Shape"] = 0; - // vectors - row["ScaleX"] = s.Scale.X; - row["ScaleY"] = s.Scale.Y; - row["ScaleZ"] = s.Scale.Z; - // paths - row["PCode"] = s.PCode; - row["PathBegin"] = s.PathBegin; - row["PathEnd"] = s.PathEnd; - row["PathScaleX"] = s.PathScaleX; - row["PathScaleY"] = s.PathScaleY; - row["PathShearX"] = s.PathShearX; - row["PathShearY"] = s.PathShearY; - row["PathSkew"] = s.PathSkew; - row["PathCurve"] = s.PathCurve; - row["PathRadiusOffset"] = s.PathRadiusOffset; - row["PathRevolutions"] = s.PathRevolutions; - row["PathTaperX"] = s.PathTaperX; - row["PathTaperY"] = s.PathTaperY; - row["PathTwist"] = s.PathTwist; - row["PathTwistBegin"] = s.PathTwistBegin; - // profile - row["ProfileBegin"] = s.ProfileBegin; - row["ProfileEnd"] = s.ProfileEnd; - row["ProfileCurve"] = s.ProfileCurve; - row["ProfileHollow"] = s.ProfileHollow; - row["State"] = s.State; - - row["Texture"] = s.TextureEntry; - row["ExtraParams"] = s.ExtraParams; - - if (s.Media != null) - row["Media"] = s.Media.ToXml(); - } - - /// - /// Persistently store a prim. - /// - /// - /// - /// - private void addPrim(SceneObjectPart prim, UUID sceneGroupID, UUID regionUUID) - { - DataTable prims = ds.Tables["prims"]; - DataTable shapes = ds.Tables["primshapes"]; - - DataRow primRow = prims.Rows.Find(prim.UUID.ToString()); - if (primRow == null) - { - primRow = prims.NewRow(); - fillPrimRow(primRow, prim, sceneGroupID, regionUUID); - prims.Rows.Add(primRow); - } - else - { - fillPrimRow(primRow, prim, sceneGroupID, regionUUID); - } - - DataRow shapeRow = shapes.Rows.Find(prim.UUID.ToString()); - if (shapeRow == null) - { - shapeRow = shapes.NewRow(); - fillShapeRow(shapeRow, prim); - shapes.Rows.Add(shapeRow); - } - else - { - fillShapeRow(shapeRow, prim); - } - } - - /// - /// see IRegionDatastore - /// - /// - /// - public void StorePrimInventory(UUID primID, ICollection items) - { -// m_log.DebugFormat("[SQLITE REGION DB]: Entered StorePrimInventory with prim ID {0}", primID); - - DataTable dbItems = ds.Tables["primitems"]; - - // For now, we're just going to crudely remove all the previous inventory items - // no matter whether they have changed or not, and replace them with the current set. - lock (ds) - { - RemoveItems(primID); - - // repalce with current inventory details - foreach (TaskInventoryItem newItem in items) - { -// m_log.InfoFormat( -// "[DATASTORE]: ", -// "Adding item {0}, {1} to prim ID {2}", -// newItem.Name, newItem.ItemID, newItem.ParentPartID); - - DataRow newItemRow = dbItems.NewRow(); - fillItemRow(newItemRow, newItem); - dbItems.Rows.Add(newItemRow); - } - } - - Commit(); - } - - /*********************************************************************** - * - * SQL Statement Creation Functions - * - * These functions create SQL statements for update, insert, and create. - * They can probably be factored later to have a db independant - * portion and a db specific portion - * - **********************************************************************/ - - /// - /// Create an insert command - /// - /// table name - /// data table - /// the created command - /// - /// This is subtle enough to deserve some commentary. - /// Instead of doing *lots* and *lots of hardcoded strings - /// for database definitions we'll use the fact that - /// realistically all insert statements look like "insert - /// into A(b, c) values(:b, :c) on the parameterized query - /// front. If we just have a list of b, c, etc... we can - /// generate these strings instead of typing them out. - /// - private static SqliteCommand createInsertCommand(string table, DataTable dt) - { - string[] cols = new string[dt.Columns.Count]; - for (int i = 0; i < dt.Columns.Count; i++) - { - DataColumn col = dt.Columns[i]; - cols[i] = col.ColumnName; - } - - string sql = "insert into " + table + "("; - sql += String.Join(", ", cols); - // important, the first ':' needs to be here, the rest get added in the join - sql += ") values (:"; - sql += String.Join(", :", cols); - sql += ")"; - //m_log.DebugFormat("[SQLITE]: Created insert command {0}", sql); - SqliteCommand cmd = new SqliteCommand(sql); - - // this provides the binding for all our parameters, so - // much less code than it used to be - foreach (DataColumn col in dt.Columns) - { - cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType)); - } - return cmd; - } - - - /// - /// create an update command - /// - /// table name - /// - /// - /// the created command - private static SqliteCommand createUpdateCommand(string table, string pk, DataTable dt) - { - string sql = "update " + table + " set "; - string subsql = String.Empty; - foreach (DataColumn col in dt.Columns) - { - if (subsql.Length > 0) - { - // a map function would rock so much here - subsql += ", "; - } - subsql += col.ColumnName + "= :" + col.ColumnName; - } - sql += subsql; - sql += " where " + pk; - SqliteCommand cmd = new SqliteCommand(sql); - - // this provides the binding for all our parameters, so - // much less code than it used to be - - foreach (DataColumn col in dt.Columns) - { - cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType)); - } - return cmd; - } - - /// - /// create an update command - /// - /// table name - /// - /// - /// the created command - private static SqliteCommand createUpdateCommand(string table, string pk1, string pk2, DataTable dt) - { - string sql = "update " + table + " set "; - string subsql = String.Empty; - foreach (DataColumn col in dt.Columns) - { - if (subsql.Length > 0) - { - // a map function would rock so much here - subsql += ", "; - } - subsql += col.ColumnName + "= :" + col.ColumnName; - } - sql += subsql; - sql += " where " + pk1 + " and " + pk2; - SqliteCommand cmd = new SqliteCommand(sql); - - // this provides the binding for all our parameters, so - // much less code than it used to be - - foreach (DataColumn col in dt.Columns) - { - cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType)); - } - return cmd; - } - - /// - /// - /// - /// Data Table - /// - // private static string defineTable(DataTable dt) - // { - // string sql = "create table " + dt.TableName + "("; - // string subsql = String.Empty; - // foreach (DataColumn col in dt.Columns) - // { - // if (subsql.Length > 0) - // { - // // a map function would rock so much here - // subsql += ",\n"; - // } - // subsql += col.ColumnName + " " + sqliteType(col.DataType); - // if (dt.PrimaryKey.Length > 0 && col == dt.PrimaryKey[0]) - // { - // subsql += " primary key"; - // } - // } - // sql += subsql; - // sql += ")"; - // return sql; - // } - - /*********************************************************************** - * - * Database Binding functions - * - * These will be db specific due to typing, and minor differences - * in databases. - * - **********************************************************************/ - - /// - /// This is a convenience function that collapses 5 repetitive - /// lines for defining SqliteParameters to 2 parameters: - /// column name and database type. - /// - /// It assumes certain conventions like :param as the param - /// name to replace in parametrized queries, and that source - /// version is always current version, both of which are fine - /// for us. - /// - ///a built sqlite parameter - private static SqliteParameter createSqliteParameter(string name, Type type) - { - SqliteParameter param = new SqliteParameter(); - param.ParameterName = ":" + name; - param.DbType = dbtypeFromType(type); - param.SourceColumn = name; - param.SourceVersion = DataRowVersion.Current; - return param; - } - - /// - /// - /// - /// - /// - private void setupPrimCommands(SqliteDataAdapter da, SqliteConnection conn) - { - da.InsertCommand = createInsertCommand("prims", ds.Tables["prims"]); - da.InsertCommand.Connection = conn; - - da.UpdateCommand = createUpdateCommand("prims", "UUID=:UUID", ds.Tables["prims"]); - da.UpdateCommand.Connection = conn; - - SqliteCommand delete = new SqliteCommand("delete from prims where UUID = :UUID"); - delete.Parameters.Add(createSqliteParameter("UUID", typeof (String))); - delete.Connection = conn; - da.DeleteCommand = delete; - } - - /// - /// - /// - /// - /// - private void setupItemsCommands(SqliteDataAdapter da, SqliteConnection conn) - { - da.InsertCommand = createInsertCommand("primitems", ds.Tables["primitems"]); - da.InsertCommand.Connection = conn; - - da.UpdateCommand = createUpdateCommand("primitems", "itemID = :itemID", ds.Tables["primitems"]); - da.UpdateCommand.Connection = conn; - - SqliteCommand delete = new SqliteCommand("delete from primitems where itemID = :itemID"); - delete.Parameters.Add(createSqliteParameter("itemID", typeof (String))); - delete.Connection = conn; - da.DeleteCommand = delete; - } - - /// - /// - /// - /// - /// - private void setupTerrainCommands(SqliteDataAdapter da, SqliteConnection conn) - { - da.InsertCommand = createInsertCommand("terrain", ds.Tables["terrain"]); - da.InsertCommand.Connection = conn; - } - - /// - /// - /// - /// - /// - private void setupLandCommands(SqliteDataAdapter da, SqliteConnection conn) - { - da.InsertCommand = createInsertCommand("land", ds.Tables["land"]); - da.InsertCommand.Connection = conn; - - da.UpdateCommand = createUpdateCommand("land", "UUID=:UUID", ds.Tables["land"]); - da.UpdateCommand.Connection = conn; - - SqliteCommand delete = new SqliteCommand("delete from land where UUID=:UUID"); - delete.Parameters.Add(createSqliteParameter("UUID", typeof(String))); - da.DeleteCommand = delete; - da.DeleteCommand.Connection = conn; - } - - /// - /// - /// - /// - /// - private void setupLandAccessCommands(SqliteDataAdapter da, SqliteConnection conn) - { - da.InsertCommand = createInsertCommand("landaccesslist", ds.Tables["landaccesslist"]); - da.InsertCommand.Connection = conn; - - da.UpdateCommand = createUpdateCommand("landaccesslist", "LandUUID=:landUUID", "AccessUUID=:AccessUUID", ds.Tables["landaccesslist"]); - da.UpdateCommand.Connection = conn; - - SqliteCommand delete = new SqliteCommand("delete from landaccesslist where LandUUID= :LandUUID and AccessUUID= :AccessUUID"); - delete.Parameters.Add(createSqliteParameter("LandUUID", typeof(String))); - delete.Parameters.Add(createSqliteParameter("AccessUUID", typeof(String))); - da.DeleteCommand = delete; - da.DeleteCommand.Connection = conn; - - } - - private void setupRegionSettingsCommands(SqliteDataAdapter da, SqliteConnection conn) - { - da.InsertCommand = createInsertCommand("regionsettings", ds.Tables["regionsettings"]); - da.InsertCommand.Connection = conn; - da.UpdateCommand = createUpdateCommand("regionsettings", "regionUUID=:regionUUID", ds.Tables["regionsettings"]); - da.UpdateCommand.Connection = conn; - } - - /// - /// - /// - /// - /// - private void setupShapeCommands(SqliteDataAdapter da, SqliteConnection conn) - { - da.InsertCommand = createInsertCommand("primshapes", ds.Tables["primshapes"]); - da.InsertCommand.Connection = conn; - - da.UpdateCommand = createUpdateCommand("primshapes", "UUID=:UUID", ds.Tables["primshapes"]); - da.UpdateCommand.Connection = conn; - - SqliteCommand delete = new SqliteCommand("delete from primshapes where UUID = :UUID"); - delete.Parameters.Add(createSqliteParameter("UUID", typeof (String))); - delete.Connection = conn; - da.DeleteCommand = delete; - } - - /*********************************************************************** - * - * Type conversion functions - * - **********************************************************************/ - - /// - /// Type conversion function - /// - /// - /// - private static DbType dbtypeFromType(Type type) - { - if (type == typeof (String)) - { - return DbType.String; - } - else if (type == typeof (Int32)) - { - return DbType.Int32; - } - else if (type == typeof (Double)) - { - return DbType.Double; - } - else if (type == typeof (Byte)) - { - return DbType.Byte; - } - else if (type == typeof (Double)) - { - return DbType.Double; - } - else if (type == typeof (Byte[])) - { - return DbType.Binary; - } - else - { - return DbType.String; - } - } - - static void PrintDataSet(DataSet ds) - { - // Print out any name and extended properties. - Console.WriteLine("DataSet is named: {0}", ds.DataSetName); - foreach (System.Collections.DictionaryEntry de in ds.ExtendedProperties) - { - Console.WriteLine("Key = {0}, Value = {1}", de.Key, de.Value); - } - Console.WriteLine(); - foreach (DataTable dt in ds.Tables) - { - Console.WriteLine("=> {0} Table:", dt.TableName); - // Print out the column names. - for (int curCol = 0; curCol < dt.Columns.Count; curCol++) - { - Console.Write(dt.Columns[curCol].ColumnName + "\t"); - } - Console.WriteLine("\n----------------------------------"); - // Print the DataTable. - for (int curRow = 0; curRow < dt.Rows.Count; curRow++) - { - for (int curCol = 0; curCol < dt.Columns.Count; curCol++) - { - Console.Write(dt.Rows[curRow][curCol].ToString() + "\t"); - } - Console.WriteLine(); - } - } - } - - } -} diff --git a/OpenSim/Data/SQLite/SQLiteSimulationData.cs b/OpenSim/Data/SQLite/SQLiteSimulationData.cs new file mode 100644 index 0000000..55c27b2 --- /dev/null +++ b/OpenSim/Data/SQLite/SQLiteSimulationData.cs @@ -0,0 +1,2355 @@ +/* + * 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.Data; +using System.Drawing; +using System.IO; +using System.Reflection; +using log4net; +using Mono.Data.Sqlite; +using OpenMetaverse; +using OpenMetaverse.StructuredData; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Data.SQLite +{ + /// + /// A RegionData Interface to the SQLite database + /// + public class SQLiteSimulationData : ISimulationDataStore + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private const string primSelect = "select * from prims"; + private const string shapeSelect = "select * from primshapes"; + private const string itemsSelect = "select * from primitems"; + private const string terrainSelect = "select * from terrain limit 1"; + private const string landSelect = "select * from land"; + private const string landAccessListSelect = "select distinct * from landaccesslist"; + private const string regionbanListSelect = "select * from regionban"; + private const string regionSettingsSelect = "select * from regionsettings"; + + private DataSet ds; + private SqliteDataAdapter primDa; + private SqliteDataAdapter shapeDa; + private SqliteDataAdapter itemsDa; + private SqliteDataAdapter terrainDa; + private SqliteDataAdapter landDa; + private SqliteDataAdapter landAccessListDa; + private SqliteDataAdapter regionSettingsDa; + + private SqliteConnection m_conn; + + private String m_connectionString; + + // Temporary attribute while this is experimental + + /*********************************************************************** + * + * Public Interface Functions + * + **********************************************************************/ + + /// + /// See IRegionDataStore + /// + /// Initialises RegionData Interface + /// Loads and initialises a new SQLite connection and maintains it. + /// + /// + /// the connection string + public void Initialise(string connectionString) + { + try + { + m_connectionString = connectionString; + + ds = new DataSet("Region"); + + m_log.Info("[SQLITE REGION DB]: Sqlite - connecting: " + connectionString); + m_conn = new SqliteConnection(m_connectionString); + m_conn.Open(); + + SqliteCommand primSelectCmd = new SqliteCommand(primSelect, m_conn); + primDa = new SqliteDataAdapter(primSelectCmd); + + SqliteCommand shapeSelectCmd = new SqliteCommand(shapeSelect, m_conn); + shapeDa = new SqliteDataAdapter(shapeSelectCmd); + // SqliteCommandBuilder shapeCb = new SqliteCommandBuilder(shapeDa); + + SqliteCommand itemsSelectCmd = new SqliteCommand(itemsSelect, m_conn); + itemsDa = new SqliteDataAdapter(itemsSelectCmd); + + SqliteCommand terrainSelectCmd = new SqliteCommand(terrainSelect, m_conn); + terrainDa = new SqliteDataAdapter(terrainSelectCmd); + + SqliteCommand landSelectCmd = new SqliteCommand(landSelect, m_conn); + landDa = new SqliteDataAdapter(landSelectCmd); + + SqliteCommand landAccessListSelectCmd = new SqliteCommand(landAccessListSelect, m_conn); + landAccessListDa = new SqliteDataAdapter(landAccessListSelectCmd); + + SqliteCommand regionSettingsSelectCmd = new SqliteCommand(regionSettingsSelect, m_conn); + regionSettingsDa = new SqliteDataAdapter(regionSettingsSelectCmd); + // This actually does the roll forward assembly stuff + Assembly assem = GetType().Assembly; + Migration m = new Migration(m_conn, assem, "RegionStore"); + m.Update(); + + lock (ds) + { + ds.Tables.Add(createPrimTable()); + setupPrimCommands(primDa, m_conn); + + ds.Tables.Add(createShapeTable()); + setupShapeCommands(shapeDa, m_conn); + + ds.Tables.Add(createItemsTable()); + setupItemsCommands(itemsDa, m_conn); + + ds.Tables.Add(createTerrainTable()); + setupTerrainCommands(terrainDa, m_conn); + + ds.Tables.Add(createLandTable()); + setupLandCommands(landDa, m_conn); + + ds.Tables.Add(createLandAccessListTable()); + setupLandAccessCommands(landAccessListDa, m_conn); + + ds.Tables.Add(createRegionSettingsTable()); + setupRegionSettingsCommands(regionSettingsDa, m_conn); + + // WORKAROUND: This is a work around for sqlite on + // windows, which gets really unhappy with blob columns + // that have no sample data in them. At some point we + // need to actually find a proper way to handle this. + try + { + primDa.Fill(ds.Tables["prims"]); + } + catch (Exception) + { + m_log.Info("[SQLITE REGION DB]: Caught fill error on prims table"); + } + + try + { + shapeDa.Fill(ds.Tables["primshapes"]); + } + catch (Exception) + { + m_log.Info("[SQLITE REGION DB]: Caught fill error on primshapes table"); + } + + try + { + itemsDa.Fill(ds.Tables["primitems"]); + } + catch (Exception) + { + m_log.Info("[SQLITE REGION DB]: Caught fill error on primitems table"); + } + + try + { + terrainDa.Fill(ds.Tables["terrain"]); + } + catch (Exception) + { + m_log.Info("[SQLITE REGION DB]: Caught fill error on terrain table"); + } + + try + { + landDa.Fill(ds.Tables["land"]); + } + catch (Exception) + { + m_log.Info("[SQLITE REGION DB]: Caught fill error on land table"); + } + + try + { + landAccessListDa.Fill(ds.Tables["landaccesslist"]); + } + catch (Exception) + { + m_log.Info("[SQLITE REGION DB]: Caught fill error on landaccesslist table"); + } + + try + { + regionSettingsDa.Fill(ds.Tables["regionsettings"]); + } + catch (Exception) + { + m_log.Info("[SQLITE REGION DB]: Caught fill error on regionsettings table"); + } + + // We have to create a data set mapping for every table, otherwise the IDataAdaptor.Update() will not populate rows with values! + // Not sure exactly why this is - this kind of thing was not necessary before - justincc 20100409 + // Possibly because we manually set up our own DataTables before connecting to the database + CreateDataSetMapping(primDa, "prims"); + CreateDataSetMapping(shapeDa, "primshapes"); + CreateDataSetMapping(itemsDa, "primitems"); + CreateDataSetMapping(terrainDa, "terrain"); + CreateDataSetMapping(landDa, "land"); + CreateDataSetMapping(landAccessListDa, "landaccesslist"); + CreateDataSetMapping(regionSettingsDa, "regionsettings"); + } + } + catch (Exception e) + { + m_log.Error(e); + Environment.Exit(23); + } + + return; + } + + public void Dispose() + { + if (m_conn != null) + { + m_conn.Close(); + m_conn = null; + } + if (ds != null) + { + ds.Dispose(); + ds = null; + } + if (primDa != null) + { + primDa.Dispose(); + primDa = null; + } + if (shapeDa != null) + { + shapeDa.Dispose(); + shapeDa = null; + } + if (itemsDa != null) + { + itemsDa.Dispose(); + itemsDa = null; + } + if (terrainDa != null) + { + terrainDa.Dispose(); + terrainDa = null; + } + if (landDa != null) + { + landDa.Dispose(); + landDa = null; + } + if (landAccessListDa != null) + { + landAccessListDa.Dispose(); + landAccessListDa = null; + } + if (regionSettingsDa != null) + { + regionSettingsDa.Dispose(); + regionSettingsDa = null; + } + } + + public void StoreRegionSettings(RegionSettings rs) + { + lock (ds) + { + DataTable regionsettings = ds.Tables["regionsettings"]; + + DataRow settingsRow = regionsettings.Rows.Find(rs.RegionUUID.ToString()); + if (settingsRow == null) + { + settingsRow = regionsettings.NewRow(); + fillRegionSettingsRow(settingsRow, rs); + regionsettings.Rows.Add(settingsRow); + } + else + { + fillRegionSettingsRow(settingsRow, rs); + } + + Commit(); + } + } + public RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID) + { + //This connector doesn't support the windlight module yet + //Return default LL windlight settings + return new RegionLightShareData(); + } + public void StoreRegionWindlightSettings(RegionLightShareData wl) + { + //This connector doesn't support the windlight module yet + } + public RegionSettings LoadRegionSettings(UUID regionUUID) + { + lock (ds) + { + DataTable regionsettings = ds.Tables["regionsettings"]; + + string searchExp = "regionUUID = '" + regionUUID.ToString() + "'"; + DataRow[] rawsettings = regionsettings.Select(searchExp); + if (rawsettings.Length == 0) + { + RegionSettings rs = new RegionSettings(); + rs.RegionUUID = regionUUID; + rs.OnSave += StoreRegionSettings; + + StoreRegionSettings(rs); + + return rs; + } + DataRow row = rawsettings[0]; + + RegionSettings newSettings = buildRegionSettings(row); + newSettings.OnSave += StoreRegionSettings; + + return newSettings; + } + } + + /// + /// Adds an object into region storage + /// + /// the object + /// the region UUID + public void StoreObject(SceneObjectGroup obj, UUID regionUUID) + { + uint flags = obj.RootPart.GetEffectiveObjectFlags(); + + // Eligibility check + // + if ((flags & (uint)PrimFlags.Temporary) != 0) + return; + if ((flags & (uint)PrimFlags.TemporaryOnRez) != 0) + return; + + lock (ds) + { + foreach (SceneObjectPart prim in obj.Children.Values) + { +// m_log.Info("[REGION DB]: Adding obj: " + obj.UUID + " to region: " + regionUUID); + addPrim(prim, obj.UUID, regionUUID); + } + } + + Commit(); + // m_log.Info("[Dump of prims]: " + ds.GetXml()); + } + + /// + /// Removes an object from region storage + /// + /// the object + /// the region UUID + public void RemoveObject(UUID obj, UUID regionUUID) + { + // m_log.InfoFormat("[REGION DB]: Removing obj: {0} from region: {1}", obj.Guid, regionUUID); + + DataTable prims = ds.Tables["prims"]; + DataTable shapes = ds.Tables["primshapes"]; + + string selectExp = "SceneGroupID = '" + obj + "' and RegionUUID = '" + regionUUID + "'"; + lock (ds) + { + DataRow[] primRows = prims.Select(selectExp); + foreach (DataRow row in primRows) + { + // Remove shape rows + UUID uuid = new UUID((string) row["UUID"]); + DataRow shapeRow = shapes.Rows.Find(uuid.ToString()); + if (shapeRow != null) + { + shapeRow.Delete(); + } + + RemoveItems(uuid); + + // Remove prim row + row.Delete(); + } + } + + Commit(); + } + + /// + /// Remove all persisted items of the given prim. + /// The caller must acquire the necessrary synchronization locks and commit or rollback changes. + /// + /// The item UUID + private void RemoveItems(UUID uuid) + { + DataTable items = ds.Tables["primitems"]; + + String sql = String.Format("primID = '{0}'", uuid); + DataRow[] itemRows = items.Select(sql); + + foreach (DataRow itemRow in itemRows) + { + itemRow.Delete(); + } + } + + /// + /// Load persisted objects from region storage. + /// + /// The region UUID + /// List of loaded groups + public List LoadObjects(UUID regionUUID) + { + Dictionary createdObjects = new Dictionary(); + + List retvals = new List(); + + DataTable prims = ds.Tables["prims"]; + DataTable shapes = ds.Tables["primshapes"]; + + string byRegion = "RegionUUID = '" + regionUUID + "'"; + + lock (ds) + { + DataRow[] primsForRegion = prims.Select(byRegion); +// m_log.Info("[SQLITE REGION DB]: Loaded " + primsForRegion.Length + " prims for region: " + regionUUID); + + // First, create all groups + foreach (DataRow primRow in primsForRegion) + { + try + { + SceneObjectPart prim = null; + + string uuid = (string) primRow["UUID"]; + string objID = (string) primRow["SceneGroupID"]; + + if (uuid == objID) //is new SceneObjectGroup ? + { + prim = buildPrim(primRow); + DataRow shapeRow = shapes.Rows.Find(prim.UUID.ToString()); + if (shapeRow != null) + { + prim.Shape = buildShape(shapeRow); + } + else + { + m_log.Warn( + "[SQLITE REGION DB]: No shape found for prim in storage, so setting default box shape"); + prim.Shape = PrimitiveBaseShape.Default; + } + + SceneObjectGroup group = new SceneObjectGroup(prim); + createdObjects.Add(group.UUID, group); + retvals.Add(group); + LoadItems(prim); + } + } + catch (Exception e) + { + m_log.Error("[SQLITE REGION DB]: Failed create prim object in new group, exception and data follows"); + m_log.Error("[SQLITE REGION DB]: ", e); + foreach (DataColumn col in prims.Columns) + { + m_log.Error("[SQLITE REGION DB]: Col: " + col.ColumnName + " => " + primRow[col]); + } + } + } + + // Now fill the groups with part data + foreach (DataRow primRow in primsForRegion) + { + try + { + SceneObjectPart prim = null; + + string uuid = (string) primRow["UUID"]; + string objID = (string) primRow["SceneGroupID"]; + if (uuid != objID) //is new SceneObjectGroup ? + { + prim = buildPrim(primRow); + DataRow shapeRow = shapes.Rows.Find(prim.UUID.ToString()); + if (shapeRow != null) + { + prim.Shape = buildShape(shapeRow); + } + else + { + m_log.Warn( + "[SQLITE REGION DB]: No shape found for prim in storage, so setting default box shape"); + prim.Shape = PrimitiveBaseShape.Default; + } + + createdObjects[new UUID(objID)].AddPart(prim); + LoadItems(prim); + } + } + catch (Exception e) + { + m_log.Error("[SQLITE REGION DB]: Failed create prim object in group, exception and data follows"); + m_log.Error("[SQLITE REGION DB]: ", e); + foreach (DataColumn col in prims.Columns) + { + m_log.Error("[SQLITE REGION DB]: Col: " + col.ColumnName + " => " + primRow[col]); + } + } + } + } + return retvals; + } + + /// + /// Load in a prim's persisted inventory. + /// + /// the prim + private void LoadItems(SceneObjectPart prim) + { +// m_log.DebugFormat("[SQLITE REGION DB]: Loading inventory for {0} {1}", prim.Name, prim.UUID); + + DataTable dbItems = ds.Tables["primitems"]; + String sql = String.Format("primID = '{0}'", prim.UUID.ToString()); + DataRow[] dbItemRows = dbItems.Select(sql); + IList inventory = new List(); + +// m_log.DebugFormat( +// "[SQLITE REGION DB]: Found {0} items for {1} {2}", dbItemRows.Length, prim.Name, prim.UUID); + + foreach (DataRow row in dbItemRows) + { + TaskInventoryItem item = buildItem(row); + inventory.Add(item); + +// m_log.DebugFormat("[SQLITE REGION DB]: Restored item {0} {1}", item.Name, item.ItemID); + } + + prim.Inventory.RestoreInventoryItems(inventory); + } + + /// + /// Store a terrain revision in region storage + /// + /// terrain heightfield + /// region UUID + public void StoreTerrain(double[,] ter, UUID regionID) + { + lock (ds) + { + int revision = Util.UnixTimeSinceEpoch(); + + // This is added to get rid of the infinitely growing + // terrain databases which negatively impact on SQLite + // over time. Before reenabling this feature there + // needs to be a limitter put on the number of + // revisions in the database, as this old + // implementation is a DOS attack waiting to happen. + + using ( + SqliteCommand cmd = + new SqliteCommand("delete from terrain where RegionUUID=:RegionUUID and Revision <= :Revision", + m_conn)) + { + cmd.Parameters.Add(new SqliteParameter(":RegionUUID", regionID.ToString())); + cmd.Parameters.Add(new SqliteParameter(":Revision", revision)); + cmd.ExecuteNonQuery(); + } + + // the following is an work around for .NET. The perf + // issues associated with it aren't as bad as you think. + m_log.Debug("[SQLITE REGION DB]: Storing terrain revision r" + revision.ToString()); + String sql = "insert into terrain(RegionUUID, Revision, Heightfield)" + + " values(:RegionUUID, :Revision, :Heightfield)"; + + using (SqliteCommand cmd = new SqliteCommand(sql, m_conn)) + { + cmd.Parameters.Add(new SqliteParameter(":RegionUUID", regionID.ToString())); + cmd.Parameters.Add(new SqliteParameter(":Revision", revision)); + cmd.Parameters.Add(new SqliteParameter(":Heightfield", serializeTerrain(ter))); + cmd.ExecuteNonQuery(); + } + } + } + + /// + /// Load the latest terrain revision from region storage + /// + /// the region UUID + /// Heightfield data + public double[,] LoadTerrain(UUID regionID) + { + lock (ds) + { + double[,] terret = new double[(int)Constants.RegionSize, (int)Constants.RegionSize]; + terret.Initialize(); + + String sql = "select RegionUUID, Revision, Heightfield from terrain" + + " where RegionUUID=:RegionUUID order by Revision desc"; + + using (SqliteCommand cmd = new SqliteCommand(sql, m_conn)) + { + cmd.Parameters.Add(new SqliteParameter(":RegionUUID", regionID.ToString())); + + using (IDataReader row = cmd.ExecuteReader()) + { + int rev = 0; + if (row.Read()) + { + // TODO: put this into a function + using (MemoryStream str = new MemoryStream((byte[])row["Heightfield"])) + { + using (BinaryReader br = new BinaryReader(str)) + { + for (int x = 0; x < (int)Constants.RegionSize; x++) + { + for (int y = 0; y < (int)Constants.RegionSize; y++) + { + terret[x, y] = br.ReadDouble(); + } + } + } + } + rev = Convert.ToInt32(row["Revision"]); + } + else + { + m_log.Warn("[SQLITE REGION DB]: No terrain found for region"); + return null; + } + + m_log.Debug("[SQLITE REGION DB]: Loaded terrain revision r" + rev.ToString()); + } + } + return terret; + } + } + + /// + /// + /// + /// + public void RemoveLandObject(UUID globalID) + { + lock (ds) + { + // Can't use blanket SQL statements when using SqlAdapters unless you re-read the data into the adapter + // after you're done. + // replaced below code with the SqliteAdapter version. + //using (SqliteCommand cmd = new SqliteCommand("delete from land where UUID=:UUID", m_conn)) + //{ + // cmd.Parameters.Add(new SqliteParameter(":UUID", globalID.ToString())); + // cmd.ExecuteNonQuery(); + //} + + //using (SqliteCommand cmd = new SqliteCommand("delete from landaccesslist where LandUUID=:UUID", m_conn)) + //{ + // cmd.Parameters.Add(new SqliteParameter(":UUID", globalID.ToString())); + // cmd.ExecuteNonQuery(); + //} + + DataTable land = ds.Tables["land"]; + DataTable landaccesslist = ds.Tables["landaccesslist"]; + DataRow landRow = land.Rows.Find(globalID.ToString()); + if (landRow != null) + { + land.Rows.Remove(landRow); + } + List rowsToDelete = new List(); + foreach (DataRow rowToCheck in landaccesslist.Rows) + { + if (rowToCheck["LandUUID"].ToString() == globalID.ToString()) + rowsToDelete.Add(rowToCheck); + } + for (int iter = 0; iter < rowsToDelete.Count; iter++) + { + landaccesslist.Rows.Remove(rowsToDelete[iter]); + } + + + } + Commit(); + } + + /// + /// + /// + /// + public void StoreLandObject(ILandObject parcel) + { + lock (ds) + { + DataTable land = ds.Tables["land"]; + DataTable landaccesslist = ds.Tables["landaccesslist"]; + + DataRow landRow = land.Rows.Find(parcel.LandData.GlobalID.ToString()); + if (landRow == null) + { + landRow = land.NewRow(); + fillLandRow(landRow, parcel.LandData, parcel.RegionUUID); + land.Rows.Add(landRow); + } + else + { + fillLandRow(landRow, parcel.LandData, parcel.RegionUUID); + } + + // I know this caused someone issues before, but OpenSim is unusable if we leave this stuff around + //using (SqliteCommand cmd = new SqliteCommand("delete from landaccesslist where LandUUID=:LandUUID", m_conn)) + //{ + // cmd.Parameters.Add(new SqliteParameter(":LandUUID", parcel.LandData.GlobalID.ToString())); + // cmd.ExecuteNonQuery(); + +// } + + // This is the slower.. but more appropriate thing to do + + // We can't modify the table with direct queries before calling Commit() and re-filling them. + List rowsToDelete = new List(); + foreach (DataRow rowToCheck in landaccesslist.Rows) + { + if (rowToCheck["LandUUID"].ToString() == parcel.LandData.GlobalID.ToString()) + rowsToDelete.Add(rowToCheck); + } + for (int iter = 0; iter < rowsToDelete.Count; iter++) + { + landaccesslist.Rows.Remove(rowsToDelete[iter]); + } + rowsToDelete.Clear(); + foreach (ParcelManager.ParcelAccessEntry entry in parcel.LandData.ParcelAccessList) + { + DataRow newAccessRow = landaccesslist.NewRow(); + fillLandAccessRow(newAccessRow, entry, parcel.LandData.GlobalID); + landaccesslist.Rows.Add(newAccessRow); + } + } + + Commit(); + } + + /// + /// + /// + /// + /// + public List LoadLandObjects(UUID regionUUID) + { + List landDataForRegion = new List(); + lock (ds) + { + DataTable land = ds.Tables["land"]; + DataTable landaccesslist = ds.Tables["landaccesslist"]; + string searchExp = "RegionUUID = '" + regionUUID + "'"; + DataRow[] rawDataForRegion = land.Select(searchExp); + foreach (DataRow rawDataLand in rawDataForRegion) + { + LandData newLand = buildLandData(rawDataLand); + string accessListSearchExp = "LandUUID = '" + newLand.GlobalID + "'"; + DataRow[] rawDataForLandAccessList = landaccesslist.Select(accessListSearchExp); + foreach (DataRow rawDataLandAccess in rawDataForLandAccessList) + { + newLand.ParcelAccessList.Add(buildLandAccessData(rawDataLandAccess)); + } + + landDataForRegion.Add(newLand); + } + } + return landDataForRegion; + } + + /// + /// + /// + public void Commit() + { + //m_log.Debug("[SQLITE]: Starting commit"); + lock (ds) + { + primDa.Update(ds, "prims"); + shapeDa.Update(ds, "primshapes"); + + itemsDa.Update(ds, "primitems"); + + terrainDa.Update(ds, "terrain"); + landDa.Update(ds, "land"); + landAccessListDa.Update(ds, "landaccesslist"); + try + { + regionSettingsDa.Update(ds, "regionsettings"); + } + catch (SqliteException SqlEx) + { + throw new Exception( + "There was a SQL error or connection string configuration error when saving the region settings. This could be a bug, it could also happen if ConnectionString is defined in the [DatabaseService] section of StandaloneCommon.ini in the config_include folder. This could also happen if the config_include folder doesn't exist or if the OpenSim.ini [Architecture] section isn't set. If this is your first time running OpenSimulator, please restart the simulator and bug a developer to fix this!", + SqlEx); + } + ds.AcceptChanges(); + } + } + + /// + /// See + /// + public void Shutdown() + { + Commit(); + } + + /*********************************************************************** + * + * Database Definition Functions + * + * This should be db agnostic as we define them in ADO.NET terms + * + **********************************************************************/ + + protected void CreateDataSetMapping(IDataAdapter da, string tableName) + { + ITableMapping dbMapping = da.TableMappings.Add(tableName, tableName); + foreach (DataColumn col in ds.Tables[tableName].Columns) + { + dbMapping.ColumnMappings.Add(col.ColumnName, col.ColumnName); + } + } + + /// + /// + /// + /// + /// + /// + private static void createCol(DataTable dt, string name, Type type) + { + DataColumn col = new DataColumn(name, type); + dt.Columns.Add(col); + } + + /// + /// Creates the "terrain" table + /// + /// terrain table DataTable + private static DataTable createTerrainTable() + { + DataTable terrain = new DataTable("terrain"); + + createCol(terrain, "RegionUUID", typeof (String)); + createCol(terrain, "Revision", typeof (Int32)); + createCol(terrain, "Heightfield", typeof (Byte[])); + + return terrain; + } + + /// + /// Creates the "prims" table + /// + /// prim table DataTable + private static DataTable createPrimTable() + { + DataTable prims = new DataTable("prims"); + + createCol(prims, "UUID", typeof (String)); + createCol(prims, "RegionUUID", typeof (String)); + createCol(prims, "CreationDate", typeof (Int32)); + createCol(prims, "Name", typeof (String)); + createCol(prims, "SceneGroupID", typeof (String)); + // various text fields + createCol(prims, "Text", typeof (String)); + createCol(prims, "ColorR", typeof (Int32)); + createCol(prims, "ColorG", typeof (Int32)); + createCol(prims, "ColorB", typeof (Int32)); + createCol(prims, "ColorA", typeof (Int32)); + createCol(prims, "Description", typeof (String)); + createCol(prims, "SitName", typeof (String)); + createCol(prims, "TouchName", typeof (String)); + // permissions + createCol(prims, "ObjectFlags", typeof (Int32)); + createCol(prims, "CreatorID", typeof (String)); + createCol(prims, "OwnerID", typeof (String)); + createCol(prims, "GroupID", typeof (String)); + createCol(prims, "LastOwnerID", typeof (String)); + createCol(prims, "OwnerMask", typeof (Int32)); + createCol(prims, "NextOwnerMask", typeof (Int32)); + createCol(prims, "GroupMask", typeof (Int32)); + createCol(prims, "EveryoneMask", typeof (Int32)); + createCol(prims, "BaseMask", typeof (Int32)); + // vectors + createCol(prims, "PositionX", typeof (Double)); + createCol(prims, "PositionY", typeof (Double)); + createCol(prims, "PositionZ", typeof (Double)); + createCol(prims, "GroupPositionX", typeof (Double)); + createCol(prims, "GroupPositionY", typeof (Double)); + createCol(prims, "GroupPositionZ", typeof (Double)); + createCol(prims, "VelocityX", typeof (Double)); + createCol(prims, "VelocityY", typeof (Double)); + createCol(prims, "VelocityZ", typeof (Double)); + createCol(prims, "AngularVelocityX", typeof (Double)); + createCol(prims, "AngularVelocityY", typeof (Double)); + createCol(prims, "AngularVelocityZ", typeof (Double)); + createCol(prims, "AccelerationX", typeof (Double)); + createCol(prims, "AccelerationY", typeof (Double)); + createCol(prims, "AccelerationZ", typeof (Double)); + // quaternions + createCol(prims, "RotationX", typeof (Double)); + createCol(prims, "RotationY", typeof (Double)); + createCol(prims, "RotationZ", typeof (Double)); + createCol(prims, "RotationW", typeof (Double)); + + // sit target + createCol(prims, "SitTargetOffsetX", typeof (Double)); + createCol(prims, "SitTargetOffsetY", typeof (Double)); + createCol(prims, "SitTargetOffsetZ", typeof (Double)); + + createCol(prims, "SitTargetOrientW", typeof (Double)); + createCol(prims, "SitTargetOrientX", typeof (Double)); + createCol(prims, "SitTargetOrientY", typeof (Double)); + createCol(prims, "SitTargetOrientZ", typeof (Double)); + + createCol(prims, "PayPrice", typeof(Int32)); + createCol(prims, "PayButton1", typeof(Int32)); + createCol(prims, "PayButton2", typeof(Int32)); + createCol(prims, "PayButton3", typeof(Int32)); + createCol(prims, "PayButton4", typeof(Int32)); + + createCol(prims, "LoopedSound", typeof(String)); + createCol(prims, "LoopedSoundGain", typeof(Double)); + createCol(prims, "TextureAnimation", typeof(String)); + createCol(prims, "ParticleSystem", typeof(String)); + + createCol(prims, "OmegaX", typeof(Double)); + createCol(prims, "OmegaY", typeof(Double)); + createCol(prims, "OmegaZ", typeof(Double)); + + createCol(prims, "CameraEyeOffsetX", typeof(Double)); + createCol(prims, "CameraEyeOffsetY", typeof(Double)); + createCol(prims, "CameraEyeOffsetZ", typeof(Double)); + + createCol(prims, "CameraAtOffsetX", typeof(Double)); + createCol(prims, "CameraAtOffsetY", typeof(Double)); + createCol(prims, "CameraAtOffsetZ", typeof(Double)); + + createCol(prims, "ForceMouselook", typeof(Int16)); + + createCol(prims, "ScriptAccessPin", typeof(Int32)); + + createCol(prims, "AllowedDrop", typeof(Int16)); + createCol(prims, "DieAtEdge", typeof(Int16)); + + createCol(prims, "SalePrice", typeof(Int32)); + createCol(prims, "SaleType", typeof(Int16)); + + // click action + createCol(prims, "ClickAction", typeof (Byte)); + + createCol(prims, "Material", typeof(Byte)); + + createCol(prims, "CollisionSound", typeof(String)); + createCol(prims, "CollisionSoundVolume", typeof(Double)); + + createCol(prims, "VolumeDetect", typeof(Int16)); + + createCol(prims, "MediaURL", typeof(String)); + + // Add in contraints + prims.PrimaryKey = new DataColumn[] {prims.Columns["UUID"]}; + + return prims; + } + + /// + /// Creates "primshapes" table + /// + /// shape table DataTable + private static DataTable createShapeTable() + { + DataTable shapes = new DataTable("primshapes"); + createCol(shapes, "UUID", typeof (String)); + // shape is an enum + createCol(shapes, "Shape", typeof (Int32)); + // vectors + createCol(shapes, "ScaleX", typeof (Double)); + createCol(shapes, "ScaleY", typeof (Double)); + createCol(shapes, "ScaleZ", typeof (Double)); + // paths + createCol(shapes, "PCode", typeof (Int32)); + createCol(shapes, "PathBegin", typeof (Int32)); + createCol(shapes, "PathEnd", typeof (Int32)); + createCol(shapes, "PathScaleX", typeof (Int32)); + createCol(shapes, "PathScaleY", typeof (Int32)); + createCol(shapes, "PathShearX", typeof (Int32)); + createCol(shapes, "PathShearY", typeof (Int32)); + createCol(shapes, "PathSkew", typeof (Int32)); + createCol(shapes, "PathCurve", typeof (Int32)); + createCol(shapes, "PathRadiusOffset", typeof (Int32)); + createCol(shapes, "PathRevolutions", typeof (Int32)); + createCol(shapes, "PathTaperX", typeof (Int32)); + createCol(shapes, "PathTaperY", typeof (Int32)); + createCol(shapes, "PathTwist", typeof (Int32)); + createCol(shapes, "PathTwistBegin", typeof (Int32)); + // profile + createCol(shapes, "ProfileBegin", typeof (Int32)); + createCol(shapes, "ProfileEnd", typeof (Int32)); + createCol(shapes, "ProfileCurve", typeof (Int32)); + createCol(shapes, "ProfileHollow", typeof (Int32)); + createCol(shapes, "State", typeof(Int32)); + // text TODO: this isn't right, but I'm not sure the right + // way to specify this as a blob atm + createCol(shapes, "Texture", typeof (Byte[])); + createCol(shapes, "ExtraParams", typeof (Byte[])); + createCol(shapes, "Media", typeof(String)); + + shapes.PrimaryKey = new DataColumn[] {shapes.Columns["UUID"]}; + + return shapes; + } + + /// + /// creates "primitems" table + /// + /// item table DataTable + private static DataTable createItemsTable() + { + DataTable items = new DataTable("primitems"); + + createCol(items, "itemID", typeof (String)); + createCol(items, "primID", typeof (String)); + createCol(items, "assetID", typeof (String)); + createCol(items, "parentFolderID", typeof (String)); + + createCol(items, "invType", typeof (Int32)); + createCol(items, "assetType", typeof (Int32)); + + createCol(items, "name", typeof (String)); + createCol(items, "description", typeof (String)); + + createCol(items, "creationDate", typeof (Int64)); + createCol(items, "creatorID", typeof (String)); + createCol(items, "ownerID", typeof (String)); + createCol(items, "lastOwnerID", typeof (String)); + createCol(items, "groupID", typeof (String)); + + createCol(items, "nextPermissions", typeof (UInt32)); + createCol(items, "currentPermissions", typeof (UInt32)); + createCol(items, "basePermissions", typeof (UInt32)); + createCol(items, "everyonePermissions", typeof (UInt32)); + createCol(items, "groupPermissions", typeof (UInt32)); + createCol(items, "flags", typeof (UInt32)); + + items.PrimaryKey = new DataColumn[] { items.Columns["itemID"] }; + + return items; + } + + /// + /// Creates "land" table + /// + /// land table DataTable + private static DataTable createLandTable() + { + DataTable land = new DataTable("land"); + createCol(land, "UUID", typeof (String)); + createCol(land, "RegionUUID", typeof (String)); + createCol(land, "LocalLandID", typeof (UInt32)); + + // Bitmap is a byte[512] + createCol(land, "Bitmap", typeof (Byte[])); + + createCol(land, "Name", typeof (String)); + createCol(land, "Desc", typeof (String)); + createCol(land, "OwnerUUID", typeof (String)); + createCol(land, "IsGroupOwned", typeof (Boolean)); + createCol(land, "Area", typeof (Int32)); + createCol(land, "AuctionID", typeof (Int32)); //Unemplemented + createCol(land, "Category", typeof (Int32)); //Enum OpenMetaverse.Parcel.ParcelCategory + createCol(land, "ClaimDate", typeof (Int32)); + createCol(land, "ClaimPrice", typeof (Int32)); + createCol(land, "GroupUUID", typeof (string)); + createCol(land, "SalePrice", typeof (Int32)); + createCol(land, "LandStatus", typeof (Int32)); //Enum. OpenMetaverse.Parcel.ParcelStatus + createCol(land, "LandFlags", typeof (UInt32)); + createCol(land, "LandingType", typeof (Byte)); + createCol(land, "MediaAutoScale", typeof (Byte)); + createCol(land, "MediaTextureUUID", typeof (String)); + createCol(land, "MediaURL", typeof (String)); + createCol(land, "MusicURL", typeof (String)); + createCol(land, "PassHours", typeof (Double)); + createCol(land, "PassPrice", typeof (UInt32)); + createCol(land, "SnapshotUUID", typeof (String)); + createCol(land, "UserLocationX", typeof (Double)); + createCol(land, "UserLocationY", typeof (Double)); + createCol(land, "UserLocationZ", typeof (Double)); + createCol(land, "UserLookAtX", typeof (Double)); + createCol(land, "UserLookAtY", typeof (Double)); + createCol(land, "UserLookAtZ", typeof (Double)); + createCol(land, "AuthbuyerID", typeof(String)); + createCol(land, "OtherCleanTime", typeof(Int32)); + + land.PrimaryKey = new DataColumn[] {land.Columns["UUID"]}; + + return land; + } + + /// + /// create "landaccesslist" table + /// + /// Landacceslist DataTable + private static DataTable createLandAccessListTable() + { + DataTable landaccess = new DataTable("landaccesslist"); + createCol(landaccess, "LandUUID", typeof (String)); + createCol(landaccess, "AccessUUID", typeof (String)); + createCol(landaccess, "Flags", typeof (UInt32)); + + return landaccess; + } + + private static DataTable createRegionSettingsTable() + { + DataTable regionsettings = new DataTable("regionsettings"); + createCol(regionsettings, "regionUUID", typeof(String)); + createCol(regionsettings, "block_terraform", typeof (Int32)); + createCol(regionsettings, "block_fly", typeof (Int32)); + createCol(regionsettings, "allow_damage", typeof (Int32)); + createCol(regionsettings, "restrict_pushing", typeof (Int32)); + createCol(regionsettings, "allow_land_resell", typeof (Int32)); + createCol(regionsettings, "allow_land_join_divide", typeof (Int32)); + createCol(regionsettings, "block_show_in_search", typeof (Int32)); + createCol(regionsettings, "agent_limit", typeof (Int32)); + createCol(regionsettings, "object_bonus", typeof (Double)); + createCol(regionsettings, "maturity", typeof (Int32)); + createCol(regionsettings, "disable_scripts", typeof (Int32)); + createCol(regionsettings, "disable_collisions", typeof (Int32)); + createCol(regionsettings, "disable_physics", typeof (Int32)); + createCol(regionsettings, "terrain_texture_1", typeof(String)); + createCol(regionsettings, "terrain_texture_2", typeof(String)); + createCol(regionsettings, "terrain_texture_3", typeof(String)); + createCol(regionsettings, "terrain_texture_4", typeof(String)); + createCol(regionsettings, "elevation_1_nw", typeof (Double)); + createCol(regionsettings, "elevation_2_nw", typeof (Double)); + createCol(regionsettings, "elevation_1_ne", typeof (Double)); + createCol(regionsettings, "elevation_2_ne", typeof (Double)); + createCol(regionsettings, "elevation_1_se", typeof (Double)); + createCol(regionsettings, "elevation_2_se", typeof (Double)); + createCol(regionsettings, "elevation_1_sw", typeof (Double)); + createCol(regionsettings, "elevation_2_sw", typeof (Double)); + createCol(regionsettings, "water_height", typeof (Double)); + createCol(regionsettings, "terrain_raise_limit", typeof (Double)); + createCol(regionsettings, "terrain_lower_limit", typeof (Double)); + createCol(regionsettings, "use_estate_sun", typeof (Int32)); + createCol(regionsettings, "sandbox", typeof (Int32)); + createCol(regionsettings, "sunvectorx",typeof (Double)); + createCol(regionsettings, "sunvectory",typeof (Double)); + createCol(regionsettings, "sunvectorz",typeof (Double)); + createCol(regionsettings, "fixed_sun", typeof (Int32)); + createCol(regionsettings, "sun_position", typeof (Double)); + createCol(regionsettings, "covenant", typeof(String)); + createCol(regionsettings, "map_tile_ID", typeof(String)); + regionsettings.PrimaryKey = new DataColumn[] { regionsettings.Columns["regionUUID"] }; + return regionsettings; + } + + /*********************************************************************** + * + * Convert between ADO.NET <=> OpenSim Objects + * + * These should be database independant + * + **********************************************************************/ + + /// + /// + /// + /// + /// + private SceneObjectPart buildPrim(DataRow row) + { + // Code commented. Uncomment to test the unit test inline. + + // The unit test mentions this commented code for the purposes + // of debugging a unit test failure + + // SceneObjectGroup sog = new SceneObjectGroup(); + // SceneObjectPart sop = new SceneObjectPart(); + // sop.LocalId = 1; + // sop.Name = "object1"; + // sop.Description = "object1"; + // sop.Text = ""; + // sop.SitName = ""; + // sop.TouchName = ""; + // sop.UUID = UUID.Random(); + // sop.Shape = PrimitiveBaseShape.Default; + // sog.SetRootPart(sop); + // Add breakpoint in above line. Check sop fields. + + // TODO: this doesn't work yet because something more + // interesting has to be done to actually get these values + // back out. Not enough time to figure it out yet. + + SceneObjectPart prim = new SceneObjectPart(); + prim.UUID = new UUID((String) row["UUID"]); + // explicit conversion of integers is required, which sort + // of sucks. No idea if there is a shortcut here or not. + prim.CreationDate = Convert.ToInt32(row["CreationDate"]); + prim.Name = row["Name"] == DBNull.Value ? string.Empty : (string)row["Name"]; + // various text fields + prim.Text = (String) row["Text"]; + prim.Color = Color.FromArgb(Convert.ToInt32(row["ColorA"]), + Convert.ToInt32(row["ColorR"]), + Convert.ToInt32(row["ColorG"]), + Convert.ToInt32(row["ColorB"])); + prim.Description = (String) row["Description"]; + prim.SitName = (String) row["SitName"]; + prim.TouchName = (String) row["TouchName"]; + // permissions + prim.ObjectFlags = Convert.ToUInt32(row["ObjectFlags"]); + prim.CreatorID = new UUID((String) row["CreatorID"]); + prim.OwnerID = new UUID((String) row["OwnerID"]); + prim.GroupID = new UUID((String) row["GroupID"]); + prim.LastOwnerID = new UUID((String) row["LastOwnerID"]); + prim.OwnerMask = Convert.ToUInt32(row["OwnerMask"]); + prim.NextOwnerMask = Convert.ToUInt32(row["NextOwnerMask"]); + prim.GroupMask = Convert.ToUInt32(row["GroupMask"]); + prim.EveryoneMask = Convert.ToUInt32(row["EveryoneMask"]); + prim.BaseMask = Convert.ToUInt32(row["BaseMask"]); + // vectors + prim.OffsetPosition = new Vector3( + Convert.ToSingle(row["PositionX"]), + Convert.ToSingle(row["PositionY"]), + Convert.ToSingle(row["PositionZ"]) + ); + prim.GroupPosition = new Vector3( + Convert.ToSingle(row["GroupPositionX"]), + Convert.ToSingle(row["GroupPositionY"]), + Convert.ToSingle(row["GroupPositionZ"]) + ); + prim.Velocity = new Vector3( + Convert.ToSingle(row["VelocityX"]), + Convert.ToSingle(row["VelocityY"]), + Convert.ToSingle(row["VelocityZ"]) + ); + prim.AngularVelocity = new Vector3( + Convert.ToSingle(row["AngularVelocityX"]), + Convert.ToSingle(row["AngularVelocityY"]), + Convert.ToSingle(row["AngularVelocityZ"]) + ); + prim.Acceleration = new Vector3( + Convert.ToSingle(row["AccelerationX"]), + Convert.ToSingle(row["AccelerationY"]), + Convert.ToSingle(row["AccelerationZ"]) + ); + // quaternions + prim.RotationOffset = new Quaternion( + Convert.ToSingle(row["RotationX"]), + Convert.ToSingle(row["RotationY"]), + Convert.ToSingle(row["RotationZ"]), + Convert.ToSingle(row["RotationW"]) + ); + + prim.SitTargetPositionLL = new Vector3( + Convert.ToSingle(row["SitTargetOffsetX"]), + Convert.ToSingle(row["SitTargetOffsetY"]), + Convert.ToSingle(row["SitTargetOffsetZ"])); + prim.SitTargetOrientationLL = new Quaternion( + Convert.ToSingle( + row["SitTargetOrientX"]), + Convert.ToSingle( + row["SitTargetOrientY"]), + Convert.ToSingle( + row["SitTargetOrientZ"]), + Convert.ToSingle( + row["SitTargetOrientW"])); + + prim.ClickAction = Convert.ToByte(row["ClickAction"]); + prim.PayPrice[0] = Convert.ToInt32(row["PayPrice"]); + prim.PayPrice[1] = Convert.ToInt32(row["PayButton1"]); + prim.PayPrice[2] = Convert.ToInt32(row["PayButton2"]); + prim.PayPrice[3] = Convert.ToInt32(row["PayButton3"]); + prim.PayPrice[4] = Convert.ToInt32(row["PayButton4"]); + + prim.Sound = new UUID(row["LoopedSound"].ToString()); + prim.SoundGain = Convert.ToSingle(row["LoopedSoundGain"]); + prim.SoundFlags = 1; // If it's persisted at all, it's looped + + if (!row.IsNull("TextureAnimation")) + prim.TextureAnimation = Convert.FromBase64String(row["TextureAnimation"].ToString()); + if (!row.IsNull("ParticleSystem")) + prim.ParticleSystem = Convert.FromBase64String(row["ParticleSystem"].ToString()); + + prim.AngularVelocity = new Vector3( + Convert.ToSingle(row["OmegaX"]), + Convert.ToSingle(row["OmegaY"]), + Convert.ToSingle(row["OmegaZ"]) + ); + + prim.SetCameraEyeOffset(new Vector3( + Convert.ToSingle(row["CameraEyeOffsetX"]), + Convert.ToSingle(row["CameraEyeOffsetY"]), + Convert.ToSingle(row["CameraEyeOffsetZ"]) + )); + + prim.SetCameraAtOffset(new Vector3( + Convert.ToSingle(row["CameraAtOffsetX"]), + Convert.ToSingle(row["CameraAtOffsetY"]), + Convert.ToSingle(row["CameraAtOffsetZ"]) + )); + + if (Convert.ToInt16(row["ForceMouselook"]) != 0) + prim.SetForceMouselook(true); + + prim.ScriptAccessPin = Convert.ToInt32(row["ScriptAccessPin"]); + + if (Convert.ToInt16(row["AllowedDrop"]) != 0) + prim.AllowedDrop = true; + + if (Convert.ToInt16(row["DieAtEdge"]) != 0) + prim.DIE_AT_EDGE = true; + + prim.SalePrice = Convert.ToInt32(row["SalePrice"]); + prim.ObjectSaleType = Convert.ToByte(row["SaleType"]); + + prim.Material = Convert.ToByte(row["Material"]); + + prim.CollisionSound = new UUID(row["CollisionSound"].ToString()); + prim.CollisionSoundVolume = Convert.ToSingle(row["CollisionSoundVolume"]); + + if (Convert.ToInt16(row["VolumeDetect"]) != 0) + prim.VolumeDetectActive = true; + + if (!(row["MediaURL"] is System.DBNull)) + { + //m_log.DebugFormat("[SQLITE]: MediaUrl type [{0}]", row["MediaURL"].GetType()); + prim.MediaUrl = (string)row["MediaURL"]; + } + + return prim; + } + + /// + /// Build a prim inventory item from the persisted data. + /// + /// + /// + private static TaskInventoryItem buildItem(DataRow row) + { + TaskInventoryItem taskItem = new TaskInventoryItem(); + + taskItem.ItemID = new UUID((String)row["itemID"]); + taskItem.ParentPartID = new UUID((String)row["primID"]); + taskItem.AssetID = new UUID((String)row["assetID"]); + taskItem.ParentID = new UUID((String)row["parentFolderID"]); + + taskItem.InvType = Convert.ToInt32(row["invType"]); + taskItem.Type = Convert.ToInt32(row["assetType"]); + + taskItem.Name = (String)row["name"]; + taskItem.Description = (String)row["description"]; + taskItem.CreationDate = Convert.ToUInt32(row["creationDate"]); + taskItem.CreatorID = new UUID((String)row["creatorID"]); + taskItem.OwnerID = new UUID((String)row["ownerID"]); + taskItem.LastOwnerID = new UUID((String)row["lastOwnerID"]); + taskItem.GroupID = new UUID((String)row["groupID"]); + + taskItem.NextPermissions = Convert.ToUInt32(row["nextPermissions"]); + taskItem.CurrentPermissions = Convert.ToUInt32(row["currentPermissions"]); + taskItem.BasePermissions = Convert.ToUInt32(row["basePermissions"]); + taskItem.EveryonePermissions = Convert.ToUInt32(row["everyonePermissions"]); + taskItem.GroupPermissions = Convert.ToUInt32(row["groupPermissions"]); + taskItem.Flags = Convert.ToUInt32(row["flags"]); + + return taskItem; + } + + /// + /// Build a Land Data from the persisted data. + /// + /// + /// + private LandData buildLandData(DataRow row) + { + LandData newData = new LandData(); + + newData.GlobalID = new UUID((String) row["UUID"]); + newData.LocalID = Convert.ToInt32(row["LocalLandID"]); + + // Bitmap is a byte[512] + newData.Bitmap = (Byte[]) row["Bitmap"]; + + newData.Name = (String) row["Name"]; + newData.Description = (String) row["Desc"]; + newData.OwnerID = (UUID)(String) row["OwnerUUID"]; + newData.IsGroupOwned = (Boolean) row["IsGroupOwned"]; + newData.Area = Convert.ToInt32(row["Area"]); + newData.AuctionID = Convert.ToUInt32(row["AuctionID"]); //Unemplemented + newData.Category = (ParcelCategory) Convert.ToInt32(row["Category"]); + //Enum OpenMetaverse.Parcel.ParcelCategory + newData.ClaimDate = Convert.ToInt32(row["ClaimDate"]); + newData.ClaimPrice = Convert.ToInt32(row["ClaimPrice"]); + newData.GroupID = new UUID((String) row["GroupUUID"]); + newData.SalePrice = Convert.ToInt32(row["SalePrice"]); + newData.Status = (ParcelStatus) Convert.ToInt32(row["LandStatus"]); + //Enum. OpenMetaverse.Parcel.ParcelStatus + newData.Flags = Convert.ToUInt32(row["LandFlags"]); + newData.LandingType = (Byte) row["LandingType"]; + newData.MediaAutoScale = (Byte) row["MediaAutoScale"]; + newData.MediaID = new UUID((String) row["MediaTextureUUID"]); + newData.MediaURL = (String) row["MediaURL"]; + newData.MusicURL = (String) row["MusicURL"]; + newData.PassHours = Convert.ToSingle(row["PassHours"]); + newData.PassPrice = Convert.ToInt32(row["PassPrice"]); + newData.SnapshotID = (UUID)(String) row["SnapshotUUID"]; + try + { + + newData.UserLocation = + new Vector3(Convert.ToSingle(row["UserLocationX"]), Convert.ToSingle(row["UserLocationY"]), + Convert.ToSingle(row["UserLocationZ"])); + newData.UserLookAt = + new Vector3(Convert.ToSingle(row["UserLookAtX"]), Convert.ToSingle(row["UserLookAtY"]), + Convert.ToSingle(row["UserLookAtZ"])); + + } + catch (InvalidCastException) + { + m_log.ErrorFormat("[SQLITE REGION DB]: unable to get parcel telehub settings for {1}", newData.Name); + newData.UserLocation = Vector3.Zero; + newData.UserLookAt = Vector3.Zero; + } + newData.ParcelAccessList = new List(); + UUID authBuyerID = UUID.Zero; + + UUID.TryParse((string)row["AuthbuyerID"], out authBuyerID); + + newData.OtherCleanTime = Convert.ToInt32(row["OtherCleanTime"]); + + return newData; + } + + private RegionSettings buildRegionSettings(DataRow row) + { + RegionSettings newSettings = new RegionSettings(); + + newSettings.RegionUUID = new UUID((string) row["regionUUID"]); + newSettings.BlockTerraform = Convert.ToBoolean(row["block_terraform"]); + newSettings.AllowDamage = Convert.ToBoolean(row["allow_damage"]); + newSettings.BlockFly = Convert.ToBoolean(row["block_fly"]); + newSettings.RestrictPushing = Convert.ToBoolean(row["restrict_pushing"]); + newSettings.AllowLandResell = Convert.ToBoolean(row["allow_land_resell"]); + newSettings.AllowLandJoinDivide = Convert.ToBoolean(row["allow_land_join_divide"]); + newSettings.BlockShowInSearch = Convert.ToBoolean(row["block_show_in_search"]); + newSettings.AgentLimit = Convert.ToInt32(row["agent_limit"]); + newSettings.ObjectBonus = Convert.ToDouble(row["object_bonus"]); + newSettings.Maturity = Convert.ToInt32(row["maturity"]); + newSettings.DisableScripts = Convert.ToBoolean(row["disable_scripts"]); + newSettings.DisableCollisions = Convert.ToBoolean(row["disable_collisions"]); + newSettings.DisablePhysics = Convert.ToBoolean(row["disable_physics"]); + newSettings.TerrainTexture1 = new UUID((String) row["terrain_texture_1"]); + newSettings.TerrainTexture2 = new UUID((String) row["terrain_texture_2"]); + newSettings.TerrainTexture3 = new UUID((String) row["terrain_texture_3"]); + newSettings.TerrainTexture4 = new UUID((String) row["terrain_texture_4"]); + newSettings.Elevation1NW = Convert.ToDouble(row["elevation_1_nw"]); + newSettings.Elevation2NW = Convert.ToDouble(row["elevation_2_nw"]); + newSettings.Elevation1NE = Convert.ToDouble(row["elevation_1_ne"]); + newSettings.Elevation2NE = Convert.ToDouble(row["elevation_2_ne"]); + newSettings.Elevation1SE = Convert.ToDouble(row["elevation_1_se"]); + newSettings.Elevation2SE = Convert.ToDouble(row["elevation_2_se"]); + newSettings.Elevation1SW = Convert.ToDouble(row["elevation_1_sw"]); + newSettings.Elevation2SW = Convert.ToDouble(row["elevation_2_sw"]); + newSettings.WaterHeight = Convert.ToDouble(row["water_height"]); + newSettings.TerrainRaiseLimit = Convert.ToDouble(row["terrain_raise_limit"]); + newSettings.TerrainLowerLimit = Convert.ToDouble(row["terrain_lower_limit"]); + newSettings.UseEstateSun = Convert.ToBoolean(row["use_estate_sun"]); + newSettings.Sandbox = Convert.ToBoolean(row["sandbox"]); + newSettings.SunVector = new Vector3 ( + Convert.ToSingle(row["sunvectorx"]), + Convert.ToSingle(row["sunvectory"]), + Convert.ToSingle(row["sunvectorz"]) + ); + newSettings.FixedSun = Convert.ToBoolean(row["fixed_sun"]); + newSettings.SunPosition = Convert.ToDouble(row["sun_position"]); + newSettings.Covenant = new UUID((String) row["covenant"]); + newSettings.TerrainImageID = new UUID((String)row["map_tile_ID"]); + + return newSettings; + } + + /// + /// Build a land access entry from the persisted data. + /// + /// + /// + private static ParcelManager.ParcelAccessEntry buildLandAccessData(DataRow row) + { + ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); + entry.AgentID = new UUID((string) row["AccessUUID"]); + entry.Flags = (AccessList) row["Flags"]; + entry.Time = new DateTime(); + return entry; + } + + /// + /// + /// + /// + /// + private static Array serializeTerrain(double[,] val) + { + MemoryStream str = new MemoryStream(((int)Constants.RegionSize * (int)Constants.RegionSize) *sizeof (double)); + BinaryWriter bw = new BinaryWriter(str); + + // TODO: COMPATIBILITY - Add byte-order conversions + for (int x = 0; x < (int)Constants.RegionSize; x++) + for (int y = 0; y < (int)Constants.RegionSize; y++) + bw.Write(val[x, y]); + + return str.ToArray(); + } + +// private void fillTerrainRow(DataRow row, UUID regionUUID, int rev, double[,] val) +// { +// row["RegionUUID"] = regionUUID; +// row["Revision"] = rev; + + // MemoryStream str = new MemoryStream(((int)Constants.RegionSize * (int)Constants.RegionSize)*sizeof (double)); +// BinaryWriter bw = new BinaryWriter(str); + +// // TODO: COMPATIBILITY - Add byte-order conversions + // for (int x = 0; x < (int)Constants.RegionSize; x++) + // for (int y = 0; y < (int)Constants.RegionSize; y++) +// bw.Write(val[x, y]); + +// row["Heightfield"] = str.ToArray(); +// } + + /// + /// + /// + /// + /// + /// + /// + private static void fillPrimRow(DataRow row, SceneObjectPart prim, UUID sceneGroupID, UUID regionUUID) + { + row["UUID"] = prim.UUID.ToString(); + row["RegionUUID"] = regionUUID.ToString(); + row["CreationDate"] = prim.CreationDate; + row["Name"] = prim.Name; + row["SceneGroupID"] = sceneGroupID.ToString(); + // the UUID of the root part for this SceneObjectGroup + // various text fields + row["Text"] = prim.Text; + row["Description"] = prim.Description; + row["SitName"] = prim.SitName; + row["TouchName"] = prim.TouchName; + // permissions + row["ObjectFlags"] = prim.ObjectFlags; + row["CreatorID"] = prim.CreatorID.ToString(); + row["OwnerID"] = prim.OwnerID.ToString(); + row["GroupID"] = prim.GroupID.ToString(); + row["LastOwnerID"] = prim.LastOwnerID.ToString(); + row["OwnerMask"] = prim.OwnerMask; + row["NextOwnerMask"] = prim.NextOwnerMask; + row["GroupMask"] = prim.GroupMask; + row["EveryoneMask"] = prim.EveryoneMask; + row["BaseMask"] = prim.BaseMask; + // vectors + row["PositionX"] = prim.OffsetPosition.X; + row["PositionY"] = prim.OffsetPosition.Y; + row["PositionZ"] = prim.OffsetPosition.Z; + row["GroupPositionX"] = prim.GroupPosition.X; + row["GroupPositionY"] = prim.GroupPosition.Y; + row["GroupPositionZ"] = prim.GroupPosition.Z; + row["VelocityX"] = prim.Velocity.X; + row["VelocityY"] = prim.Velocity.Y; + row["VelocityZ"] = prim.Velocity.Z; + row["AngularVelocityX"] = prim.AngularVelocity.X; + row["AngularVelocityY"] = prim.AngularVelocity.Y; + row["AngularVelocityZ"] = prim.AngularVelocity.Z; + row["AccelerationX"] = prim.Acceleration.X; + row["AccelerationY"] = prim.Acceleration.Y; + row["AccelerationZ"] = prim.Acceleration.Z; + // quaternions + row["RotationX"] = prim.RotationOffset.X; + row["RotationY"] = prim.RotationOffset.Y; + row["RotationZ"] = prim.RotationOffset.Z; + row["RotationW"] = prim.RotationOffset.W; + + // Sit target + Vector3 sitTargetPos = prim.SitTargetPositionLL; + row["SitTargetOffsetX"] = sitTargetPos.X; + row["SitTargetOffsetY"] = sitTargetPos.Y; + row["SitTargetOffsetZ"] = sitTargetPos.Z; + + Quaternion sitTargetOrient = prim.SitTargetOrientationLL; + row["SitTargetOrientW"] = sitTargetOrient.W; + row["SitTargetOrientX"] = sitTargetOrient.X; + row["SitTargetOrientY"] = sitTargetOrient.Y; + row["SitTargetOrientZ"] = sitTargetOrient.Z; + row["ColorR"] = Convert.ToInt32(prim.Color.R); + row["ColorG"] = Convert.ToInt32(prim.Color.G); + row["ColorB"] = Convert.ToInt32(prim.Color.B); + row["ColorA"] = Convert.ToInt32(prim.Color.A); + row["PayPrice"] = prim.PayPrice[0]; + row["PayButton1"] = prim.PayPrice[1]; + row["PayButton2"] = prim.PayPrice[2]; + row["PayButton3"] = prim.PayPrice[3]; + row["PayButton4"] = prim.PayPrice[4]; + + row["TextureAnimation"] = Convert.ToBase64String(prim.TextureAnimation); + row["ParticleSystem"] = Convert.ToBase64String(prim.ParticleSystem); + + row["OmegaX"] = prim.AngularVelocity.X; + row["OmegaY"] = prim.AngularVelocity.Y; + row["OmegaZ"] = prim.AngularVelocity.Z; + + row["CameraEyeOffsetX"] = prim.GetCameraEyeOffset().X; + row["CameraEyeOffsetY"] = prim.GetCameraEyeOffset().Y; + row["CameraEyeOffsetZ"] = prim.GetCameraEyeOffset().Z; + + row["CameraAtOffsetX"] = prim.GetCameraAtOffset().X; + row["CameraAtOffsetY"] = prim.GetCameraAtOffset().Y; + row["CameraAtOffsetZ"] = prim.GetCameraAtOffset().Z; + + + if ((prim.SoundFlags & 1) != 0) // Looped + { + row["LoopedSound"] = prim.Sound.ToString(); + row["LoopedSoundGain"] = prim.SoundGain; + } + else + { + row["LoopedSound"] = UUID.Zero.ToString(); + row["LoopedSoundGain"] = 0.0f; + } + + if (prim.GetForceMouselook()) + row["ForceMouselook"] = 1; + else + row["ForceMouselook"] = 0; + + row["ScriptAccessPin"] = prim.ScriptAccessPin; + + if (prim.AllowedDrop) + row["AllowedDrop"] = 1; + else + row["AllowedDrop"] = 0; + + if (prim.DIE_AT_EDGE) + row["DieAtEdge"] = 1; + else + row["DieAtEdge"] = 0; + + row["SalePrice"] = prim.SalePrice; + row["SaleType"] = Convert.ToInt16(prim.ObjectSaleType); + + // click action + row["ClickAction"] = prim.ClickAction; + + row["SalePrice"] = prim.SalePrice; + row["Material"] = prim.Material; + + row["CollisionSound"] = prim.CollisionSound.ToString(); + row["CollisionSoundVolume"] = prim.CollisionSoundVolume; + if (prim.VolumeDetectActive) + row["VolumeDetect"] = 1; + else + row["VolumeDetect"] = 0; + + row["MediaURL"] = prim.MediaUrl; + } + + /// + /// + /// + /// + /// + private static void fillItemRow(DataRow row, TaskInventoryItem taskItem) + { + row["itemID"] = taskItem.ItemID.ToString(); + row["primID"] = taskItem.ParentPartID.ToString(); + row["assetID"] = taskItem.AssetID.ToString(); + row["parentFolderID"] = taskItem.ParentID.ToString(); + + row["invType"] = taskItem.InvType; + row["assetType"] = taskItem.Type; + + row["name"] = taskItem.Name; + row["description"] = taskItem.Description; + row["creationDate"] = taskItem.CreationDate; + row["creatorID"] = taskItem.CreatorID.ToString(); + row["ownerID"] = taskItem.OwnerID.ToString(); + row["lastOwnerID"] = taskItem.LastOwnerID.ToString(); + row["groupID"] = taskItem.GroupID.ToString(); + row["nextPermissions"] = taskItem.NextPermissions; + row["currentPermissions"] = taskItem.CurrentPermissions; + row["basePermissions"] = taskItem.BasePermissions; + row["everyonePermissions"] = taskItem.EveryonePermissions; + row["groupPermissions"] = taskItem.GroupPermissions; + row["flags"] = taskItem.Flags; + } + + /// + /// + /// + /// + /// + /// + private static void fillLandRow(DataRow row, LandData land, UUID regionUUID) + { + row["UUID"] = land.GlobalID.ToString(); + row["RegionUUID"] = regionUUID.ToString(); + row["LocalLandID"] = land.LocalID; + + // Bitmap is a byte[512] + row["Bitmap"] = land.Bitmap; + + row["Name"] = land.Name; + row["Desc"] = land.Description; + row["OwnerUUID"] = land.OwnerID.ToString(); + row["IsGroupOwned"] = land.IsGroupOwned; + row["Area"] = land.Area; + row["AuctionID"] = land.AuctionID; //Unemplemented + row["Category"] = land.Category; //Enum OpenMetaverse.Parcel.ParcelCategory + row["ClaimDate"] = land.ClaimDate; + row["ClaimPrice"] = land.ClaimPrice; + row["GroupUUID"] = land.GroupID.ToString(); + row["SalePrice"] = land.SalePrice; + row["LandStatus"] = land.Status; //Enum. OpenMetaverse.Parcel.ParcelStatus + row["LandFlags"] = land.Flags; + row["LandingType"] = land.LandingType; + row["MediaAutoScale"] = land.MediaAutoScale; + row["MediaTextureUUID"] = land.MediaID.ToString(); + row["MediaURL"] = land.MediaURL; + row["MusicURL"] = land.MusicURL; + row["PassHours"] = land.PassHours; + row["PassPrice"] = land.PassPrice; + row["SnapshotUUID"] = land.SnapshotID.ToString(); + row["UserLocationX"] = land.UserLocation.X; + row["UserLocationY"] = land.UserLocation.Y; + row["UserLocationZ"] = land.UserLocation.Z; + row["UserLookAtX"] = land.UserLookAt.X; + row["UserLookAtY"] = land.UserLookAt.Y; + row["UserLookAtZ"] = land.UserLookAt.Z; + row["AuthbuyerID"] = land.AuthBuyerID.ToString(); + row["OtherCleanTime"] = land.OtherCleanTime; + row["MediaType"] = land.MediaType; + row["MediaDescription"] = land.MediaDescription; + row["MediaSize"] = land.MediaWidth.ToString() + "," + land.MediaHeight.ToString(); + row["MediaLoop"] = land.MediaLoop.ToString(); + row["ObscureMusic"] = land.ObscureMusic.ToString(); + row["ObscureMedia"] = land.ObscureMedia.ToString(); + } + + /// + /// + /// + /// + /// + /// + private static void fillLandAccessRow(DataRow row, ParcelManager.ParcelAccessEntry entry, UUID parcelID) + { + row["LandUUID"] = parcelID.ToString(); + row["AccessUUID"] = entry.AgentID.ToString(); + row["Flags"] = entry.Flags; + } + + private static void fillRegionSettingsRow(DataRow row, RegionSettings settings) + { + row["regionUUID"] = settings.RegionUUID.ToString(); + row["block_terraform"] = settings.BlockTerraform; + row["block_fly"] = settings.BlockFly; + row["allow_damage"] = settings.AllowDamage; + row["restrict_pushing"] = settings.RestrictPushing; + row["allow_land_resell"] = settings.AllowLandResell; + row["allow_land_join_divide"] = settings.AllowLandJoinDivide; + row["block_show_in_search"] = settings.BlockShowInSearch; + row["agent_limit"] = settings.AgentLimit; + row["object_bonus"] = settings.ObjectBonus; + row["maturity"] = settings.Maturity; + row["disable_scripts"] = settings.DisableScripts; + row["disable_collisions"] = settings.DisableCollisions; + row["disable_physics"] = settings.DisablePhysics; + row["terrain_texture_1"] = settings.TerrainTexture1.ToString(); + row["terrain_texture_2"] = settings.TerrainTexture2.ToString(); + row["terrain_texture_3"] = settings.TerrainTexture3.ToString(); + row["terrain_texture_4"] = settings.TerrainTexture4.ToString(); + row["elevation_1_nw"] = settings.Elevation1NW; + row["elevation_2_nw"] = settings.Elevation2NW; + row["elevation_1_ne"] = settings.Elevation1NE; + row["elevation_2_ne"] = settings.Elevation2NE; + row["elevation_1_se"] = settings.Elevation1SE; + row["elevation_2_se"] = settings.Elevation2SE; + row["elevation_1_sw"] = settings.Elevation1SW; + row["elevation_2_sw"] = settings.Elevation2SW; + row["water_height"] = settings.WaterHeight; + row["terrain_raise_limit"] = settings.TerrainRaiseLimit; + row["terrain_lower_limit"] = settings.TerrainLowerLimit; + row["use_estate_sun"] = settings.UseEstateSun; + row["Sandbox"] = settings.Sandbox; // database uses upper case S for sandbox + row["sunvectorx"] = settings.SunVector.X; + row["sunvectory"] = settings.SunVector.Y; + row["sunvectorz"] = settings.SunVector.Z; + row["fixed_sun"] = settings.FixedSun; + row["sun_position"] = settings.SunPosition; + row["covenant"] = settings.Covenant.ToString(); + row["map_tile_ID"] = settings.TerrainImageID.ToString(); + } + + /// + /// + /// + /// + /// + private PrimitiveBaseShape buildShape(DataRow row) + { + PrimitiveBaseShape s = new PrimitiveBaseShape(); + s.Scale = new Vector3( + Convert.ToSingle(row["ScaleX"]), + Convert.ToSingle(row["ScaleY"]), + Convert.ToSingle(row["ScaleZ"]) + ); + // paths + s.PCode = Convert.ToByte(row["PCode"]); + s.PathBegin = Convert.ToUInt16(row["PathBegin"]); + s.PathEnd = Convert.ToUInt16(row["PathEnd"]); + s.PathScaleX = Convert.ToByte(row["PathScaleX"]); + s.PathScaleY = Convert.ToByte(row["PathScaleY"]); + s.PathShearX = Convert.ToByte(row["PathShearX"]); + s.PathShearY = Convert.ToByte(row["PathShearY"]); + s.PathSkew = Convert.ToSByte(row["PathSkew"]); + s.PathCurve = Convert.ToByte(row["PathCurve"]); + s.PathRadiusOffset = Convert.ToSByte(row["PathRadiusOffset"]); + s.PathRevolutions = Convert.ToByte(row["PathRevolutions"]); + s.PathTaperX = Convert.ToSByte(row["PathTaperX"]); + s.PathTaperY = Convert.ToSByte(row["PathTaperY"]); + s.PathTwist = Convert.ToSByte(row["PathTwist"]); + s.PathTwistBegin = Convert.ToSByte(row["PathTwistBegin"]); + // profile + s.ProfileBegin = Convert.ToUInt16(row["ProfileBegin"]); + s.ProfileEnd = Convert.ToUInt16(row["ProfileEnd"]); + s.ProfileCurve = Convert.ToByte(row["ProfileCurve"]); + s.ProfileHollow = Convert.ToUInt16(row["ProfileHollow"]); + s.State = Convert.ToByte(row["State"]); + + byte[] textureEntry = (byte[])row["Texture"]; + s.TextureEntry = textureEntry; + + s.ExtraParams = (byte[]) row["ExtraParams"]; + + if (!(row["Media"] is System.DBNull)) + s.Media = PrimitiveBaseShape.MediaList.FromXml((string)row["Media"]); + + return s; + } + + /// + /// + /// + /// + /// + private static void fillShapeRow(DataRow row, SceneObjectPart prim) + { + PrimitiveBaseShape s = prim.Shape; + row["UUID"] = prim.UUID.ToString(); + // shape is an enum + row["Shape"] = 0; + // vectors + row["ScaleX"] = s.Scale.X; + row["ScaleY"] = s.Scale.Y; + row["ScaleZ"] = s.Scale.Z; + // paths + row["PCode"] = s.PCode; + row["PathBegin"] = s.PathBegin; + row["PathEnd"] = s.PathEnd; + row["PathScaleX"] = s.PathScaleX; + row["PathScaleY"] = s.PathScaleY; + row["PathShearX"] = s.PathShearX; + row["PathShearY"] = s.PathShearY; + row["PathSkew"] = s.PathSkew; + row["PathCurve"] = s.PathCurve; + row["PathRadiusOffset"] = s.PathRadiusOffset; + row["PathRevolutions"] = s.PathRevolutions; + row["PathTaperX"] = s.PathTaperX; + row["PathTaperY"] = s.PathTaperY; + row["PathTwist"] = s.PathTwist; + row["PathTwistBegin"] = s.PathTwistBegin; + // profile + row["ProfileBegin"] = s.ProfileBegin; + row["ProfileEnd"] = s.ProfileEnd; + row["ProfileCurve"] = s.ProfileCurve; + row["ProfileHollow"] = s.ProfileHollow; + row["State"] = s.State; + + row["Texture"] = s.TextureEntry; + row["ExtraParams"] = s.ExtraParams; + + if (s.Media != null) + row["Media"] = s.Media.ToXml(); + } + + /// + /// Persistently store a prim. + /// + /// + /// + /// + private void addPrim(SceneObjectPart prim, UUID sceneGroupID, UUID regionUUID) + { + DataTable prims = ds.Tables["prims"]; + DataTable shapes = ds.Tables["primshapes"]; + + DataRow primRow = prims.Rows.Find(prim.UUID.ToString()); + if (primRow == null) + { + primRow = prims.NewRow(); + fillPrimRow(primRow, prim, sceneGroupID, regionUUID); + prims.Rows.Add(primRow); + } + else + { + fillPrimRow(primRow, prim, sceneGroupID, regionUUID); + } + + DataRow shapeRow = shapes.Rows.Find(prim.UUID.ToString()); + if (shapeRow == null) + { + shapeRow = shapes.NewRow(); + fillShapeRow(shapeRow, prim); + shapes.Rows.Add(shapeRow); + } + else + { + fillShapeRow(shapeRow, prim); + } + } + + /// + /// see IRegionDatastore + /// + /// + /// + public void StorePrimInventory(UUID primID, ICollection items) + { +// m_log.DebugFormat("[SQLITE REGION DB]: Entered StorePrimInventory with prim ID {0}", primID); + + DataTable dbItems = ds.Tables["primitems"]; + + // For now, we're just going to crudely remove all the previous inventory items + // no matter whether they have changed or not, and replace them with the current set. + lock (ds) + { + RemoveItems(primID); + + // repalce with current inventory details + foreach (TaskInventoryItem newItem in items) + { +// m_log.InfoFormat( +// "[DATASTORE]: ", +// "Adding item {0}, {1} to prim ID {2}", +// newItem.Name, newItem.ItemID, newItem.ParentPartID); + + DataRow newItemRow = dbItems.NewRow(); + fillItemRow(newItemRow, newItem); + dbItems.Rows.Add(newItemRow); + } + } + + Commit(); + } + + /*********************************************************************** + * + * SQL Statement Creation Functions + * + * These functions create SQL statements for update, insert, and create. + * They can probably be factored later to have a db independant + * portion and a db specific portion + * + **********************************************************************/ + + /// + /// Create an insert command + /// + /// table name + /// data table + /// the created command + /// + /// This is subtle enough to deserve some commentary. + /// Instead of doing *lots* and *lots of hardcoded strings + /// for database definitions we'll use the fact that + /// realistically all insert statements look like "insert + /// into A(b, c) values(:b, :c) on the parameterized query + /// front. If we just have a list of b, c, etc... we can + /// generate these strings instead of typing them out. + /// + private static SqliteCommand createInsertCommand(string table, DataTable dt) + { + string[] cols = new string[dt.Columns.Count]; + for (int i = 0; i < dt.Columns.Count; i++) + { + DataColumn col = dt.Columns[i]; + cols[i] = col.ColumnName; + } + + string sql = "insert into " + table + "("; + sql += String.Join(", ", cols); + // important, the first ':' needs to be here, the rest get added in the join + sql += ") values (:"; + sql += String.Join(", :", cols); + sql += ")"; + //m_log.DebugFormat("[SQLITE]: Created insert command {0}", sql); + SqliteCommand cmd = new SqliteCommand(sql); + + // this provides the binding for all our parameters, so + // much less code than it used to be + foreach (DataColumn col in dt.Columns) + { + cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType)); + } + return cmd; + } + + + /// + /// create an update command + /// + /// table name + /// + /// + /// the created command + private static SqliteCommand createUpdateCommand(string table, string pk, DataTable dt) + { + string sql = "update " + table + " set "; + string subsql = String.Empty; + foreach (DataColumn col in dt.Columns) + { + if (subsql.Length > 0) + { + // a map function would rock so much here + subsql += ", "; + } + subsql += col.ColumnName + "= :" + col.ColumnName; + } + sql += subsql; + sql += " where " + pk; + SqliteCommand cmd = new SqliteCommand(sql); + + // this provides the binding for all our parameters, so + // much less code than it used to be + + foreach (DataColumn col in dt.Columns) + { + cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType)); + } + return cmd; + } + + /// + /// create an update command + /// + /// table name + /// + /// + /// the created command + private static SqliteCommand createUpdateCommand(string table, string pk1, string pk2, DataTable dt) + { + string sql = "update " + table + " set "; + string subsql = String.Empty; + foreach (DataColumn col in dt.Columns) + { + if (subsql.Length > 0) + { + // a map function would rock so much here + subsql += ", "; + } + subsql += col.ColumnName + "= :" + col.ColumnName; + } + sql += subsql; + sql += " where " + pk1 + " and " + pk2; + SqliteCommand cmd = new SqliteCommand(sql); + + // this provides the binding for all our parameters, so + // much less code than it used to be + + foreach (DataColumn col in dt.Columns) + { + cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType)); + } + return cmd; + } + + /// + /// + /// + /// Data Table + /// + // private static string defineTable(DataTable dt) + // { + // string sql = "create table " + dt.TableName + "("; + // string subsql = String.Empty; + // foreach (DataColumn col in dt.Columns) + // { + // if (subsql.Length > 0) + // { + // // a map function would rock so much here + // subsql += ",\n"; + // } + // subsql += col.ColumnName + " " + sqliteType(col.DataType); + // if (dt.PrimaryKey.Length > 0 && col == dt.PrimaryKey[0]) + // { + // subsql += " primary key"; + // } + // } + // sql += subsql; + // sql += ")"; + // return sql; + // } + + /*********************************************************************** + * + * Database Binding functions + * + * These will be db specific due to typing, and minor differences + * in databases. + * + **********************************************************************/ + + /// + /// This is a convenience function that collapses 5 repetitive + /// lines for defining SqliteParameters to 2 parameters: + /// column name and database type. + /// + /// It assumes certain conventions like :param as the param + /// name to replace in parametrized queries, and that source + /// version is always current version, both of which are fine + /// for us. + /// + ///a built sqlite parameter + private static SqliteParameter createSqliteParameter(string name, Type type) + { + SqliteParameter param = new SqliteParameter(); + param.ParameterName = ":" + name; + param.DbType = dbtypeFromType(type); + param.SourceColumn = name; + param.SourceVersion = DataRowVersion.Current; + return param; + } + + /// + /// + /// + /// + /// + private void setupPrimCommands(SqliteDataAdapter da, SqliteConnection conn) + { + da.InsertCommand = createInsertCommand("prims", ds.Tables["prims"]); + da.InsertCommand.Connection = conn; + + da.UpdateCommand = createUpdateCommand("prims", "UUID=:UUID", ds.Tables["prims"]); + da.UpdateCommand.Connection = conn; + + SqliteCommand delete = new SqliteCommand("delete from prims where UUID = :UUID"); + delete.Parameters.Add(createSqliteParameter("UUID", typeof (String))); + delete.Connection = conn; + da.DeleteCommand = delete; + } + + /// + /// + /// + /// + /// + private void setupItemsCommands(SqliteDataAdapter da, SqliteConnection conn) + { + da.InsertCommand = createInsertCommand("primitems", ds.Tables["primitems"]); + da.InsertCommand.Connection = conn; + + da.UpdateCommand = createUpdateCommand("primitems", "itemID = :itemID", ds.Tables["primitems"]); + da.UpdateCommand.Connection = conn; + + SqliteCommand delete = new SqliteCommand("delete from primitems where itemID = :itemID"); + delete.Parameters.Add(createSqliteParameter("itemID", typeof (String))); + delete.Connection = conn; + da.DeleteCommand = delete; + } + + /// + /// + /// + /// + /// + private void setupTerrainCommands(SqliteDataAdapter da, SqliteConnection conn) + { + da.InsertCommand = createInsertCommand("terrain", ds.Tables["terrain"]); + da.InsertCommand.Connection = conn; + } + + /// + /// + /// + /// + /// + private void setupLandCommands(SqliteDataAdapter da, SqliteConnection conn) + { + da.InsertCommand = createInsertCommand("land", ds.Tables["land"]); + da.InsertCommand.Connection = conn; + + da.UpdateCommand = createUpdateCommand("land", "UUID=:UUID", ds.Tables["land"]); + da.UpdateCommand.Connection = conn; + + SqliteCommand delete = new SqliteCommand("delete from land where UUID=:UUID"); + delete.Parameters.Add(createSqliteParameter("UUID", typeof(String))); + da.DeleteCommand = delete; + da.DeleteCommand.Connection = conn; + } + + /// + /// + /// + /// + /// + private void setupLandAccessCommands(SqliteDataAdapter da, SqliteConnection conn) + { + da.InsertCommand = createInsertCommand("landaccesslist", ds.Tables["landaccesslist"]); + da.InsertCommand.Connection = conn; + + da.UpdateCommand = createUpdateCommand("landaccesslist", "LandUUID=:landUUID", "AccessUUID=:AccessUUID", ds.Tables["landaccesslist"]); + da.UpdateCommand.Connection = conn; + + SqliteCommand delete = new SqliteCommand("delete from landaccesslist where LandUUID= :LandUUID and AccessUUID= :AccessUUID"); + delete.Parameters.Add(createSqliteParameter("LandUUID", typeof(String))); + delete.Parameters.Add(createSqliteParameter("AccessUUID", typeof(String))); + da.DeleteCommand = delete; + da.DeleteCommand.Connection = conn; + + } + + private void setupRegionSettingsCommands(SqliteDataAdapter da, SqliteConnection conn) + { + da.InsertCommand = createInsertCommand("regionsettings", ds.Tables["regionsettings"]); + da.InsertCommand.Connection = conn; + da.UpdateCommand = createUpdateCommand("regionsettings", "regionUUID=:regionUUID", ds.Tables["regionsettings"]); + da.UpdateCommand.Connection = conn; + } + + /// + /// + /// + /// + /// + private void setupShapeCommands(SqliteDataAdapter da, SqliteConnection conn) + { + da.InsertCommand = createInsertCommand("primshapes", ds.Tables["primshapes"]); + da.InsertCommand.Connection = conn; + + da.UpdateCommand = createUpdateCommand("primshapes", "UUID=:UUID", ds.Tables["primshapes"]); + da.UpdateCommand.Connection = conn; + + SqliteCommand delete = new SqliteCommand("delete from primshapes where UUID = :UUID"); + delete.Parameters.Add(createSqliteParameter("UUID", typeof (String))); + delete.Connection = conn; + da.DeleteCommand = delete; + } + + /*********************************************************************** + * + * Type conversion functions + * + **********************************************************************/ + + /// + /// Type conversion function + /// + /// + /// + private static DbType dbtypeFromType(Type type) + { + if (type == typeof (String)) + { + return DbType.String; + } + else if (type == typeof (Int32)) + { + return DbType.Int32; + } + else if (type == typeof (Double)) + { + return DbType.Double; + } + else if (type == typeof (Byte)) + { + return DbType.Byte; + } + else if (type == typeof (Double)) + { + return DbType.Double; + } + else if (type == typeof (Byte[])) + { + return DbType.Binary; + } + else + { + return DbType.String; + } + } + + static void PrintDataSet(DataSet ds) + { + // Print out any name and extended properties. + Console.WriteLine("DataSet is named: {0}", ds.DataSetName); + foreach (System.Collections.DictionaryEntry de in ds.ExtendedProperties) + { + Console.WriteLine("Key = {0}, Value = {1}", de.Key, de.Value); + } + Console.WriteLine(); + foreach (DataTable dt in ds.Tables) + { + Console.WriteLine("=> {0} Table:", dt.TableName); + // Print out the column names. + for (int curCol = 0; curCol < dt.Columns.Count; curCol++) + { + Console.Write(dt.Columns[curCol].ColumnName + "\t"); + } + Console.WriteLine("\n----------------------------------"); + // Print the DataTable. + for (int curRow = 0; curRow < dt.Rows.Count; curRow++) + { + for (int curCol = 0; curCol < dt.Columns.Count; curCol++) + { + Console.Write(dt.Rows[curRow][curCol].ToString() + "\t"); + } + Console.WriteLine(); + } + } + } + + } +} diff --git a/OpenSim/Data/SQLiteLegacy/SQLiteRegionData.cs b/OpenSim/Data/SQLiteLegacy/SQLiteRegionData.cs deleted file mode 100644 index b5ce4c0..0000000 --- a/OpenSim/Data/SQLiteLegacy/SQLiteRegionData.cs +++ /dev/null @@ -1,2261 +0,0 @@ -/* - * 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.Data; -using System.Drawing; -using System.IO; -using System.Reflection; -using log4net; -using Mono.Data.SqliteClient; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Data.SQLiteLegacy -{ - /// - /// A RegionData Interface to the SQLite database - /// - public class SQLiteRegionData : IRegionDataStore - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private const string primSelect = "select * from prims"; - private const string shapeSelect = "select * from primshapes"; - private const string itemsSelect = "select * from primitems"; - private const string terrainSelect = "select * from terrain limit 1"; - private const string landSelect = "select * from land"; - private const string landAccessListSelect = "select distinct * from landaccesslist"; - private const string regionbanListSelect = "select * from regionban"; - private const string regionSettingsSelect = "select * from regionsettings"; - - private DataSet ds; - private SqliteDataAdapter primDa; - private SqliteDataAdapter shapeDa; - private SqliteDataAdapter itemsDa; - private SqliteDataAdapter terrainDa; - private SqliteDataAdapter landDa; - private SqliteDataAdapter landAccessListDa; - private SqliteDataAdapter regionSettingsDa; - - private SqliteConnection m_conn; - - private String m_connectionString; - - // Temporary attribute while this is experimental - - /*********************************************************************** - * - * Public Interface Functions - * - **********************************************************************/ - - /// - /// See IRegionDataStore - /// - /// Initialises RegionData Interface - /// Loads and initialises a new SQLite connection and maintains it. - /// - /// - /// the connection string - public void Initialise(string connectionString) - { - m_connectionString = connectionString; - - ds = new DataSet(); - - m_log.Info("[REGION DB]: Sqlite - connecting: " + connectionString); - m_conn = new SqliteConnection(m_connectionString); - m_conn.Open(); - - - - SqliteCommand primSelectCmd = new SqliteCommand(primSelect, m_conn); - primDa = new SqliteDataAdapter(primSelectCmd); - // SqliteCommandBuilder primCb = new SqliteCommandBuilder(primDa); - - SqliteCommand shapeSelectCmd = new SqliteCommand(shapeSelect, m_conn); - shapeDa = new SqliteDataAdapter(shapeSelectCmd); - // SqliteCommandBuilder shapeCb = new SqliteCommandBuilder(shapeDa); - - SqliteCommand itemsSelectCmd = new SqliteCommand(itemsSelect, m_conn); - itemsDa = new SqliteDataAdapter(itemsSelectCmd); - - SqliteCommand terrainSelectCmd = new SqliteCommand(terrainSelect, m_conn); - terrainDa = new SqliteDataAdapter(terrainSelectCmd); - - SqliteCommand landSelectCmd = new SqliteCommand(landSelect, m_conn); - landDa = new SqliteDataAdapter(landSelectCmd); - - SqliteCommand landAccessListSelectCmd = new SqliteCommand(landAccessListSelect, m_conn); - landAccessListDa = new SqliteDataAdapter(landAccessListSelectCmd); - - SqliteCommand regionSettingsSelectCmd = new SqliteCommand(regionSettingsSelect, m_conn); - regionSettingsDa = new SqliteDataAdapter(regionSettingsSelectCmd); - // This actually does the roll forward assembly stuff - Assembly assem = GetType().Assembly; - Migration m = new Migration(m_conn, assem, "RegionStore"); - m.Update(); - - lock (ds) - { - ds.Tables.Add(createPrimTable()); - setupPrimCommands(primDa, m_conn); - primDa.Fill(ds.Tables["prims"]); - - ds.Tables.Add(createShapeTable()); - setupShapeCommands(shapeDa, m_conn); - - ds.Tables.Add(createItemsTable()); - setupItemsCommands(itemsDa, m_conn); - itemsDa.Fill(ds.Tables["primitems"]); - - ds.Tables.Add(createTerrainTable()); - setupTerrainCommands(terrainDa, m_conn); - - ds.Tables.Add(createLandTable()); - setupLandCommands(landDa, m_conn); - - ds.Tables.Add(createLandAccessListTable()); - setupLandAccessCommands(landAccessListDa, m_conn); - - ds.Tables.Add(createRegionSettingsTable()); - - setupRegionSettingsCommands(regionSettingsDa, m_conn); - - // WORKAROUND: This is a work around for sqlite on - // windows, which gets really unhappy with blob columns - // that have no sample data in them. At some point we - // need to actually find a proper way to handle this. - try - { - shapeDa.Fill(ds.Tables["primshapes"]); - } - catch (Exception) - { - m_log.Info("[REGION DB]: Caught fill error on primshapes table"); - } - - try - { - terrainDa.Fill(ds.Tables["terrain"]); - } - catch (Exception) - { - m_log.Info("[REGION DB]: Caught fill error on terrain table"); - } - - try - { - landDa.Fill(ds.Tables["land"]); - } - catch (Exception) - { - m_log.Info("[REGION DB]: Caught fill error on land table"); - } - - try - { - landAccessListDa.Fill(ds.Tables["landaccesslist"]); - } - catch (Exception) - { - m_log.Info("[REGION DB]: Caught fill error on landaccesslist table"); - } - - try - { - regionSettingsDa.Fill(ds.Tables["regionsettings"]); - } - catch (Exception) - { - m_log.Info("[REGION DB]: Caught fill error on regionsettings table"); - } - return; - } - } - - public void Dispose() - { - if (m_conn != null) - { - m_conn.Close(); - m_conn = null; - } - if (ds != null) - { - ds.Dispose(); - ds = null; - } - if (primDa != null) - { - primDa.Dispose(); - primDa = null; - } - if (shapeDa != null) - { - shapeDa.Dispose(); - shapeDa = null; - } - if (itemsDa != null) - { - itemsDa.Dispose(); - itemsDa = null; - } - if (terrainDa != null) - { - terrainDa.Dispose(); - terrainDa = null; - } - if (landDa != null) - { - landDa.Dispose(); - landDa = null; - } - if (landAccessListDa != null) - { - landAccessListDa.Dispose(); - landAccessListDa = null; - } - if (regionSettingsDa != null) - { - regionSettingsDa.Dispose(); - regionSettingsDa = null; - } - } - - public void StoreRegionSettings(RegionSettings rs) - { - lock (ds) - { - DataTable regionsettings = ds.Tables["regionsettings"]; - - DataRow settingsRow = regionsettings.Rows.Find(rs.RegionUUID.ToString()); - if (settingsRow == null) - { - settingsRow = regionsettings.NewRow(); - fillRegionSettingsRow(settingsRow, rs); - regionsettings.Rows.Add(settingsRow); - } - else - { - fillRegionSettingsRow(settingsRow, rs); - } - - Commit(); - } - } - public RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID) - { - //This connector doesn't support the windlight module yet - //Return default LL windlight settings - return new RegionLightShareData(); - } - public void StoreRegionWindlightSettings(RegionLightShareData wl) - { - //This connector doesn't support the windlight module yet - } - public RegionSettings LoadRegionSettings(UUID regionUUID) - { - lock (ds) - { - DataTable regionsettings = ds.Tables["regionsettings"]; - - string searchExp = "regionUUID = '" + regionUUID.ToString() + "'"; - DataRow[] rawsettings = regionsettings.Select(searchExp); - if (rawsettings.Length == 0) - { - RegionSettings rs = new RegionSettings(); - rs.RegionUUID = regionUUID; - rs.OnSave += StoreRegionSettings; - - StoreRegionSettings(rs); - - return rs; - } - DataRow row = rawsettings[0]; - - RegionSettings newSettings = buildRegionSettings(row); - newSettings.OnSave += StoreRegionSettings; - - return newSettings; - } - } - - /// - /// Adds an object into region storage - /// - /// the object - /// the region UUID - public void StoreObject(SceneObjectGroup obj, UUID regionUUID) - { - uint flags = obj.RootPart.GetEffectiveObjectFlags(); - - // Eligibility check - // - if ((flags & (uint)PrimFlags.Temporary) != 0) - return; - if ((flags & (uint)PrimFlags.TemporaryOnRez) != 0) - return; - - lock (ds) - { - foreach (SceneObjectPart prim in obj.Children.Values) - { -// m_log.Info("[REGION DB]: Adding obj: " + obj.UUID + " to region: " + regionUUID); - addPrim(prim, obj.UUID, regionUUID); - } - } - - Commit(); - // m_log.Info("[Dump of prims]: " + ds.GetXml()); - } - - /// - /// Removes an object from region storage - /// - /// the object - /// the region UUID - public void RemoveObject(UUID obj, UUID regionUUID) - { - // m_log.InfoFormat("[REGION DB]: Removing obj: {0} from region: {1}", obj.Guid, regionUUID); - - DataTable prims = ds.Tables["prims"]; - DataTable shapes = ds.Tables["primshapes"]; - - string selectExp = "SceneGroupID = '" + obj + "' and RegionUUID = '" + regionUUID + "'"; - lock (ds) - { - DataRow[] primRows = prims.Select(selectExp); - foreach (DataRow row in primRows) - { - // Remove shape rows - UUID uuid = new UUID((string) row["UUID"]); - DataRow shapeRow = shapes.Rows.Find(uuid.ToString()); - if (shapeRow != null) - { - shapeRow.Delete(); - } - - RemoveItems(uuid); - - // Remove prim row - row.Delete(); - } - } - - Commit(); - } - - /// - /// Remove all persisted items of the given prim. - /// The caller must acquire the necessrary synchronization locks and commit or rollback changes. - /// - /// The item UUID - private void RemoveItems(UUID uuid) - { - DataTable items = ds.Tables["primitems"]; - - String sql = String.Format("primID = '{0}'", uuid); - DataRow[] itemRows = items.Select(sql); - - foreach (DataRow itemRow in itemRows) - { - itemRow.Delete(); - } - } - - /// - /// Load persisted objects from region storage. - /// - /// The region UUID - /// List of loaded groups - public List LoadObjects(UUID regionUUID) - { - Dictionary createdObjects = new Dictionary(); - - List retvals = new List(); - - DataTable prims = ds.Tables["prims"]; - DataTable shapes = ds.Tables["primshapes"]; - - string byRegion = "RegionUUID = '" + regionUUID + "'"; - - lock (ds) - { - DataRow[] primsForRegion = prims.Select(byRegion); - m_log.Info("[REGION DB]: Loaded " + primsForRegion.Length + " prims for region: " + regionUUID); - - // First, create all groups - foreach (DataRow primRow in primsForRegion) - { - try - { - SceneObjectPart prim = null; - - string uuid = (string) primRow["UUID"]; - string objID = (string) primRow["SceneGroupID"]; - - if (uuid == objID) //is new SceneObjectGroup ? - { - prim = buildPrim(primRow); - DataRow shapeRow = shapes.Rows.Find(prim.UUID.ToString()); - if (shapeRow != null) - { - prim.Shape = buildShape(shapeRow); - } - else - { - m_log.Info( - "[REGION DB]: No shape found for prim in storage, so setting default box shape"); - prim.Shape = PrimitiveBaseShape.Default; - } - - SceneObjectGroup group = new SceneObjectGroup(prim); - createdObjects.Add(group.UUID, group); - retvals.Add(group); - LoadItems(prim); - } - } - catch (Exception e) - { - m_log.Error("[REGION DB]: Failed create prim object in new group, exception and data follows"); - m_log.Info("[REGION DB]: " + e.ToString()); - foreach (DataColumn col in prims.Columns) - { - m_log.Info("[REGION DB]: Col: " + col.ColumnName + " => " + primRow[col]); - } - } - } - - // Now fill the groups with part data - foreach (DataRow primRow in primsForRegion) - { - try - { - SceneObjectPart prim = null; - - string uuid = (string) primRow["UUID"]; - string objID = (string) primRow["SceneGroupID"]; - if (uuid != objID) //is new SceneObjectGroup ? - { - prim = buildPrim(primRow); - DataRow shapeRow = shapes.Rows.Find(prim.UUID.ToString()); - if (shapeRow != null) - { - prim.Shape = buildShape(shapeRow); - } - else - { - m_log.Warn( - "[REGION DB]: No shape found for prim in storage, so setting default box shape"); - prim.Shape = PrimitiveBaseShape.Default; - } - - createdObjects[new UUID(objID)].AddPart(prim); - LoadItems(prim); - } - } - catch (Exception e) - { - m_log.Error("[REGION DB]: Failed create prim object in group, exception and data follows"); - m_log.Info("[REGION DB]: " + e.ToString()); - foreach (DataColumn col in prims.Columns) - { - m_log.Info("[REGION DB]: Col: " + col.ColumnName + " => " + primRow[col]); - } - } - } - } - return retvals; - } - - /// - /// Load in a prim's persisted inventory. - /// - /// the prim - private void LoadItems(SceneObjectPart prim) - { - //m_log.DebugFormat("[DATASTORE]: Loading inventory for {0}, {1}", prim.Name, prim.UUID); - - DataTable dbItems = ds.Tables["primitems"]; - String sql = String.Format("primID = '{0}'", prim.UUID.ToString()); - DataRow[] dbItemRows = dbItems.Select(sql); - IList inventory = new List(); - - foreach (DataRow row in dbItemRows) - { - TaskInventoryItem item = buildItem(row); - inventory.Add(item); - - //m_log.DebugFormat("[DATASTORE]: Restored item {0}, {1}", item.Name, item.ItemID); - } - - prim.Inventory.RestoreInventoryItems(inventory); - } - - /// - /// Store a terrain revision in region storage - /// - /// terrain heightfield - /// region UUID - public void StoreTerrain(double[,] ter, UUID regionID) - { - lock (ds) - { - int revision = Util.UnixTimeSinceEpoch(); - - // This is added to get rid of the infinitely growing - // terrain databases which negatively impact on SQLite - // over time. Before reenabling this feature there - // needs to be a limitter put on the number of - // revisions in the database, as this old - // implementation is a DOS attack waiting to happen. - - using ( - SqliteCommand cmd = - new SqliteCommand("delete from terrain where RegionUUID=:RegionUUID and Revision <= :Revision", - m_conn)) - { - cmd.Parameters.Add(new SqliteParameter(":RegionUUID", regionID.ToString())); - cmd.Parameters.Add(new SqliteParameter(":Revision", revision)); - cmd.ExecuteNonQuery(); - } - - // the following is an work around for .NET. The perf - // issues associated with it aren't as bad as you think. - m_log.Info("[REGION DB]: Storing terrain revision r" + revision.ToString()); - String sql = "insert into terrain(RegionUUID, Revision, Heightfield)" + - " values(:RegionUUID, :Revision, :Heightfield)"; - - using (SqliteCommand cmd = new SqliteCommand(sql, m_conn)) - { - cmd.Parameters.Add(new SqliteParameter(":RegionUUID", regionID.ToString())); - cmd.Parameters.Add(new SqliteParameter(":Revision", revision)); - cmd.Parameters.Add(new SqliteParameter(":Heightfield", serializeTerrain(ter))); - cmd.ExecuteNonQuery(); - } - } - } - - /// - /// Load the latest terrain revision from region storage - /// - /// the region UUID - /// Heightfield data - public double[,] LoadTerrain(UUID regionID) - { - lock (ds) - { - double[,] terret = new double[(int)Constants.RegionSize, (int)Constants.RegionSize]; - terret.Initialize(); - - String sql = "select RegionUUID, Revision, Heightfield from terrain" + - " where RegionUUID=:RegionUUID order by Revision desc"; - - using (SqliteCommand cmd = new SqliteCommand(sql, m_conn)) - { - cmd.Parameters.Add(new SqliteParameter(":RegionUUID", regionID.ToString())); - - using (IDataReader row = cmd.ExecuteReader()) - { - int rev = 0; - if (row.Read()) - { - // TODO: put this into a function - using (MemoryStream str = new MemoryStream((byte[])row["Heightfield"])) - { - using (BinaryReader br = new BinaryReader(str)) - { - for (int x = 0; x < (int)Constants.RegionSize; x++) - { - for (int y = 0; y < (int)Constants.RegionSize; y++) - { - terret[x, y] = br.ReadDouble(); - } - } - } - } - rev = (int) row["Revision"]; - } - else - { - m_log.Info("[REGION DB]: No terrain found for region"); - return null; - } - - m_log.Info("[REGION DB]: Loaded terrain revision r" + rev.ToString()); - } - } - return terret; - } - } - - /// - /// - /// - /// - public void RemoveLandObject(UUID globalID) - { - lock (ds) - { - // Can't use blanket SQL statements when using SqlAdapters unless you re-read the data into the adapter - // after you're done. - // replaced below code with the SqliteAdapter version. - //using (SqliteCommand cmd = new SqliteCommand("delete from land where UUID=:UUID", m_conn)) - //{ - // cmd.Parameters.Add(new SqliteParameter(":UUID", globalID.ToString())); - // cmd.ExecuteNonQuery(); - //} - - //using (SqliteCommand cmd = new SqliteCommand("delete from landaccesslist where LandUUID=:UUID", m_conn)) - //{ - // cmd.Parameters.Add(new SqliteParameter(":UUID", globalID.ToString())); - // cmd.ExecuteNonQuery(); - //} - - DataTable land = ds.Tables["land"]; - DataTable landaccesslist = ds.Tables["landaccesslist"]; - DataRow landRow = land.Rows.Find(globalID.ToString()); - if (landRow != null) - { - land.Rows.Remove(landRow); - } - List rowsToDelete = new List(); - foreach (DataRow rowToCheck in landaccesslist.Rows) - { - if (rowToCheck["LandUUID"].ToString() == globalID.ToString()) - rowsToDelete.Add(rowToCheck); - } - for (int iter = 0; iter < rowsToDelete.Count; iter++) - { - landaccesslist.Rows.Remove(rowsToDelete[iter]); - } - - - } - Commit(); - } - - /// - /// - /// - /// - public void StoreLandObject(ILandObject parcel) - { - lock (ds) - { - DataTable land = ds.Tables["land"]; - DataTable landaccesslist = ds.Tables["landaccesslist"]; - - DataRow landRow = land.Rows.Find(parcel.LandData.GlobalID.ToString()); - if (landRow == null) - { - landRow = land.NewRow(); - fillLandRow(landRow, parcel.LandData, parcel.RegionUUID); - land.Rows.Add(landRow); - } - else - { - fillLandRow(landRow, parcel.LandData, parcel.RegionUUID); - } - - // I know this caused someone issues before, but OpenSim is unusable if we leave this stuff around - //using (SqliteCommand cmd = new SqliteCommand("delete from landaccesslist where LandUUID=:LandUUID", m_conn)) - //{ - // cmd.Parameters.Add(new SqliteParameter(":LandUUID", parcel.LandData.GlobalID.ToString())); - // cmd.ExecuteNonQuery(); - -// } - - // This is the slower.. but more appropriate thing to do - - // We can't modify the table with direct queries before calling Commit() and re-filling them. - List rowsToDelete = new List(); - foreach (DataRow rowToCheck in landaccesslist.Rows) - { - if (rowToCheck["LandUUID"].ToString() == parcel.LandData.GlobalID.ToString()) - rowsToDelete.Add(rowToCheck); - } - for (int iter = 0; iter < rowsToDelete.Count; iter++) - { - landaccesslist.Rows.Remove(rowsToDelete[iter]); - } - rowsToDelete.Clear(); - foreach (ParcelManager.ParcelAccessEntry entry in parcel.LandData.ParcelAccessList) - { - DataRow newAccessRow = landaccesslist.NewRow(); - fillLandAccessRow(newAccessRow, entry, parcel.LandData.GlobalID); - landaccesslist.Rows.Add(newAccessRow); - } - } - - Commit(); - } - - /// - /// - /// - /// - /// - public List LoadLandObjects(UUID regionUUID) - { - List landDataForRegion = new List(); - lock (ds) - { - DataTable land = ds.Tables["land"]; - DataTable landaccesslist = ds.Tables["landaccesslist"]; - string searchExp = "RegionUUID = '" + regionUUID + "'"; - DataRow[] rawDataForRegion = land.Select(searchExp); - foreach (DataRow rawDataLand in rawDataForRegion) - { - LandData newLand = buildLandData(rawDataLand); - string accessListSearchExp = "LandUUID = '" + newLand.GlobalID + "'"; - DataRow[] rawDataForLandAccessList = landaccesslist.Select(accessListSearchExp); - foreach (DataRow rawDataLandAccess in rawDataForLandAccessList) - { - newLand.ParcelAccessList.Add(buildLandAccessData(rawDataLandAccess)); - } - - landDataForRegion.Add(newLand); - } - } - return landDataForRegion; - } - - /// - /// - /// - public void Commit() - { - lock (ds) - { - primDa.Update(ds, "prims"); - shapeDa.Update(ds, "primshapes"); - - itemsDa.Update(ds, "primitems"); - - terrainDa.Update(ds, "terrain"); - landDa.Update(ds, "land"); - landAccessListDa.Update(ds, "landaccesslist"); - try - { - regionSettingsDa.Update(ds, "regionsettings"); - } - catch (SqliteExecutionException SqlEx) - { - if (SqlEx.Message.Contains("logic error")) - { - throw new Exception( - "There was a SQL error or connection string configuration error when saving the region settings. This could be a bug, it could also happen if ConnectionString is defined in the [DatabaseService] section of StandaloneCommon.ini in the config_include folder. This could also happen if the config_include folder doesn't exist or if the OpenSim.ini [Architecture] section isn't set. If this is your first time running OpenSimulator, please restart the simulator and bug a developer to fix this!", - SqlEx); - } - else - { - throw SqlEx; - } - } - ds.AcceptChanges(); - } - } - - /// - /// See - /// - public void Shutdown() - { - Commit(); - } - - /*********************************************************************** - * - * Database Definition Functions - * - * This should be db agnostic as we define them in ADO.NET terms - * - **********************************************************************/ - - /// - /// - /// - /// - /// - /// - private static void createCol(DataTable dt, string name, Type type) - { - DataColumn col = new DataColumn(name, type); - dt.Columns.Add(col); - } - - /// - /// Creates the "terrain" table - /// - /// terrain table DataTable - private static DataTable createTerrainTable() - { - DataTable terrain = new DataTable("terrain"); - - createCol(terrain, "RegionUUID", typeof (String)); - createCol(terrain, "Revision", typeof (Int32)); - createCol(terrain, "Heightfield", typeof (Byte[])); - - return terrain; - } - - /// - /// Creates the "prims" table - /// - /// prim table DataTable - private static DataTable createPrimTable() - { - DataTable prims = new DataTable("prims"); - - createCol(prims, "UUID", typeof (String)); - createCol(prims, "RegionUUID", typeof (String)); - createCol(prims, "CreationDate", typeof (Int32)); - createCol(prims, "Name", typeof (String)); - createCol(prims, "SceneGroupID", typeof (String)); - // various text fields - createCol(prims, "Text", typeof (String)); - createCol(prims, "ColorR", typeof (Int32)); - createCol(prims, "ColorG", typeof (Int32)); - createCol(prims, "ColorB", typeof (Int32)); - createCol(prims, "ColorA", typeof (Int32)); - createCol(prims, "Description", typeof (String)); - createCol(prims, "SitName", typeof (String)); - createCol(prims, "TouchName", typeof (String)); - // permissions - createCol(prims, "ObjectFlags", typeof (Int32)); - createCol(prims, "CreatorID", typeof (String)); - createCol(prims, "OwnerID", typeof (String)); - createCol(prims, "GroupID", typeof (String)); - createCol(prims, "LastOwnerID", typeof (String)); - createCol(prims, "OwnerMask", typeof (Int32)); - createCol(prims, "NextOwnerMask", typeof (Int32)); - createCol(prims, "GroupMask", typeof (Int32)); - createCol(prims, "EveryoneMask", typeof (Int32)); - createCol(prims, "BaseMask", typeof (Int32)); - // vectors - createCol(prims, "PositionX", typeof (Double)); - createCol(prims, "PositionY", typeof (Double)); - createCol(prims, "PositionZ", typeof (Double)); - createCol(prims, "GroupPositionX", typeof (Double)); - createCol(prims, "GroupPositionY", typeof (Double)); - createCol(prims, "GroupPositionZ", typeof (Double)); - createCol(prims, "VelocityX", typeof (Double)); - createCol(prims, "VelocityY", typeof (Double)); - createCol(prims, "VelocityZ", typeof (Double)); - createCol(prims, "AngularVelocityX", typeof (Double)); - createCol(prims, "AngularVelocityY", typeof (Double)); - createCol(prims, "AngularVelocityZ", typeof (Double)); - createCol(prims, "AccelerationX", typeof (Double)); - createCol(prims, "AccelerationY", typeof (Double)); - createCol(prims, "AccelerationZ", typeof (Double)); - // quaternions - createCol(prims, "RotationX", typeof (Double)); - createCol(prims, "RotationY", typeof (Double)); - createCol(prims, "RotationZ", typeof (Double)); - createCol(prims, "RotationW", typeof (Double)); - - // sit target - createCol(prims, "SitTargetOffsetX", typeof (Double)); - createCol(prims, "SitTargetOffsetY", typeof (Double)); - createCol(prims, "SitTargetOffsetZ", typeof (Double)); - - createCol(prims, "SitTargetOrientW", typeof (Double)); - createCol(prims, "SitTargetOrientX", typeof (Double)); - createCol(prims, "SitTargetOrientY", typeof (Double)); - createCol(prims, "SitTargetOrientZ", typeof (Double)); - - createCol(prims, "PayPrice", typeof(Int32)); - createCol(prims, "PayButton1", typeof(Int32)); - createCol(prims, "PayButton2", typeof(Int32)); - createCol(prims, "PayButton3", typeof(Int32)); - createCol(prims, "PayButton4", typeof(Int32)); - - createCol(prims, "LoopedSound", typeof(String)); - createCol(prims, "LoopedSoundGain", typeof(Double)); - createCol(prims, "TextureAnimation", typeof(String)); - createCol(prims, "ParticleSystem", typeof(String)); - - createCol(prims, "OmegaX", typeof(Double)); - createCol(prims, "OmegaY", typeof(Double)); - createCol(prims, "OmegaZ", typeof(Double)); - - createCol(prims, "CameraEyeOffsetX", typeof(Double)); - createCol(prims, "CameraEyeOffsetY", typeof(Double)); - createCol(prims, "CameraEyeOffsetZ", typeof(Double)); - - createCol(prims, "CameraAtOffsetX", typeof(Double)); - createCol(prims, "CameraAtOffsetY", typeof(Double)); - createCol(prims, "CameraAtOffsetZ", typeof(Double)); - - createCol(prims, "ForceMouselook", typeof(Int16)); - - createCol(prims, "ScriptAccessPin", typeof(Int32)); - - createCol(prims, "AllowedDrop", typeof(Int16)); - createCol(prims, "DieAtEdge", typeof(Int16)); - - createCol(prims, "SalePrice", typeof(Int32)); - createCol(prims, "SaleType", typeof(Int16)); - - // click action - createCol(prims, "ClickAction", typeof (Byte)); - - createCol(prims, "Material", typeof(Byte)); - - createCol(prims, "CollisionSound", typeof(String)); - createCol(prims, "CollisionSoundVolume", typeof(Double)); - - createCol(prims, "VolumeDetect", typeof(Int16)); - - // Add in contraints - prims.PrimaryKey = new DataColumn[] {prims.Columns["UUID"]}; - - return prims; - } - - /// - /// Creates "primshapes" table - /// - /// shape table DataTable - private static DataTable createShapeTable() - { - DataTable shapes = new DataTable("primshapes"); - createCol(shapes, "UUID", typeof (String)); - // shape is an enum - createCol(shapes, "Shape", typeof (Int32)); - // vectors - createCol(shapes, "ScaleX", typeof (Double)); - createCol(shapes, "ScaleY", typeof (Double)); - createCol(shapes, "ScaleZ", typeof (Double)); - // paths - createCol(shapes, "PCode", typeof (Int32)); - createCol(shapes, "PathBegin", typeof (Int32)); - createCol(shapes, "PathEnd", typeof (Int32)); - createCol(shapes, "PathScaleX", typeof (Int32)); - createCol(shapes, "PathScaleY", typeof (Int32)); - createCol(shapes, "PathShearX", typeof (Int32)); - createCol(shapes, "PathShearY", typeof (Int32)); - createCol(shapes, "PathSkew", typeof (Int32)); - createCol(shapes, "PathCurve", typeof (Int32)); - createCol(shapes, "PathRadiusOffset", typeof (Int32)); - createCol(shapes, "PathRevolutions", typeof (Int32)); - createCol(shapes, "PathTaperX", typeof (Int32)); - createCol(shapes, "PathTaperY", typeof (Int32)); - createCol(shapes, "PathTwist", typeof (Int32)); - createCol(shapes, "PathTwistBegin", typeof (Int32)); - // profile - createCol(shapes, "ProfileBegin", typeof (Int32)); - createCol(shapes, "ProfileEnd", typeof (Int32)); - createCol(shapes, "ProfileCurve", typeof (Int32)); - createCol(shapes, "ProfileHollow", typeof (Int32)); - createCol(shapes, "State", typeof(Int32)); - // text TODO: this isn't right, but I'm not sure the right - // way to specify this as a blob atm - createCol(shapes, "Texture", typeof (Byte[])); - createCol(shapes, "ExtraParams", typeof (Byte[])); - - shapes.PrimaryKey = new DataColumn[] {shapes.Columns["UUID"]}; - - return shapes; - } - - /// - /// creates "primitems" table - /// - /// item table DataTable - private static DataTable createItemsTable() - { - DataTable items = new DataTable("primitems"); - - createCol(items, "itemID", typeof (String)); - createCol(items, "primID", typeof (String)); - createCol(items, "assetID", typeof (String)); - createCol(items, "parentFolderID", typeof (String)); - - createCol(items, "invType", typeof (Int32)); - createCol(items, "assetType", typeof (Int32)); - - createCol(items, "name", typeof (String)); - createCol(items, "description", typeof (String)); - - createCol(items, "creationDate", typeof (Int64)); - createCol(items, "creatorID", typeof (String)); - createCol(items, "ownerID", typeof (String)); - createCol(items, "lastOwnerID", typeof (String)); - createCol(items, "groupID", typeof (String)); - - createCol(items, "nextPermissions", typeof (UInt32)); - createCol(items, "currentPermissions", typeof (UInt32)); - createCol(items, "basePermissions", typeof (UInt32)); - createCol(items, "everyonePermissions", typeof (UInt32)); - createCol(items, "groupPermissions", typeof (UInt32)); - createCol(items, "flags", typeof (UInt32)); - - items.PrimaryKey = new DataColumn[] { items.Columns["itemID"] }; - - return items; - } - - /// - /// Creates "land" table - /// - /// land table DataTable - private static DataTable createLandTable() - { - DataTable land = new DataTable("land"); - createCol(land, "UUID", typeof (String)); - createCol(land, "RegionUUID", typeof (String)); - createCol(land, "LocalLandID", typeof (UInt32)); - - // Bitmap is a byte[512] - createCol(land, "Bitmap", typeof (Byte[])); - - createCol(land, "Name", typeof (String)); - createCol(land, "Desc", typeof (String)); - createCol(land, "OwnerUUID", typeof (String)); - createCol(land, "IsGroupOwned", typeof (Boolean)); - createCol(land, "Area", typeof (Int32)); - createCol(land, "AuctionID", typeof (Int32)); //Unemplemented - createCol(land, "Category", typeof (Int32)); //Enum OpenMetaverse.Parcel.ParcelCategory - createCol(land, "ClaimDate", typeof (Int32)); - createCol(land, "ClaimPrice", typeof (Int32)); - createCol(land, "GroupUUID", typeof (string)); - createCol(land, "SalePrice", typeof (Int32)); - createCol(land, "LandStatus", typeof (Int32)); //Enum. OpenMetaverse.Parcel.ParcelStatus - createCol(land, "LandFlags", typeof (UInt32)); - createCol(land, "LandingType", typeof (Byte)); - createCol(land, "MediaAutoScale", typeof (Byte)); - createCol(land, "MediaTextureUUID", typeof (String)); - createCol(land, "MediaURL", typeof (String)); - createCol(land, "MusicURL", typeof (String)); - createCol(land, "PassHours", typeof (Double)); - createCol(land, "PassPrice", typeof (UInt32)); - createCol(land, "SnapshotUUID", typeof (String)); - createCol(land, "UserLocationX", typeof (Double)); - createCol(land, "UserLocationY", typeof (Double)); - createCol(land, "UserLocationZ", typeof (Double)); - createCol(land, "UserLookAtX", typeof (Double)); - createCol(land, "UserLookAtY", typeof (Double)); - createCol(land, "UserLookAtZ", typeof (Double)); - createCol(land, "AuthbuyerID", typeof(String)); - createCol(land, "OtherCleanTime", typeof(Int32)); - - land.PrimaryKey = new DataColumn[] {land.Columns["UUID"]}; - - return land; - } - - /// - /// create "landaccesslist" table - /// - /// Landacceslist DataTable - private static DataTable createLandAccessListTable() - { - DataTable landaccess = new DataTable("landaccesslist"); - createCol(landaccess, "LandUUID", typeof (String)); - createCol(landaccess, "AccessUUID", typeof (String)); - createCol(landaccess, "Flags", typeof (UInt32)); - - return landaccess; - } - - private static DataTable createRegionSettingsTable() - { - DataTable regionsettings = new DataTable("regionsettings"); - createCol(regionsettings, "regionUUID", typeof(String)); - createCol(regionsettings, "block_terraform", typeof (Int32)); - createCol(regionsettings, "block_fly", typeof (Int32)); - createCol(regionsettings, "allow_damage", typeof (Int32)); - createCol(regionsettings, "restrict_pushing", typeof (Int32)); - createCol(regionsettings, "allow_land_resell", typeof (Int32)); - createCol(regionsettings, "allow_land_join_divide", typeof (Int32)); - createCol(regionsettings, "block_show_in_search", typeof (Int32)); - createCol(regionsettings, "agent_limit", typeof (Int32)); - createCol(regionsettings, "object_bonus", typeof (Double)); - createCol(regionsettings, "maturity", typeof (Int32)); - createCol(regionsettings, "disable_scripts", typeof (Int32)); - createCol(regionsettings, "disable_collisions", typeof (Int32)); - createCol(regionsettings, "disable_physics", typeof (Int32)); - createCol(regionsettings, "terrain_texture_1", typeof(String)); - createCol(regionsettings, "terrain_texture_2", typeof(String)); - createCol(regionsettings, "terrain_texture_3", typeof(String)); - createCol(regionsettings, "terrain_texture_4", typeof(String)); - createCol(regionsettings, "elevation_1_nw", typeof (Double)); - createCol(regionsettings, "elevation_2_nw", typeof (Double)); - createCol(regionsettings, "elevation_1_ne", typeof (Double)); - createCol(regionsettings, "elevation_2_ne", typeof (Double)); - createCol(regionsettings, "elevation_1_se", typeof (Double)); - createCol(regionsettings, "elevation_2_se", typeof (Double)); - createCol(regionsettings, "elevation_1_sw", typeof (Double)); - createCol(regionsettings, "elevation_2_sw", typeof (Double)); - createCol(regionsettings, "water_height", typeof (Double)); - createCol(regionsettings, "terrain_raise_limit", typeof (Double)); - createCol(regionsettings, "terrain_lower_limit", typeof (Double)); - createCol(regionsettings, "use_estate_sun", typeof (Int32)); - createCol(regionsettings, "sandbox", typeof (Int32)); - createCol(regionsettings, "sunvectorx",typeof (Double)); - createCol(regionsettings, "sunvectory",typeof (Double)); - createCol(regionsettings, "sunvectorz",typeof (Double)); - createCol(regionsettings, "fixed_sun", typeof (Int32)); - createCol(regionsettings, "sun_position", typeof (Double)); - createCol(regionsettings, "covenant", typeof(String)); - regionsettings.PrimaryKey = new DataColumn[] { regionsettings.Columns["regionUUID"] }; - return regionsettings; - } - - /*********************************************************************** - * - * Convert between ADO.NET <=> OpenSim Objects - * - * These should be database independant - * - **********************************************************************/ - - /// - /// - /// - /// - /// - private SceneObjectPart buildPrim(DataRow row) - { - // Code commented. Uncomment to test the unit test inline. - - // The unit test mentions this commented code for the purposes - // of debugging a unit test failure - - // SceneObjectGroup sog = new SceneObjectGroup(); - // SceneObjectPart sop = new SceneObjectPart(); - // sop.LocalId = 1; - // sop.Name = "object1"; - // sop.Description = "object1"; - // sop.Text = ""; - // sop.SitName = ""; - // sop.TouchName = ""; - // sop.UUID = UUID.Random(); - // sop.Shape = PrimitiveBaseShape.Default; - // sog.SetRootPart(sop); - // Add breakpoint in above line. Check sop fields. - - // TODO: this doesn't work yet because something more - // interesting has to be done to actually get these values - // back out. Not enough time to figure it out yet. - - SceneObjectPart prim = new SceneObjectPart(); - prim.UUID = new UUID((String) row["UUID"]); - // explicit conversion of integers is required, which sort - // of sucks. No idea if there is a shortcut here or not. - prim.CreationDate = Convert.ToInt32(row["CreationDate"]); - prim.Name = row["Name"] == DBNull.Value ? string.Empty : (string)row["Name"]; - // various text fields - prim.Text = (String) row["Text"]; - prim.Color = Color.FromArgb(Convert.ToInt32(row["ColorA"]), - Convert.ToInt32(row["ColorR"]), - Convert.ToInt32(row["ColorG"]), - Convert.ToInt32(row["ColorB"])); - prim.Description = (String) row["Description"]; - prim.SitName = (String) row["SitName"]; - prim.TouchName = (String) row["TouchName"]; - // permissions - prim.Flags = (PrimFlags)Convert.ToUInt32(row["ObjectFlags"]); - prim.CreatorID = new UUID((String) row["CreatorID"]); - prim.OwnerID = new UUID((String) row["OwnerID"]); - prim.GroupID = new UUID((String) row["GroupID"]); - prim.LastOwnerID = new UUID((String) row["LastOwnerID"]); - prim.OwnerMask = Convert.ToUInt32(row["OwnerMask"]); - prim.NextOwnerMask = Convert.ToUInt32(row["NextOwnerMask"]); - prim.GroupMask = Convert.ToUInt32(row["GroupMask"]); - prim.EveryoneMask = Convert.ToUInt32(row["EveryoneMask"]); - prim.BaseMask = Convert.ToUInt32(row["BaseMask"]); - // vectors - prim.OffsetPosition = new Vector3( - Convert.ToSingle(row["PositionX"]), - Convert.ToSingle(row["PositionY"]), - Convert.ToSingle(row["PositionZ"]) - ); - prim.GroupPosition = new Vector3( - Convert.ToSingle(row["GroupPositionX"]), - Convert.ToSingle(row["GroupPositionY"]), - Convert.ToSingle(row["GroupPositionZ"]) - ); - prim.Velocity = new Vector3( - Convert.ToSingle(row["VelocityX"]), - Convert.ToSingle(row["VelocityY"]), - Convert.ToSingle(row["VelocityZ"]) - ); - prim.AngularVelocity = new Vector3( - Convert.ToSingle(row["AngularVelocityX"]), - Convert.ToSingle(row["AngularVelocityY"]), - Convert.ToSingle(row["AngularVelocityZ"]) - ); - prim.Acceleration = new Vector3( - Convert.ToSingle(row["AccelerationX"]), - Convert.ToSingle(row["AccelerationY"]), - Convert.ToSingle(row["AccelerationZ"]) - ); - // quaternions - prim.RotationOffset = new Quaternion( - Convert.ToSingle(row["RotationX"]), - Convert.ToSingle(row["RotationY"]), - Convert.ToSingle(row["RotationZ"]), - Convert.ToSingle(row["RotationW"]) - ); - - prim.SitTargetPositionLL = new Vector3( - Convert.ToSingle(row["SitTargetOffsetX"]), - Convert.ToSingle(row["SitTargetOffsetY"]), - Convert.ToSingle(row["SitTargetOffsetZ"])); - prim.SitTargetOrientationLL = new Quaternion( - Convert.ToSingle( - row["SitTargetOrientX"]), - Convert.ToSingle( - row["SitTargetOrientY"]), - Convert.ToSingle( - row["SitTargetOrientZ"]), - Convert.ToSingle( - row["SitTargetOrientW"])); - - prim.ClickAction = Convert.ToByte(row["ClickAction"]); - prim.PayPrice[0] = Convert.ToInt32(row["PayPrice"]); - prim.PayPrice[1] = Convert.ToInt32(row["PayButton1"]); - prim.PayPrice[2] = Convert.ToInt32(row["PayButton2"]); - prim.PayPrice[3] = Convert.ToInt32(row["PayButton3"]); - prim.PayPrice[4] = Convert.ToInt32(row["PayButton4"]); - - prim.Sound = new UUID(row["LoopedSound"].ToString()); - prim.SoundGain = Convert.ToSingle(row["LoopedSoundGain"]); - prim.SoundFlags = 1; // If it's persisted at all, it's looped - - if (!row.IsNull("TextureAnimation")) - prim.TextureAnimation = Convert.FromBase64String(row["TextureAnimation"].ToString()); - if (!row.IsNull("ParticleSystem")) - prim.ParticleSystem = Convert.FromBase64String(row["ParticleSystem"].ToString()); - - prim.AngularVelocity = new Vector3( - Convert.ToSingle(row["OmegaX"]), - Convert.ToSingle(row["OmegaY"]), - Convert.ToSingle(row["OmegaZ"]) - ); - - prim.SetCameraEyeOffset(new Vector3( - Convert.ToSingle(row["CameraEyeOffsetX"]), - Convert.ToSingle(row["CameraEyeOffsetY"]), - Convert.ToSingle(row["CameraEyeOffsetZ"]) - )); - - prim.SetCameraAtOffset(new Vector3( - Convert.ToSingle(row["CameraAtOffsetX"]), - Convert.ToSingle(row["CameraAtOffsetY"]), - Convert.ToSingle(row["CameraAtOffsetZ"]) - )); - - if (Convert.ToInt16(row["ForceMouselook"]) != 0) - prim.SetForceMouselook(true); - - prim.ScriptAccessPin = Convert.ToInt32(row["ScriptAccessPin"]); - - if (Convert.ToInt16(row["AllowedDrop"]) != 0) - prim.AllowedDrop = true; - - if (Convert.ToInt16(row["DieAtEdge"]) != 0) - prim.DIE_AT_EDGE = true; - - prim.SalePrice = Convert.ToInt32(row["SalePrice"]); - prim.ObjectSaleType = Convert.ToByte(row["SaleType"]); - - prim.Material = Convert.ToByte(row["Material"]); - - prim.CollisionSound = new UUID(row["CollisionSound"].ToString()); - prim.CollisionSoundVolume = Convert.ToSingle(row["CollisionSoundVolume"]); - - if (Convert.ToInt16(row["VolumeDetect"]) != 0) - prim.VolumeDetectActive = true; - - return prim; - } - - /// - /// Build a prim inventory item from the persisted data. - /// - /// - /// - private static TaskInventoryItem buildItem(DataRow row) - { - TaskInventoryItem taskItem = new TaskInventoryItem(); - - taskItem.ItemID = new UUID((String)row["itemID"]); - taskItem.ParentPartID = new UUID((String)row["primID"]); - taskItem.AssetID = new UUID((String)row["assetID"]); - taskItem.ParentID = new UUID((String)row["parentFolderID"]); - - taskItem.InvType = Convert.ToInt32(row["invType"]); - taskItem.Type = Convert.ToInt32(row["assetType"]); - - taskItem.Name = (String)row["name"]; - taskItem.Description = (String)row["description"]; - taskItem.CreationDate = Convert.ToUInt32(row["creationDate"]); - taskItem.CreatorID = new UUID((String)row["creatorID"]); - taskItem.OwnerID = new UUID((String)row["ownerID"]); - taskItem.LastOwnerID = new UUID((String)row["lastOwnerID"]); - taskItem.GroupID = new UUID((String)row["groupID"]); - - taskItem.NextPermissions = Convert.ToUInt32(row["nextPermissions"]); - taskItem.CurrentPermissions = Convert.ToUInt32(row["currentPermissions"]); - taskItem.BasePermissions = Convert.ToUInt32(row["basePermissions"]); - taskItem.EveryonePermissions = Convert.ToUInt32(row["everyonePermissions"]); - taskItem.GroupPermissions = Convert.ToUInt32(row["groupPermissions"]); - taskItem.Flags = Convert.ToUInt32(row["flags"]); - - return taskItem; - } - - /// - /// Build a Land Data from the persisted data. - /// - /// - /// - private LandData buildLandData(DataRow row) - { - LandData newData = new LandData(); - - newData.GlobalID = new UUID((String) row["UUID"]); - newData.LocalID = Convert.ToInt32(row["LocalLandID"]); - - // Bitmap is a byte[512] - newData.Bitmap = (Byte[]) row["Bitmap"]; - - newData.Name = (String) row["Name"]; - newData.Description = (String) row["Desc"]; - newData.OwnerID = (UUID)(String) row["OwnerUUID"]; - newData.IsGroupOwned = (Boolean) row["IsGroupOwned"]; - newData.Area = Convert.ToInt32(row["Area"]); - newData.AuctionID = Convert.ToUInt32(row["AuctionID"]); //Unemplemented - newData.Category = (ParcelCategory) Convert.ToInt32(row["Category"]); - //Enum OpenMetaverse.Parcel.ParcelCategory - newData.ClaimDate = Convert.ToInt32(row["ClaimDate"]); - newData.ClaimPrice = Convert.ToInt32(row["ClaimPrice"]); - newData.GroupID = new UUID((String) row["GroupUUID"]); - newData.SalePrice = Convert.ToInt32(row["SalePrice"]); - newData.Status = (ParcelStatus) Convert.ToInt32(row["LandStatus"]); - //Enum. OpenMetaverse.Parcel.ParcelStatus - newData.Flags = Convert.ToUInt32(row["LandFlags"]); - newData.LandingType = (Byte) row["LandingType"]; - newData.MediaAutoScale = (Byte) row["MediaAutoScale"]; - newData.MediaID = new UUID((String) row["MediaTextureUUID"]); - newData.MediaURL = (String) row["MediaURL"]; - newData.MusicURL = (String) row["MusicURL"]; - newData.PassHours = Convert.ToSingle(row["PassHours"]); - newData.PassPrice = Convert.ToInt32(row["PassPrice"]); - newData.SnapshotID = (UUID)(String) row["SnapshotUUID"]; - try - { - - newData.UserLocation = - new Vector3(Convert.ToSingle(row["UserLocationX"]), Convert.ToSingle(row["UserLocationY"]), - Convert.ToSingle(row["UserLocationZ"])); - newData.UserLookAt = - new Vector3(Convert.ToSingle(row["UserLookAtX"]), Convert.ToSingle(row["UserLookAtY"]), - Convert.ToSingle(row["UserLookAtZ"])); - - } - catch (InvalidCastException) - { - m_log.ErrorFormat("[PARCEL]: unable to get parcel telehub settings for {1}", newData.Name); - newData.UserLocation = Vector3.Zero; - newData.UserLookAt = Vector3.Zero; - } - newData.ParcelAccessList = new List(); - UUID authBuyerID = UUID.Zero; - - UUID.TryParse((string)row["AuthbuyerID"], out authBuyerID); - - newData.OtherCleanTime = Convert.ToInt32(row["OtherCleanTime"]); - - return newData; - } - - private RegionSettings buildRegionSettings(DataRow row) - { - RegionSettings newSettings = new RegionSettings(); - - newSettings.RegionUUID = new UUID((string) row["regionUUID"]); - newSettings.BlockTerraform = Convert.ToBoolean(row["block_terraform"]); - newSettings.AllowDamage = Convert.ToBoolean(row["allow_damage"]); - newSettings.BlockFly = Convert.ToBoolean(row["block_fly"]); - newSettings.RestrictPushing = Convert.ToBoolean(row["restrict_pushing"]); - newSettings.AllowLandResell = Convert.ToBoolean(row["allow_land_resell"]); - newSettings.AllowLandJoinDivide = Convert.ToBoolean(row["allow_land_join_divide"]); - newSettings.BlockShowInSearch = Convert.ToBoolean(row["block_show_in_search"]); - newSettings.AgentLimit = Convert.ToInt32(row["agent_limit"]); - newSettings.ObjectBonus = Convert.ToDouble(row["object_bonus"]); - newSettings.Maturity = Convert.ToInt32(row["maturity"]); - newSettings.DisableScripts = Convert.ToBoolean(row["disable_scripts"]); - newSettings.DisableCollisions = Convert.ToBoolean(row["disable_collisions"]); - newSettings.DisablePhysics = Convert.ToBoolean(row["disable_physics"]); - newSettings.TerrainTexture1 = new UUID((String) row["terrain_texture_1"]); - newSettings.TerrainTexture2 = new UUID((String) row["terrain_texture_2"]); - newSettings.TerrainTexture3 = new UUID((String) row["terrain_texture_3"]); - newSettings.TerrainTexture4 = new UUID((String) row["terrain_texture_4"]); - newSettings.Elevation1NW = Convert.ToDouble(row["elevation_1_nw"]); - newSettings.Elevation2NW = Convert.ToDouble(row["elevation_2_nw"]); - newSettings.Elevation1NE = Convert.ToDouble(row["elevation_1_ne"]); - newSettings.Elevation2NE = Convert.ToDouble(row["elevation_2_ne"]); - newSettings.Elevation1SE = Convert.ToDouble(row["elevation_1_se"]); - newSettings.Elevation2SE = Convert.ToDouble(row["elevation_2_se"]); - newSettings.Elevation1SW = Convert.ToDouble(row["elevation_1_sw"]); - newSettings.Elevation2SW = Convert.ToDouble(row["elevation_2_sw"]); - newSettings.WaterHeight = Convert.ToDouble(row["water_height"]); - newSettings.TerrainRaiseLimit = Convert.ToDouble(row["terrain_raise_limit"]); - newSettings.TerrainLowerLimit = Convert.ToDouble(row["terrain_lower_limit"]); - newSettings.UseEstateSun = Convert.ToBoolean(row["use_estate_sun"]); - newSettings.Sandbox = Convert.ToBoolean(row["sandbox"]); - newSettings.SunVector = new Vector3 ( - Convert.ToSingle(row["sunvectorx"]), - Convert.ToSingle(row["sunvectory"]), - Convert.ToSingle(row["sunvectorz"]) - ); - newSettings.FixedSun = Convert.ToBoolean(row["fixed_sun"]); - newSettings.SunPosition = Convert.ToDouble(row["sun_position"]); - newSettings.Covenant = new UUID((String) row["covenant"]); - - return newSettings; - } - - /// - /// Build a land access entry from the persisted data. - /// - /// - /// - private static ParcelManager.ParcelAccessEntry buildLandAccessData(DataRow row) - { - ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); - entry.AgentID = new UUID((string) row["AccessUUID"]); - entry.Flags = (AccessList) row["Flags"]; - entry.Time = new DateTime(); - return entry; - } - - /// - /// - /// - /// - /// - private static Array serializeTerrain(double[,] val) - { - MemoryStream str = new MemoryStream(((int)Constants.RegionSize * (int)Constants.RegionSize) *sizeof (double)); - BinaryWriter bw = new BinaryWriter(str); - - // TODO: COMPATIBILITY - Add byte-order conversions - for (int x = 0; x < (int)Constants.RegionSize; x++) - for (int y = 0; y < (int)Constants.RegionSize; y++) - bw.Write(val[x, y]); - - return str.ToArray(); - } - -// private void fillTerrainRow(DataRow row, UUID regionUUID, int rev, double[,] val) -// { -// row["RegionUUID"] = regionUUID; -// row["Revision"] = rev; - - // MemoryStream str = new MemoryStream(((int)Constants.RegionSize * (int)Constants.RegionSize)*sizeof (double)); -// BinaryWriter bw = new BinaryWriter(str); - -// // TODO: COMPATIBILITY - Add byte-order conversions - // for (int x = 0; x < (int)Constants.RegionSize; x++) - // for (int y = 0; y < (int)Constants.RegionSize; y++) -// bw.Write(val[x, y]); - -// row["Heightfield"] = str.ToArray(); -// } - - /// - /// - /// - /// - /// - /// - /// - private static void fillPrimRow(DataRow row, SceneObjectPart prim, UUID sceneGroupID, UUID regionUUID) - { - row["UUID"] = prim.UUID.ToString(); - row["RegionUUID"] = regionUUID.ToString(); - row["CreationDate"] = prim.CreationDate; - row["Name"] = prim.Name; - row["SceneGroupID"] = sceneGroupID.ToString(); - // the UUID of the root part for this SceneObjectGroup - // various text fields - row["Text"] = prim.Text; - row["Description"] = prim.Description; - row["SitName"] = prim.SitName; - row["TouchName"] = prim.TouchName; - // permissions - row["ObjectFlags"] = (uint)prim.Flags; - row["CreatorID"] = prim.CreatorID.ToString(); - row["OwnerID"] = prim.OwnerID.ToString(); - row["GroupID"] = prim.GroupID.ToString(); - row["LastOwnerID"] = prim.LastOwnerID.ToString(); - row["OwnerMask"] = prim.OwnerMask; - row["NextOwnerMask"] = prim.NextOwnerMask; - row["GroupMask"] = prim.GroupMask; - row["EveryoneMask"] = prim.EveryoneMask; - row["BaseMask"] = prim.BaseMask; - // vectors - row["PositionX"] = prim.OffsetPosition.X; - row["PositionY"] = prim.OffsetPosition.Y; - row["PositionZ"] = prim.OffsetPosition.Z; - row["GroupPositionX"] = prim.GroupPosition.X; - row["GroupPositionY"] = prim.GroupPosition.Y; - row["GroupPositionZ"] = prim.GroupPosition.Z; - row["VelocityX"] = prim.Velocity.X; - row["VelocityY"] = prim.Velocity.Y; - row["VelocityZ"] = prim.Velocity.Z; - row["AngularVelocityX"] = prim.AngularVelocity.X; - row["AngularVelocityY"] = prim.AngularVelocity.Y; - row["AngularVelocityZ"] = prim.AngularVelocity.Z; - row["AccelerationX"] = prim.Acceleration.X; - row["AccelerationY"] = prim.Acceleration.Y; - row["AccelerationZ"] = prim.Acceleration.Z; - // quaternions - row["RotationX"] = prim.RotationOffset.X; - row["RotationY"] = prim.RotationOffset.Y; - row["RotationZ"] = prim.RotationOffset.Z; - row["RotationW"] = prim.RotationOffset.W; - - // Sit target - Vector3 sitTargetPos = prim.SitTargetPositionLL; - row["SitTargetOffsetX"] = sitTargetPos.X; - row["SitTargetOffsetY"] = sitTargetPos.Y; - row["SitTargetOffsetZ"] = sitTargetPos.Z; - - Quaternion sitTargetOrient = prim.SitTargetOrientationLL; - row["SitTargetOrientW"] = sitTargetOrient.W; - row["SitTargetOrientX"] = sitTargetOrient.X; - row["SitTargetOrientY"] = sitTargetOrient.Y; - row["SitTargetOrientZ"] = sitTargetOrient.Z; - row["ColorR"] = Convert.ToInt32(prim.Color.R); - row["ColorG"] = Convert.ToInt32(prim.Color.G); - row["ColorB"] = Convert.ToInt32(prim.Color.B); - row["ColorA"] = Convert.ToInt32(prim.Color.A); - row["PayPrice"] = prim.PayPrice[0]; - row["PayButton1"] = prim.PayPrice[1]; - row["PayButton2"] = prim.PayPrice[2]; - row["PayButton3"] = prim.PayPrice[3]; - row["PayButton4"] = prim.PayPrice[4]; - - - row["TextureAnimation"] = Convert.ToBase64String(prim.TextureAnimation); - row["ParticleSystem"] = Convert.ToBase64String(prim.ParticleSystem); - - row["OmegaX"] = prim.AngularVelocity.X; - row["OmegaY"] = prim.AngularVelocity.Y; - row["OmegaZ"] = prim.AngularVelocity.Z; - - row["CameraEyeOffsetX"] = prim.GetCameraEyeOffset().X; - row["CameraEyeOffsetY"] = prim.GetCameraEyeOffset().Y; - row["CameraEyeOffsetZ"] = prim.GetCameraEyeOffset().Z; - - row["CameraAtOffsetX"] = prim.GetCameraAtOffset().X; - row["CameraAtOffsetY"] = prim.GetCameraAtOffset().Y; - row["CameraAtOffsetZ"] = prim.GetCameraAtOffset().Z; - - - if ((prim.SoundFlags & 1) != 0) // Looped - { - row["LoopedSound"] = prim.Sound.ToString(); - row["LoopedSoundGain"] = prim.SoundGain; - } - else - { - row["LoopedSound"] = UUID.Zero.ToString(); - row["LoopedSoundGain"] = 0.0f; - } - - if (prim.GetForceMouselook()) - row["ForceMouselook"] = 1; - else - row["ForceMouselook"] = 0; - - row["ScriptAccessPin"] = prim.ScriptAccessPin; - - if (prim.AllowedDrop) - row["AllowedDrop"] = 1; - else - row["AllowedDrop"] = 0; - - if (prim.DIE_AT_EDGE) - row["DieAtEdge"] = 1; - else - row["DieAtEdge"] = 0; - - row["SalePrice"] = prim.SalePrice; - row["SaleType"] = Convert.ToInt16(prim.ObjectSaleType); - - // click action - row["ClickAction"] = prim.ClickAction; - - row["SalePrice"] = prim.SalePrice; - row["Material"] = prim.Material; - - row["CollisionSound"] = prim.CollisionSound.ToString(); - row["CollisionSoundVolume"] = prim.CollisionSoundVolume; - if (prim.VolumeDetectActive) - row["VolumeDetect"] = 1; - else - row["VolumeDetect"] = 0; - - } - - /// - /// - /// - /// - /// - private static void fillItemRow(DataRow row, TaskInventoryItem taskItem) - { - row["itemID"] = taskItem.ItemID.ToString(); - row["primID"] = taskItem.ParentPartID.ToString(); - row["assetID"] = taskItem.AssetID.ToString(); - row["parentFolderID"] = taskItem.ParentID.ToString(); - - row["invType"] = taskItem.InvType; - row["assetType"] = taskItem.Type; - - row["name"] = taskItem.Name; - row["description"] = taskItem.Description; - row["creationDate"] = taskItem.CreationDate; - row["creatorID"] = taskItem.CreatorID.ToString(); - row["ownerID"] = taskItem.OwnerID.ToString(); - row["lastOwnerID"] = taskItem.LastOwnerID.ToString(); - row["groupID"] = taskItem.GroupID.ToString(); - row["nextPermissions"] = taskItem.NextPermissions; - row["currentPermissions"] = taskItem.CurrentPermissions; - row["basePermissions"] = taskItem.BasePermissions; - row["everyonePermissions"] = taskItem.EveryonePermissions; - row["groupPermissions"] = taskItem.GroupPermissions; - row["flags"] = taskItem.Flags; - } - - /// - /// - /// - /// - /// - /// - private static void fillLandRow(DataRow row, LandData land, UUID regionUUID) - { - row["UUID"] = land.GlobalID.ToString(); - row["RegionUUID"] = regionUUID.ToString(); - row["LocalLandID"] = land.LocalID; - - // Bitmap is a byte[512] - row["Bitmap"] = land.Bitmap; - - row["Name"] = land.Name; - row["Desc"] = land.Description; - row["OwnerUUID"] = land.OwnerID.ToString(); - row["IsGroupOwned"] = land.IsGroupOwned; - row["Area"] = land.Area; - row["AuctionID"] = land.AuctionID; //Unemplemented - row["Category"] = land.Category; //Enum OpenMetaverse.Parcel.ParcelCategory - row["ClaimDate"] = land.ClaimDate; - row["ClaimPrice"] = land.ClaimPrice; - row["GroupUUID"] = land.GroupID.ToString(); - row["SalePrice"] = land.SalePrice; - row["LandStatus"] = land.Status; //Enum. OpenMetaverse.Parcel.ParcelStatus - row["LandFlags"] = land.Flags; - row["LandingType"] = land.LandingType; - row["MediaAutoScale"] = land.MediaAutoScale; - row["MediaTextureUUID"] = land.MediaID.ToString(); - row["MediaURL"] = land.MediaURL; - row["MusicURL"] = land.MusicURL; - row["PassHours"] = land.PassHours; - row["PassPrice"] = land.PassPrice; - row["SnapshotUUID"] = land.SnapshotID.ToString(); - row["UserLocationX"] = land.UserLocation.X; - row["UserLocationY"] = land.UserLocation.Y; - row["UserLocationZ"] = land.UserLocation.Z; - row["UserLookAtX"] = land.UserLookAt.X; - row["UserLookAtY"] = land.UserLookAt.Y; - row["UserLookAtZ"] = land.UserLookAt.Z; - row["AuthbuyerID"] = land.AuthBuyerID.ToString(); - row["OtherCleanTime"] = land.OtherCleanTime; - } - - /// - /// - /// - /// - /// - /// - private static void fillLandAccessRow(DataRow row, ParcelManager.ParcelAccessEntry entry, UUID parcelID) - { - row["LandUUID"] = parcelID.ToString(); - row["AccessUUID"] = entry.AgentID.ToString(); - row["Flags"] = entry.Flags; - } - - private static void fillRegionSettingsRow(DataRow row, RegionSettings settings) - { - row["regionUUID"] = settings.RegionUUID.ToString(); - row["block_terraform"] = settings.BlockTerraform; - row["block_fly"] = settings.BlockFly; - row["allow_damage"] = settings.AllowDamage; - row["restrict_pushing"] = settings.RestrictPushing; - row["allow_land_resell"] = settings.AllowLandResell; - row["allow_land_join_divide"] = settings.AllowLandJoinDivide; - row["block_show_in_search"] = settings.BlockShowInSearch; - row["agent_limit"] = settings.AgentLimit; - row["object_bonus"] = settings.ObjectBonus; - row["maturity"] = settings.Maturity; - row["disable_scripts"] = settings.DisableScripts; - row["disable_collisions"] = settings.DisableCollisions; - row["disable_physics"] = settings.DisablePhysics; - row["terrain_texture_1"] = settings.TerrainTexture1.ToString(); - row["terrain_texture_2"] = settings.TerrainTexture2.ToString(); - row["terrain_texture_3"] = settings.TerrainTexture3.ToString(); - row["terrain_texture_4"] = settings.TerrainTexture4.ToString(); - row["elevation_1_nw"] = settings.Elevation1NW; - row["elevation_2_nw"] = settings.Elevation2NW; - row["elevation_1_ne"] = settings.Elevation1NE; - row["elevation_2_ne"] = settings.Elevation2NE; - row["elevation_1_se"] = settings.Elevation1SE; - row["elevation_2_se"] = settings.Elevation2SE; - row["elevation_1_sw"] = settings.Elevation1SW; - row["elevation_2_sw"] = settings.Elevation2SW; - row["water_height"] = settings.WaterHeight; - row["terrain_raise_limit"] = settings.TerrainRaiseLimit; - row["terrain_lower_limit"] = settings.TerrainLowerLimit; - row["use_estate_sun"] = settings.UseEstateSun; - row["Sandbox"] = settings.Sandbox; // database uses upper case S for sandbox - row["sunvectorx"] = settings.SunVector.X; - row["sunvectory"] = settings.SunVector.Y; - row["sunvectorz"] = settings.SunVector.Z; - row["fixed_sun"] = settings.FixedSun; - row["sun_position"] = settings.SunPosition; - row["covenant"] = settings.Covenant.ToString(); - } - - /// - /// - /// - /// - /// - private PrimitiveBaseShape buildShape(DataRow row) - { - PrimitiveBaseShape s = new PrimitiveBaseShape(); - s.Scale = new Vector3( - Convert.ToSingle(row["ScaleX"]), - Convert.ToSingle(row["ScaleY"]), - Convert.ToSingle(row["ScaleZ"]) - ); - // paths - s.PCode = Convert.ToByte(row["PCode"]); - s.PathBegin = Convert.ToUInt16(row["PathBegin"]); - s.PathEnd = Convert.ToUInt16(row["PathEnd"]); - s.PathScaleX = Convert.ToByte(row["PathScaleX"]); - s.PathScaleY = Convert.ToByte(row["PathScaleY"]); - s.PathShearX = Convert.ToByte(row["PathShearX"]); - s.PathShearY = Convert.ToByte(row["PathShearY"]); - s.PathSkew = Convert.ToSByte(row["PathSkew"]); - s.PathCurve = Convert.ToByte(row["PathCurve"]); - s.PathRadiusOffset = Convert.ToSByte(row["PathRadiusOffset"]); - s.PathRevolutions = Convert.ToByte(row["PathRevolutions"]); - s.PathTaperX = Convert.ToSByte(row["PathTaperX"]); - s.PathTaperY = Convert.ToSByte(row["PathTaperY"]); - s.PathTwist = Convert.ToSByte(row["PathTwist"]); - s.PathTwistBegin = Convert.ToSByte(row["PathTwistBegin"]); - // profile - s.ProfileBegin = Convert.ToUInt16(row["ProfileBegin"]); - s.ProfileEnd = Convert.ToUInt16(row["ProfileEnd"]); - s.ProfileCurve = Convert.ToByte(row["ProfileCurve"]); - s.ProfileHollow = Convert.ToUInt16(row["ProfileHollow"]); - s.State = Convert.ToByte(row["State"]); - - byte[] textureEntry = (byte[])row["Texture"]; - s.TextureEntry = textureEntry; - - s.ExtraParams = (byte[]) row["ExtraParams"]; - return s; - } - - /// - /// - /// - /// - /// - private static void fillShapeRow(DataRow row, SceneObjectPart prim) - { - PrimitiveBaseShape s = prim.Shape; - row["UUID"] = prim.UUID.ToString(); - // shape is an enum - row["Shape"] = 0; - // vectors - row["ScaleX"] = s.Scale.X; - row["ScaleY"] = s.Scale.Y; - row["ScaleZ"] = s.Scale.Z; - // paths - row["PCode"] = s.PCode; - row["PathBegin"] = s.PathBegin; - row["PathEnd"] = s.PathEnd; - row["PathScaleX"] = s.PathScaleX; - row["PathScaleY"] = s.PathScaleY; - row["PathShearX"] = s.PathShearX; - row["PathShearY"] = s.PathShearY; - row["PathSkew"] = s.PathSkew; - row["PathCurve"] = s.PathCurve; - row["PathRadiusOffset"] = s.PathRadiusOffset; - row["PathRevolutions"] = s.PathRevolutions; - row["PathTaperX"] = s.PathTaperX; - row["PathTaperY"] = s.PathTaperY; - row["PathTwist"] = s.PathTwist; - row["PathTwistBegin"] = s.PathTwistBegin; - // profile - row["ProfileBegin"] = s.ProfileBegin; - row["ProfileEnd"] = s.ProfileEnd; - row["ProfileCurve"] = s.ProfileCurve; - row["ProfileHollow"] = s.ProfileHollow; - row["State"] = s.State; - - row["Texture"] = s.TextureEntry; - row["ExtraParams"] = s.ExtraParams; - } - - /// - /// - /// - /// - /// - /// - private void addPrim(SceneObjectPart prim, UUID sceneGroupID, UUID regionUUID) - { - - DataTable prims = ds.Tables["prims"]; - DataTable shapes = ds.Tables["primshapes"]; - - DataRow primRow = prims.Rows.Find(prim.UUID.ToString()); - if (primRow == null) - { - primRow = prims.NewRow(); - fillPrimRow(primRow, prim, sceneGroupID, regionUUID); - prims.Rows.Add(primRow); - } - else - { - fillPrimRow(primRow, prim, sceneGroupID, regionUUID); - } - - DataRow shapeRow = shapes.Rows.Find(prim.UUID.ToString()); - if (shapeRow == null) - { - shapeRow = shapes.NewRow(); - fillShapeRow(shapeRow, prim); - shapes.Rows.Add(shapeRow); - } - else - { - fillShapeRow(shapeRow, prim); - } - } - - /// - /// see IRegionDatastore - /// - /// - /// - public void StorePrimInventory(UUID primID, ICollection items) - { - m_log.InfoFormat("[REGION DB]: Entered StorePrimInventory with prim ID {0}", primID); - - DataTable dbItems = ds.Tables["primitems"]; - - // For now, we're just going to crudely remove all the previous inventory items - // no matter whether they have changed or not, and replace them with the current set. - lock (ds) - { - RemoveItems(primID); - - // repalce with current inventory details - foreach (TaskInventoryItem newItem in items) - { -// m_log.InfoFormat( -// "[DATASTORE]: ", -// "Adding item {0}, {1} to prim ID {2}", -// newItem.Name, newItem.ItemID, newItem.ParentPartID); - - DataRow newItemRow = dbItems.NewRow(); - fillItemRow(newItemRow, newItem); - dbItems.Rows.Add(newItemRow); - } - } - - Commit(); - } - - /*********************************************************************** - * - * SQL Statement Creation Functions - * - * These functions create SQL statements for update, insert, and create. - * They can probably be factored later to have a db independant - * portion and a db specific portion - * - **********************************************************************/ - - /// - /// Create an insert command - /// - /// table name - /// data table - /// the created command - /// - /// This is subtle enough to deserve some commentary. - /// Instead of doing *lots* and *lots of hardcoded strings - /// for database definitions we'll use the fact that - /// realistically all insert statements look like "insert - /// into A(b, c) values(:b, :c) on the parameterized query - /// front. If we just have a list of b, c, etc... we can - /// generate these strings instead of typing them out. - /// - private static SqliteCommand createInsertCommand(string table, DataTable dt) - { - string[] cols = new string[dt.Columns.Count]; - for (int i = 0; i < dt.Columns.Count; i++) - { - DataColumn col = dt.Columns[i]; - cols[i] = col.ColumnName; - } - - string sql = "insert into " + table + "("; - sql += String.Join(", ", cols); - // important, the first ':' needs to be here, the rest get added in the join - sql += ") values (:"; - sql += String.Join(", :", cols); - sql += ")"; - SqliteCommand cmd = new SqliteCommand(sql); - - // this provides the binding for all our parameters, so - // much less code than it used to be - foreach (DataColumn col in dt.Columns) - { - cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType)); - } - return cmd; - } - - - /// - /// create an update command - /// - /// table name - /// - /// - /// the created command - private static SqliteCommand createUpdateCommand(string table, string pk, DataTable dt) - { - string sql = "update " + table + " set "; - string subsql = String.Empty; - foreach (DataColumn col in dt.Columns) - { - if (subsql.Length > 0) - { - // a map function would rock so much here - subsql += ", "; - } - subsql += col.ColumnName + "= :" + col.ColumnName; - } - sql += subsql; - sql += " where " + pk; - SqliteCommand cmd = new SqliteCommand(sql); - - // this provides the binding for all our parameters, so - // much less code than it used to be - - foreach (DataColumn col in dt.Columns) - { - cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType)); - } - return cmd; - } - - /// - /// create an update command - /// - /// table name - /// - /// - /// the created command - private static SqliteCommand createUpdateCommand(string table, string pk1, string pk2, DataTable dt) - { - string sql = "update " + table + " set "; - string subsql = String.Empty; - foreach (DataColumn col in dt.Columns) - { - if (subsql.Length > 0) - { - // a map function would rock so much here - subsql += ", "; - } - subsql += col.ColumnName + "= :" + col.ColumnName; - } - sql += subsql; - sql += " where " + pk1 + " and " + pk2; - SqliteCommand cmd = new SqliteCommand(sql); - - // this provides the binding for all our parameters, so - // much less code than it used to be - - foreach (DataColumn col in dt.Columns) - { - cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType)); - } - return cmd; - } - - /// - /// - /// - /// Data Table - /// - // private static string defineTable(DataTable dt) - // { - // string sql = "create table " + dt.TableName + "("; - // string subsql = String.Empty; - // foreach (DataColumn col in dt.Columns) - // { - // if (subsql.Length > 0) - // { - // // a map function would rock so much here - // subsql += ",\n"; - // } - // subsql += col.ColumnName + " " + sqliteType(col.DataType); - // if (dt.PrimaryKey.Length > 0 && col == dt.PrimaryKey[0]) - // { - // subsql += " primary key"; - // } - // } - // sql += subsql; - // sql += ")"; - // return sql; - // } - - /*********************************************************************** - * - * Database Binding functions - * - * These will be db specific due to typing, and minor differences - * in databases. - * - **********************************************************************/ - - /// - /// This is a convenience function that collapses 5 repetitive - /// lines for defining SqliteParameters to 2 parameters: - /// column name and database type. - /// - /// It assumes certain conventions like :param as the param - /// name to replace in parametrized queries, and that source - /// version is always current version, both of which are fine - /// for us. - /// - ///a built sqlite parameter - private static SqliteParameter createSqliteParameter(string name, Type type) - { - SqliteParameter param = new SqliteParameter(); - param.ParameterName = ":" + name; - param.DbType = dbtypeFromType(type); - param.SourceColumn = name; - param.SourceVersion = DataRowVersion.Current; - return param; - } - - /// - /// - /// - /// - /// - private void setupPrimCommands(SqliteDataAdapter da, SqliteConnection conn) - { - da.InsertCommand = createInsertCommand("prims", ds.Tables["prims"]); - da.InsertCommand.Connection = conn; - - da.UpdateCommand = createUpdateCommand("prims", "UUID=:UUID", ds.Tables["prims"]); - da.UpdateCommand.Connection = conn; - - SqliteCommand delete = new SqliteCommand("delete from prims where UUID = :UUID"); - delete.Parameters.Add(createSqliteParameter("UUID", typeof (String))); - delete.Connection = conn; - da.DeleteCommand = delete; - } - - /// - /// - /// - /// - /// - private void setupItemsCommands(SqliteDataAdapter da, SqliteConnection conn) - { - da.InsertCommand = createInsertCommand("primitems", ds.Tables["primitems"]); - da.InsertCommand.Connection = conn; - - da.UpdateCommand = createUpdateCommand("primitems", "itemID = :itemID", ds.Tables["primitems"]); - da.UpdateCommand.Connection = conn; - - SqliteCommand delete = new SqliteCommand("delete from primitems where itemID = :itemID"); - delete.Parameters.Add(createSqliteParameter("itemID", typeof (String))); - delete.Connection = conn; - da.DeleteCommand = delete; - } - - /// - /// - /// - /// - /// - private void setupTerrainCommands(SqliteDataAdapter da, SqliteConnection conn) - { - da.InsertCommand = createInsertCommand("terrain", ds.Tables["terrain"]); - da.InsertCommand.Connection = conn; - } - - /// - /// - /// - /// - /// - private void setupLandCommands(SqliteDataAdapter da, SqliteConnection conn) - { - da.InsertCommand = createInsertCommand("land", ds.Tables["land"]); - da.InsertCommand.Connection = conn; - - da.UpdateCommand = createUpdateCommand("land", "UUID=:UUID", ds.Tables["land"]); - da.UpdateCommand.Connection = conn; - - SqliteCommand delete = new SqliteCommand("delete from land where UUID=:UUID"); - delete.Parameters.Add(createSqliteParameter("UUID", typeof(String))); - da.DeleteCommand = delete; - da.DeleteCommand.Connection = conn; - } - - /// - /// - /// - /// - /// - private void setupLandAccessCommands(SqliteDataAdapter da, SqliteConnection conn) - { - da.InsertCommand = createInsertCommand("landaccesslist", ds.Tables["landaccesslist"]); - da.InsertCommand.Connection = conn; - - da.UpdateCommand = createUpdateCommand("landaccesslist", "LandUUID=:landUUID", "AccessUUID=:AccessUUID", ds.Tables["landaccesslist"]); - da.UpdateCommand.Connection = conn; - - SqliteCommand delete = new SqliteCommand("delete from landaccesslist where LandUUID= :LandUUID and AccessUUID= :AccessUUID"); - delete.Parameters.Add(createSqliteParameter("LandUUID", typeof(String))); - delete.Parameters.Add(createSqliteParameter("AccessUUID", typeof(String))); - da.DeleteCommand = delete; - da.DeleteCommand.Connection = conn; - - } - - private void setupRegionSettingsCommands(SqliteDataAdapter da, SqliteConnection conn) - { - da.InsertCommand = createInsertCommand("regionsettings", ds.Tables["regionsettings"]); - da.InsertCommand.Connection = conn; - da.UpdateCommand = createUpdateCommand("regionsettings", "regionUUID=:regionUUID", ds.Tables["regionsettings"]); - da.UpdateCommand.Connection = conn; - } - - /// - /// - /// - /// - /// - private void setupShapeCommands(SqliteDataAdapter da, SqliteConnection conn) - { - da.InsertCommand = createInsertCommand("primshapes", ds.Tables["primshapes"]); - da.InsertCommand.Connection = conn; - - da.UpdateCommand = createUpdateCommand("primshapes", "UUID=:UUID", ds.Tables["primshapes"]); - da.UpdateCommand.Connection = conn; - - SqliteCommand delete = new SqliteCommand("delete from primshapes where UUID = :UUID"); - delete.Parameters.Add(createSqliteParameter("UUID", typeof (String))); - delete.Connection = conn; - da.DeleteCommand = delete; - } - - /*********************************************************************** - * - * Type conversion functions - * - **********************************************************************/ - - /// - /// Type conversion function - /// - /// - /// - private static DbType dbtypeFromType(Type type) - { - if (type == typeof (String)) - { - return DbType.String; - } - else if (type == typeof (Int32)) - { - return DbType.Int32; - } - else if (type == typeof (Double)) - { - return DbType.Double; - } - else if (type == typeof (Byte)) - { - return DbType.Byte; - } - else if (type == typeof (Double)) - { - return DbType.Double; - } - else if (type == typeof (Byte[])) - { - return DbType.Binary; - } - else - { - return DbType.String; - } - } - - } -} diff --git a/OpenSim/Data/SQLiteLegacy/SQLiteSimulationData.cs b/OpenSim/Data/SQLiteLegacy/SQLiteSimulationData.cs new file mode 100644 index 0000000..878117e --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/SQLiteSimulationData.cs @@ -0,0 +1,2261 @@ +/* + * 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.Data; +using System.Drawing; +using System.IO; +using System.Reflection; +using log4net; +using Mono.Data.SqliteClient; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Data.SQLiteLegacy +{ + /// + /// A RegionData Interface to the SQLite database + /// + public class SQLiteSimulationData : ISimulationDataStore + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private const string primSelect = "select * from prims"; + private const string shapeSelect = "select * from primshapes"; + private const string itemsSelect = "select * from primitems"; + private const string terrainSelect = "select * from terrain limit 1"; + private const string landSelect = "select * from land"; + private const string landAccessListSelect = "select distinct * from landaccesslist"; + private const string regionbanListSelect = "select * from regionban"; + private const string regionSettingsSelect = "select * from regionsettings"; + + private DataSet ds; + private SqliteDataAdapter primDa; + private SqliteDataAdapter shapeDa; + private SqliteDataAdapter itemsDa; + private SqliteDataAdapter terrainDa; + private SqliteDataAdapter landDa; + private SqliteDataAdapter landAccessListDa; + private SqliteDataAdapter regionSettingsDa; + + private SqliteConnection m_conn; + + private String m_connectionString; + + // Temporary attribute while this is experimental + + /*********************************************************************** + * + * Public Interface Functions + * + **********************************************************************/ + + /// + /// See IRegionDataStore + /// + /// Initialises RegionData Interface + /// Loads and initialises a new SQLite connection and maintains it. + /// + /// + /// the connection string + public void Initialise(string connectionString) + { + m_connectionString = connectionString; + + ds = new DataSet(); + + m_log.Info("[REGION DB]: Sqlite - connecting: " + connectionString); + m_conn = new SqliteConnection(m_connectionString); + m_conn.Open(); + + + + SqliteCommand primSelectCmd = new SqliteCommand(primSelect, m_conn); + primDa = new SqliteDataAdapter(primSelectCmd); + // SqliteCommandBuilder primCb = new SqliteCommandBuilder(primDa); + + SqliteCommand shapeSelectCmd = new SqliteCommand(shapeSelect, m_conn); + shapeDa = new SqliteDataAdapter(shapeSelectCmd); + // SqliteCommandBuilder shapeCb = new SqliteCommandBuilder(shapeDa); + + SqliteCommand itemsSelectCmd = new SqliteCommand(itemsSelect, m_conn); + itemsDa = new SqliteDataAdapter(itemsSelectCmd); + + SqliteCommand terrainSelectCmd = new SqliteCommand(terrainSelect, m_conn); + terrainDa = new SqliteDataAdapter(terrainSelectCmd); + + SqliteCommand landSelectCmd = new SqliteCommand(landSelect, m_conn); + landDa = new SqliteDataAdapter(landSelectCmd); + + SqliteCommand landAccessListSelectCmd = new SqliteCommand(landAccessListSelect, m_conn); + landAccessListDa = new SqliteDataAdapter(landAccessListSelectCmd); + + SqliteCommand regionSettingsSelectCmd = new SqliteCommand(regionSettingsSelect, m_conn); + regionSettingsDa = new SqliteDataAdapter(regionSettingsSelectCmd); + // This actually does the roll forward assembly stuff + Assembly assem = GetType().Assembly; + Migration m = new Migration(m_conn, assem, "RegionStore"); + m.Update(); + + lock (ds) + { + ds.Tables.Add(createPrimTable()); + setupPrimCommands(primDa, m_conn); + primDa.Fill(ds.Tables["prims"]); + + ds.Tables.Add(createShapeTable()); + setupShapeCommands(shapeDa, m_conn); + + ds.Tables.Add(createItemsTable()); + setupItemsCommands(itemsDa, m_conn); + itemsDa.Fill(ds.Tables["primitems"]); + + ds.Tables.Add(createTerrainTable()); + setupTerrainCommands(terrainDa, m_conn); + + ds.Tables.Add(createLandTable()); + setupLandCommands(landDa, m_conn); + + ds.Tables.Add(createLandAccessListTable()); + setupLandAccessCommands(landAccessListDa, m_conn); + + ds.Tables.Add(createRegionSettingsTable()); + + setupRegionSettingsCommands(regionSettingsDa, m_conn); + + // WORKAROUND: This is a work around for sqlite on + // windows, which gets really unhappy with blob columns + // that have no sample data in them. At some point we + // need to actually find a proper way to handle this. + try + { + shapeDa.Fill(ds.Tables["primshapes"]); + } + catch (Exception) + { + m_log.Info("[REGION DB]: Caught fill error on primshapes table"); + } + + try + { + terrainDa.Fill(ds.Tables["terrain"]); + } + catch (Exception) + { + m_log.Info("[REGION DB]: Caught fill error on terrain table"); + } + + try + { + landDa.Fill(ds.Tables["land"]); + } + catch (Exception) + { + m_log.Info("[REGION DB]: Caught fill error on land table"); + } + + try + { + landAccessListDa.Fill(ds.Tables["landaccesslist"]); + } + catch (Exception) + { + m_log.Info("[REGION DB]: Caught fill error on landaccesslist table"); + } + + try + { + regionSettingsDa.Fill(ds.Tables["regionsettings"]); + } + catch (Exception) + { + m_log.Info("[REGION DB]: Caught fill error on regionsettings table"); + } + return; + } + } + + public void Dispose() + { + if (m_conn != null) + { + m_conn.Close(); + m_conn = null; + } + if (ds != null) + { + ds.Dispose(); + ds = null; + } + if (primDa != null) + { + primDa.Dispose(); + primDa = null; + } + if (shapeDa != null) + { + shapeDa.Dispose(); + shapeDa = null; + } + if (itemsDa != null) + { + itemsDa.Dispose(); + itemsDa = null; + } + if (terrainDa != null) + { + terrainDa.Dispose(); + terrainDa = null; + } + if (landDa != null) + { + landDa.Dispose(); + landDa = null; + } + if (landAccessListDa != null) + { + landAccessListDa.Dispose(); + landAccessListDa = null; + } + if (regionSettingsDa != null) + { + regionSettingsDa.Dispose(); + regionSettingsDa = null; + } + } + + public void StoreRegionSettings(RegionSettings rs) + { + lock (ds) + { + DataTable regionsettings = ds.Tables["regionsettings"]; + + DataRow settingsRow = regionsettings.Rows.Find(rs.RegionUUID.ToString()); + if (settingsRow == null) + { + settingsRow = regionsettings.NewRow(); + fillRegionSettingsRow(settingsRow, rs); + regionsettings.Rows.Add(settingsRow); + } + else + { + fillRegionSettingsRow(settingsRow, rs); + } + + Commit(); + } + } + public RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID) + { + //This connector doesn't support the windlight module yet + //Return default LL windlight settings + return new RegionLightShareData(); + } + public void StoreRegionWindlightSettings(RegionLightShareData wl) + { + //This connector doesn't support the windlight module yet + } + public RegionSettings LoadRegionSettings(UUID regionUUID) + { + lock (ds) + { + DataTable regionsettings = ds.Tables["regionsettings"]; + + string searchExp = "regionUUID = '" + regionUUID.ToString() + "'"; + DataRow[] rawsettings = regionsettings.Select(searchExp); + if (rawsettings.Length == 0) + { + RegionSettings rs = new RegionSettings(); + rs.RegionUUID = regionUUID; + rs.OnSave += StoreRegionSettings; + + StoreRegionSettings(rs); + + return rs; + } + DataRow row = rawsettings[0]; + + RegionSettings newSettings = buildRegionSettings(row); + newSettings.OnSave += StoreRegionSettings; + + return newSettings; + } + } + + /// + /// Adds an object into region storage + /// + /// the object + /// the region UUID + public void StoreObject(SceneObjectGroup obj, UUID regionUUID) + { + uint flags = obj.RootPart.GetEffectiveObjectFlags(); + + // Eligibility check + // + if ((flags & (uint)PrimFlags.Temporary) != 0) + return; + if ((flags & (uint)PrimFlags.TemporaryOnRez) != 0) + return; + + lock (ds) + { + foreach (SceneObjectPart prim in obj.Children.Values) + { +// m_log.Info("[REGION DB]: Adding obj: " + obj.UUID + " to region: " + regionUUID); + addPrim(prim, obj.UUID, regionUUID); + } + } + + Commit(); + // m_log.Info("[Dump of prims]: " + ds.GetXml()); + } + + /// + /// Removes an object from region storage + /// + /// the object + /// the region UUID + public void RemoveObject(UUID obj, UUID regionUUID) + { + // m_log.InfoFormat("[REGION DB]: Removing obj: {0} from region: {1}", obj.Guid, regionUUID); + + DataTable prims = ds.Tables["prims"]; + DataTable shapes = ds.Tables["primshapes"]; + + string selectExp = "SceneGroupID = '" + obj + "' and RegionUUID = '" + regionUUID + "'"; + lock (ds) + { + DataRow[] primRows = prims.Select(selectExp); + foreach (DataRow row in primRows) + { + // Remove shape rows + UUID uuid = new UUID((string) row["UUID"]); + DataRow shapeRow = shapes.Rows.Find(uuid.ToString()); + if (shapeRow != null) + { + shapeRow.Delete(); + } + + RemoveItems(uuid); + + // Remove prim row + row.Delete(); + } + } + + Commit(); + } + + /// + /// Remove all persisted items of the given prim. + /// The caller must acquire the necessrary synchronization locks and commit or rollback changes. + /// + /// The item UUID + private void RemoveItems(UUID uuid) + { + DataTable items = ds.Tables["primitems"]; + + String sql = String.Format("primID = '{0}'", uuid); + DataRow[] itemRows = items.Select(sql); + + foreach (DataRow itemRow in itemRows) + { + itemRow.Delete(); + } + } + + /// + /// Load persisted objects from region storage. + /// + /// The region UUID + /// List of loaded groups + public List LoadObjects(UUID regionUUID) + { + Dictionary createdObjects = new Dictionary(); + + List retvals = new List(); + + DataTable prims = ds.Tables["prims"]; + DataTable shapes = ds.Tables["primshapes"]; + + string byRegion = "RegionUUID = '" + regionUUID + "'"; + + lock (ds) + { + DataRow[] primsForRegion = prims.Select(byRegion); + m_log.Info("[REGION DB]: Loaded " + primsForRegion.Length + " prims for region: " + regionUUID); + + // First, create all groups + foreach (DataRow primRow in primsForRegion) + { + try + { + SceneObjectPart prim = null; + + string uuid = (string) primRow["UUID"]; + string objID = (string) primRow["SceneGroupID"]; + + if (uuid == objID) //is new SceneObjectGroup ? + { + prim = buildPrim(primRow); + DataRow shapeRow = shapes.Rows.Find(prim.UUID.ToString()); + if (shapeRow != null) + { + prim.Shape = buildShape(shapeRow); + } + else + { + m_log.Info( + "[REGION DB]: No shape found for prim in storage, so setting default box shape"); + prim.Shape = PrimitiveBaseShape.Default; + } + + SceneObjectGroup group = new SceneObjectGroup(prim); + createdObjects.Add(group.UUID, group); + retvals.Add(group); + LoadItems(prim); + } + } + catch (Exception e) + { + m_log.Error("[REGION DB]: Failed create prim object in new group, exception and data follows"); + m_log.Info("[REGION DB]: " + e.ToString()); + foreach (DataColumn col in prims.Columns) + { + m_log.Info("[REGION DB]: Col: " + col.ColumnName + " => " + primRow[col]); + } + } + } + + // Now fill the groups with part data + foreach (DataRow primRow in primsForRegion) + { + try + { + SceneObjectPart prim = null; + + string uuid = (string) primRow["UUID"]; + string objID = (string) primRow["SceneGroupID"]; + if (uuid != objID) //is new SceneObjectGroup ? + { + prim = buildPrim(primRow); + DataRow shapeRow = shapes.Rows.Find(prim.UUID.ToString()); + if (shapeRow != null) + { + prim.Shape = buildShape(shapeRow); + } + else + { + m_log.Warn( + "[REGION DB]: No shape found for prim in storage, so setting default box shape"); + prim.Shape = PrimitiveBaseShape.Default; + } + + createdObjects[new UUID(objID)].AddPart(prim); + LoadItems(prim); + } + } + catch (Exception e) + { + m_log.Error("[REGION DB]: Failed create prim object in group, exception and data follows"); + m_log.Info("[REGION DB]: " + e.ToString()); + foreach (DataColumn col in prims.Columns) + { + m_log.Info("[REGION DB]: Col: " + col.ColumnName + " => " + primRow[col]); + } + } + } + } + return retvals; + } + + /// + /// Load in a prim's persisted inventory. + /// + /// the prim + private void LoadItems(SceneObjectPart prim) + { + //m_log.DebugFormat("[DATASTORE]: Loading inventory for {0}, {1}", prim.Name, prim.UUID); + + DataTable dbItems = ds.Tables["primitems"]; + String sql = String.Format("primID = '{0}'", prim.UUID.ToString()); + DataRow[] dbItemRows = dbItems.Select(sql); + IList inventory = new List(); + + foreach (DataRow row in dbItemRows) + { + TaskInventoryItem item = buildItem(row); + inventory.Add(item); + + //m_log.DebugFormat("[DATASTORE]: Restored item {0}, {1}", item.Name, item.ItemID); + } + + prim.Inventory.RestoreInventoryItems(inventory); + } + + /// + /// Store a terrain revision in region storage + /// + /// terrain heightfield + /// region UUID + public void StoreTerrain(double[,] ter, UUID regionID) + { + lock (ds) + { + int revision = Util.UnixTimeSinceEpoch(); + + // This is added to get rid of the infinitely growing + // terrain databases which negatively impact on SQLite + // over time. Before reenabling this feature there + // needs to be a limitter put on the number of + // revisions in the database, as this old + // implementation is a DOS attack waiting to happen. + + using ( + SqliteCommand cmd = + new SqliteCommand("delete from terrain where RegionUUID=:RegionUUID and Revision <= :Revision", + m_conn)) + { + cmd.Parameters.Add(new SqliteParameter(":RegionUUID", regionID.ToString())); + cmd.Parameters.Add(new SqliteParameter(":Revision", revision)); + cmd.ExecuteNonQuery(); + } + + // the following is an work around for .NET. The perf + // issues associated with it aren't as bad as you think. + m_log.Info("[REGION DB]: Storing terrain revision r" + revision.ToString()); + String sql = "insert into terrain(RegionUUID, Revision, Heightfield)" + + " values(:RegionUUID, :Revision, :Heightfield)"; + + using (SqliteCommand cmd = new SqliteCommand(sql, m_conn)) + { + cmd.Parameters.Add(new SqliteParameter(":RegionUUID", regionID.ToString())); + cmd.Parameters.Add(new SqliteParameter(":Revision", revision)); + cmd.Parameters.Add(new SqliteParameter(":Heightfield", serializeTerrain(ter))); + cmd.ExecuteNonQuery(); + } + } + } + + /// + /// Load the latest terrain revision from region storage + /// + /// the region UUID + /// Heightfield data + public double[,] LoadTerrain(UUID regionID) + { + lock (ds) + { + double[,] terret = new double[(int)Constants.RegionSize, (int)Constants.RegionSize]; + terret.Initialize(); + + String sql = "select RegionUUID, Revision, Heightfield from terrain" + + " where RegionUUID=:RegionUUID order by Revision desc"; + + using (SqliteCommand cmd = new SqliteCommand(sql, m_conn)) + { + cmd.Parameters.Add(new SqliteParameter(":RegionUUID", regionID.ToString())); + + using (IDataReader row = cmd.ExecuteReader()) + { + int rev = 0; + if (row.Read()) + { + // TODO: put this into a function + using (MemoryStream str = new MemoryStream((byte[])row["Heightfield"])) + { + using (BinaryReader br = new BinaryReader(str)) + { + for (int x = 0; x < (int)Constants.RegionSize; x++) + { + for (int y = 0; y < (int)Constants.RegionSize; y++) + { + terret[x, y] = br.ReadDouble(); + } + } + } + } + rev = (int) row["Revision"]; + } + else + { + m_log.Info("[REGION DB]: No terrain found for region"); + return null; + } + + m_log.Info("[REGION DB]: Loaded terrain revision r" + rev.ToString()); + } + } + return terret; + } + } + + /// + /// + /// + /// + public void RemoveLandObject(UUID globalID) + { + lock (ds) + { + // Can't use blanket SQL statements when using SqlAdapters unless you re-read the data into the adapter + // after you're done. + // replaced below code with the SqliteAdapter version. + //using (SqliteCommand cmd = new SqliteCommand("delete from land where UUID=:UUID", m_conn)) + //{ + // cmd.Parameters.Add(new SqliteParameter(":UUID", globalID.ToString())); + // cmd.ExecuteNonQuery(); + //} + + //using (SqliteCommand cmd = new SqliteCommand("delete from landaccesslist where LandUUID=:UUID", m_conn)) + //{ + // cmd.Parameters.Add(new SqliteParameter(":UUID", globalID.ToString())); + // cmd.ExecuteNonQuery(); + //} + + DataTable land = ds.Tables["land"]; + DataTable landaccesslist = ds.Tables["landaccesslist"]; + DataRow landRow = land.Rows.Find(globalID.ToString()); + if (landRow != null) + { + land.Rows.Remove(landRow); + } + List rowsToDelete = new List(); + foreach (DataRow rowToCheck in landaccesslist.Rows) + { + if (rowToCheck["LandUUID"].ToString() == globalID.ToString()) + rowsToDelete.Add(rowToCheck); + } + for (int iter = 0; iter < rowsToDelete.Count; iter++) + { + landaccesslist.Rows.Remove(rowsToDelete[iter]); + } + + + } + Commit(); + } + + /// + /// + /// + /// + public void StoreLandObject(ILandObject parcel) + { + lock (ds) + { + DataTable land = ds.Tables["land"]; + DataTable landaccesslist = ds.Tables["landaccesslist"]; + + DataRow landRow = land.Rows.Find(parcel.LandData.GlobalID.ToString()); + if (landRow == null) + { + landRow = land.NewRow(); + fillLandRow(landRow, parcel.LandData, parcel.RegionUUID); + land.Rows.Add(landRow); + } + else + { + fillLandRow(landRow, parcel.LandData, parcel.RegionUUID); + } + + // I know this caused someone issues before, but OpenSim is unusable if we leave this stuff around + //using (SqliteCommand cmd = new SqliteCommand("delete from landaccesslist where LandUUID=:LandUUID", m_conn)) + //{ + // cmd.Parameters.Add(new SqliteParameter(":LandUUID", parcel.LandData.GlobalID.ToString())); + // cmd.ExecuteNonQuery(); + +// } + + // This is the slower.. but more appropriate thing to do + + // We can't modify the table with direct queries before calling Commit() and re-filling them. + List rowsToDelete = new List(); + foreach (DataRow rowToCheck in landaccesslist.Rows) + { + if (rowToCheck["LandUUID"].ToString() == parcel.LandData.GlobalID.ToString()) + rowsToDelete.Add(rowToCheck); + } + for (int iter = 0; iter < rowsToDelete.Count; iter++) + { + landaccesslist.Rows.Remove(rowsToDelete[iter]); + } + rowsToDelete.Clear(); + foreach (ParcelManager.ParcelAccessEntry entry in parcel.LandData.ParcelAccessList) + { + DataRow newAccessRow = landaccesslist.NewRow(); + fillLandAccessRow(newAccessRow, entry, parcel.LandData.GlobalID); + landaccesslist.Rows.Add(newAccessRow); + } + } + + Commit(); + } + + /// + /// + /// + /// + /// + public List LoadLandObjects(UUID regionUUID) + { + List landDataForRegion = new List(); + lock (ds) + { + DataTable land = ds.Tables["land"]; + DataTable landaccesslist = ds.Tables["landaccesslist"]; + string searchExp = "RegionUUID = '" + regionUUID + "'"; + DataRow[] rawDataForRegion = land.Select(searchExp); + foreach (DataRow rawDataLand in rawDataForRegion) + { + LandData newLand = buildLandData(rawDataLand); + string accessListSearchExp = "LandUUID = '" + newLand.GlobalID + "'"; + DataRow[] rawDataForLandAccessList = landaccesslist.Select(accessListSearchExp); + foreach (DataRow rawDataLandAccess in rawDataForLandAccessList) + { + newLand.ParcelAccessList.Add(buildLandAccessData(rawDataLandAccess)); + } + + landDataForRegion.Add(newLand); + } + } + return landDataForRegion; + } + + /// + /// + /// + public void Commit() + { + lock (ds) + { + primDa.Update(ds, "prims"); + shapeDa.Update(ds, "primshapes"); + + itemsDa.Update(ds, "primitems"); + + terrainDa.Update(ds, "terrain"); + landDa.Update(ds, "land"); + landAccessListDa.Update(ds, "landaccesslist"); + try + { + regionSettingsDa.Update(ds, "regionsettings"); + } + catch (SqliteExecutionException SqlEx) + { + if (SqlEx.Message.Contains("logic error")) + { + throw new Exception( + "There was a SQL error or connection string configuration error when saving the region settings. This could be a bug, it could also happen if ConnectionString is defined in the [DatabaseService] section of StandaloneCommon.ini in the config_include folder. This could also happen if the config_include folder doesn't exist or if the OpenSim.ini [Architecture] section isn't set. If this is your first time running OpenSimulator, please restart the simulator and bug a developer to fix this!", + SqlEx); + } + else + { + throw SqlEx; + } + } + ds.AcceptChanges(); + } + } + + /// + /// See + /// + public void Shutdown() + { + Commit(); + } + + /*********************************************************************** + * + * Database Definition Functions + * + * This should be db agnostic as we define them in ADO.NET terms + * + **********************************************************************/ + + /// + /// + /// + /// + /// + /// + private static void createCol(DataTable dt, string name, Type type) + { + DataColumn col = new DataColumn(name, type); + dt.Columns.Add(col); + } + + /// + /// Creates the "terrain" table + /// + /// terrain table DataTable + private static DataTable createTerrainTable() + { + DataTable terrain = new DataTable("terrain"); + + createCol(terrain, "RegionUUID", typeof (String)); + createCol(terrain, "Revision", typeof (Int32)); + createCol(terrain, "Heightfield", typeof (Byte[])); + + return terrain; + } + + /// + /// Creates the "prims" table + /// + /// prim table DataTable + private static DataTable createPrimTable() + { + DataTable prims = new DataTable("prims"); + + createCol(prims, "UUID", typeof (String)); + createCol(prims, "RegionUUID", typeof (String)); + createCol(prims, "CreationDate", typeof (Int32)); + createCol(prims, "Name", typeof (String)); + createCol(prims, "SceneGroupID", typeof (String)); + // various text fields + createCol(prims, "Text", typeof (String)); + createCol(prims, "ColorR", typeof (Int32)); + createCol(prims, "ColorG", typeof (Int32)); + createCol(prims, "ColorB", typeof (Int32)); + createCol(prims, "ColorA", typeof (Int32)); + createCol(prims, "Description", typeof (String)); + createCol(prims, "SitName", typeof (String)); + createCol(prims, "TouchName", typeof (String)); + // permissions + createCol(prims, "ObjectFlags", typeof (Int32)); + createCol(prims, "CreatorID", typeof (String)); + createCol(prims, "OwnerID", typeof (String)); + createCol(prims, "GroupID", typeof (String)); + createCol(prims, "LastOwnerID", typeof (String)); + createCol(prims, "OwnerMask", typeof (Int32)); + createCol(prims, "NextOwnerMask", typeof (Int32)); + createCol(prims, "GroupMask", typeof (Int32)); + createCol(prims, "EveryoneMask", typeof (Int32)); + createCol(prims, "BaseMask", typeof (Int32)); + // vectors + createCol(prims, "PositionX", typeof (Double)); + createCol(prims, "PositionY", typeof (Double)); + createCol(prims, "PositionZ", typeof (Double)); + createCol(prims, "GroupPositionX", typeof (Double)); + createCol(prims, "GroupPositionY", typeof (Double)); + createCol(prims, "GroupPositionZ", typeof (Double)); + createCol(prims, "VelocityX", typeof (Double)); + createCol(prims, "VelocityY", typeof (Double)); + createCol(prims, "VelocityZ", typeof (Double)); + createCol(prims, "AngularVelocityX", typeof (Double)); + createCol(prims, "AngularVelocityY", typeof (Double)); + createCol(prims, "AngularVelocityZ", typeof (Double)); + createCol(prims, "AccelerationX", typeof (Double)); + createCol(prims, "AccelerationY", typeof (Double)); + createCol(prims, "AccelerationZ", typeof (Double)); + // quaternions + createCol(prims, "RotationX", typeof (Double)); + createCol(prims, "RotationY", typeof (Double)); + createCol(prims, "RotationZ", typeof (Double)); + createCol(prims, "RotationW", typeof (Double)); + + // sit target + createCol(prims, "SitTargetOffsetX", typeof (Double)); + createCol(prims, "SitTargetOffsetY", typeof (Double)); + createCol(prims, "SitTargetOffsetZ", typeof (Double)); + + createCol(prims, "SitTargetOrientW", typeof (Double)); + createCol(prims, "SitTargetOrientX", typeof (Double)); + createCol(prims, "SitTargetOrientY", typeof (Double)); + createCol(prims, "SitTargetOrientZ", typeof (Double)); + + createCol(prims, "PayPrice", typeof(Int32)); + createCol(prims, "PayButton1", typeof(Int32)); + createCol(prims, "PayButton2", typeof(Int32)); + createCol(prims, "PayButton3", typeof(Int32)); + createCol(prims, "PayButton4", typeof(Int32)); + + createCol(prims, "LoopedSound", typeof(String)); + createCol(prims, "LoopedSoundGain", typeof(Double)); + createCol(prims, "TextureAnimation", typeof(String)); + createCol(prims, "ParticleSystem", typeof(String)); + + createCol(prims, "OmegaX", typeof(Double)); + createCol(prims, "OmegaY", typeof(Double)); + createCol(prims, "OmegaZ", typeof(Double)); + + createCol(prims, "CameraEyeOffsetX", typeof(Double)); + createCol(prims, "CameraEyeOffsetY", typeof(Double)); + createCol(prims, "CameraEyeOffsetZ", typeof(Double)); + + createCol(prims, "CameraAtOffsetX", typeof(Double)); + createCol(prims, "CameraAtOffsetY", typeof(Double)); + createCol(prims, "CameraAtOffsetZ", typeof(Double)); + + createCol(prims, "ForceMouselook", typeof(Int16)); + + createCol(prims, "ScriptAccessPin", typeof(Int32)); + + createCol(prims, "AllowedDrop", typeof(Int16)); + createCol(prims, "DieAtEdge", typeof(Int16)); + + createCol(prims, "SalePrice", typeof(Int32)); + createCol(prims, "SaleType", typeof(Int16)); + + // click action + createCol(prims, "ClickAction", typeof (Byte)); + + createCol(prims, "Material", typeof(Byte)); + + createCol(prims, "CollisionSound", typeof(String)); + createCol(prims, "CollisionSoundVolume", typeof(Double)); + + createCol(prims, "VolumeDetect", typeof(Int16)); + + // Add in contraints + prims.PrimaryKey = new DataColumn[] {prims.Columns["UUID"]}; + + return prims; + } + + /// + /// Creates "primshapes" table + /// + /// shape table DataTable + private static DataTable createShapeTable() + { + DataTable shapes = new DataTable("primshapes"); + createCol(shapes, "UUID", typeof (String)); + // shape is an enum + createCol(shapes, "Shape", typeof (Int32)); + // vectors + createCol(shapes, "ScaleX", typeof (Double)); + createCol(shapes, "ScaleY", typeof (Double)); + createCol(shapes, "ScaleZ", typeof (Double)); + // paths + createCol(shapes, "PCode", typeof (Int32)); + createCol(shapes, "PathBegin", typeof (Int32)); + createCol(shapes, "PathEnd", typeof (Int32)); + createCol(shapes, "PathScaleX", typeof (Int32)); + createCol(shapes, "PathScaleY", typeof (Int32)); + createCol(shapes, "PathShearX", typeof (Int32)); + createCol(shapes, "PathShearY", typeof (Int32)); + createCol(shapes, "PathSkew", typeof (Int32)); + createCol(shapes, "PathCurve", typeof (Int32)); + createCol(shapes, "PathRadiusOffset", typeof (Int32)); + createCol(shapes, "PathRevolutions", typeof (Int32)); + createCol(shapes, "PathTaperX", typeof (Int32)); + createCol(shapes, "PathTaperY", typeof (Int32)); + createCol(shapes, "PathTwist", typeof (Int32)); + createCol(shapes, "PathTwistBegin", typeof (Int32)); + // profile + createCol(shapes, "ProfileBegin", typeof (Int32)); + createCol(shapes, "ProfileEnd", typeof (Int32)); + createCol(shapes, "ProfileCurve", typeof (Int32)); + createCol(shapes, "ProfileHollow", typeof (Int32)); + createCol(shapes, "State", typeof(Int32)); + // text TODO: this isn't right, but I'm not sure the right + // way to specify this as a blob atm + createCol(shapes, "Texture", typeof (Byte[])); + createCol(shapes, "ExtraParams", typeof (Byte[])); + + shapes.PrimaryKey = new DataColumn[] {shapes.Columns["UUID"]}; + + return shapes; + } + + /// + /// creates "primitems" table + /// + /// item table DataTable + private static DataTable createItemsTable() + { + DataTable items = new DataTable("primitems"); + + createCol(items, "itemID", typeof (String)); + createCol(items, "primID", typeof (String)); + createCol(items, "assetID", typeof (String)); + createCol(items, "parentFolderID", typeof (String)); + + createCol(items, "invType", typeof (Int32)); + createCol(items, "assetType", typeof (Int32)); + + createCol(items, "name", typeof (String)); + createCol(items, "description", typeof (String)); + + createCol(items, "creationDate", typeof (Int64)); + createCol(items, "creatorID", typeof (String)); + createCol(items, "ownerID", typeof (String)); + createCol(items, "lastOwnerID", typeof (String)); + createCol(items, "groupID", typeof (String)); + + createCol(items, "nextPermissions", typeof (UInt32)); + createCol(items, "currentPermissions", typeof (UInt32)); + createCol(items, "basePermissions", typeof (UInt32)); + createCol(items, "everyonePermissions", typeof (UInt32)); + createCol(items, "groupPermissions", typeof (UInt32)); + createCol(items, "flags", typeof (UInt32)); + + items.PrimaryKey = new DataColumn[] { items.Columns["itemID"] }; + + return items; + } + + /// + /// Creates "land" table + /// + /// land table DataTable + private static DataTable createLandTable() + { + DataTable land = new DataTable("land"); + createCol(land, "UUID", typeof (String)); + createCol(land, "RegionUUID", typeof (String)); + createCol(land, "LocalLandID", typeof (UInt32)); + + // Bitmap is a byte[512] + createCol(land, "Bitmap", typeof (Byte[])); + + createCol(land, "Name", typeof (String)); + createCol(land, "Desc", typeof (String)); + createCol(land, "OwnerUUID", typeof (String)); + createCol(land, "IsGroupOwned", typeof (Boolean)); + createCol(land, "Area", typeof (Int32)); + createCol(land, "AuctionID", typeof (Int32)); //Unemplemented + createCol(land, "Category", typeof (Int32)); //Enum OpenMetaverse.Parcel.ParcelCategory + createCol(land, "ClaimDate", typeof (Int32)); + createCol(land, "ClaimPrice", typeof (Int32)); + createCol(land, "GroupUUID", typeof (string)); + createCol(land, "SalePrice", typeof (Int32)); + createCol(land, "LandStatus", typeof (Int32)); //Enum. OpenMetaverse.Parcel.ParcelStatus + createCol(land, "LandFlags", typeof (UInt32)); + createCol(land, "LandingType", typeof (Byte)); + createCol(land, "MediaAutoScale", typeof (Byte)); + createCol(land, "MediaTextureUUID", typeof (String)); + createCol(land, "MediaURL", typeof (String)); + createCol(land, "MusicURL", typeof (String)); + createCol(land, "PassHours", typeof (Double)); + createCol(land, "PassPrice", typeof (UInt32)); + createCol(land, "SnapshotUUID", typeof (String)); + createCol(land, "UserLocationX", typeof (Double)); + createCol(land, "UserLocationY", typeof (Double)); + createCol(land, "UserLocationZ", typeof (Double)); + createCol(land, "UserLookAtX", typeof (Double)); + createCol(land, "UserLookAtY", typeof (Double)); + createCol(land, "UserLookAtZ", typeof (Double)); + createCol(land, "AuthbuyerID", typeof(String)); + createCol(land, "OtherCleanTime", typeof(Int32)); + + land.PrimaryKey = new DataColumn[] {land.Columns["UUID"]}; + + return land; + } + + /// + /// create "landaccesslist" table + /// + /// Landacceslist DataTable + private static DataTable createLandAccessListTable() + { + DataTable landaccess = new DataTable("landaccesslist"); + createCol(landaccess, "LandUUID", typeof (String)); + createCol(landaccess, "AccessUUID", typeof (String)); + createCol(landaccess, "Flags", typeof (UInt32)); + + return landaccess; + } + + private static DataTable createRegionSettingsTable() + { + DataTable regionsettings = new DataTable("regionsettings"); + createCol(regionsettings, "regionUUID", typeof(String)); + createCol(regionsettings, "block_terraform", typeof (Int32)); + createCol(regionsettings, "block_fly", typeof (Int32)); + createCol(regionsettings, "allow_damage", typeof (Int32)); + createCol(regionsettings, "restrict_pushing", typeof (Int32)); + createCol(regionsettings, "allow_land_resell", typeof (Int32)); + createCol(regionsettings, "allow_land_join_divide", typeof (Int32)); + createCol(regionsettings, "block_show_in_search", typeof (Int32)); + createCol(regionsettings, "agent_limit", typeof (Int32)); + createCol(regionsettings, "object_bonus", typeof (Double)); + createCol(regionsettings, "maturity", typeof (Int32)); + createCol(regionsettings, "disable_scripts", typeof (Int32)); + createCol(regionsettings, "disable_collisions", typeof (Int32)); + createCol(regionsettings, "disable_physics", typeof (Int32)); + createCol(regionsettings, "terrain_texture_1", typeof(String)); + createCol(regionsettings, "terrain_texture_2", typeof(String)); + createCol(regionsettings, "terrain_texture_3", typeof(String)); + createCol(regionsettings, "terrain_texture_4", typeof(String)); + createCol(regionsettings, "elevation_1_nw", typeof (Double)); + createCol(regionsettings, "elevation_2_nw", typeof (Double)); + createCol(regionsettings, "elevation_1_ne", typeof (Double)); + createCol(regionsettings, "elevation_2_ne", typeof (Double)); + createCol(regionsettings, "elevation_1_se", typeof (Double)); + createCol(regionsettings, "elevation_2_se", typeof (Double)); + createCol(regionsettings, "elevation_1_sw", typeof (Double)); + createCol(regionsettings, "elevation_2_sw", typeof (Double)); + createCol(regionsettings, "water_height", typeof (Double)); + createCol(regionsettings, "terrain_raise_limit", typeof (Double)); + createCol(regionsettings, "terrain_lower_limit", typeof (Double)); + createCol(regionsettings, "use_estate_sun", typeof (Int32)); + createCol(regionsettings, "sandbox", typeof (Int32)); + createCol(regionsettings, "sunvectorx",typeof (Double)); + createCol(regionsettings, "sunvectory",typeof (Double)); + createCol(regionsettings, "sunvectorz",typeof (Double)); + createCol(regionsettings, "fixed_sun", typeof (Int32)); + createCol(regionsettings, "sun_position", typeof (Double)); + createCol(regionsettings, "covenant", typeof(String)); + regionsettings.PrimaryKey = new DataColumn[] { regionsettings.Columns["regionUUID"] }; + return regionsettings; + } + + /*********************************************************************** + * + * Convert between ADO.NET <=> OpenSim Objects + * + * These should be database independant + * + **********************************************************************/ + + /// + /// + /// + /// + /// + private SceneObjectPart buildPrim(DataRow row) + { + // Code commented. Uncomment to test the unit test inline. + + // The unit test mentions this commented code for the purposes + // of debugging a unit test failure + + // SceneObjectGroup sog = new SceneObjectGroup(); + // SceneObjectPart sop = new SceneObjectPart(); + // sop.LocalId = 1; + // sop.Name = "object1"; + // sop.Description = "object1"; + // sop.Text = ""; + // sop.SitName = ""; + // sop.TouchName = ""; + // sop.UUID = UUID.Random(); + // sop.Shape = PrimitiveBaseShape.Default; + // sog.SetRootPart(sop); + // Add breakpoint in above line. Check sop fields. + + // TODO: this doesn't work yet because something more + // interesting has to be done to actually get these values + // back out. Not enough time to figure it out yet. + + SceneObjectPart prim = new SceneObjectPart(); + prim.UUID = new UUID((String) row["UUID"]); + // explicit conversion of integers is required, which sort + // of sucks. No idea if there is a shortcut here or not. + prim.CreationDate = Convert.ToInt32(row["CreationDate"]); + prim.Name = row["Name"] == DBNull.Value ? string.Empty : (string)row["Name"]; + // various text fields + prim.Text = (String) row["Text"]; + prim.Color = Color.FromArgb(Convert.ToInt32(row["ColorA"]), + Convert.ToInt32(row["ColorR"]), + Convert.ToInt32(row["ColorG"]), + Convert.ToInt32(row["ColorB"])); + prim.Description = (String) row["Description"]; + prim.SitName = (String) row["SitName"]; + prim.TouchName = (String) row["TouchName"]; + // permissions + prim.Flags = (PrimFlags)Convert.ToUInt32(row["ObjectFlags"]); + prim.CreatorID = new UUID((String) row["CreatorID"]); + prim.OwnerID = new UUID((String) row["OwnerID"]); + prim.GroupID = new UUID((String) row["GroupID"]); + prim.LastOwnerID = new UUID((String) row["LastOwnerID"]); + prim.OwnerMask = Convert.ToUInt32(row["OwnerMask"]); + prim.NextOwnerMask = Convert.ToUInt32(row["NextOwnerMask"]); + prim.GroupMask = Convert.ToUInt32(row["GroupMask"]); + prim.EveryoneMask = Convert.ToUInt32(row["EveryoneMask"]); + prim.BaseMask = Convert.ToUInt32(row["BaseMask"]); + // vectors + prim.OffsetPosition = new Vector3( + Convert.ToSingle(row["PositionX"]), + Convert.ToSingle(row["PositionY"]), + Convert.ToSingle(row["PositionZ"]) + ); + prim.GroupPosition = new Vector3( + Convert.ToSingle(row["GroupPositionX"]), + Convert.ToSingle(row["GroupPositionY"]), + Convert.ToSingle(row["GroupPositionZ"]) + ); + prim.Velocity = new Vector3( + Convert.ToSingle(row["VelocityX"]), + Convert.ToSingle(row["VelocityY"]), + Convert.ToSingle(row["VelocityZ"]) + ); + prim.AngularVelocity = new Vector3( + Convert.ToSingle(row["AngularVelocityX"]), + Convert.ToSingle(row["AngularVelocityY"]), + Convert.ToSingle(row["AngularVelocityZ"]) + ); + prim.Acceleration = new Vector3( + Convert.ToSingle(row["AccelerationX"]), + Convert.ToSingle(row["AccelerationY"]), + Convert.ToSingle(row["AccelerationZ"]) + ); + // quaternions + prim.RotationOffset = new Quaternion( + Convert.ToSingle(row["RotationX"]), + Convert.ToSingle(row["RotationY"]), + Convert.ToSingle(row["RotationZ"]), + Convert.ToSingle(row["RotationW"]) + ); + + prim.SitTargetPositionLL = new Vector3( + Convert.ToSingle(row["SitTargetOffsetX"]), + Convert.ToSingle(row["SitTargetOffsetY"]), + Convert.ToSingle(row["SitTargetOffsetZ"])); + prim.SitTargetOrientationLL = new Quaternion( + Convert.ToSingle( + row["SitTargetOrientX"]), + Convert.ToSingle( + row["SitTargetOrientY"]), + Convert.ToSingle( + row["SitTargetOrientZ"]), + Convert.ToSingle( + row["SitTargetOrientW"])); + + prim.ClickAction = Convert.ToByte(row["ClickAction"]); + prim.PayPrice[0] = Convert.ToInt32(row["PayPrice"]); + prim.PayPrice[1] = Convert.ToInt32(row["PayButton1"]); + prim.PayPrice[2] = Convert.ToInt32(row["PayButton2"]); + prim.PayPrice[3] = Convert.ToInt32(row["PayButton3"]); + prim.PayPrice[4] = Convert.ToInt32(row["PayButton4"]); + + prim.Sound = new UUID(row["LoopedSound"].ToString()); + prim.SoundGain = Convert.ToSingle(row["LoopedSoundGain"]); + prim.SoundFlags = 1; // If it's persisted at all, it's looped + + if (!row.IsNull("TextureAnimation")) + prim.TextureAnimation = Convert.FromBase64String(row["TextureAnimation"].ToString()); + if (!row.IsNull("ParticleSystem")) + prim.ParticleSystem = Convert.FromBase64String(row["ParticleSystem"].ToString()); + + prim.AngularVelocity = new Vector3( + Convert.ToSingle(row["OmegaX"]), + Convert.ToSingle(row["OmegaY"]), + Convert.ToSingle(row["OmegaZ"]) + ); + + prim.SetCameraEyeOffset(new Vector3( + Convert.ToSingle(row["CameraEyeOffsetX"]), + Convert.ToSingle(row["CameraEyeOffsetY"]), + Convert.ToSingle(row["CameraEyeOffsetZ"]) + )); + + prim.SetCameraAtOffset(new Vector3( + Convert.ToSingle(row["CameraAtOffsetX"]), + Convert.ToSingle(row["CameraAtOffsetY"]), + Convert.ToSingle(row["CameraAtOffsetZ"]) + )); + + if (Convert.ToInt16(row["ForceMouselook"]) != 0) + prim.SetForceMouselook(true); + + prim.ScriptAccessPin = Convert.ToInt32(row["ScriptAccessPin"]); + + if (Convert.ToInt16(row["AllowedDrop"]) != 0) + prim.AllowedDrop = true; + + if (Convert.ToInt16(row["DieAtEdge"]) != 0) + prim.DIE_AT_EDGE = true; + + prim.SalePrice = Convert.ToInt32(row["SalePrice"]); + prim.ObjectSaleType = Convert.ToByte(row["SaleType"]); + + prim.Material = Convert.ToByte(row["Material"]); + + prim.CollisionSound = new UUID(row["CollisionSound"].ToString()); + prim.CollisionSoundVolume = Convert.ToSingle(row["CollisionSoundVolume"]); + + if (Convert.ToInt16(row["VolumeDetect"]) != 0) + prim.VolumeDetectActive = true; + + return prim; + } + + /// + /// Build a prim inventory item from the persisted data. + /// + /// + /// + private static TaskInventoryItem buildItem(DataRow row) + { + TaskInventoryItem taskItem = new TaskInventoryItem(); + + taskItem.ItemID = new UUID((String)row["itemID"]); + taskItem.ParentPartID = new UUID((String)row["primID"]); + taskItem.AssetID = new UUID((String)row["assetID"]); + taskItem.ParentID = new UUID((String)row["parentFolderID"]); + + taskItem.InvType = Convert.ToInt32(row["invType"]); + taskItem.Type = Convert.ToInt32(row["assetType"]); + + taskItem.Name = (String)row["name"]; + taskItem.Description = (String)row["description"]; + taskItem.CreationDate = Convert.ToUInt32(row["creationDate"]); + taskItem.CreatorID = new UUID((String)row["creatorID"]); + taskItem.OwnerID = new UUID((String)row["ownerID"]); + taskItem.LastOwnerID = new UUID((String)row["lastOwnerID"]); + taskItem.GroupID = new UUID((String)row["groupID"]); + + taskItem.NextPermissions = Convert.ToUInt32(row["nextPermissions"]); + taskItem.CurrentPermissions = Convert.ToUInt32(row["currentPermissions"]); + taskItem.BasePermissions = Convert.ToUInt32(row["basePermissions"]); + taskItem.EveryonePermissions = Convert.ToUInt32(row["everyonePermissions"]); + taskItem.GroupPermissions = Convert.ToUInt32(row["groupPermissions"]); + taskItem.Flags = Convert.ToUInt32(row["flags"]); + + return taskItem; + } + + /// + /// Build a Land Data from the persisted data. + /// + /// + /// + private LandData buildLandData(DataRow row) + { + LandData newData = new LandData(); + + newData.GlobalID = new UUID((String) row["UUID"]); + newData.LocalID = Convert.ToInt32(row["LocalLandID"]); + + // Bitmap is a byte[512] + newData.Bitmap = (Byte[]) row["Bitmap"]; + + newData.Name = (String) row["Name"]; + newData.Description = (String) row["Desc"]; + newData.OwnerID = (UUID)(String) row["OwnerUUID"]; + newData.IsGroupOwned = (Boolean) row["IsGroupOwned"]; + newData.Area = Convert.ToInt32(row["Area"]); + newData.AuctionID = Convert.ToUInt32(row["AuctionID"]); //Unemplemented + newData.Category = (ParcelCategory) Convert.ToInt32(row["Category"]); + //Enum OpenMetaverse.Parcel.ParcelCategory + newData.ClaimDate = Convert.ToInt32(row["ClaimDate"]); + newData.ClaimPrice = Convert.ToInt32(row["ClaimPrice"]); + newData.GroupID = new UUID((String) row["GroupUUID"]); + newData.SalePrice = Convert.ToInt32(row["SalePrice"]); + newData.Status = (ParcelStatus) Convert.ToInt32(row["LandStatus"]); + //Enum. OpenMetaverse.Parcel.ParcelStatus + newData.Flags = Convert.ToUInt32(row["LandFlags"]); + newData.LandingType = (Byte) row["LandingType"]; + newData.MediaAutoScale = (Byte) row["MediaAutoScale"]; + newData.MediaID = new UUID((String) row["MediaTextureUUID"]); + newData.MediaURL = (String) row["MediaURL"]; + newData.MusicURL = (String) row["MusicURL"]; + newData.PassHours = Convert.ToSingle(row["PassHours"]); + newData.PassPrice = Convert.ToInt32(row["PassPrice"]); + newData.SnapshotID = (UUID)(String) row["SnapshotUUID"]; + try + { + + newData.UserLocation = + new Vector3(Convert.ToSingle(row["UserLocationX"]), Convert.ToSingle(row["UserLocationY"]), + Convert.ToSingle(row["UserLocationZ"])); + newData.UserLookAt = + new Vector3(Convert.ToSingle(row["UserLookAtX"]), Convert.ToSingle(row["UserLookAtY"]), + Convert.ToSingle(row["UserLookAtZ"])); + + } + catch (InvalidCastException) + { + m_log.ErrorFormat("[PARCEL]: unable to get parcel telehub settings for {1}", newData.Name); + newData.UserLocation = Vector3.Zero; + newData.UserLookAt = Vector3.Zero; + } + newData.ParcelAccessList = new List(); + UUID authBuyerID = UUID.Zero; + + UUID.TryParse((string)row["AuthbuyerID"], out authBuyerID); + + newData.OtherCleanTime = Convert.ToInt32(row["OtherCleanTime"]); + + return newData; + } + + private RegionSettings buildRegionSettings(DataRow row) + { + RegionSettings newSettings = new RegionSettings(); + + newSettings.RegionUUID = new UUID((string) row["regionUUID"]); + newSettings.BlockTerraform = Convert.ToBoolean(row["block_terraform"]); + newSettings.AllowDamage = Convert.ToBoolean(row["allow_damage"]); + newSettings.BlockFly = Convert.ToBoolean(row["block_fly"]); + newSettings.RestrictPushing = Convert.ToBoolean(row["restrict_pushing"]); + newSettings.AllowLandResell = Convert.ToBoolean(row["allow_land_resell"]); + newSettings.AllowLandJoinDivide = Convert.ToBoolean(row["allow_land_join_divide"]); + newSettings.BlockShowInSearch = Convert.ToBoolean(row["block_show_in_search"]); + newSettings.AgentLimit = Convert.ToInt32(row["agent_limit"]); + newSettings.ObjectBonus = Convert.ToDouble(row["object_bonus"]); + newSettings.Maturity = Convert.ToInt32(row["maturity"]); + newSettings.DisableScripts = Convert.ToBoolean(row["disable_scripts"]); + newSettings.DisableCollisions = Convert.ToBoolean(row["disable_collisions"]); + newSettings.DisablePhysics = Convert.ToBoolean(row["disable_physics"]); + newSettings.TerrainTexture1 = new UUID((String) row["terrain_texture_1"]); + newSettings.TerrainTexture2 = new UUID((String) row["terrain_texture_2"]); + newSettings.TerrainTexture3 = new UUID((String) row["terrain_texture_3"]); + newSettings.TerrainTexture4 = new UUID((String) row["terrain_texture_4"]); + newSettings.Elevation1NW = Convert.ToDouble(row["elevation_1_nw"]); + newSettings.Elevation2NW = Convert.ToDouble(row["elevation_2_nw"]); + newSettings.Elevation1NE = Convert.ToDouble(row["elevation_1_ne"]); + newSettings.Elevation2NE = Convert.ToDouble(row["elevation_2_ne"]); + newSettings.Elevation1SE = Convert.ToDouble(row["elevation_1_se"]); + newSettings.Elevation2SE = Convert.ToDouble(row["elevation_2_se"]); + newSettings.Elevation1SW = Convert.ToDouble(row["elevation_1_sw"]); + newSettings.Elevation2SW = Convert.ToDouble(row["elevation_2_sw"]); + newSettings.WaterHeight = Convert.ToDouble(row["water_height"]); + newSettings.TerrainRaiseLimit = Convert.ToDouble(row["terrain_raise_limit"]); + newSettings.TerrainLowerLimit = Convert.ToDouble(row["terrain_lower_limit"]); + newSettings.UseEstateSun = Convert.ToBoolean(row["use_estate_sun"]); + newSettings.Sandbox = Convert.ToBoolean(row["sandbox"]); + newSettings.SunVector = new Vector3 ( + Convert.ToSingle(row["sunvectorx"]), + Convert.ToSingle(row["sunvectory"]), + Convert.ToSingle(row["sunvectorz"]) + ); + newSettings.FixedSun = Convert.ToBoolean(row["fixed_sun"]); + newSettings.SunPosition = Convert.ToDouble(row["sun_position"]); + newSettings.Covenant = new UUID((String) row["covenant"]); + + return newSettings; + } + + /// + /// Build a land access entry from the persisted data. + /// + /// + /// + private static ParcelManager.ParcelAccessEntry buildLandAccessData(DataRow row) + { + ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); + entry.AgentID = new UUID((string) row["AccessUUID"]); + entry.Flags = (AccessList) row["Flags"]; + entry.Time = new DateTime(); + return entry; + } + + /// + /// + /// + /// + /// + private static Array serializeTerrain(double[,] val) + { + MemoryStream str = new MemoryStream(((int)Constants.RegionSize * (int)Constants.RegionSize) *sizeof (double)); + BinaryWriter bw = new BinaryWriter(str); + + // TODO: COMPATIBILITY - Add byte-order conversions + for (int x = 0; x < (int)Constants.RegionSize; x++) + for (int y = 0; y < (int)Constants.RegionSize; y++) + bw.Write(val[x, y]); + + return str.ToArray(); + } + +// private void fillTerrainRow(DataRow row, UUID regionUUID, int rev, double[,] val) +// { +// row["RegionUUID"] = regionUUID; +// row["Revision"] = rev; + + // MemoryStream str = new MemoryStream(((int)Constants.RegionSize * (int)Constants.RegionSize)*sizeof (double)); +// BinaryWriter bw = new BinaryWriter(str); + +// // TODO: COMPATIBILITY - Add byte-order conversions + // for (int x = 0; x < (int)Constants.RegionSize; x++) + // for (int y = 0; y < (int)Constants.RegionSize; y++) +// bw.Write(val[x, y]); + +// row["Heightfield"] = str.ToArray(); +// } + + /// + /// + /// + /// + /// + /// + /// + private static void fillPrimRow(DataRow row, SceneObjectPart prim, UUID sceneGroupID, UUID regionUUID) + { + row["UUID"] = prim.UUID.ToString(); + row["RegionUUID"] = regionUUID.ToString(); + row["CreationDate"] = prim.CreationDate; + row["Name"] = prim.Name; + row["SceneGroupID"] = sceneGroupID.ToString(); + // the UUID of the root part for this SceneObjectGroup + // various text fields + row["Text"] = prim.Text; + row["Description"] = prim.Description; + row["SitName"] = prim.SitName; + row["TouchName"] = prim.TouchName; + // permissions + row["ObjectFlags"] = (uint)prim.Flags; + row["CreatorID"] = prim.CreatorID.ToString(); + row["OwnerID"] = prim.OwnerID.ToString(); + row["GroupID"] = prim.GroupID.ToString(); + row["LastOwnerID"] = prim.LastOwnerID.ToString(); + row["OwnerMask"] = prim.OwnerMask; + row["NextOwnerMask"] = prim.NextOwnerMask; + row["GroupMask"] = prim.GroupMask; + row["EveryoneMask"] = prim.EveryoneMask; + row["BaseMask"] = prim.BaseMask; + // vectors + row["PositionX"] = prim.OffsetPosition.X; + row["PositionY"] = prim.OffsetPosition.Y; + row["PositionZ"] = prim.OffsetPosition.Z; + row["GroupPositionX"] = prim.GroupPosition.X; + row["GroupPositionY"] = prim.GroupPosition.Y; + row["GroupPositionZ"] = prim.GroupPosition.Z; + row["VelocityX"] = prim.Velocity.X; + row["VelocityY"] = prim.Velocity.Y; + row["VelocityZ"] = prim.Velocity.Z; + row["AngularVelocityX"] = prim.AngularVelocity.X; + row["AngularVelocityY"] = prim.AngularVelocity.Y; + row["AngularVelocityZ"] = prim.AngularVelocity.Z; + row["AccelerationX"] = prim.Acceleration.X; + row["AccelerationY"] = prim.Acceleration.Y; + row["AccelerationZ"] = prim.Acceleration.Z; + // quaternions + row["RotationX"] = prim.RotationOffset.X; + row["RotationY"] = prim.RotationOffset.Y; + row["RotationZ"] = prim.RotationOffset.Z; + row["RotationW"] = prim.RotationOffset.W; + + // Sit target + Vector3 sitTargetPos = prim.SitTargetPositionLL; + row["SitTargetOffsetX"] = sitTargetPos.X; + row["SitTargetOffsetY"] = sitTargetPos.Y; + row["SitTargetOffsetZ"] = sitTargetPos.Z; + + Quaternion sitTargetOrient = prim.SitTargetOrientationLL; + row["SitTargetOrientW"] = sitTargetOrient.W; + row["SitTargetOrientX"] = sitTargetOrient.X; + row["SitTargetOrientY"] = sitTargetOrient.Y; + row["SitTargetOrientZ"] = sitTargetOrient.Z; + row["ColorR"] = Convert.ToInt32(prim.Color.R); + row["ColorG"] = Convert.ToInt32(prim.Color.G); + row["ColorB"] = Convert.ToInt32(prim.Color.B); + row["ColorA"] = Convert.ToInt32(prim.Color.A); + row["PayPrice"] = prim.PayPrice[0]; + row["PayButton1"] = prim.PayPrice[1]; + row["PayButton2"] = prim.PayPrice[2]; + row["PayButton3"] = prim.PayPrice[3]; + row["PayButton4"] = prim.PayPrice[4]; + + + row["TextureAnimation"] = Convert.ToBase64String(prim.TextureAnimation); + row["ParticleSystem"] = Convert.ToBase64String(prim.ParticleSystem); + + row["OmegaX"] = prim.AngularVelocity.X; + row["OmegaY"] = prim.AngularVelocity.Y; + row["OmegaZ"] = prim.AngularVelocity.Z; + + row["CameraEyeOffsetX"] = prim.GetCameraEyeOffset().X; + row["CameraEyeOffsetY"] = prim.GetCameraEyeOffset().Y; + row["CameraEyeOffsetZ"] = prim.GetCameraEyeOffset().Z; + + row["CameraAtOffsetX"] = prim.GetCameraAtOffset().X; + row["CameraAtOffsetY"] = prim.GetCameraAtOffset().Y; + row["CameraAtOffsetZ"] = prim.GetCameraAtOffset().Z; + + + if ((prim.SoundFlags & 1) != 0) // Looped + { + row["LoopedSound"] = prim.Sound.ToString(); + row["LoopedSoundGain"] = prim.SoundGain; + } + else + { + row["LoopedSound"] = UUID.Zero.ToString(); + row["LoopedSoundGain"] = 0.0f; + } + + if (prim.GetForceMouselook()) + row["ForceMouselook"] = 1; + else + row["ForceMouselook"] = 0; + + row["ScriptAccessPin"] = prim.ScriptAccessPin; + + if (prim.AllowedDrop) + row["AllowedDrop"] = 1; + else + row["AllowedDrop"] = 0; + + if (prim.DIE_AT_EDGE) + row["DieAtEdge"] = 1; + else + row["DieAtEdge"] = 0; + + row["SalePrice"] = prim.SalePrice; + row["SaleType"] = Convert.ToInt16(prim.ObjectSaleType); + + // click action + row["ClickAction"] = prim.ClickAction; + + row["SalePrice"] = prim.SalePrice; + row["Material"] = prim.Material; + + row["CollisionSound"] = prim.CollisionSound.ToString(); + row["CollisionSoundVolume"] = prim.CollisionSoundVolume; + if (prim.VolumeDetectActive) + row["VolumeDetect"] = 1; + else + row["VolumeDetect"] = 0; + + } + + /// + /// + /// + /// + /// + private static void fillItemRow(DataRow row, TaskInventoryItem taskItem) + { + row["itemID"] = taskItem.ItemID.ToString(); + row["primID"] = taskItem.ParentPartID.ToString(); + row["assetID"] = taskItem.AssetID.ToString(); + row["parentFolderID"] = taskItem.ParentID.ToString(); + + row["invType"] = taskItem.InvType; + row["assetType"] = taskItem.Type; + + row["name"] = taskItem.Name; + row["description"] = taskItem.Description; + row["creationDate"] = taskItem.CreationDate; + row["creatorID"] = taskItem.CreatorID.ToString(); + row["ownerID"] = taskItem.OwnerID.ToString(); + row["lastOwnerID"] = taskItem.LastOwnerID.ToString(); + row["groupID"] = taskItem.GroupID.ToString(); + row["nextPermissions"] = taskItem.NextPermissions; + row["currentPermissions"] = taskItem.CurrentPermissions; + row["basePermissions"] = taskItem.BasePermissions; + row["everyonePermissions"] = taskItem.EveryonePermissions; + row["groupPermissions"] = taskItem.GroupPermissions; + row["flags"] = taskItem.Flags; + } + + /// + /// + /// + /// + /// + /// + private static void fillLandRow(DataRow row, LandData land, UUID regionUUID) + { + row["UUID"] = land.GlobalID.ToString(); + row["RegionUUID"] = regionUUID.ToString(); + row["LocalLandID"] = land.LocalID; + + // Bitmap is a byte[512] + row["Bitmap"] = land.Bitmap; + + row["Name"] = land.Name; + row["Desc"] = land.Description; + row["OwnerUUID"] = land.OwnerID.ToString(); + row["IsGroupOwned"] = land.IsGroupOwned; + row["Area"] = land.Area; + row["AuctionID"] = land.AuctionID; //Unemplemented + row["Category"] = land.Category; //Enum OpenMetaverse.Parcel.ParcelCategory + row["ClaimDate"] = land.ClaimDate; + row["ClaimPrice"] = land.ClaimPrice; + row["GroupUUID"] = land.GroupID.ToString(); + row["SalePrice"] = land.SalePrice; + row["LandStatus"] = land.Status; //Enum. OpenMetaverse.Parcel.ParcelStatus + row["LandFlags"] = land.Flags; + row["LandingType"] = land.LandingType; + row["MediaAutoScale"] = land.MediaAutoScale; + row["MediaTextureUUID"] = land.MediaID.ToString(); + row["MediaURL"] = land.MediaURL; + row["MusicURL"] = land.MusicURL; + row["PassHours"] = land.PassHours; + row["PassPrice"] = land.PassPrice; + row["SnapshotUUID"] = land.SnapshotID.ToString(); + row["UserLocationX"] = land.UserLocation.X; + row["UserLocationY"] = land.UserLocation.Y; + row["UserLocationZ"] = land.UserLocation.Z; + row["UserLookAtX"] = land.UserLookAt.X; + row["UserLookAtY"] = land.UserLookAt.Y; + row["UserLookAtZ"] = land.UserLookAt.Z; + row["AuthbuyerID"] = land.AuthBuyerID.ToString(); + row["OtherCleanTime"] = land.OtherCleanTime; + } + + /// + /// + /// + /// + /// + /// + private static void fillLandAccessRow(DataRow row, ParcelManager.ParcelAccessEntry entry, UUID parcelID) + { + row["LandUUID"] = parcelID.ToString(); + row["AccessUUID"] = entry.AgentID.ToString(); + row["Flags"] = entry.Flags; + } + + private static void fillRegionSettingsRow(DataRow row, RegionSettings settings) + { + row["regionUUID"] = settings.RegionUUID.ToString(); + row["block_terraform"] = settings.BlockTerraform; + row["block_fly"] = settings.BlockFly; + row["allow_damage"] = settings.AllowDamage; + row["restrict_pushing"] = settings.RestrictPushing; + row["allow_land_resell"] = settings.AllowLandResell; + row["allow_land_join_divide"] = settings.AllowLandJoinDivide; + row["block_show_in_search"] = settings.BlockShowInSearch; + row["agent_limit"] = settings.AgentLimit; + row["object_bonus"] = settings.ObjectBonus; + row["maturity"] = settings.Maturity; + row["disable_scripts"] = settings.DisableScripts; + row["disable_collisions"] = settings.DisableCollisions; + row["disable_physics"] = settings.DisablePhysics; + row["terrain_texture_1"] = settings.TerrainTexture1.ToString(); + row["terrain_texture_2"] = settings.TerrainTexture2.ToString(); + row["terrain_texture_3"] = settings.TerrainTexture3.ToString(); + row["terrain_texture_4"] = settings.TerrainTexture4.ToString(); + row["elevation_1_nw"] = settings.Elevation1NW; + row["elevation_2_nw"] = settings.Elevation2NW; + row["elevation_1_ne"] = settings.Elevation1NE; + row["elevation_2_ne"] = settings.Elevation2NE; + row["elevation_1_se"] = settings.Elevation1SE; + row["elevation_2_se"] = settings.Elevation2SE; + row["elevation_1_sw"] = settings.Elevation1SW; + row["elevation_2_sw"] = settings.Elevation2SW; + row["water_height"] = settings.WaterHeight; + row["terrain_raise_limit"] = settings.TerrainRaiseLimit; + row["terrain_lower_limit"] = settings.TerrainLowerLimit; + row["use_estate_sun"] = settings.UseEstateSun; + row["Sandbox"] = settings.Sandbox; // database uses upper case S for sandbox + row["sunvectorx"] = settings.SunVector.X; + row["sunvectory"] = settings.SunVector.Y; + row["sunvectorz"] = settings.SunVector.Z; + row["fixed_sun"] = settings.FixedSun; + row["sun_position"] = settings.SunPosition; + row["covenant"] = settings.Covenant.ToString(); + } + + /// + /// + /// + /// + /// + private PrimitiveBaseShape buildShape(DataRow row) + { + PrimitiveBaseShape s = new PrimitiveBaseShape(); + s.Scale = new Vector3( + Convert.ToSingle(row["ScaleX"]), + Convert.ToSingle(row["ScaleY"]), + Convert.ToSingle(row["ScaleZ"]) + ); + // paths + s.PCode = Convert.ToByte(row["PCode"]); + s.PathBegin = Convert.ToUInt16(row["PathBegin"]); + s.PathEnd = Convert.ToUInt16(row["PathEnd"]); + s.PathScaleX = Convert.ToByte(row["PathScaleX"]); + s.PathScaleY = Convert.ToByte(row["PathScaleY"]); + s.PathShearX = Convert.ToByte(row["PathShearX"]); + s.PathShearY = Convert.ToByte(row["PathShearY"]); + s.PathSkew = Convert.ToSByte(row["PathSkew"]); + s.PathCurve = Convert.ToByte(row["PathCurve"]); + s.PathRadiusOffset = Convert.ToSByte(row["PathRadiusOffset"]); + s.PathRevolutions = Convert.ToByte(row["PathRevolutions"]); + s.PathTaperX = Convert.ToSByte(row["PathTaperX"]); + s.PathTaperY = Convert.ToSByte(row["PathTaperY"]); + s.PathTwist = Convert.ToSByte(row["PathTwist"]); + s.PathTwistBegin = Convert.ToSByte(row["PathTwistBegin"]); + // profile + s.ProfileBegin = Convert.ToUInt16(row["ProfileBegin"]); + s.ProfileEnd = Convert.ToUInt16(row["ProfileEnd"]); + s.ProfileCurve = Convert.ToByte(row["ProfileCurve"]); + s.ProfileHollow = Convert.ToUInt16(row["ProfileHollow"]); + s.State = Convert.ToByte(row["State"]); + + byte[] textureEntry = (byte[])row["Texture"]; + s.TextureEntry = textureEntry; + + s.ExtraParams = (byte[]) row["ExtraParams"]; + return s; + } + + /// + /// + /// + /// + /// + private static void fillShapeRow(DataRow row, SceneObjectPart prim) + { + PrimitiveBaseShape s = prim.Shape; + row["UUID"] = prim.UUID.ToString(); + // shape is an enum + row["Shape"] = 0; + // vectors + row["ScaleX"] = s.Scale.X; + row["ScaleY"] = s.Scale.Y; + row["ScaleZ"] = s.Scale.Z; + // paths + row["PCode"] = s.PCode; + row["PathBegin"] = s.PathBegin; + row["PathEnd"] = s.PathEnd; + row["PathScaleX"] = s.PathScaleX; + row["PathScaleY"] = s.PathScaleY; + row["PathShearX"] = s.PathShearX; + row["PathShearY"] = s.PathShearY; + row["PathSkew"] = s.PathSkew; + row["PathCurve"] = s.PathCurve; + row["PathRadiusOffset"] = s.PathRadiusOffset; + row["PathRevolutions"] = s.PathRevolutions; + row["PathTaperX"] = s.PathTaperX; + row["PathTaperY"] = s.PathTaperY; + row["PathTwist"] = s.PathTwist; + row["PathTwistBegin"] = s.PathTwistBegin; + // profile + row["ProfileBegin"] = s.ProfileBegin; + row["ProfileEnd"] = s.ProfileEnd; + row["ProfileCurve"] = s.ProfileCurve; + row["ProfileHollow"] = s.ProfileHollow; + row["State"] = s.State; + + row["Texture"] = s.TextureEntry; + row["ExtraParams"] = s.ExtraParams; + } + + /// + /// + /// + /// + /// + /// + private void addPrim(SceneObjectPart prim, UUID sceneGroupID, UUID regionUUID) + { + + DataTable prims = ds.Tables["prims"]; + DataTable shapes = ds.Tables["primshapes"]; + + DataRow primRow = prims.Rows.Find(prim.UUID.ToString()); + if (primRow == null) + { + primRow = prims.NewRow(); + fillPrimRow(primRow, prim, sceneGroupID, regionUUID); + prims.Rows.Add(primRow); + } + else + { + fillPrimRow(primRow, prim, sceneGroupID, regionUUID); + } + + DataRow shapeRow = shapes.Rows.Find(prim.UUID.ToString()); + if (shapeRow == null) + { + shapeRow = shapes.NewRow(); + fillShapeRow(shapeRow, prim); + shapes.Rows.Add(shapeRow); + } + else + { + fillShapeRow(shapeRow, prim); + } + } + + /// + /// see IRegionDatastore + /// + /// + /// + public void StorePrimInventory(UUID primID, ICollection items) + { + m_log.InfoFormat("[REGION DB]: Entered StorePrimInventory with prim ID {0}", primID); + + DataTable dbItems = ds.Tables["primitems"]; + + // For now, we're just going to crudely remove all the previous inventory items + // no matter whether they have changed or not, and replace them with the current set. + lock (ds) + { + RemoveItems(primID); + + // repalce with current inventory details + foreach (TaskInventoryItem newItem in items) + { +// m_log.InfoFormat( +// "[DATASTORE]: ", +// "Adding item {0}, {1} to prim ID {2}", +// newItem.Name, newItem.ItemID, newItem.ParentPartID); + + DataRow newItemRow = dbItems.NewRow(); + fillItemRow(newItemRow, newItem); + dbItems.Rows.Add(newItemRow); + } + } + + Commit(); + } + + /*********************************************************************** + * + * SQL Statement Creation Functions + * + * These functions create SQL statements for update, insert, and create. + * They can probably be factored later to have a db independant + * portion and a db specific portion + * + **********************************************************************/ + + /// + /// Create an insert command + /// + /// table name + /// data table + /// the created command + /// + /// This is subtle enough to deserve some commentary. + /// Instead of doing *lots* and *lots of hardcoded strings + /// for database definitions we'll use the fact that + /// realistically all insert statements look like "insert + /// into A(b, c) values(:b, :c) on the parameterized query + /// front. If we just have a list of b, c, etc... we can + /// generate these strings instead of typing them out. + /// + private static SqliteCommand createInsertCommand(string table, DataTable dt) + { + string[] cols = new string[dt.Columns.Count]; + for (int i = 0; i < dt.Columns.Count; i++) + { + DataColumn col = dt.Columns[i]; + cols[i] = col.ColumnName; + } + + string sql = "insert into " + table + "("; + sql += String.Join(", ", cols); + // important, the first ':' needs to be here, the rest get added in the join + sql += ") values (:"; + sql += String.Join(", :", cols); + sql += ")"; + SqliteCommand cmd = new SqliteCommand(sql); + + // this provides the binding for all our parameters, so + // much less code than it used to be + foreach (DataColumn col in dt.Columns) + { + cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType)); + } + return cmd; + } + + + /// + /// create an update command + /// + /// table name + /// + /// + /// the created command + private static SqliteCommand createUpdateCommand(string table, string pk, DataTable dt) + { + string sql = "update " + table + " set "; + string subsql = String.Empty; + foreach (DataColumn col in dt.Columns) + { + if (subsql.Length > 0) + { + // a map function would rock so much here + subsql += ", "; + } + subsql += col.ColumnName + "= :" + col.ColumnName; + } + sql += subsql; + sql += " where " + pk; + SqliteCommand cmd = new SqliteCommand(sql); + + // this provides the binding for all our parameters, so + // much less code than it used to be + + foreach (DataColumn col in dt.Columns) + { + cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType)); + } + return cmd; + } + + /// + /// create an update command + /// + /// table name + /// + /// + /// the created command + private static SqliteCommand createUpdateCommand(string table, string pk1, string pk2, DataTable dt) + { + string sql = "update " + table + " set "; + string subsql = String.Empty; + foreach (DataColumn col in dt.Columns) + { + if (subsql.Length > 0) + { + // a map function would rock so much here + subsql += ", "; + } + subsql += col.ColumnName + "= :" + col.ColumnName; + } + sql += subsql; + sql += " where " + pk1 + " and " + pk2; + SqliteCommand cmd = new SqliteCommand(sql); + + // this provides the binding for all our parameters, so + // much less code than it used to be + + foreach (DataColumn col in dt.Columns) + { + cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType)); + } + return cmd; + } + + /// + /// + /// + /// Data Table + /// + // private static string defineTable(DataTable dt) + // { + // string sql = "create table " + dt.TableName + "("; + // string subsql = String.Empty; + // foreach (DataColumn col in dt.Columns) + // { + // if (subsql.Length > 0) + // { + // // a map function would rock so much here + // subsql += ",\n"; + // } + // subsql += col.ColumnName + " " + sqliteType(col.DataType); + // if (dt.PrimaryKey.Length > 0 && col == dt.PrimaryKey[0]) + // { + // subsql += " primary key"; + // } + // } + // sql += subsql; + // sql += ")"; + // return sql; + // } + + /*********************************************************************** + * + * Database Binding functions + * + * These will be db specific due to typing, and minor differences + * in databases. + * + **********************************************************************/ + + /// + /// This is a convenience function that collapses 5 repetitive + /// lines for defining SqliteParameters to 2 parameters: + /// column name and database type. + /// + /// It assumes certain conventions like :param as the param + /// name to replace in parametrized queries, and that source + /// version is always current version, both of which are fine + /// for us. + /// + ///a built sqlite parameter + private static SqliteParameter createSqliteParameter(string name, Type type) + { + SqliteParameter param = new SqliteParameter(); + param.ParameterName = ":" + name; + param.DbType = dbtypeFromType(type); + param.SourceColumn = name; + param.SourceVersion = DataRowVersion.Current; + return param; + } + + /// + /// + /// + /// + /// + private void setupPrimCommands(SqliteDataAdapter da, SqliteConnection conn) + { + da.InsertCommand = createInsertCommand("prims", ds.Tables["prims"]); + da.InsertCommand.Connection = conn; + + da.UpdateCommand = createUpdateCommand("prims", "UUID=:UUID", ds.Tables["prims"]); + da.UpdateCommand.Connection = conn; + + SqliteCommand delete = new SqliteCommand("delete from prims where UUID = :UUID"); + delete.Parameters.Add(createSqliteParameter("UUID", typeof (String))); + delete.Connection = conn; + da.DeleteCommand = delete; + } + + /// + /// + /// + /// + /// + private void setupItemsCommands(SqliteDataAdapter da, SqliteConnection conn) + { + da.InsertCommand = createInsertCommand("primitems", ds.Tables["primitems"]); + da.InsertCommand.Connection = conn; + + da.UpdateCommand = createUpdateCommand("primitems", "itemID = :itemID", ds.Tables["primitems"]); + da.UpdateCommand.Connection = conn; + + SqliteCommand delete = new SqliteCommand("delete from primitems where itemID = :itemID"); + delete.Parameters.Add(createSqliteParameter("itemID", typeof (String))); + delete.Connection = conn; + da.DeleteCommand = delete; + } + + /// + /// + /// + /// + /// + private void setupTerrainCommands(SqliteDataAdapter da, SqliteConnection conn) + { + da.InsertCommand = createInsertCommand("terrain", ds.Tables["terrain"]); + da.InsertCommand.Connection = conn; + } + + /// + /// + /// + /// + /// + private void setupLandCommands(SqliteDataAdapter da, SqliteConnection conn) + { + da.InsertCommand = createInsertCommand("land", ds.Tables["land"]); + da.InsertCommand.Connection = conn; + + da.UpdateCommand = createUpdateCommand("land", "UUID=:UUID", ds.Tables["land"]); + da.UpdateCommand.Connection = conn; + + SqliteCommand delete = new SqliteCommand("delete from land where UUID=:UUID"); + delete.Parameters.Add(createSqliteParameter("UUID", typeof(String))); + da.DeleteCommand = delete; + da.DeleteCommand.Connection = conn; + } + + /// + /// + /// + /// + /// + private void setupLandAccessCommands(SqliteDataAdapter da, SqliteConnection conn) + { + da.InsertCommand = createInsertCommand("landaccesslist", ds.Tables["landaccesslist"]); + da.InsertCommand.Connection = conn; + + da.UpdateCommand = createUpdateCommand("landaccesslist", "LandUUID=:landUUID", "AccessUUID=:AccessUUID", ds.Tables["landaccesslist"]); + da.UpdateCommand.Connection = conn; + + SqliteCommand delete = new SqliteCommand("delete from landaccesslist where LandUUID= :LandUUID and AccessUUID= :AccessUUID"); + delete.Parameters.Add(createSqliteParameter("LandUUID", typeof(String))); + delete.Parameters.Add(createSqliteParameter("AccessUUID", typeof(String))); + da.DeleteCommand = delete; + da.DeleteCommand.Connection = conn; + + } + + private void setupRegionSettingsCommands(SqliteDataAdapter da, SqliteConnection conn) + { + da.InsertCommand = createInsertCommand("regionsettings", ds.Tables["regionsettings"]); + da.InsertCommand.Connection = conn; + da.UpdateCommand = createUpdateCommand("regionsettings", "regionUUID=:regionUUID", ds.Tables["regionsettings"]); + da.UpdateCommand.Connection = conn; + } + + /// + /// + /// + /// + /// + private void setupShapeCommands(SqliteDataAdapter da, SqliteConnection conn) + { + da.InsertCommand = createInsertCommand("primshapes", ds.Tables["primshapes"]); + da.InsertCommand.Connection = conn; + + da.UpdateCommand = createUpdateCommand("primshapes", "UUID=:UUID", ds.Tables["primshapes"]); + da.UpdateCommand.Connection = conn; + + SqliteCommand delete = new SqliteCommand("delete from primshapes where UUID = :UUID"); + delete.Parameters.Add(createSqliteParameter("UUID", typeof (String))); + delete.Connection = conn; + da.DeleteCommand = delete; + } + + /*********************************************************************** + * + * Type conversion functions + * + **********************************************************************/ + + /// + /// Type conversion function + /// + /// + /// + private static DbType dbtypeFromType(Type type) + { + if (type == typeof (String)) + { + return DbType.String; + } + else if (type == typeof (Int32)) + { + return DbType.Int32; + } + else if (type == typeof (Double)) + { + return DbType.Double; + } + else if (type == typeof (Byte)) + { + return DbType.Byte; + } + else if (type == typeof (Double)) + { + return DbType.Double; + } + else if (type == typeof (Byte[])) + { + return DbType.Binary; + } + else + { + return DbType.String; + } + } + + } +} diff --git a/OpenSim/Data/Tests/RegionTests.cs b/OpenSim/Data/Tests/RegionTests.cs index 29bf5a3..a081462 100644 --- a/OpenSim/Data/Tests/RegionTests.cs +++ b/OpenSim/Data/Tests/RegionTests.cs @@ -61,17 +61,17 @@ namespace OpenSim.Data.Tests #else [TestFixture(Description = "Region store tests (SQLite)")] - public class SQLiteRegionTests : RegionTests + public class SQLiteRegionTests : RegionTests { } [TestFixture(Description = "Region store tests (MySQL)")] - public class MySqlRegionTests : RegionTests + public class MySqlRegionTests : RegionTests { } [TestFixture(Description = "Region store tests (MS SQL Server)")] - public class MSSQLRegionTests : RegionTests + public class MSSQLRegionTests : RegionTests { } @@ -79,11 +79,11 @@ namespace OpenSim.Data.Tests public class RegionTests : BasicDataServiceTest where TConn : DbConnection, new() - where TRegStore : class, IRegionDataStore, new() + where TRegStore : class, ISimulationDataStore, new() { bool m_rebuildDB; - public IRegionDataStore db; + public ISimulationDataStore db; public UUID zero = UUID.Zero; public UUID region1 = UUID.Random(); public UUID region2 = UUID.Random(); @@ -122,7 +122,7 @@ namespace OpenSim.Data.Tests protected override void InitService(object service) { ClearDB(); - db = (IRegionDataStore)service; + db = (ISimulationDataStore)service; db.Initialise(m_connStr); } -- cgit v1.1