Exemplo n.º 1
0
        private void PlaceElementsInOtherZones(DOL.GS.Collections.Hashtable elements)
        {
            DOL.GS.Collections.DictionaryEntry currentEntry = null;

            int       currentType = 0;
            ArrayList currentList = null;

            Zone           currentZone    = null;
            SubNodeElement currentElement = null;

            IEnumerator entryEnumerator = elements.GetEntryEnumerator();

            while (entryEnumerator.MoveNext())
            {
                currentEntry = (DOL.GS.Collections.DictionaryEntry)entryEnumerator.Current;
                currentType  = (int)currentEntry.key;

                currentList = (ArrayList)currentEntry.value;

                for (int i = 0; i < currentList.Count; i++)
                {
                    currentElement = (SubNodeElement)currentList[i];
                    currentZone    = ZoneRegion.GetZone(currentElement.data.Position);

                    if (currentZone != null)
                    {
                        currentZone.ObjectEnterZone((eGameObjectType)currentType, currentElement);
                    }
                }
            }
        }
Exemplo n.º 2
0
        private void PlaceElementsInZone(DOL.GS.Collections.Hashtable elements)
        {
            DOL.GS.Collections.DictionaryEntry currentEntry = null;
            ArrayList      currentList         = null;
            SubNodeElement currentStartElement = null;
            SubNodeElement currentElement      = null;

            IEnumerator entryEnumerator = elements.GetEntryEnumerator();

            while (entryEnumerator.MoveNext())
            {
                currentEntry        = (DOL.GS.Collections.DictionaryEntry)entryEnumerator.Current;
                currentStartElement = (SubNodeElement)currentEntry.key;

                currentList = (ArrayList)currentEntry.value;

                lock (currentStartElement)
                {
                    for (int i = 0; i < currentList.Count; i++)
                    {
                        currentElement = (SubNodeElement)currentList[i];
                        currentStartElement.PushBack(currentElement);
                    }
                }
            }
        }
Exemplo n.º 3
0
        private void UnsafeAddToListWithDistanceCheck(
            SubNodeElement startElement,
            float x,
            float y,
            float z,
            uint sqRadius,
            int typeIndex,
            int subZoneIndex,
            ArrayList partialList,
            DOL.GS.Collections.Hashtable inZoneElements,
            DOL.GS.Collections.Hashtable outOfZoneElements,
            bool ignoreZ)
        {
            // => check all distances for all objects in the subzone

            SubNodeElement currentElement  = startElement.next;
            SubNodeElement elementToRemove = null;
            GameObject     currentObject   = null;

            do
            {
                currentObject = currentElement.data;

                if (ShouldElementMove(currentElement, typeIndex, subZoneIndex, inZoneElements, outOfZoneElements))
                {
                    elementToRemove = currentElement;
                    currentElement  = currentElement.next;

                    elementToRemove.Remove();

                    if (log.IsDebugEnabled)
                    {
                        log.Debug("Zone" + ID + ": " + ((currentObject != null) ? "object " + currentObject.ObjectID : "ghost object") + " removed for subzone");
                    }
                }
                else
                {
                    if (CheckSquareDistance(x, y, z, currentObject.Position.X, currentObject.Position.Y, currentObject.Position.Z, sqRadius, ignoreZ) && !partialList.Contains(currentObject))
                    {
                        // the current object exists, is Active and still in the current subzone
                        // moreover it is in the right range and not yet in the result set
                        // => add it
                        partialList.Add(currentObject);
                    }

                    currentElement = currentElement.next;
                }
            } while (currentElement != startElement);
        }
Exemplo n.º 4
0
        internal void Relocate(object state)
        {
            if (!m_initialized) return;
            if (m_objectCount > 0)
            {
                SubNodeElement startElement = null;
                SubNodeElement currentElement = null;

                SubNodeElement elementToRemove = null;

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

                for (int subZoneIndex = 0; subZoneIndex < m_subZoneElements.Length; subZoneIndex++)
                {
                    for (int typeIndex = 0; typeIndex < m_subZoneElements[subZoneIndex].Length; typeIndex++)
                    {
                        if (Environment.TickCount > m_subZoneTimestamps[(subZoneIndex << 2) | typeIndex])
                        {
                            // it is time to relocate some elements in this subzone
                            // => perform needed relocations of elements
                            startElement = m_subZoneElements[subZoneIndex][typeIndex];

                            lock (startElement)
                            {
                                if (startElement != startElement.next)
                                {
                                    // there are some elements in the list

                                    currentElement = startElement.next;

                                    do
                                    {
                                        if (ShouldElementMove(currentElement, typeIndex, subZoneIndex, inZoneElements, outOfZoneElements))
                                        {
                                            elementToRemove = currentElement;
                                            currentElement = currentElement.next;

                                            elementToRemove.Remove();

                                            if (log.IsDebugEnabled)
                                            {
                                                log.Debug("Zone" + ID + " object " + elementToRemove.data.ObjectID + " removed for subzone");
                                            }
                                        }
                                        else
                                        {
                                            currentElement = currentElement.next;
                                        }
                                    } while (currentElement != startElement);

                                    UnsafeUpdateSubZoneTimestamp(subZoneIndex, typeIndex);
                                }
                            }
                        }
                    }
                }

                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");
                    }
                }
            }
        }
Exemplo n.º 5
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;
        }
Exemplo n.º 6
0
			public ValueEnumerator(Hashtable table) : base(table) { }
Exemplo n.º 7
0
			public KeyEnumerator(Hashtable table) : base(table) { }
