Beispiel #1
0
        /// <summary>
        /// Handles movement of objects from zone to zone
        /// </summary>
        /// <param name="objectType"></param>
        /// <param name="element"></param>
        private void ObjectEnterZone(eGameObjectType objectType, SubNodeElement element)
        {
            if (!m_initialized)
            {
                InitializeZone();
            }
            int subZoneIndex = GetSubZoneIndex(element.data);

            if (log.IsDebugEnabled)
            {
                log.Debug("Object " + element.data.ObjectID + "(" + objectType + ") entering (inner) subzone " + subZoneIndex + " in zone " + this.ID + " in region " + m_Region.ID);
            }

            if ((subZoneIndex >= 0) && (subZoneIndex < SUBZONE_NBR))
            {
                int type = (int)objectType;

                lock (m_subZoneElements[subZoneIndex][type])
                {
                    // add to subzone list
                    m_subZoneElements[subZoneIndex][type].PushBack(element);
                }

                Interlocked.Increment(ref m_objectCount);
            }
        }
Beispiel #2
0
        /// <summary>
        /// Gets the lists of objects, located in the current Zone and of the given type, that are at most at a 'radius' distance from (x,y,z)
        /// The found objects are appended to the given 'partialList'.
        /// </summary>
        /// <param name="type">the type of objects to look for</param>
        /// <param name="x">the x coordinate of the observation position</param>
        /// <param name="y">the y coordinate of the observation position</param>
        /// <param name="z">the z coordinate of the observation position</param>
        /// <param name="radius">the radius to check against</param>
        /// <param name="partialList">an initial (eventually empty but initialized, i.e. never null !!) list of objects</param>
        /// <returns>partialList augmented with the new objects verigying both type and radius in the current Zone</returns>
        internal ArrayList GetObjectsInRadius(eGameObjectType type, int x, int y, int z, ushort radius, ArrayList partialList, bool ignoreZ)
        {
            if (!m_initialized) InitializeZone();
            // initialise parameters
            uint sqRadius = (uint)radius * (uint)radius;
            int referenceSubzoneIndex = GetSubZoneIndex(x, y);
            int typeIndex = (int)type;

            int xInZone = x - m_XOffset; // x in zone coordinates
            int yInZone = y - m_YOffset; // y in zone coordinates

            int cellNbr = (radius >> SUBZONE_SHIFT) + 1; // radius in terms of subzone number
            int xInCell = xInZone >> SUBZONE_SHIFT; // xInZone in terms of subzone coord
            int yInCell = yInZone >> SUBZONE_SHIFT; // yInZone in terms of subzone coord

            int minColumn = xInCell - cellNbr;
            if (minColumn < 0)
            {
                minColumn = 0;
            }

            int maxColumn = xInCell + cellNbr;
            if (maxColumn > (SUBZONE_NBR_ON_ZONE_SIDE - 1))
            {
                maxColumn = SUBZONE_NBR_ON_ZONE_SIDE - 1;
            }

            int minLine = yInCell - cellNbr;
            if (minLine < 0)
            {
                minLine = 0;
            }

            int maxLine = yInCell + cellNbr;
            if (maxLine > (SUBZONE_NBR_ON_ZONE_SIDE - 1))
            {
                maxLine = SUBZONE_NBR_ON_ZONE_SIDE - 1;
            }

            DOL.GS.Collections.Hashtable inZoneElements = new DOL.GS.Collections.Hashtable();
            DOL.GS.Collections.Hashtable outOfZoneElements = new DOL.GS.Collections.Hashtable();

            for (int currentLine = minLine; currentLine <= maxLine; ++currentLine)
            {
                int currentSubZoneIndex = 0;
                SubNodeElement startElement = null;

                for (int currentColumn = minColumn; currentColumn <= maxColumn; ++currentColumn)
                {
                    currentSubZoneIndex = GetSubZoneOffset(currentLine, currentColumn);

                    // get the right list of objects
                    startElement = m_subZoneElements[currentSubZoneIndex][typeIndex];

                    if (startElement != startElement.next)
                    { // allow dirty read here to enable a more efficient and fine grained locking later...
                        // the current subzone contains some objects

                        if (currentSubZoneIndex == referenceSubzoneIndex)
                        {
                            lock (startElement)
                            {
                                // we are in the subzone of the observation point
                                // => check all distances for all objects in the subzone
                                UnsafeAddToListWithDistanceCheck(startElement, x, y, z, sqRadius, typeIndex, currentSubZoneIndex, partialList, inZoneElements, outOfZoneElements, ignoreZ);
                                UnsafeUpdateSubZoneTimestamp(currentSubZoneIndex, typeIndex);
                            }
                        }
                        else
                        {
                            int xLeft = currentColumn << SUBZONE_SHIFT;
                            int xRight = xLeft + SUBZONE_SIZE;
                            int yTop = currentLine << SUBZONE_SHIFT;
                            int yBottom = yTop + SUBZONE_SIZE;

                            if (CheckMinDistance(xInZone, yInZone, xLeft, xRight, yTop, yBottom, sqRadius))
                            {
                                // the minimum distance is smaller than radius

                                if (CheckMaxDistance(xInZone, yInZone, xLeft, xRight, yTop, yBottom, sqRadius))
                                {
                                    // the current subzone is fully enclosed within the radius
                                    // => add all the objects of the current subzone

                                    lock (startElement)
                                    {
                                        UnsafeAddToListWithoutDistanceCheck(startElement, typeIndex, currentSubZoneIndex, partialList, inZoneElements, outOfZoneElements);
                                        UnsafeUpdateSubZoneTimestamp(currentSubZoneIndex, typeIndex);
                                    }
                                }
                                else
                                {
                                    // the current subzone is partially enclosed within the radius
                                    // => only add the objects within the right area

                                    lock (startElement)
                                    {
                                        UnsafeAddToListWithDistanceCheck(startElement, x, y, z, sqRadius, typeIndex, currentSubZoneIndex, partialList, inZoneElements, outOfZoneElements, ignoreZ);
                                        UnsafeUpdateSubZoneTimestamp(currentSubZoneIndex, typeIndex);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            //
            // perform needed relocations
            //

            if (inZoneElements.Count > 0)
            {
                PlaceElementsInZone(inZoneElements);

                if (log.IsDebugEnabled)
                {
                    log.Debug("Zone" + ID + " " + inZoneElements.Count + " objects moved inside zone");
                }
            }

            if (outOfZoneElements.Count > 0)
            {
                PlaceElementsInOtherZones(outOfZoneElements);

                if (log.IsDebugEnabled)
                {
                    log.Debug("Zone" + ID + " " + outOfZoneElements.Count + " objects moved outside zone");
                }
            }

            return partialList;
        }
Beispiel #3
0
        /// <summary>
        /// Handles movement of objects from zone to zone
        /// </summary>
        /// <param name="objectType"></param>
        /// <param name="element"></param>
        private void ObjectEnterZone(eGameObjectType objectType, SubNodeElement element)
        {
            if (!m_initialized) InitializeZone();
            int subZoneIndex = GetSubZoneIndex(element.data);

            if (log.IsDebugEnabled)
            {
                log.Debug("Object " + element.data.ObjectID + "(" + objectType + ") entering (inner) subzone " + subZoneIndex + " in zone " + this.ID + " in region " + m_Region.ID);
            }

            if ((subZoneIndex >= 0) && (subZoneIndex < SUBZONE_NBR))
            {
                int type = (int)objectType;

                lock (m_subZoneElements[subZoneIndex][type])
                {
                    // add to subzone list
                    m_subZoneElements[subZoneIndex][type].PushBack(element);
                }

                Interlocked.Increment(ref m_objectCount);
            }
        }
Beispiel #4
0
        /// <summary>
        /// Gets the lists of objects, located in the current Zone and of the given type, that are at most at a 'radius' distance from (x,y,z)
        /// The found objects are appended to the given 'partialList'.
        /// </summary>
        /// <param name="type">the type of objects to look for</param>
        /// <param name="x">the x coordinate of the observation position</param>
        /// <param name="y">the y coordinate of the observation position</param>
        /// <param name="z">the z coordinate of the observation position</param>
        /// <param name="radius">the radius to check against</param>
        /// <param name="partialList">an initial (eventually empty but initialized, i.e. never null !!) list of objects</param>
        /// <returns>partialList augmented with the new objects verigying both type and radius in the current Zone</returns>
        internal ArrayList GetObjectsInRadius(eGameObjectType type, float x, float y, float z, ushort radius, ArrayList partialList, bool ignoreZ)
        {
            if (!m_initialized)
            {
                InitializeZone();
            }
            // initialise parameters
            uint sqRadius = (uint)radius * (uint)radius;
            int  referenceSubzoneIndex = GetSubZoneIndex(x, y);
            int  typeIndex             = (int)type;

            int xInZone = (int)(x - m_XOffset);             // x in zone coordinates
            int yInZone = (int)(y - m_YOffset);             // y in zone coordinates

            int cellNbr = (radius >> SUBZONE_SHIFT) + 1;    // radius in terms of subzone number
            int xInCell = xInZone >> SUBZONE_SHIFT;         // xInZone in terms of subzone coord
            int yInCell = yInZone >> SUBZONE_SHIFT;         // yInZone in terms of subzone coord

            int minColumn = xInCell - cellNbr;

            if (minColumn < 0)
            {
                minColumn = 0;
            }

            int maxColumn = xInCell + cellNbr;

            if (maxColumn > (SUBZONE_NBR_ON_ZONE_SIDE - 1))
            {
                maxColumn = SUBZONE_NBR_ON_ZONE_SIDE - 1;
            }

            int minLine = yInCell - cellNbr;

            if (minLine < 0)
            {
                minLine = 0;
            }

            int maxLine = yInCell + cellNbr;

            if (maxLine > (SUBZONE_NBR_ON_ZONE_SIDE - 1))
            {
                maxLine = SUBZONE_NBR_ON_ZONE_SIDE - 1;
            }

            DOL.GS.Collections.Hashtable inZoneElements    = new DOL.GS.Collections.Hashtable();
            DOL.GS.Collections.Hashtable outOfZoneElements = new DOL.GS.Collections.Hashtable();

            for (int currentLine = minLine; currentLine <= maxLine; ++currentLine)
            {
                int            currentSubZoneIndex = 0;
                SubNodeElement startElement        = null;

                for (int currentColumn = minColumn; currentColumn <= maxColumn; ++currentColumn)
                {
                    currentSubZoneIndex = GetSubZoneOffset(currentLine, currentColumn);

                    // get the right list of objects
                    startElement = m_subZoneElements[currentSubZoneIndex][typeIndex];

                    if (startElement != startElement.next)
                    {                     // allow dirty read here to enable a more efficient and fine grained locking later...
                        // the current subzone contains some objects

                        if (currentSubZoneIndex == referenceSubzoneIndex)
                        {
                            lock (startElement)
                            {
                                // we are in the subzone of the observation point
                                // => check all distances for all objects in the subzone
                                UnsafeAddToListWithDistanceCheck(startElement, x, y, z, sqRadius, typeIndex, currentSubZoneIndex, partialList, inZoneElements, outOfZoneElements, ignoreZ);
                                UnsafeUpdateSubZoneTimestamp(currentSubZoneIndex, typeIndex);
                            }
                        }
                        else
                        {
                            int xLeft   = currentColumn << SUBZONE_SHIFT;
                            int xRight  = xLeft + SUBZONE_SIZE;
                            int yTop    = currentLine << SUBZONE_SHIFT;
                            int yBottom = yTop + SUBZONE_SIZE;

                            if (CheckMinDistance(xInZone, yInZone, xLeft, xRight, yTop, yBottom, sqRadius))
                            {
                                // the minimum distance is smaller than radius

                                if (CheckMaxDistance(xInZone, yInZone, xLeft, xRight, yTop, yBottom, sqRadius))
                                {
                                    // the current subzone is fully enclosed within the radius
                                    // => add all the objects of the current subzone

                                    lock (startElement)
                                    {
                                        UnsafeAddToListWithoutDistanceCheck(startElement, typeIndex, currentSubZoneIndex, partialList, inZoneElements, outOfZoneElements);
                                        UnsafeUpdateSubZoneTimestamp(currentSubZoneIndex, typeIndex);
                                    }
                                }
                                else
                                {
                                    // the current subzone is partially enclosed within the radius
                                    // => only add the objects within the right area

                                    lock (startElement)
                                    {
                                        UnsafeAddToListWithDistanceCheck(startElement, x, y, z, sqRadius, typeIndex, currentSubZoneIndex, partialList, inZoneElements, outOfZoneElements, ignoreZ);
                                        UnsafeUpdateSubZoneTimestamp(currentSubZoneIndex, typeIndex);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            //
            // perform needed relocations
            //

            if (inZoneElements.Count > 0)
            {
                PlaceElementsInZone(inZoneElements);

                if (log.IsDebugEnabled)
                {
                    log.Debug("Zone" + ID + " " + inZoneElements.Count + " objects moved inside zone");
                }
            }

            if (outOfZoneElements.Count > 0)
            {
                PlaceElementsInOtherZones(outOfZoneElements);

                if (log.IsDebugEnabled)
                {
                    log.Debug("Zone" + ID + " " + outOfZoneElements.Count + " objects moved outside zone");
                }
            }


            return(partialList);
        }