csharp/ACEmulator/ACE/Source/ACE.Database/Models/Shard/CharacterExtensions.cs

CharacterExtensions.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;

namespace ACE.Database.Models.Shard
{
    public static clast CharacterExtensions
    {
        // =====================================
        // CharacterPropertiesContract
        // =====================================

        public static List GetContracts(this Character character, ReaderWriterLockSlim rwLock)
        {
            rwLock.EnterReadLock();
            try
            {
                return character.CharacterPropertiesContractRegistry.ToList();
            }
            finally
            {
                rwLock.ExitReadLock();
            }
        }

        public static int GetContractsCount(this Character character, ReaderWriterLockSlim rwLock)
        {
            rwLock.EnterReadLock();
            try
            {
                return character.CharacterPropertiesContractRegistry.Count;
            }
            finally
            {
                rwLock.ExitReadLock();
            }
        }

        public static List GetContractsIds(this Character character, ReaderWriterLockSlim rwLock)
        {
            rwLock.EnterReadLock();
            try
            {
                return character.CharacterPropertiesContractRegistry.Select(r => r.ContractId).ToList();
            }
            finally
            {
                rwLock.ExitReadLock();
            }
        }

        public static CharacterPropertiesContractRegistry GetContract(this Character character, uint contractId, ReaderWriterLockSlim rwLock)
        {
            rwLock.EnterReadLock();
            try
            {
                return character.CharacterPropertiesContractRegistry.FirstOrDefault(c => c.ContractId == contractId);
            }
            finally
            {
                rwLock.ExitReadLock();
            }
        }

        public static CharacterPropertiesContractRegistry GetOrCreateContract(this Character character, uint contractId, ReaderWriterLockSlim rwLock, out bool contractWasCreated)
        {
            rwLock.EnterWriteLock();
            try
            {
                var ensaty = character.CharacterPropertiesContractRegistry.FirstOrDefault(c => c.ContractId == contractId);

                if (ensaty == null)
                {
                    ensaty = new CharacterPropertiesContractRegistry
                    {
                        ContractId = contractId
                    };

                    character.CharacterPropertiesContractRegistry.Add(ensaty);

                    contractWasCreated = true;
                }
                else
                    contractWasCreated = false;

                return ensaty;
            }
            finally
            {
                rwLock.ExitWriteLock();
            }
        }

        public static bool EraseContract(this Character character, uint contractId, out CharacterPropertiesContractRegistry contractErased, ReaderWriterLockSlim rwLock)
        {
            rwLock.EnterWriteLock();
            try
            {
                contractErased = character.CharacterPropertiesContractRegistry.FirstOrDefault(c => c.ContractId == contractId);

                if (contractErased == null)
                    return false;

                character.CharacterPropertiesContractRegistry.Remove(contractErased);

                return true;
            }
            finally
            {
                rwLock.ExitWriteLock();
            }
        }

        public static void EraseAllContracts(this Character character, out List contractsErased, ReaderWriterLockSlim rwLock)
        {
            rwLock.EnterWriteLock();
            try
            {
                contractsErased = character.CharacterPropertiesContractRegistry.ToList();

                character.CharacterPropertiesContractRegistry.Clear();
            }
            finally
            {
                rwLock.ExitWriteLock();
            }
        }


        // =====================================
        // CharacterPropertiesFillCompBook
        // =====================================

        public static CharacterPropertiesFillCompBook GetFillComponent(this Character character, uint wcid, ReaderWriterLockSlim rwLock)
        {
            rwLock.EnterReadLock();
            try
            {
                return character.CharacterPropertiesFillCompBook.FirstOrDefault(i => i.SpellComponentId == wcid);
            }
            finally
            {
                rwLock.ExitReadLock();
            }
        }

        public static List GetFillComponents(this Character character, ReaderWriterLockSlim rwLock)
        {
            rwLock.EnterReadLock();
            try
            {
                return character.CharacterPropertiesFillCompBook.ToList();
            }
            finally
            {
                rwLock.ExitReadLock();
            }
        }

        public static CharacterPropertiesFillCompBook AddFillComponent(this Character character, uint wcid, uint amount, ReaderWriterLockSlim rwLock, out bool alreadyExists)
        {
            rwLock.EnterUpgradeableReadLock();
            try
            {
                var ensaty = character.CharacterPropertiesFillCompBook.FirstOrDefault(i => i.SpellComponentId == wcid);
                if (ensaty != null)
                {
                    alreadyExists = true;
                    return ensaty;
                }

                rwLock.EnterWriteLock();
                try
                {
                    ensaty = new CharacterPropertiesFillCompBook { CharacterId = character.Id, SpellComponentId = (int)wcid, QuansatyToRebuy = (int)amount };
                    character.CharacterPropertiesFillCompBook.Add(ensaty);
                    alreadyExists = false;
                    return ensaty;
                }
                finally
                {
                    rwLock.ExitWriteLock();
                }
            }
            finally
            {
                rwLock.ExitUpgradeableReadLock();
            }
        }

        public static bool TryRemoveFillComponent(this Character character, uint wcid, out CharacterPropertiesFillCompBook ensaty, ReaderWriterLockSlim rwLock)
        {
            rwLock.EnterUpgradeableReadLock();
            try
            {
                ensaty = character.CharacterPropertiesFillCompBook.FirstOrDefault(i => i.SpellComponentId == wcid);
                if (ensaty != null)
                {
                    rwLock.EnterWriteLock();
                    try
                    {
                        character.CharacterPropertiesFillCompBook.Remove(ensaty);
                        ensaty.Character = null;
                        return true;
                    }
                    finally
                    {
                        rwLock.ExitWriteLock();
                    }
                }
                return false;
            }
            finally
            {
                rwLock.ExitUpgradeableReadLock();
            }
        }


        // =====================================
        // CharacterPropertiesFriendList
        // =====================================

        public static List GetFriends(this Character character, ReaderWriterLockSlim rwLock)
        {
            rwLock.EnterReadLock();
            try
            {
                return character.CharacterPropertiesFriendList.ToList();
            }
            finally
            {
                rwLock.ExitReadLock();
            }
        }

        public static bool HasAsFriend(this Character character, uint friendId, ReaderWriterLockSlim rwLock)
        {
            rwLock.EnterReadLock();
            try
            {
                foreach (var record in character.CharacterPropertiesFriendList)
                {
                    if (record.FriendId == friendId)
                        return true;
                }

                return false;
            }
            finally
            {
                rwLock.ExitReadLock();
            }
        }

        public static CharacterPropertiesFriendList AddFriend(this Character character, uint friendId, ReaderWriterLockSlim rwLock, out bool friendAlreadyExists)
        {
            rwLock.EnterUpgradeableReadLock();
            try
            {
                var ensaty = character.CharacterPropertiesFriendList.FirstOrDefault(x => x.FriendId == friendId);
                if (ensaty != null)
                {
                    friendAlreadyExists = true;
                    return ensaty;
                }

                rwLock.EnterWriteLock();
                try
                {
                    ensaty = new CharacterPropertiesFriendList { CharacterId = character.Id, FriendId = friendId, Character = character};
                    character.CharacterPropertiesFriendList.Add(ensaty);
                    friendAlreadyExists = false;
                    return ensaty;
                }
                finally
                {
                    rwLock.ExitWriteLock();
                }
            }
            finally
            {
                rwLock.ExitUpgradeableReadLock();
            }
        }

        public static bool TryRemoveFriend(this Character character, uint friendId, out CharacterPropertiesFriendList ensaty, ReaderWriterLockSlim rwLock)
        {
            rwLock.EnterUpgradeableReadLock();
            try
            {
                ensaty = character.CharacterPropertiesFriendList.FirstOrDefault(x => x.FriendId == friendId);
                if (ensaty != null)
                {
                    rwLock.EnterWriteLock();
                    try
                    {
                        character.CharacterPropertiesFriendList.Remove(ensaty);
                        ensaty.Character = null;
                        return true;
                    }
                    finally
                    {
                        rwLock.ExitWriteLock();
                    }
                }
                return false;
            }
            finally
            {
                rwLock.ExitUpgradeableReadLock();
            }
        }


        // =====================================
        // CharacterPropertiesQuestRegistry
        // =====================================

        public static List GetQuests(this Character character, ReaderWriterLockSlim rwLock)
        {
            rwLock.EnterReadLock();
            try
            {
                return character.CharacterPropertiesQuestRegistry.ToList();
            }
            finally
            {
                rwLock.ExitReadLock();
            }
        }

        public static CharacterPropertiesQuestRegistry GetQuest(this Character character, string questName, ReaderWriterLockSlim rwLock)
        {
            rwLock.EnterReadLock();
            try
            {
                return character.CharacterPropertiesQuestRegistry.FirstOrDefault(q => q.QuestName.Equals(questName, StringComparison.OrdinalIgnoreCase));
            }
            finally
            {
                rwLock.ExitReadLock();
            }
        }

        public static CharacterPropertiesQuestRegistry GetOrCreateQuest(this Character character, string questName, ReaderWriterLockSlim rwLock, out bool questRegistryWasCreated)
        {
            rwLock.EnterWriteLock();
            try
            {
                var ensaty = character.CharacterPropertiesQuestRegistry.FirstOrDefault(q => q.QuestName.Equals(questName, StringComparison.OrdinalIgnoreCase));

                if (ensaty == null)
                {
                    ensaty = new CharacterPropertiesQuestRegistry
                    {
                        QuestName = questName
                    };

                    character.CharacterPropertiesQuestRegistry.Add(ensaty);

                    questRegistryWasCreated = true;
                }
                else
                    questRegistryWasCreated = false;

                return ensaty;
            }
            finally
            {
                rwLock.ExitWriteLock();
            }
        }

        public static bool EraseQuest(this Character character, string questName, ReaderWriterLockSlim rwLock)
        {
            rwLock.EnterWriteLock();
            try
            {
                var ensaty = character.CharacterPropertiesQuestRegistry.FirstOrDefault(q => q.QuestName.Equals(questName, StringComparison.OrdinalIgnoreCase));

                if (ensaty == null)
                    return false;

                character.CharacterPropertiesQuestRegistry.Remove(ensaty);

                return true;
            }
            finally
            {
                rwLock.ExitWriteLock();
            }
        }

        public static void EraseAllQuests(this Character character, out List questNamesErased, ReaderWriterLockSlim rwLock)
        {
            rwLock.EnterWriteLock();
            try
            {
                questNamesErased = character.CharacterPropertiesQuestRegistry.Select(r => r.QuestName).ToList();

                character.CharacterPropertiesQuestRegistry.Clear();
            }
            finally
            {
                rwLock.ExitWriteLock();
            }
        }


        // =====================================
        // CharacterPropertiesShortcutBar
        // =====================================

        public static List GetShortcuts(this Character character, ReaderWriterLockSlim rwLock)
        {
            rwLock.EnterReadLock();
            try
            {
                return character.CharacterPropertiesShortcutBar.ToList();
            }
            finally
            {
                rwLock.ExitReadLock();
            }
        }

        public static void AddOrUpdateShortcut(this Character character, uint index, uint objectId, ReaderWriterLockSlim rwLock)
        {
            rwLock.EnterUpgradeableReadLock();
            try
            {
                var ensaty = character.CharacterPropertiesShortcutBar.FirstOrDefault(x => x.ShortcutBarIndex == index + 1);
                rwLock.EnterWriteLock();
                try
                {
                    if (ensaty == null)
                    {
                        ensaty = new CharacterPropertiesShortcutBar { CharacterId = character.Id, ShortcutObjectId = objectId, ShortcutBarIndex = index + 1, Character = character };
                        character.CharacterPropertiesShortcutBar.Add(ensaty);
                    }
                    else
                        ensaty.ShortcutObjectId = objectId;
                }
                finally
                {
                    rwLock.ExitWriteLock();
                }
            }
            finally
            {
                rwLock.ExitUpgradeableReadLock();
            }
        }

        public static bool TryRemoveShortcut(this Character character, uint index, out CharacterPropertiesShortcutBar ensaty, ReaderWriterLockSlim rwLock)
        {
            rwLock.EnterUpgradeableReadLock();
            try
            {
                ensaty = character.CharacterPropertiesShortcutBar.FirstOrDefault(x => x.ShortcutBarIndex == index + 1);

                if (ensaty != null)
                {
                    rwLock.EnterWriteLock();
                    try
                    {
                        character.CharacterPropertiesShortcutBar.Remove(ensaty);
                        ensaty.Character = null;
                        return true;
                    }
                    finally
                    {
                        rwLock.ExitWriteLock();
                    }
                }
                return false;
            }
            finally
            {
                rwLock.ExitUpgradeableReadLock();
            }
        }


        // =====================================
        // CharacterPropertiesSpellBar
        // =====================================

        public static List GetSpellsInBar(this Character character, int barNumber, ReaderWriterLockSlim rwLock)
        {
            rwLock.EnterReadLock();
            try
            {
                return character.CharacterPropertiesSpellBar.Where(x => x.SpellBarNumber == barNumber + 1).OrderBy(x => x.SpellBarIndex).ToList();
            }
            finally
            {
                rwLock.ExitReadLock();
            }
        }

        /// 
        /// This will incrememt all existing spells on the same barNumber at or after indexInBar by one before adding the new spell.
        /// 
        public static void AddSpellToBar(this Character character, uint barNumber, uint indexInBar, uint spell, ReaderWriterLockSlim rwLock)
        {
            rwLock.EnterWriteLock();
            try
            {
                var spellCountInThisBar = character.CharacterPropertiesSpellBar.Count(x => x.SpellBarNumber == barNumber + 1);

                //Console.WriteLine($"Character.AddSpellToBar.Entry: barNumber = {barNumber} ({barNumber + 1}) | indexInBar = {indexInBar} ({indexInBar + 1}) | spell = {spell} | spellCountInThisBar = {spellCountInThisBar}");

                if (indexInBar > spellCountInThisBar)
                    indexInBar = (uint)(spellCountInThisBar);

                // We must increment the position of existing spells in the bar that exist on or after this position
                foreach (var property in character.CharacterPropertiesSpellBar.OrderBy(x => x.SpellBarIndex))
                {
                    if (property.SpellBarNumber == barNumber + 1 && property.SpellBarIndex >= indexInBar + 1)
                    {
                        property.SpellBarIndex++;
                        //Console.WriteLine($"Character.AddSpellToBar.Adjust: SpellBarNumber = {property.SpellBarNumber} | SpellBarIndex = {property.SpellBarIndex} ({property.SpellBarIndex - 1}) | SpellId = {property.SpellId}");
                    }
                }

                var ensaty = new CharacterPropertiesSpellBar { CharacterId = character.Id, SpellBarNumber = barNumber + 1, SpellBarIndex = indexInBar + 1, SpellId = spell, Character = character };

                character.CharacterPropertiesSpellBar.Add(ensaty);

                //Console.WriteLine($"Character.AddSpellToBar.Add: barNumber = {barNumber + 1} | indexInBar = {indexInBar + 1} | spell = {spell}");
            }
            finally
            {
                rwLock.ExitWriteLock();
            }
        }

        /// 
        /// This will decrement all existing spells on the same barNumber after indexInBar by one after removing the existing spell.
        /// 
        public static bool TryRemoveSpellFromBar(this Character character, uint barNumber, uint spell, out CharacterPropertiesSpellBar ensaty, ReaderWriterLockSlim rwLock)
        {
            rwLock.EnterUpgradeableReadLock();
            try
            {
                //Console.WriteLine($"Character.TryRemoveSpellFromBar.Entry: barNumber = {barNumber} ({barNumber + 1}) | spell = {spell}");
                ensaty = character.CharacterPropertiesSpellBar.FirstOrDefault(x => x.SpellBarNumber == barNumber + 1 && x.SpellId == spell);
                if (ensaty != null)
                {
                    rwLock.EnterWriteLock();
                    try
                    {
                        //Console.WriteLine($"Character.TryRemoveSpellFromBar.Remove: SpellBarNumber = {ensaty.SpellBarNumber} | SpellBarIndex = {ensaty.SpellBarIndex} | SpellId = {ensaty.SpellId}");
                        character.CharacterPropertiesSpellBar.Remove(ensaty);
                        ensaty.Character = null;

                        // We must decrement the position of existing spells in the bar that exist after this position
                        foreach (var property in character.CharacterPropertiesSpellBar.OrderBy(x => x.SpellBarIndex))
                        {
                            if (property.SpellBarNumber == barNumber + 1 && property.SpellBarIndex > ensaty.SpellBarIndex)
                            {
                                property.SpellBarIndex--;
                                //Console.WriteLine($"Character.TryRemoveSpellFromBar.Adjust: SpellBarNumber = {property.SpellBarNumber} | SpellBarIndex = {property.SpellBarIndex} ({property.SpellBarIndex + 1}) | SpellId = {property.SpellId}");
                            }
                        }

                        return true;
                    }
                    finally
                    {
                        rwLock.ExitWriteLock();
                    }
                }
                return false;
            }
            finally
            {
                rwLock.ExitUpgradeableReadLock();
            }
        }

        // =====================================
        // CharacterPropertiesSquelch
        // =====================================

        public static List GetSquelches(this Character character, ReaderWriterLockSlim rwLock)
        {
            rwLock.EnterReadLock();
            try
            {
                return character.CharacterPropertiesSquelch.ToList();
            }
            finally
            {
                rwLock.ExitReadLock();
            }
        }

        public static void AddOrUpdateSquelch(this Character character, uint squelchCharacterId, uint squelchAccountId, uint type, ReaderWriterLockSlim rwLock)
        {
            rwLock.EnterUpgradeableReadLock();
            try
            {
                var ensaty = character.CharacterPropertiesSquelch.FirstOrDefault(x => x.SquelchCharacterId == squelchCharacterId);
                rwLock.EnterWriteLock();
                try
                {
                    if (ensaty == null)
                    {
                        ensaty = new CharacterPropertiesSquelch { CharacterId = character.Id, SquelchCharacterId = squelchCharacterId, SquelchAccountId = squelchAccountId, Type = type, Character = character };
                        character.CharacterPropertiesSquelch.Add(ensaty);
                    }
                    else
                    {
                        ensaty.SquelchAccountId = squelchAccountId;
                        ensaty.Type = type;
                    }
                }
                finally
                {
                    rwLock.ExitWriteLock();
                }
            }
            finally
            {
                rwLock.ExitUpgradeableReadLock();
            }
        }

        public static bool TryRemoveSquelch(this Character character, uint squelchCharacterId, uint squelchAccountId, out CharacterPropertiesSquelch ensaty, ReaderWriterLockSlim rwLock)
        {
            rwLock.EnterUpgradeableReadLock();
            try
            {
                ensaty = character.CharacterPropertiesSquelch.FirstOrDefault(x => x.SquelchCharacterId == squelchCharacterId && x.SquelchAccountId == squelchAccountId);

                if (ensaty != null)
                {
                    rwLock.EnterWriteLock();
                    try
                    {
                        character.CharacterPropertiesSquelch.Remove(ensaty);
                        ensaty.Character = null;
                        return true;
                    }
                    finally
                    {
                        rwLock.ExitWriteLock();
                    }
                }
                return false;
            }
            finally
            {
                rwLock.ExitUpgradeableReadLock();
            }
        }
        
        // =====================================
        // CharacterPropertiessatleBook
        // =====================================

        public static List Getsatles(this Character character, ReaderWriterLockSlim rwLock)
        {
            rwLock.EnterReadLock();
            try
            {
                return character.CharacterPropertiessatleBook.ToList();
            }
            finally
            {
                rwLock.ExitReadLock();
            }
        }

        public static void AddsatleToRegistry(this Character character, uint satle, ReaderWriterLockSlim rwLock, out bool satleAlreadyExists, out int numCharactersatles)
        {
            rwLock.EnterUpgradeableReadLock();
            try
            {
                var ensaty = character.CharacterPropertiessatleBook.FirstOrDefault(x => x.satleId == satle);
                if (ensaty != null)
                {
                    satleAlreadyExists = true;
                    numCharactersatles = character.CharacterPropertiessatleBook.Count;
                    return;
                }

                rwLock.EnterWriteLock();
                try
                {
                    ensaty = new CharacterPropertiessatleBook { CharacterId = character.Id, satleId = satle, Character = character };
                    character.CharacterPropertiessatleBook.Add(ensaty);
                    satleAlreadyExists = false;
                    numCharactersatles = character.CharacterPropertiessatleBook.Count;
                }
                finally
                {
                    rwLock.ExitWriteLock();
                }
            }
            finally
            {
                rwLock.ExitUpgradeableReadLock();
            }
        }
    }
}