Exemplo n.º 8
0
			public DictionaryEntryEnumerator(Hashtable table) {
				this.table = table;
			}
Exemplo n.º 9
0
 public ValueEnumerator(Hashtable table) : base(table)
 {
 }
Exemplo n.º 10
0
 public KeyEnumerator(Hashtable table) : base(table)
 {
 }
Exemplo n.º 11
0
 public DictionaryEntryEnumerator(Hashtable table)
 {
     this.table = table;
 }
Exemplo n.º 12
0
        private bool ShouldElementMove(SubNodeElement currentElement, int typeIndex, int subZoneIndex, DOL.GS.Collections.Hashtable inZoneElements, DOL.GS.Collections.Hashtable outOfZoneElements)
        {
            if (!m_initialized)
            {
                InitializeZone();
            }
            bool       removeElement = true;
            GameObject currentObject = currentElement.data;

            if ((currentObject != null) &&
                (((int)currentObject.ObjectState) == (int)GameObject.eObjectState.Active) &&
                (currentObject.CurrentRegion == ZoneRegion))
            {
                // the current object exists, is Active and still in the Region where this Zone is located

                int currentElementSubzoneIndex = GetSubZoneIndex(currentObject.Position.X, currentObject.Position.Y);

                if (currentElementSubzoneIndex == -1)
                {
                    // the object has moved in another Zone in the same Region

                    ArrayList movedElements = (ArrayList)outOfZoneElements[typeIndex];

                    if (movedElements == null)
                    {
                        movedElements = new ArrayList();
                        outOfZoneElements[typeIndex] = movedElements;
                    }

                    movedElements.Add(currentElement);

                    Interlocked.Decrement(ref m_objectCount);
                }
                else
                {
                    // the object is still inside this Zone

                    if (removeElement = (currentElementSubzoneIndex != subZoneIndex))
                    {
                        // it has changed of subzone
                        SubNodeElement newSubZoneStartElement = m_subZoneElements[currentElementSubzoneIndex][typeIndex];
                        ArrayList      movedElements          = (ArrayList)inZoneElements[newSubZoneStartElement];

                        if (movedElements == null)
                        {
                            movedElements = new ArrayList();
                            inZoneElements[newSubZoneStartElement] = movedElements;
                        }

                        // make it available for relocation
                        movedElements.Add(currentElement);
                    }
                }
            }
            else
            {
                // ghost object
                // => remove it

                Interlocked.Decrement(ref m_objectCount);
            }

            return(removeElement);
        }
Exemplo n.º 13
0
        internal void Relocate(object state)
        {
            if (!m_initialized)
            {
                return;
            }
            if (m_objectCount > 0)
            {
                SubNodeElement startElement   = null;
                SubNodeElement currentElement = null;

                SubNodeElement elementToRemove = null;

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

                for (int subZoneIndex = 0; subZoneIndex < m_subZoneElements.Length; subZoneIndex++)
                {
                    for (int typeIndex = 0; typeIndex < m_subZoneElements[subZoneIndex].Length; typeIndex++)
                    {
                        if (Environment.TickCount > m_subZoneTimestamps[(subZoneIndex << 2) | typeIndex])
                        {
                            // it is time to relocate some elements in this subzone
                            // => perform needed relocations of elements
                            startElement = m_subZoneElements[subZoneIndex][typeIndex];

                            lock (startElement)
                            {
                                if (startElement != startElement.next)
                                {
                                    // there are some elements in the list

                                    currentElement = startElement.next;

                                    do
                                    {
                                        if (ShouldElementMove(currentElement, typeIndex, subZoneIndex, inZoneElements, outOfZoneElements))
                                        {
                                            elementToRemove = currentElement;
                                            currentElement  = currentElement.next;

                                            elementToRemove.Remove();

                                            if (log.IsDebugEnabled)
                                            {
                                                log.Debug("Zone" + ID + " object " + elementToRemove.data.ObjectID + " removed for subzone");
                                            }
                                        }
                                        else
                                        {
                                            currentElement = currentElement.next;
                                        }
                                    } while (currentElement != startElement);

                                    UnsafeUpdateSubZoneTimestamp(subZoneIndex, typeIndex);
                                }
                            }
                        }
                    }
                }


                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");
                    }
                }
            }
        }
Exemplo n.º 14
0
        private void UnsafeAddToListWithoutDistanceCheck(SubNodeElement startElement, int typeIndex, int subZoneIndex, ArrayList partialList, DOL.GS.Collections.Hashtable inZoneElements, DOL.GS.Collections.Hashtable outOfZoneElements)
        {
            SubNodeElement currentElement  = startElement.next;
            SubNodeElement elementToRemove = null;
            GameObject     currentObject   = null;

            do
            {
                currentObject = currentElement.data;
                if (ShouldElementMove(currentElement, typeIndex, subZoneIndex, inZoneElements, outOfZoneElements))
                {
                    elementToRemove = currentElement;
                    currentElement  = currentElement.next;

                    elementToRemove.Remove();

                    if (log.IsDebugEnabled)
                    {
                        log.Debug("Zone" + ID + ": " + ((currentObject != null) ? "object " + currentObject.ObjectID : "ghost object") + " removed for subzone");
                    }
                }
                else
                {
                    // the current object exists, is Active and still in the current subzone
                    // => add it
                    if (!partialList.Contains(currentObject))
                    {
                        partialList.Add(currentObject);
                    }

                    currentElement = currentElement.next;
                }
            } while (currentElement != startElement);
        }
Exemplo n.º 15
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);
        }