/*************************************************************************** * Sector.cs * ------------------- * begin : May 1, 2002 * copyright : (C) The RunUO Software Team * email : info@runuo.com * * $Id$ * ***************************************************************************/ /*************************************************************************** * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * ***************************************************************************/ using System; using System.Collections.Generic; using Server.Items; using Server.Network; namespace Server { public class RegionRect : IComparable { private Rectangle3D m_Rect; public RegionRect(Region region, Rectangle3D rect) { Region = region; m_Rect = rect; } public Region Region{ get; } public Rectangle3D Rect => m_Rect; int IComparable.CompareTo(object obj) { if (obj == null) return 1; if (!(obj is RegionRect regRect)) throw new ArgumentException("obj is not a RegionRect", nameof(obj)); return ((IComparable)Region).CompareTo(regRect.Region); } public bool Contains(Point3D loc) { return m_Rect.Contains(loc); } } public class Sector { // TODO: Can we avoid this? private static List m_DefaultMobileList = new List(); private static List m_DefaultItemList = new List(); private static List m_DefaultClientList = new List(); private static List m_DefaultMultiList = new List(); private static List m_DefaultRectList = new List(); private bool m_Active; private List m_Clients; private List m_Items; private List m_Mobiles; private List m_Multis; private List m_Players; private List m_RegionRects; public Sector(int x, int y, Map owner) { X = x; Y = y; Owner = owner; m_Active = false; } public List RegionRects { get { if (m_RegionRects == null) return m_DefaultRectList; return m_RegionRects; } } public List Multis { get { if (m_Multis == null) return m_DefaultMultiList; return m_Multis; } } public List Mobiles { get { if (m_Mobiles == null) return m_DefaultMobileList; return m_Mobiles; } } public List Items { get { if (m_Items == null) return m_DefaultItemList; return m_Items; } } public List Clients { get { if (m_Clients == null) return m_DefaultClientList; return m_Clients; } } public List Players { get { if (m_Players == null) return m_DefaultMobileList; return m_Players; } } public bool Active => m_Active && Owner != Map.Internal; public Map Owner{ get; } public int X{ get; } public int Y{ get; } private void Add(ref List list, T value) { if (list == null) list = new List(); list.Add(value); } private void Remove(ref List list, T value) { if (list != null) { list.Remove(value); if (list.Count == 0) list = null; } } private void Replace(ref List list, T oldValue, T newValue) { if (oldValue != null && newValue != null) { int index = list?.IndexOf(oldValue) ?? -1; if (index >= 0) list[index] = newValue; else Add(ref list, newValue); } else if (oldValue != null) { Remove(ref list, oldValue); } else if (newValue != null) { Add(ref list, newValue); } } public void OnClientChange(NetState oldState, NetState newState) { Replace(ref m_Clients, oldState, newState); } public void OnEnter(Item item) { Add(ref m_Items, item); } public void OnLeave(Item item) { Remove(ref m_Items, item); } public void OnEnter(Mobile mob) { Add(ref m_Mobiles, mob); if (mob.NetState != null) Add(ref m_Clients, mob.NetState); if (mob.Player) { if (m_Players == null) Owner.ActivateSectors(X, Y); Add(ref m_Players, mob); } } public void OnLeave(Mobile mob) { Remove(ref m_Mobiles, mob); if (mob.NetState != null) Remove(ref m_Clients, mob.NetState); if (mob.Player && m_Players != null) { Remove(ref m_Players, mob); if (m_Players == null) Owner.DeactivateSectors(X, Y); } } public void OnEnter(Region region, Rectangle3D rect) { Add(ref m_RegionRects, new RegionRect(region, rect)); m_RegionRects.Sort(); UpdateMobileRegions(); } public void OnLeave(Region region) { if (m_RegionRects != null) { for (int i = m_RegionRects.Count - 1; i >= 0; i--) { RegionRect regRect = m_RegionRects[i]; if (regRect.Region == region) m_RegionRects.RemoveAt(i); } if (m_RegionRects.Count == 0) m_RegionRects = null; } UpdateMobileRegions(); } private void UpdateMobileRegions() { if (m_Mobiles != null) { List sandbox = new List(m_Mobiles); foreach (Mobile mob in sandbox) mob.UpdateRegion(); } } public void OnMultiEnter(BaseMulti multi) { Add(ref m_Multis, multi); } public void OnMultiLeave(BaseMulti multi) { Remove(ref m_Multis, multi); } public void Activate() { if (!Active && Owner != Map.Internal) { if (m_Items != null) foreach (Item item in m_Items) item.OnSectorActivate(); if (m_Mobiles != null) foreach (Mobile mob in m_Mobiles) mob.OnSectorActivate(); m_Active = true; } } public void Deactivate() { if (Active) { if (m_Items != null) foreach (Item item in m_Items) item.OnSectorDeactivate(); if (m_Mobiles != null) foreach (Mobile mob in m_Mobiles) mob.OnSectorDeactivate(); m_Active = false; } } } }