예제 #1
0
        /// <summary>
        /// Gets the prims for this region and all adjacent from the DB.
        /// </summary>
        /// <returns>The prims.</returns>
        public IEnumerable <Prim> GetPrims()
        {
            if (!HasKnownCoordinates())
            {
                return(null);
            }
            var watch = System.Diagnostics.Stopwatch.StartNew();

            LOG.Debug($"Loading region-local prims for region {Id} named '{Name}'.");

            var prims = Prim.LoadPrims(_rdbConnectionString, Id);

            watch.Stop();
            LOG.Debug($"Loading region-local prims for region {Id} named '{Name}' took {watch.ElapsedMilliseconds}ms " + (prims != null ? $"for {prims.Count()} prims." : "but failed to update from DB."));
            watch.Reset();

            if (prims != null && _adjacentRegions != null)
            {
                prims = _adjacentRegions.Select(adjacentRegion => {
                    if (adjacentRegion.HasKnownCoordinates())
                    {
                        watch.Start();
                        LOG.Debug($"Loading prims for region {Id} named '{Name}' from adjacent region {adjacentRegion.Id} named '{adjacentRegion.Name}'.");

                        var adjacentRegionPrims = Prim.LoadPrims(adjacentRegion._rdbConnectionString, adjacentRegion.Id);

                        watch.Stop();
                        LOG.Debug($"Loading prims for region {Id} named '{Name}' from adjacent region {adjacentRegion.Id} named '{adjacentRegion.Name}' took {watch.ElapsedMilliseconds}ms " + (adjacentRegionPrims != null ? $"for {adjacentRegionPrims.Count()} prims." : "but failed to update from DB."));
                        watch.Reset();

                        if (adjacentRegionPrims != null)
                        {
                            watch.Start();
                            LOG.Debug($"Offsetting prims for region {Id} named '{Name}' from adjacent region {adjacentRegion.Id} named '{adjacentRegion.Name}'.");

                            foreach (var prim in adjacentRegionPrims)
                            {
                                var regionOffset = (Vector2)adjacentRegion.Location - (Vector2)Location;

                                prim.Offset(regionOffset * Size);                                 // Assumes constant size regions.
                            }

                            watch.Stop();
                            LOG.Debug($"Offsetting prims for region {Id} named '{Name}' from adjacent region {adjacentRegion.Id} named '{adjacentRegion.Name}' took {watch.ElapsedMilliseconds}ms for {adjacentRegionPrims.Count()} prims.");
                            watch.Reset();
                        }

                        return(adjacentRegionPrims);
                    }

                    return(null);
                })
                        .Where(region => region != null)
                        .Aggregate(prims, (primAccumulation, regionPrims) => primAccumulation.Concat(regionPrims));
            }

            return(prims);
        }
예제 #2
0
        internal static IEnumerable <Prim> LoadPrims(string rdbConnectionString, Guid regionId)
        {
            using (var conn = DBHelpers.GetConnection(rdbConnectionString)) {
                if (conn == null)
                {
                    LOG.Warn($"Could not get connection to DB for region '{regionId}'.");
                    return(null);
                }
                using (var cmd = conn.CreateCommand()) {
                    cmd.CommandText = @"SELECT
							pr.UUID,
							pr.SceneGroupID,
							pr.LinkNumber,
							pr.Name,
							pr.ObjectFlags,
							ps.State,
							pr.PositionX, pr.PositionY, pr.PositionZ,
							pr.GroupPositionX, pr.GroupPositionY, pr.GroupPositionZ,
							ps.ScaleX, ps.ScaleY, ps.ScaleZ,
							pr.RotationX, pr.RotationY, pr.RotationZ, pr.RotationW,
							ps.Texture
						FROM
							prims pr
							INNER JOIN primshapes ps USING (UUID)
						WHERE
							pr.GroupPositionZ < 766 /* = max terrain height (510) + render height (256) */
							AND LENGTH(ps.Texture) > 0
							AND pr.ObjectFlags & (0 | 0x40000 | 0x20000) = 0
							AND ps.ScaleX > 1.0
							AND ps.ScaleY > 1.0
							AND ps.ScaleZ > 1.0
							AND ps.PCode NOT IN (255, 111, 95)
							AND RegionUUID = @region_id
						ORDER BY
							GroupPositionZ, PositionZ
					"                    ;
                    cmd.Parameters.AddWithValue("region_id", regionId);
                    cmd.CommandTimeout = 600;
                    cmd.Prepare();
                    IDataReader reader = null;
                    try {
                        reader = DBHelpers.ExecuteReader(cmd);
                    }
                    catch (Exception e) {
                        LOG.Warn($"Prims DB reader query threw an error when attempting to get prims for region '{regionId}'.", e);
                    }

                    if (reader == null)
                    {
                        LOG.Warn($"Prims DB reader query returned nothing for region '{regionId}'.");
                        return(null);
                    }

                    var prims = new List <Prim>();                    // List was chosen because it guarantees that insertion order will be preserved unless explictly sorted.

                    var rootPrims  = new Dictionary <Guid, Prim>();
                    var childPrims = new List <Prim>();                    // List was chosen because it guarantees that insertion order will be preserved unless explictly sorted.

                    try {
                        while (reader.Read())
                        {
                            // Nullables start here
                            var groupPosX = RDBMap.GetDBValueOrNull <double>(reader, "GroupPositionX");
                            var groupPosY = RDBMap.GetDBValueOrNull <double>(reader, "GroupPositionY");
                            var groupPosZ = RDBMap.GetDBValueOrNull <double>(reader, "GroupPositionZ");
                            var posX      = RDBMap.GetDBValueOrNull <double>(reader, "PositionX");
                            var posY      = RDBMap.GetDBValueOrNull <double>(reader, "PositionY");
                            var posZ      = RDBMap.GetDBValueOrNull <double>(reader, "PositionZ");
                            var rotW      = RDBMap.GetDBValueOrNull <double>(reader, "RotationW");
                            var rotX      = RDBMap.GetDBValueOrNull <double>(reader, "RotationX");
                            var rotY      = RDBMap.GetDBValueOrNull <double>(reader, "RotationY");
                            var rotZ      = RDBMap.GetDBValueOrNull <double>(reader, "RotationZ");

                            var prim = new Prim {
                                GroupPosition = groupPosX != null && groupPosY != null && groupPosZ != null ? new Vector3(
                                    (float)groupPosX,
                                    (float)groupPosY,
                                    (float)groupPosZ
                                    ) : (Vector3?)null,
                                Id          = Guid.Parse(RDBMap.GetDBValue(reader, "UUID")),
                                Name        = RDBMap.GetDBValue(reader, "Name"),
                                ObjectFlags = RDBMap.GetDBValue <int>(reader, "ObjectFlags"),
                                Position    = posX != null && posY != null && posZ != null ? new Vector3(
                                    (float)posX,
                                    (float)posY,
                                    (float)posZ
                                    ) : (Vector3?)null,
                                RegionId     = regionId,
                                RootRotation = null,
                                Rotation     = rotW != null && rotX != null && rotY != null && rotZ != null ? new Quaternion(
                                    (float)rotX,
                                    (float)rotY,
                                    (float)rotZ,
                                    (float)rotW
                                    ) : (Quaternion?)null,
                                Scale = new Vector3(
                                    (float)RDBMap.GetDBValue <double>(reader, "ScaleX"),
                                    (float)RDBMap.GetDBValue <double>(reader, "ScaleY"),
                                    (float)RDBMap.GetDBValue <double>(reader, "ScaleZ")
                                    ),
                                State   = RDBMap.GetDBValue <int>(reader, "State"),
                                Texture = (byte[])reader["Texture"],
                            };

                            prims.Add(prim);

                            var sogIdStr = RDBMap.GetDBValue(reader, "SceneGroupID");
                            if (Guid.TryParse(sogIdStr, out var sogId))
                            {
                                prim.SceneGroupId = sogId;

                                var linkNumber = RDBMap.GetDBValue <int>(reader, "LinkNumber");
                                if (linkNumber == 1)
                                {
                                    rootPrims.Add(sogId, prim);
                                }
                                else if (linkNumber > 1)
                                {
                                    childPrims.Add(prim);
                                }
                            }
                        }
                    }
                    finally {
                        reader.Close();
                    }

                    foreach (var prim in childPrims)
                    {
                        if (rootPrims.TryGetValue(prim.SceneGroupId, out var rootPrim))
                        {
                            prim.RootRotation = rootPrim.Rotation;
                        }
                    }

                    return(prims);
                }
            }
        }