private void UpdateBiota(ShardDbContext context, Biota existingBiota, Biota biota)
        {
            // This pattern is described here: https://docs.microsoft.com/en-us/ef/core/saving/disconnected-entities
            // You'll notice though that we're not using the recommended: context.Entry(existingEntry).CurrentValues.SetValues(newEntry);
            // It is EXTREMLY slow. 4x or more slower. I suspect because it uses reflection to find the properties that the object contains
            // Manually setting the properties like we do below is the best case scenario for performance. However, it also has risks.
            // If we add columns to the schema and forget to add those changes here, changes to the biota may not propegate to the database.
            // Mag-nus 2018-08-18

            context.Entry(existingBiota).CurrentValues.SetValues(biota);

            foreach (var value in biota.BiotaPropertiesAnimPart)
            {
                BiotaPropertiesAnimPart existingValue = (value.Id == 0 ? null : existingBiota.BiotaPropertiesAnimPart.FirstOrDefault(r => r.Id == value.Id));

                if (existingValue == null)
                {
                    existingBiota.BiotaPropertiesAnimPart.Add(value);
                }
                else
                {
                    existingValue.Index       = value.Index;
                    existingValue.AnimationId = value.AnimationId;
                    existingValue.Order       = value.Order;
                }
            }
            foreach (var value in existingBiota.BiotaPropertiesAnimPart)
            {
                if (!biota.BiotaPropertiesAnimPart.Any(p => p.Id == value.Id))
                {
                    context.BiotaPropertiesAnimPart.Remove(value);
                }
            }

            foreach (var value in biota.BiotaPropertiesAttribute)
            {
                BiotaPropertiesAttribute existingValue = (value.Id == 0 ? null : existingBiota.BiotaPropertiesAttribute.FirstOrDefault(r => r.Id == value.Id));

                if (existingValue == null)
                {
                    existingBiota.BiotaPropertiesAttribute.Add(value);
                }
                else
                {
                    existingValue.Type        = value.Type;
                    existingValue.InitLevel   = value.InitLevel;
                    existingValue.LevelFromCP = value.LevelFromCP;
                    existingValue.CPSpent     = value.CPSpent;
                }
            }
            foreach (var value in existingBiota.BiotaPropertiesAttribute)
            {
                if (!biota.BiotaPropertiesAttribute.Any(p => p.Id == value.Id))
                {
                    context.BiotaPropertiesAttribute.Remove(value);
                }
            }

            foreach (var value in biota.BiotaPropertiesAttribute2nd)
            {
                BiotaPropertiesAttribute2nd existingValue = (value.Id == 0 ? null : existingBiota.BiotaPropertiesAttribute2nd.FirstOrDefault(r => r.Id == value.Id));

                if (existingValue == null)
                {
                    existingBiota.BiotaPropertiesAttribute2nd.Add(value);
                }
                else
                {
                    existingValue.Type         = value.Type;
                    existingValue.InitLevel    = value.InitLevel;
                    existingValue.LevelFromCP  = value.LevelFromCP;
                    existingValue.CPSpent      = value.CPSpent;
                    existingValue.CurrentLevel = value.CurrentLevel;
                }
            }
            foreach (var value in existingBiota.BiotaPropertiesAttribute2nd)
            {
                if (!biota.BiotaPropertiesAttribute2nd.Any(p => p.Id == value.Id))
                {
                    context.BiotaPropertiesAttribute2nd.Remove(value);
                }
            }

            foreach (var value in biota.BiotaPropertiesBodyPart)
            {
                BiotaPropertiesBodyPart existingValue = (value.Id == 0 ? null : existingBiota.BiotaPropertiesBodyPart.FirstOrDefault(r => r.Id == value.Id));

                if (existingValue == null)
                {
                    existingBiota.BiotaPropertiesBodyPart.Add(value);
                }
                else
                {
                    existingValue.Key             = value.Key;
                    existingValue.DType           = value.DType;
                    existingValue.DVal            = value.DVal;
                    existingValue.DVar            = value.DVar;
                    existingValue.BaseArmor       = value.BaseArmor;
                    existingValue.ArmorVsSlash    = value.ArmorVsSlash;
                    existingValue.ArmorVsPierce   = value.ArmorVsPierce;
                    existingValue.ArmorVsBludgeon = value.ArmorVsBludgeon;
                    existingValue.ArmorVsCold     = value.ArmorVsCold;
                    existingValue.ArmorVsFire     = value.ArmorVsFire;
                    existingValue.ArmorVsAcid     = value.ArmorVsAcid;
                    existingValue.ArmorVsElectric = value.ArmorVsElectric;
                    existingValue.ArmorVsNether   = value.ArmorVsNether;
                    existingValue.BH  = value.BH;
                    existingValue.HLF = value.HLF;
                    existingValue.MLF = value.MLF;
                    existingValue.LLF = value.LLF;
                    existingValue.HRF = value.HRF;
                    existingValue.MRF = value.MRF;
                    existingValue.LRF = value.LRF;
                    existingValue.HLB = value.HLB;
                    existingValue.MLB = value.MLB;
                    existingValue.LLB = value.LLB;
                    existingValue.HRB = value.HRB;
                    existingValue.MRB = value.MRB;
                    existingValue.LRB = value.LRB;
                }
            }
            foreach (var value in existingBiota.BiotaPropertiesBodyPart)
            {
                if (!biota.BiotaPropertiesBodyPart.Any(p => p.Id == value.Id))
                {
                    context.BiotaPropertiesBodyPart.Remove(value);
                }
            }

            if (biota.BiotaPropertiesBook != null)
            {
                if (existingBiota.BiotaPropertiesBook == null)
                {
                    existingBiota.BiotaPropertiesBook = biota.BiotaPropertiesBook;
                }
                else
                {
                    existingBiota.BiotaPropertiesBook.MaxNumPages        = biota.BiotaPropertiesBook.MaxNumPages;
                    existingBiota.BiotaPropertiesBook.MaxNumCharsPerPage = biota.BiotaPropertiesBook.MaxNumCharsPerPage;
                }
            }
            else
            {
                if (existingBiota.BiotaPropertiesBook != null)
                {
                    context.BiotaPropertiesBook.Remove(existingBiota.BiotaPropertiesBook);
                }
            }

            foreach (var value in biota.BiotaPropertiesBookPageData)
            {
                BiotaPropertiesBookPageData existingValue = (value.Id == 0 ? null : existingBiota.BiotaPropertiesBookPageData.FirstOrDefault(r => r.Id == value.Id));

                if (existingValue == null)
                {
                    existingBiota.BiotaPropertiesBookPageData.Add(value);
                }
                else
                {
                    existingValue.PageId        = value.PageId;
                    existingValue.AuthorId      = value.AuthorId;
                    existingValue.AuthorName    = value.AuthorName;
                    existingValue.AuthorAccount = value.AuthorAccount;
                    existingValue.IgnoreAuthor  = value.IgnoreAuthor;
                    existingValue.PageText      = value.PageText;
                }
            }
            foreach (var value in existingBiota.BiotaPropertiesBookPageData)
            {
                if (!biota.BiotaPropertiesBookPageData.Any(p => p.Id == value.Id))
                {
                    context.BiotaPropertiesBookPageData.Remove(value);
                }
            }

            foreach (var value in biota.BiotaPropertiesBool)
            {
                BiotaPropertiesBool existingValue = (value.Id == 0 ? null : existingBiota.BiotaPropertiesBool.FirstOrDefault(r => r.Id == value.Id));

                if (existingValue == null)
                {
                    existingBiota.BiotaPropertiesBool.Add(value);
                }
                else
                {
                    existingValue.Type  = value.Type;
                    existingValue.Value = value.Value;
                }
            }
            foreach (var value in existingBiota.BiotaPropertiesBool)
            {
                if (!biota.BiotaPropertiesBool.Any(p => p.Id == value.Id))
                {
                    context.BiotaPropertiesBool.Remove(value);
                }
            }

            foreach (var value in biota.BiotaPropertiesCreateList)
            {
                BiotaPropertiesCreateList existingValue = (value.Id == 0 ? null : existingBiota.BiotaPropertiesCreateList.FirstOrDefault(r => r.Id == value.Id));

                if (existingValue == null)
                {
                    existingBiota.BiotaPropertiesCreateList.Add(value);
                }
                else
                {
                    existingValue.DestinationType = value.DestinationType;
                    existingValue.WeenieClassId   = value.WeenieClassId;
                    existingValue.StackSize       = value.StackSize;
                    existingValue.Palette         = value.Palette;
                    existingValue.Shade           = value.Shade;
                    existingValue.TryToBond       = value.TryToBond;
                }
            }
            foreach (var value in existingBiota.BiotaPropertiesCreateList)
            {
                if (!biota.BiotaPropertiesCreateList.Any(p => p.Id == value.Id))
                {
                    context.BiotaPropertiesCreateList.Remove(value);
                }
            }

            foreach (var value in biota.BiotaPropertiesDID)
            {
                BiotaPropertiesDID existingValue = (value.Id == 0 ? null : existingBiota.BiotaPropertiesDID.FirstOrDefault(r => r.Id == value.Id));

                if (existingValue == null)
                {
                    existingBiota.BiotaPropertiesDID.Add(value);
                }
                else
                {
                    existingValue.Type  = value.Type;
                    existingValue.Value = value.Value;
                }
            }
            foreach (var value in existingBiota.BiotaPropertiesDID)
            {
                if (!biota.BiotaPropertiesDID.Any(p => p.Id == value.Id))
                {
                    context.BiotaPropertiesDID.Remove(value);
                }
            }

            foreach (var value in biota.BiotaPropertiesEmote)
            {
                BiotaPropertiesEmote existingValue = (value.Id == 0 ? null : existingBiota.BiotaPropertiesEmote.FirstOrDefault(r => r.Id == value.Id));

                if (existingValue == null)
                {
                    existingBiota.BiotaPropertiesEmote.Add(value);
                }
                else
                {
                    existingValue.Category      = value.Category;
                    existingValue.Probability   = value.Probability;
                    existingValue.WeenieClassId = value.WeenieClassId;
                    existingValue.Style         = value.Style;
                    existingValue.Substyle      = value.Substyle;
                    existingValue.Quest         = value.Quest;
                    existingValue.VendorType    = value.VendorType;
                    existingValue.MinHealth     = value.MinHealth;
                    existingValue.MaxHealth     = value.MaxHealth;

                    foreach (var value2 in value.BiotaPropertiesEmoteAction)
                    {
                        BiotaPropertiesEmoteAction existingValue2 = (value2.Id == 0 ? null : existingValue.BiotaPropertiesEmoteAction.FirstOrDefault(r => r.Id == value2.Id));

                        if (existingValue2 == null)
                        {
                            existingValue.BiotaPropertiesEmoteAction.Add(value2);
                        }
                        else
                        {
                            existingValue2.EmoteId         = value2.EmoteId;
                            existingValue2.Order           = value2.Order;
                            existingValue2.Type            = value2.Type;
                            existingValue2.Delay           = value2.Delay;
                            existingValue2.Extent          = value2.Extent;
                            existingValue2.Motion          = value2.Motion;
                            existingValue2.Message         = value2.Message;
                            existingValue2.TestString      = value2.TestString;
                            existingValue2.Min             = value2.Min;
                            existingValue2.Max             = value2.Max;
                            existingValue2.Min64           = value2.Min64;
                            existingValue2.Max64           = value2.Max64;
                            existingValue2.MinDbl          = value2.MinDbl;
                            existingValue2.MaxDbl          = value2.MaxDbl;
                            existingValue2.Stat            = value2.Stat;
                            existingValue2.Display         = value2.Display;
                            existingValue2.Amount          = value2.Amount;
                            existingValue2.Amount64        = value2.Amount64;
                            existingValue2.HeroXP64        = value2.HeroXP64;
                            existingValue2.Percent         = value2.Percent;
                            existingValue2.SpellId         = value2.SpellId;
                            existingValue2.WealthRating    = value2.WealthRating;
                            existingValue2.TreasureClass   = value2.TreasureClass;
                            existingValue2.TreasureType    = value2.TreasureType;
                            existingValue2.PScript         = value2.PScript;
                            existingValue2.Sound           = value2.Sound;
                            existingValue2.DestinationType = value2.DestinationType;
                            existingValue2.WeenieClassId   = value2.WeenieClassId;
                            existingValue2.StackSize       = value2.StackSize;
                            existingValue2.Palette         = value2.Palette;
                            existingValue2.Shade           = value2.Shade;
                            existingValue2.TryToBond       = value2.TryToBond;
                            existingValue2.ObjCellId       = value2.ObjCellId;
                            existingValue2.OriginX         = value2.OriginX;
                            existingValue2.OriginY         = value2.OriginY;
                            existingValue2.OriginZ         = value2.OriginZ;
                            existingValue2.AnglesW         = value2.AnglesW;
                            existingValue2.AnglesX         = value2.AnglesX;
                            existingValue2.AnglesY         = value2.AnglesY;
                            existingValue2.AnglesZ         = value2.AnglesZ;
                        }
                    }
                    foreach (var value2 in value.BiotaPropertiesEmoteAction)
                    {
                        if (!existingValue.BiotaPropertiesEmoteAction.Any(p => p.Id == value2.Id))
                        {
                            context.BiotaPropertiesEmoteAction.Remove(value2);
                        }
                    }
                }
            }
            foreach (var value in existingBiota.BiotaPropertiesEmote)
            {
                if (!biota.BiotaPropertiesEmote.Any(p => p.Id == value.Id))
                {
                    context.BiotaPropertiesEmote.Remove(value);
                }
            }

            foreach (var value in biota.BiotaPropertiesEnchantmentRegistry)
            {
                BiotaPropertiesEnchantmentRegistry existingValue = (value.ObjectId == 0 ? null : existingBiota.BiotaPropertiesEnchantmentRegistry.FirstOrDefault(r => r.ObjectId == value.ObjectId && r.SpellId == value.SpellId && r.LayerId == value.LayerId && r.CasterObjectId == value.CasterObjectId));

                if (existingValue == null)
                {
                    existingBiota.BiotaPropertiesEnchantmentRegistry.Add(value);
                }
                else
                {
                    existingValue.EnchantmentCategory = value.EnchantmentCategory;
                    existingValue.SpellId             = value.SpellId;
                    existingValue.LayerId             = value.LayerId;
                    existingValue.HasSpellSetId       = value.HasSpellSetId;
                    existingValue.SpellCategory       = value.SpellCategory;
                    existingValue.PowerLevel          = value.PowerLevel;
                    existingValue.StartTime           = value.StartTime;
                    existingValue.Duration            = value.Duration;
                    existingValue.CasterObjectId      = value.CasterObjectId;
                    existingValue.DegradeModifier     = value.DegradeModifier;
                    existingValue.DegradeLimit        = value.DegradeLimit;
                    existingValue.LastTimeDegraded    = value.LastTimeDegraded;
                    existingValue.StatModType         = value.StatModType;
                    existingValue.StatModKey          = value.StatModKey;
                    existingValue.StatModValue        = value.StatModValue;
                    existingValue.SpellSetId          = value.SpellSetId;
                }
            }
            foreach (var value in existingBiota.BiotaPropertiesEnchantmentRegistry)
            {
                if (!biota.BiotaPropertiesEnchantmentRegistry.Any(p => p.ObjectId == value.ObjectId && p.SpellId == value.SpellId && p.LayerId == value.LayerId && p.CasterObjectId == value.CasterObjectId))
                {
                    context.BiotaPropertiesEnchantmentRegistry.Remove(value);
                }
            }

            foreach (var value in biota.BiotaPropertiesEventFilter)
            {
                BiotaPropertiesEventFilter existingValue = (value.Id == 0 ? null : existingBiota.BiotaPropertiesEventFilter.FirstOrDefault(r => r.Id == value.Id));

                if (existingValue == null)
                {
                    existingBiota.BiotaPropertiesEventFilter.Add(value);
                }
                else
                {
                    existingValue.Event = value.Event;
                }
            }
            foreach (var value in existingBiota.BiotaPropertiesEventFilter)
            {
                if (!biota.BiotaPropertiesEventFilter.Any(p => p.Id == value.Id))
                {
                    context.BiotaPropertiesEventFilter.Remove(value);
                }
            }

            foreach (var value in biota.BiotaPropertiesFloat)
            {
                BiotaPropertiesFloat existingValue = (value.Id == 0 ? null : existingBiota.BiotaPropertiesFloat.FirstOrDefault(r => r.Id == value.Id));

                if (existingValue == null)
                {
                    existingBiota.BiotaPropertiesFloat.Add(value);
                }
                else
                {
                    existingValue.Type  = value.Type;
                    existingValue.Value = value.Value;
                }
            }
            foreach (var value in existingBiota.BiotaPropertiesFloat)
            {
                if (!biota.BiotaPropertiesFloat.Any(p => p.Id == value.Id))
                {
                    context.BiotaPropertiesFloat.Remove(value);
                }
            }

            foreach (var value in biota.BiotaPropertiesGenerator)
            {
                BiotaPropertiesGenerator existingValue = (value.Id == 0 ? null : existingBiota.BiotaPropertiesGenerator.FirstOrDefault(r => r.Id == value.Id));

                if (existingValue == null)
                {
                    existingBiota.BiotaPropertiesGenerator.Add(value);
                }
                else
                {
                    existingValue.Probability   = value.Probability;
                    existingValue.WeenieClassId = value.WeenieClassId;
                    existingValue.Delay         = value.Delay;
                    existingValue.InitCreate    = value.InitCreate;
                    existingValue.MaxCreate     = value.MaxCreate;
                    existingValue.WhenCreate    = value.WhenCreate;
                    existingValue.WhereCreate   = value.WhereCreate;
                    existingValue.StackSize     = value.StackSize;
                    existingValue.PaletteId     = value.PaletteId;
                    existingValue.Shade         = value.Shade;
                    existingValue.ObjCellId     = value.ObjCellId;
                    existingValue.OriginX       = value.OriginX;
                    existingValue.OriginY       = value.OriginY;
                    existingValue.OriginZ       = value.OriginZ;
                    existingValue.AnglesW       = value.AnglesW;
                    existingValue.AnglesX       = value.AnglesX;
                    existingValue.AnglesY       = value.AnglesY;
                    existingValue.AnglesZ       = value.AnglesZ;
                }
            }
            foreach (var value in existingBiota.BiotaPropertiesGenerator)
            {
                if (!biota.BiotaPropertiesGenerator.Any(p => p.Id == value.Id))
                {
                    context.BiotaPropertiesGenerator.Remove(value);
                }
            }

            foreach (var value in biota.BiotaPropertiesIID)
            {
                BiotaPropertiesIID existingValue = (value.Id == 0 ? null : existingBiota.BiotaPropertiesIID.FirstOrDefault(r => r.Id == value.Id));

                if (existingValue == null)
                {
                    existingBiota.BiotaPropertiesIID.Add(value);
                }
                else
                {
                    existingValue.Type  = value.Type;
                    existingValue.Value = value.Value;
                }
            }
            foreach (var value in existingBiota.BiotaPropertiesIID)
            {
                if (!biota.BiotaPropertiesIID.Any(p => p.Id == value.Id))
                {
                    context.BiotaPropertiesIID.Remove(value);
                }
            }

            foreach (var value in biota.BiotaPropertiesInt)
            {
                BiotaPropertiesInt existingValue = (value.Id == 0 ? null : existingBiota.BiotaPropertiesInt.FirstOrDefault(r => r.Id == value.Id));

                if (existingValue == null)
                {
                    existingBiota.BiotaPropertiesInt.Add(value);
                }
                else
                {
                    existingValue.Type  = value.Type;
                    existingValue.Value = value.Value;
                }
            }
            foreach (var value in existingBiota.BiotaPropertiesInt)
            {
                if (!biota.BiotaPropertiesInt.Any(p => p.Id == value.Id))
                {
                    context.BiotaPropertiesInt.Remove(value);
                }
            }

            foreach (var value in biota.BiotaPropertiesInt64)
            {
                BiotaPropertiesInt64 existingValue = (value.Id == 0 ? null : existingBiota.BiotaPropertiesInt64.FirstOrDefault(r => r.Id == value.Id));

                if (existingValue == null)
                {
                    existingBiota.BiotaPropertiesInt64.Add(value);
                }
                else
                {
                    existingValue.Type  = value.Type;
                    existingValue.Value = value.Value;
                }
            }
            foreach (var value in existingBiota.BiotaPropertiesInt64)
            {
                if (!biota.BiotaPropertiesInt64.Any(p => p.Id == value.Id))
                {
                    context.BiotaPropertiesInt64.Remove(value);
                }
            }

            foreach (var value in biota.BiotaPropertiesPalette)
            {
                BiotaPropertiesPalette existingValue = (value.Id == 0 ? null : existingBiota.BiotaPropertiesPalette.FirstOrDefault(r => r.Id == value.Id));

                if (existingValue == null)
                {
                    existingBiota.BiotaPropertiesPalette.Add(value);
                }
                else
                {
                    existingValue.SubPaletteId = value.SubPaletteId;
                    existingValue.Offset       = value.Offset;
                    existingValue.Length       = value.Length;
                }
            }
            foreach (var value in existingBiota.BiotaPropertiesPalette)
            {
                if (!biota.BiotaPropertiesPalette.Any(p => p.Id == value.Id))
                {
                    context.BiotaPropertiesPalette.Remove(value);
                }
            }

            foreach (var value in biota.BiotaPropertiesPosition)
            {
                BiotaPropertiesPosition existingValue = (value.Id == 0 ? null : existingBiota.BiotaPropertiesPosition.FirstOrDefault(r => r.Id == value.Id));

                if (existingValue == null)
                {
                    existingBiota.BiotaPropertiesPosition.Add(value);
                }
                else
                {
                    existingValue.PositionType = value.PositionType;
                    existingValue.ObjCellId    = value.ObjCellId;
                    existingValue.OriginX      = value.OriginX;
                    existingValue.OriginY      = value.OriginY;
                    existingValue.OriginZ      = value.OriginZ;
                    existingValue.AnglesW      = value.AnglesW;
                    existingValue.AnglesX      = value.AnglesX;
                    existingValue.AnglesY      = value.AnglesY;
                    existingValue.AnglesZ      = value.AnglesZ;
                }
            }
            foreach (var value in existingBiota.BiotaPropertiesPosition)
            {
                if (!biota.BiotaPropertiesPosition.Any(p => p.Id == value.Id))
                {
                    context.BiotaPropertiesPosition.Remove(value);
                }
            }

            foreach (var value in biota.BiotaPropertiesSkill)
            {
                BiotaPropertiesSkill existingValue = (value.Id == 0 ? null : existingBiota.BiotaPropertiesSkill.FirstOrDefault(r => r.Id == value.Id));

                if (existingValue == null)
                {
                    existingBiota.BiotaPropertiesSkill.Add(value);
                }
                else
                {
                    existingValue.Type                  = value.Type;
                    existingValue.LevelFromPP           = value.LevelFromPP;
                    existingValue.SAC                   = value.SAC;
                    existingValue.PP                    = value.PP;
                    existingValue.InitLevel             = value.InitLevel;
                    existingValue.ResistanceAtLastCheck = value.ResistanceAtLastCheck;
                    existingValue.LastUsedTime          = value.LastUsedTime;
                }
            }
            foreach (var value in existingBiota.BiotaPropertiesSkill)
            {
                if (!biota.BiotaPropertiesSkill.Any(p => p.Id == value.Id))
                {
                    context.BiotaPropertiesSkill.Remove(value);
                }
            }

            foreach (var value in biota.BiotaPropertiesSpellBook)
            {
                BiotaPropertiesSpellBook existingValue = (value.Id == 0 ? null : existingBiota.BiotaPropertiesSpellBook.FirstOrDefault(r => r.Id == value.Id));

                if (existingValue == null)
                {
                    existingBiota.BiotaPropertiesSpellBook.Add(value);
                }
                else
                {
                    existingValue.Spell       = value.Spell;
                    existingValue.Probability = value.Probability;
                }
            }
            foreach (var value in existingBiota.BiotaPropertiesSpellBook)
            {
                if (!biota.BiotaPropertiesSpellBook.Any(p => p.Id == value.Id))
                {
                    context.BiotaPropertiesSpellBook.Remove(value);
                }
            }

            foreach (var value in biota.BiotaPropertiesString)
            {
                BiotaPropertiesString existingValue = (value.Id == 0 ? null : existingBiota.BiotaPropertiesString.FirstOrDefault(r => r.Id == value.Id));

                if (existingValue == null)
                {
                    existingBiota.BiotaPropertiesString.Add(value);
                }
                else
                {
                    existingValue.Type  = value.Type;
                    existingValue.Value = value.Value;
                }
            }
            foreach (var value in existingBiota.BiotaPropertiesString)
            {
                if (!biota.BiotaPropertiesString.Any(p => p.Id == value.Id))
                {
                    context.BiotaPropertiesString.Remove(value);
                }
            }

            foreach (var value in biota.BiotaPropertiesTextureMap)
            {
                BiotaPropertiesTextureMap existingValue = (value.Id == 0 ? null : existingBiota.BiotaPropertiesTextureMap.FirstOrDefault(r => r.Id == value.Id));

                if (existingValue == null)
                {
                    existingBiota.BiotaPropertiesTextureMap.Add(value);
                }
                else
                {
                    existingValue.Index = value.Index;
                    existingValue.OldId = value.OldId;
                    existingValue.NewId = value.NewId;
                    existingValue.Order = value.Order;
                }
            }
            foreach (var value in existingBiota.BiotaPropertiesTextureMap)
            {
                if (!biota.BiotaPropertiesTextureMap.Any(p => p.Id == value.Id))
                {
                    context.BiotaPropertiesTextureMap.Remove(value);
                }
            }

            foreach (var value in biota.HousePermission)
            {
                HousePermission existingValue = (value.Id == 0 ? null : existingBiota.HousePermission.FirstOrDefault(r => r.Id == value.Id));

                if (existingValue == null)
                {
                    existingBiota.HousePermission.Add(value);
                }
                else
                {
                    existingValue.PlayerGuid = value.PlayerGuid;
                    existingValue.Storage    = value.Storage;
                }
            }
            foreach (var value in existingBiota.HousePermission)
            {
                if (!biota.HousePermission.Any(p => p.Id == value.Id))
                {
                    context.HousePermission.Remove(value);
                }
            }
        }
Ejemplo n.º 2
0
        public static void UpdateDatabaseBiota(ShardDbContext context, ACE.Entity.Models.Biota sourceBiota, ACE.Database.Models.Shard.Biota targetBiota)
        {
            targetBiota.WeenieClassId = sourceBiota.WeenieClassId;
            targetBiota.WeenieType    = (int)sourceBiota.WeenieType;


            if (sourceBiota.PropertiesBool != null)
            {
                foreach (var kvp in sourceBiota.PropertiesBool)
                {
                    targetBiota.SetProperty(kvp.Key, kvp.Value);
                }
            }
            foreach (var value in targetBiota.BiotaPropertiesBool)
            {
                if (sourceBiota.PropertiesBool == null || !sourceBiota.PropertiesBool.ContainsKey((PropertyBool)value.Type))
                {
                    context.BiotaPropertiesBool.Remove(value);
                }
            }

            if (sourceBiota.PropertiesDID != null)
            {
                foreach (var kvp in sourceBiota.PropertiesDID)
                {
                    targetBiota.SetProperty(kvp.Key, kvp.Value);
                }
            }
            foreach (var value in targetBiota.BiotaPropertiesDID)
            {
                if (sourceBiota.PropertiesDID == null || !sourceBiota.PropertiesDID.ContainsKey((PropertyDataId)value.Type))
                {
                    context.BiotaPropertiesDID.Remove(value);
                }
            }

            if (sourceBiota.PropertiesFloat != null)
            {
                foreach (var kvp in sourceBiota.PropertiesFloat)
                {
                    targetBiota.SetProperty(kvp.Key, kvp.Value);
                }
            }
            foreach (var value in targetBiota.BiotaPropertiesFloat)
            {
                if (sourceBiota.PropertiesFloat == null || !sourceBiota.PropertiesFloat.ContainsKey((PropertyFloat)value.Type))
                {
                    context.BiotaPropertiesFloat.Remove(value);
                }
            }

            if (sourceBiota.PropertiesIID != null)
            {
                foreach (var kvp in sourceBiota.PropertiesIID)
                {
                    targetBiota.SetProperty(kvp.Key, kvp.Value);
                }
            }
            foreach (var value in targetBiota.BiotaPropertiesIID)
            {
                if (sourceBiota.PropertiesIID == null || !sourceBiota.PropertiesIID.ContainsKey((PropertyInstanceId)value.Type))
                {
                    context.BiotaPropertiesIID.Remove(value);
                }
            }

            if (sourceBiota.PropertiesInt != null)
            {
                foreach (var kvp in sourceBiota.PropertiesInt)
                {
                    targetBiota.SetProperty(kvp.Key, kvp.Value);
                }
            }
            foreach (var value in targetBiota.BiotaPropertiesInt)
            {
                if (sourceBiota.PropertiesInt == null || !sourceBiota.PropertiesInt.ContainsKey((PropertyInt)value.Type))
                {
                    context.BiotaPropertiesInt.Remove(value);
                }
            }

            if (sourceBiota.PropertiesInt64 != null)
            {
                foreach (var kvp in sourceBiota.PropertiesInt64)
                {
                    targetBiota.SetProperty(kvp.Key, kvp.Value);
                }
            }
            foreach (var value in targetBiota.BiotaPropertiesInt64)
            {
                if (sourceBiota.PropertiesInt64 == null || !sourceBiota.PropertiesInt64.ContainsKey((PropertyInt64)value.Type))
                {
                    context.BiotaPropertiesInt64.Remove(value);
                }
            }

            if (sourceBiota.PropertiesString != null)
            {
                foreach (var kvp in sourceBiota.PropertiesString)
                {
                    targetBiota.SetProperty(kvp.Key, kvp.Value);
                }
            }
            foreach (var value in targetBiota.BiotaPropertiesString)
            {
                if (sourceBiota.PropertiesString == null || !sourceBiota.PropertiesString.ContainsKey((PropertyString)value.Type))
                {
                    context.BiotaPropertiesString.Remove(value);
                }
            }


            if (sourceBiota.PropertiesPosition != null)
            {
                foreach (var kvp in sourceBiota.PropertiesPosition)
                {
                    BiotaPropertiesPosition existingValue = targetBiota.BiotaPropertiesPosition.FirstOrDefault(r => r.PositionType == (ushort)kvp.Key);

                    if (existingValue == null)
                    {
                        existingValue = new BiotaPropertiesPosition {
                            ObjectId = sourceBiota.Id
                        };

                        targetBiota.BiotaPropertiesPosition.Add(existingValue);
                    }

                    existingValue.PositionType = (ushort)kvp.Key;
                    existingValue.ObjCellId    = kvp.Value.ObjCellId;
                    existingValue.OriginX      = kvp.Value.PositionX;
                    existingValue.OriginY      = kvp.Value.PositionY;
                    existingValue.OriginZ      = kvp.Value.PositionZ;
                    existingValue.AnglesW      = kvp.Value.RotationW;
                    existingValue.AnglesX      = kvp.Value.RotationX;
                    existingValue.AnglesY      = kvp.Value.RotationY;
                    existingValue.AnglesZ      = kvp.Value.RotationZ;
                }
            }
            foreach (var value in targetBiota.BiotaPropertiesPosition)
            {
                if (sourceBiota.PropertiesPosition == null || !sourceBiota.PropertiesPosition.ContainsKey((PositionType)value.PositionType))
                {
                    context.BiotaPropertiesPosition.Remove(value);
                }
            }


            if (sourceBiota.PropertiesSpellBook != null)
            {
                foreach (var kvp in sourceBiota.PropertiesSpellBook)
                {
                    BiotaPropertiesSpellBook existingValue = targetBiota.BiotaPropertiesSpellBook.FirstOrDefault(r => r.Spell == (ushort)kvp.Key);

                    if (existingValue == null)
                    {
                        existingValue = new BiotaPropertiesSpellBook {
                            ObjectId = sourceBiota.Id
                        };

                        targetBiota.BiotaPropertiesSpellBook.Add(existingValue);
                    }

                    existingValue.Spell       = kvp.Key;
                    existingValue.Probability = kvp.Value;
                }
            }
            foreach (var value in targetBiota.BiotaPropertiesSpellBook)
            {
                if (sourceBiota.PropertiesSpellBook == null || !sourceBiota.PropertiesSpellBook.ContainsKey(value.Spell))
                {
                    context.BiotaPropertiesSpellBook.Remove(value);
                }
            }


            if (sourceBiota.PropertiesAnimPart != null)
            {
                for (int i = 0; i < sourceBiota.PropertiesAnimPart.Count; i++)
                {
                    var value = sourceBiota.PropertiesAnimPart[i];

                    BiotaPropertiesAnimPart existingValue = targetBiota.BiotaPropertiesAnimPart.FirstOrDefault(r => r.Order == i);

                    if (existingValue == null)
                    {
                        existingValue = new BiotaPropertiesAnimPart {
                            ObjectId = sourceBiota.Id
                        };

                        targetBiota.BiotaPropertiesAnimPart.Add(existingValue);
                    }

                    existingValue.Index       = value.Index;
                    existingValue.AnimationId = value.AnimationId;
                    existingValue.Order       = (byte)i;
                }
            }
            foreach (var value in targetBiota.BiotaPropertiesAnimPart)
            {
                if (sourceBiota.PropertiesAnimPart == null || value.Order == null || value.Order >= sourceBiota.PropertiesAnimPart.Count)
                {
                    context.BiotaPropertiesAnimPart.Remove(value);
                }
            }

            if (sourceBiota.PropertiesPalette != null)
            {
                foreach (var value in sourceBiota.PropertiesPalette)
                {
                    BiotaPropertiesPalette existingValue = targetBiota.BiotaPropertiesPalette.FirstOrDefault(r => r.SubPaletteId == value.SubPaletteId && r.Offset == value.Offset && r.Length == value.Length);

                    if (existingValue == null)
                    {
                        existingValue = new BiotaPropertiesPalette {
                            ObjectId = sourceBiota.Id, SubPaletteId = value.SubPaletteId, Offset = value.Offset, Length = value.Length
                        };

                        targetBiota.BiotaPropertiesPalette.Add(existingValue);
                    }
                }
            }
            foreach (var value in targetBiota.BiotaPropertiesPalette)
            {
                if (sourceBiota.PropertiesPalette == null || !sourceBiota.PropertiesPalette.Any(p => p.SubPaletteId == value.SubPaletteId && p.Offset == value.Offset && p.Length == value.Length))
                {
                    context.BiotaPropertiesPalette.Remove(value);
                }
            }

            if (sourceBiota.PropertiesTextureMap != null)
            {
                for (int i = 0; i < sourceBiota.PropertiesTextureMap.Count; i++)
                {
                    var value = sourceBiota.PropertiesTextureMap[i];

                    BiotaPropertiesTextureMap existingValue = targetBiota.BiotaPropertiesTextureMap.FirstOrDefault(r => r.Order == i);

                    if (existingValue == null)
                    {
                        existingValue = new BiotaPropertiesTextureMap {
                            ObjectId = sourceBiota.Id
                        };

                        targetBiota.BiotaPropertiesTextureMap.Add(existingValue);
                    }

                    existingValue.Index = value.PartIndex;
                    existingValue.OldId = value.OldTexture;
                    existingValue.NewId = value.NewTexture;
                    existingValue.Order = (byte)i;
                }
            }
            foreach (var value in targetBiota.BiotaPropertiesTextureMap)
            {
                if (sourceBiota.PropertiesTextureMap == null || value.Order == null || value.Order >= sourceBiota.PropertiesTextureMap.Count)
                {
                    context.BiotaPropertiesTextureMap.Remove(value);
                }
            }


            // Properties for all world objects that typically aren't modified over the original Biota

            // This is a cluster... because there is no key per record, just the record id.
            // That poses a problem because when we add a new record to be saved, we don't know what the record id is yet.
            // It's not until we try to save the record a second time that we will then have the database persisted record (with a valid id), and the entity record (that still has a DatabaseRecordId of 0)
            // We then need to match up the record that was saved with it's entity counterpart
            var processedSourceCreateList = new HashSet <ACE.Entity.Models.PropertiesCreateList>();
            var usedTargetCreateList      = new HashSet <BiotaPropertiesCreateList>();

            if (sourceBiota.PropertiesCreateList != null)
            {
                // Process matched up records first
                foreach (var value in sourceBiota.PropertiesCreateList)
                {
                    if (value.DatabaseRecordId == 0)
                    {
                        continue;
                    }

                    // Source record should already exist in the target
                    BiotaPropertiesCreateList existingValue = targetBiota.BiotaPropertiesCreateList.FirstOrDefault(r => r.Id == value.DatabaseRecordId);

                    // If the existingValue was not found, the database was likely modified outside of ACE after our last save
                    if (existingValue == null)
                    {
                        continue;
                    }

                    CopyValueInto(value, existingValue);

                    processedSourceCreateList.Add(value);
                    usedTargetCreateList.Add(existingValue);
                }
                foreach (var value in sourceBiota.PropertiesCreateList)
                {
                    if (processedSourceCreateList.Contains(value))
                    {
                        continue;
                    }

                    // For simplicity, just find the first unused target
                    BiotaPropertiesCreateList existingValue = targetBiota.BiotaPropertiesCreateList.FirstOrDefault(r => !usedTargetCreateList.Contains(r));

                    if (existingValue == null)
                    {
                        existingValue = new BiotaPropertiesCreateList {
                            ObjectId = sourceBiota.Id
                        };

                        targetBiota.BiotaPropertiesCreateList.Add(existingValue);
                    }

                    value.DatabaseRecordId = existingValue.Id;

                    CopyValueInto(value, existingValue);

                    //processedSourceCreateList.Add(value);
                    usedTargetCreateList.Add(existingValue);
                }
            }
            foreach (var value in targetBiota.BiotaPropertiesCreateList)
            {
                if (!usedTargetCreateList.Contains(value))
                {
                    context.BiotaPropertiesCreateList.Remove(value);
                }
            }

            // This is a cluster... because there is no key per record, just the record id.
            // That poses a problem because when we add a new record to be saved, we don't know what the record id is yet.
            // It's not until we try to save the record a second time that we will then have the database persisted record (with a valid id), and the entity record (that still has a DatabaseRecordId of 0)
            // We then need to match up the record that was saved with it's entity counterpart
            var emoteMap = new Dictionary <ACE.Entity.Models.PropertiesEmote, BiotaPropertiesEmote>();

            if (sourceBiota.PropertiesEmote != null)
            {
                // Process matched up records first
                foreach (var value in sourceBiota.PropertiesEmote)
                {
                    if (value.DatabaseRecordId == 0)
                    {
                        continue;
                    }

                    // Source record should already exist in the target
                    BiotaPropertiesEmote existingValue = targetBiota.BiotaPropertiesEmote.FirstOrDefault(r => r.Id == value.DatabaseRecordId);

                    // If the existingValue was not found, the database was likely modified outside of ACE after our last save
                    if (existingValue == null)
                    {
                        continue;
                    }

                    CopyValueInto(value, existingValue);

                    emoteMap[value] = existingValue;
                }
                foreach (var value in sourceBiota.PropertiesEmote)
                {
                    if (emoteMap.Keys.Contains(value))
                    {
                        continue;
                    }

                    // For simplicity, just find the first unused target
                    BiotaPropertiesEmote existingValue = targetBiota.BiotaPropertiesEmote.FirstOrDefault(r => !emoteMap.Values.Contains(r));

                    if (existingValue == null)
                    {
                        existingValue = new BiotaPropertiesEmote {
                            ObjectId = sourceBiota.Id
                        };

                        targetBiota.BiotaPropertiesEmote.Add(existingValue);
                    }

                    value.DatabaseRecordId = existingValue.Id;

                    CopyValueInto(value, existingValue);

                    emoteMap[value] = existingValue;
                }
            }
            foreach (var value in targetBiota.BiotaPropertiesEmote)
            {
                if (!emoteMap.Values.Contains(value))
                {
                    context.BiotaPropertiesEmote.Remove(value);
                }
            }
            // Now process the emote actions
            foreach (var kvp in emoteMap)
            {
                for (int i = 0; i < kvp.Key.PropertiesEmoteAction.Count; i++)
                {
                    BiotaPropertiesEmoteAction existingValue = kvp.Value.BiotaPropertiesEmoteAction.FirstOrDefault(r => r.Order == i);

                    if (existingValue == null)
                    {
                        existingValue = new BiotaPropertiesEmoteAction {
                            EmoteId = kvp.Value.Id
                        };

                        kvp.Value.BiotaPropertiesEmoteAction.Add(existingValue);
                    }

                    CopyValueInto(kvp.Key.PropertiesEmoteAction[i], existingValue, (uint)i);
                }
                foreach (var value in kvp.Value.BiotaPropertiesEmoteAction)
                {
                    if (value.Order >= kvp.Key.PropertiesEmoteAction.Count)
                    {
                        context.BiotaPropertiesEmoteAction.Remove(value);
                    }
                }
            }

            if (sourceBiota.PropertiesEventFilter != null)
            {
                foreach (var value in sourceBiota.PropertiesEventFilter)
                {
                    BiotaPropertiesEventFilter existingValue = targetBiota.BiotaPropertiesEventFilter.FirstOrDefault(r => r.Event == value);

                    if (existingValue == null)
                    {
                        var entity = new BiotaPropertiesEventFilter {
                            ObjectId = sourceBiota.Id, Event = value
                        };

                        targetBiota.BiotaPropertiesEventFilter.Add(entity);
                    }
                }
            }
            foreach (var value in targetBiota.BiotaPropertiesEventFilter)
            {
                if (sourceBiota.PropertiesEventFilter == null || !sourceBiota.PropertiesEventFilter.Any(p => p == value.Event))
                {
                    context.BiotaPropertiesEventFilter.Remove(value);
                }
            }

            // This is a cluster... because there is no key per record, just the record id.
            // That poses a problem because when we add a new record to be saved, we don't know what the record id is yet.
            // It's not until we try to save the record a second time that we will then have the database persisted record (with a valid id), and the entity record (that still has a DatabaseRecordId of 0)
            // We then need to match up the record that was saved with it's entity counterpart
            var processedSourceGenerators = new HashSet <ACE.Entity.Models.PropertiesGenerator>();
            var usedTargetGenerators      = new HashSet <BiotaPropertiesGenerator>();

            if (sourceBiota.PropertiesGenerator != null)
            {
                // Process matched up records first
                foreach (var value in sourceBiota.PropertiesGenerator)
                {
                    if (value.DatabaseRecordId == 0)
                    {
                        continue;
                    }

                    // Source record should already exist in the target
                    BiotaPropertiesGenerator existingValue = targetBiota.BiotaPropertiesGenerator.FirstOrDefault(r => r.Id == value.DatabaseRecordId);

                    // If the existingValue was not found, the database was likely modified outside of ACE after our last save
                    if (existingValue == null)
                    {
                        continue;
                    }

                    CopyValueInto(value, existingValue);

                    processedSourceGenerators.Add(value);
                    usedTargetGenerators.Add(existingValue);
                }
                foreach (var value in sourceBiota.PropertiesGenerator)
                {
                    if (processedSourceGenerators.Contains(value))
                    {
                        continue;
                    }

                    // For simplicity, just find the first unused target
                    BiotaPropertiesGenerator existingValue = targetBiota.BiotaPropertiesGenerator.FirstOrDefault(r => !usedTargetGenerators.Contains(r));

                    if (existingValue == null)
                    {
                        existingValue = new BiotaPropertiesGenerator {
                            ObjectId = sourceBiota.Id
                        };

                        targetBiota.BiotaPropertiesGenerator.Add(existingValue);
                    }

                    value.DatabaseRecordId = existingValue.Id;

                    CopyValueInto(value, existingValue);

                    //processedSourceGenerators.Add(value);
                    usedTargetGenerators.Add(existingValue);
                }
            }
            foreach (var value in targetBiota.BiotaPropertiesGenerator)
            {
                if (!usedTargetGenerators.Contains(value))
                {
                    context.BiotaPropertiesGenerator.Remove(value);
                }
            }


            // Properties for creatures

            if (sourceBiota.PropertiesAttribute != null)
            {
                foreach (var kvp in sourceBiota.PropertiesAttribute)
                {
                    BiotaPropertiesAttribute existingValue = targetBiota.BiotaPropertiesAttribute.FirstOrDefault(r => r.Type == (ushort)kvp.Key);

                    if (existingValue == null)
                    {
                        existingValue = new BiotaPropertiesAttribute {
                            ObjectId = sourceBiota.Id
                        };

                        targetBiota.BiotaPropertiesAttribute.Add(existingValue);
                    }

                    existingValue.Type        = (ushort)kvp.Key;
                    existingValue.InitLevel   = kvp.Value.InitLevel;
                    existingValue.LevelFromCP = kvp.Value.LevelFromCP;
                    existingValue.CPSpent     = kvp.Value.CPSpent;
                }
            }
            foreach (var value in targetBiota.BiotaPropertiesAttribute)
            {
                if (sourceBiota.PropertiesAttribute == null || !sourceBiota.PropertiesAttribute.ContainsKey((PropertyAttribute)value.Type))
                {
                    context.BiotaPropertiesAttribute.Remove(value);
                }
            }

            if (sourceBiota.PropertiesAttribute2nd != null)
            {
                foreach (var kvp in sourceBiota.PropertiesAttribute2nd)
                {
                    BiotaPropertiesAttribute2nd existingValue = targetBiota.BiotaPropertiesAttribute2nd.FirstOrDefault(r => r.Type == (ushort)kvp.Key);

                    if (existingValue == null)
                    {
                        existingValue = new BiotaPropertiesAttribute2nd {
                            ObjectId = sourceBiota.Id
                        };

                        targetBiota.BiotaPropertiesAttribute2nd.Add(existingValue);
                    }

                    existingValue.Type         = (ushort)kvp.Key;
                    existingValue.InitLevel    = kvp.Value.InitLevel;
                    existingValue.LevelFromCP  = kvp.Value.LevelFromCP;
                    existingValue.CPSpent      = kvp.Value.CPSpent;
                    existingValue.CurrentLevel = kvp.Value.CurrentLevel;
                }
            }
            foreach (var value in targetBiota.BiotaPropertiesAttribute2nd)
            {
                if (sourceBiota.PropertiesAttribute2nd == null || !sourceBiota.PropertiesAttribute2nd.ContainsKey((PropertyAttribute2nd)value.Type))
                {
                    context.BiotaPropertiesAttribute2nd.Remove(value);
                }
            }

            if (sourceBiota.PropertiesBodyPart != null)
            {
                foreach (var kvp in sourceBiota.PropertiesBodyPart)
                {
                    BiotaPropertiesBodyPart existingValue = targetBiota.BiotaPropertiesBodyPart.FirstOrDefault(r => r.Key == (uint)kvp.Key);

                    if (existingValue == null)
                    {
                        existingValue = new BiotaPropertiesBodyPart {
                            ObjectId = sourceBiota.Id
                        };

                        targetBiota.BiotaPropertiesBodyPart.Add(existingValue);
                    }

                    existingValue.Key             = (ushort)kvp.Key;
                    existingValue.DType           = (int)kvp.Value.DType;
                    existingValue.DVal            = kvp.Value.DVal;
                    existingValue.DVar            = kvp.Value.DVar;
                    existingValue.BaseArmor       = kvp.Value.BaseArmor;
                    existingValue.ArmorVsSlash    = kvp.Value.ArmorVsSlash;
                    existingValue.ArmorVsPierce   = kvp.Value.ArmorVsPierce;
                    existingValue.ArmorVsBludgeon = kvp.Value.ArmorVsBludgeon;
                    existingValue.ArmorVsCold     = kvp.Value.ArmorVsCold;
                    existingValue.ArmorVsFire     = kvp.Value.ArmorVsFire;
                    existingValue.ArmorVsAcid     = kvp.Value.ArmorVsAcid;
                    existingValue.ArmorVsElectric = kvp.Value.ArmorVsElectric;
                    existingValue.ArmorVsNether   = kvp.Value.ArmorVsNether;
                    existingValue.BH  = kvp.Value.BH;
                    existingValue.HLF = kvp.Value.HLF;
                    existingValue.MLF = kvp.Value.MLF;
                    existingValue.LLF = kvp.Value.LLF;
                    existingValue.HRF = kvp.Value.HRF;
                    existingValue.MRF = kvp.Value.MRF;
                    existingValue.LRF = kvp.Value.LRF;
                    existingValue.HLB = kvp.Value.HLB;
                    existingValue.MLB = kvp.Value.MLB;
                    existingValue.LLB = kvp.Value.LLB;
                    existingValue.HRB = kvp.Value.HRB;
                    existingValue.MRB = kvp.Value.MRB;
                    existingValue.LRB = kvp.Value.LRB;
                }
            }
            foreach (var value in targetBiota.BiotaPropertiesBodyPart)
            {
                if (sourceBiota.PropertiesBodyPart == null || !sourceBiota.PropertiesBodyPart.ContainsKey((CombatBodyPart)value.Key))
                {
                    context.BiotaPropertiesBodyPart.Remove(value);
                }
            }

            if (sourceBiota.PropertiesSkill != null)
            {
                foreach (var kvp in sourceBiota.PropertiesSkill)
                {
                    BiotaPropertiesSkill existingValue = targetBiota.BiotaPropertiesSkill.FirstOrDefault(r => r.Type == (ushort)kvp.Key);

                    if (existingValue == null)
                    {
                        existingValue = new BiotaPropertiesSkill {
                            ObjectId = sourceBiota.Id
                        };

                        targetBiota.BiotaPropertiesSkill.Add(existingValue);
                    }

                    existingValue.Type                  = (ushort)kvp.Key;
                    existingValue.LevelFromPP           = kvp.Value.LevelFromPP;
                    existingValue.SAC                   = (uint)kvp.Value.SAC;
                    existingValue.PP                    = kvp.Value.PP;
                    existingValue.InitLevel             = kvp.Value.InitLevel;
                    existingValue.ResistanceAtLastCheck = kvp.Value.ResistanceAtLastCheck;
                    existingValue.LastUsedTime          = kvp.Value.LastUsedTime;
                }
            }
            foreach (var value in targetBiota.BiotaPropertiesSkill)
            {
                if (sourceBiota.PropertiesSkill == null || !sourceBiota.PropertiesSkill.ContainsKey((Skill)value.Type))
                {
                    context.BiotaPropertiesSkill.Remove(value);
                }
            }


            // Properties for books

            if (sourceBiota.PropertiesBook != null)
            {
                if (targetBiota.BiotaPropertiesBook == null)
                {
                    targetBiota.BiotaPropertiesBook = new BiotaPropertiesBook {
                        ObjectId = sourceBiota.Id,
                    }
                }
                ;

                targetBiota.BiotaPropertiesBook.MaxNumPages        = sourceBiota.PropertiesBook.MaxNumPages;
                targetBiota.BiotaPropertiesBook.MaxNumCharsPerPage = sourceBiota.PropertiesBook.MaxNumCharsPerPage;
            }
            else
            {
                if (targetBiota.BiotaPropertiesBook != null)
                {
                    context.BiotaPropertiesBook.Remove(targetBiota.BiotaPropertiesBook);
                }
            }

            if (sourceBiota.PropertiesBookPageData != null)
            {
                for (int i = 0; i < sourceBiota.PropertiesBookPageData.Count; i++)
                {
                    var value = sourceBiota.PropertiesBookPageData[i];

                    BiotaPropertiesBookPageData existingValue = targetBiota.BiotaPropertiesBookPageData.FirstOrDefault(r => r.PageId == i);

                    if (existingValue == null)
                    {
                        existingValue = new BiotaPropertiesBookPageData {
                            ObjectId = sourceBiota.Id
                        };

                        targetBiota.BiotaPropertiesBookPageData.Add(existingValue);
                    }

                    existingValue.PageId        = (uint)i;
                    existingValue.AuthorId      = value.AuthorId;
                    existingValue.AuthorName    = value.AuthorName;
                    existingValue.AuthorAccount = value.AuthorAccount;
                    existingValue.IgnoreAuthor  = value.IgnoreAuthor;
                    existingValue.PageText      = value.PageText;
                }
            }
            foreach (var value in targetBiota.BiotaPropertiesBookPageData)
            {
                if (sourceBiota.PropertiesBookPageData == null || value.PageId >= sourceBiota.PropertiesBookPageData.Count)
                {
                    context.BiotaPropertiesBookPageData.Remove(value);
                }
            }


            // Biota additions over Weenie

            if (sourceBiota.PropertiesAllegiance != null)
            {
                foreach (var kvp in sourceBiota.PropertiesAllegiance)
                {
                    BiotaPropertiesAllegiance existingValue = targetBiota.BiotaPropertiesAllegiance.FirstOrDefault(r => r.CharacterId == kvp.Key);

                    if (existingValue == null)
                    {
                        existingValue = new BiotaPropertiesAllegiance {
                            AllegianceId = sourceBiota.Id
                        };

                        targetBiota.BiotaPropertiesAllegiance.Add(existingValue);
                    }

                    existingValue.CharacterId    = kvp.Key;
                    existingValue.Banned         = kvp.Value.Banned;
                    existingValue.ApprovedVassal = kvp.Value.ApprovedVassal;
                }
            }
            foreach (var value in targetBiota.BiotaPropertiesAllegiance)
            {
                if (sourceBiota.PropertiesAllegiance == null || !sourceBiota.PropertiesAllegiance.ContainsKey(value.CharacterId))
                {
                    context.BiotaPropertiesAllegiance.Remove(value);
                }
            }

            if (sourceBiota.PropertiesEnchantmentRegistry != null)
            {
                foreach (var value in sourceBiota.PropertiesEnchantmentRegistry)
                {
                    BiotaPropertiesEnchantmentRegistry existingValue = targetBiota.BiotaPropertiesEnchantmentRegistry.FirstOrDefault(r => r.SpellId == value.SpellId && r.LayerId == value.LayerId && r.CasterObjectId == value.CasterObjectId);

                    if (existingValue == null)
                    {
                        existingValue = new BiotaPropertiesEnchantmentRegistry {
                            ObjectId = sourceBiota.Id
                        };

                        targetBiota.BiotaPropertiesEnchantmentRegistry.Add(existingValue);
                    }

                    existingValue.EnchantmentCategory = value.EnchantmentCategory;
                    existingValue.SpellId             = value.SpellId;
                    existingValue.LayerId             = value.LayerId;
                    existingValue.HasSpellSetId       = value.HasSpellSetId;
                    existingValue.SpellCategory       = (ushort)value.SpellCategory;
                    existingValue.PowerLevel          = value.PowerLevel;
                    existingValue.StartTime           = value.StartTime;
                    existingValue.Duration            = value.Duration;
                    existingValue.CasterObjectId      = value.CasterObjectId;
                    existingValue.DegradeModifier     = value.DegradeModifier;
                    existingValue.DegradeLimit        = value.DegradeLimit;
                    existingValue.LastTimeDegraded    = value.LastTimeDegraded;
                    existingValue.StatModType         = (uint)value.StatModType;
                    existingValue.StatModKey          = value.StatModKey;
                    existingValue.StatModValue        = value.StatModValue;
                    existingValue.SpellSetId          = (uint)value.SpellSetId;
                }
            }
            foreach (var value in targetBiota.BiotaPropertiesEnchantmentRegistry)
            {
                if (sourceBiota.PropertiesEnchantmentRegistry == null || !sourceBiota.PropertiesEnchantmentRegistry.Any(p => p.SpellId == value.SpellId && p.LayerId == value.LayerId && p.CasterObjectId == value.CasterObjectId))
                {
                    context.BiotaPropertiesEnchantmentRegistry.Remove(value);
                }
            }

            if (sourceBiota.HousePermissions != null)
            {
                foreach (var kvp in sourceBiota.HousePermissions)
                {
                    HousePermission existingValue = targetBiota.HousePermission.FirstOrDefault(r => r.PlayerGuid == kvp.Key);

                    if (existingValue == null)
                    {
                        existingValue = new HousePermission {
                            HouseId = sourceBiota.Id
                        };

                        targetBiota.HousePermission.Add(existingValue);
                    }

                    existingValue.PlayerGuid = kvp.Key;
                    existingValue.Storage    = kvp.Value;
                }
            }
            foreach (var value in targetBiota.HousePermission)
            {
                if (sourceBiota.HousePermissions == null || !sourceBiota.HousePermissions.ContainsKey(value.PlayerGuid))
                {
                    context.HousePermission.Remove(value);
                }
            }
        }
Ejemplo n.º 3
0
        public static void UpdateDatabaseBiota(ShardDbContext context, ACE.Entity.Models.Biota sourceBiota, ACE.Database.Models.Shard.Biota targetBiota)
        {
            targetBiota.WeenieClassId = sourceBiota.WeenieClassId;
            targetBiota.WeenieType    = (int)sourceBiota.WeenieType;

            throw new NotImplementedException();

            /* Uncomment this when new biota model is used
             * if (sourceBiota.PropertiesBool != null)
             * {
             *  foreach (var kvp in sourceBiota.PropertiesBool)
             *      targetBiota.SetProperty(kvp.Key, kvp.Value);
             * }
             * foreach (var value in targetBiota.BiotaPropertiesBool)
             * {
             *  if (sourceBiota.PropertiesBool == null || !sourceBiota.PropertiesBool.ContainsKey((PropertyBool)value.Type))
             *      context.BiotaPropertiesBool.Remove(value);
             * }
             *
             * if (sourceBiota.PropertiesDID != null)
             * {
             *  foreach (var kvp in sourceBiota.PropertiesDID)
             *      targetBiota.SetProperty(kvp.Key, kvp.Value);
             * }
             * foreach (var value in targetBiota.BiotaPropertiesDID)
             * {
             *  if (sourceBiota.PropertiesDID == null || !sourceBiota.PropertiesDID.ContainsKey((PropertyDataId)value.Type))
             *      context.BiotaPropertiesDID.Remove(value);
             * }
             *
             * if (sourceBiota.PropertiesFloat != null)
             * {
             *  foreach (var kvp in sourceBiota.PropertiesFloat)
             *      targetBiota.SetProperty(kvp.Key, kvp.Value);
             * }
             * foreach (var value in targetBiota.BiotaPropertiesFloat)
             * {
             *  if (sourceBiota.PropertiesFloat == null || !sourceBiota.PropertiesFloat.ContainsKey((PropertyFloat)value.Type))
             *      context.BiotaPropertiesFloat.Remove(value);
             * }
             *
             * if (sourceBiota.PropertiesIID != null)
             * {
             *  foreach (var kvp in sourceBiota.PropertiesIID)
             *      targetBiota.SetProperty(kvp.Key, kvp.Value);
             * }
             * foreach (var value in targetBiota.BiotaPropertiesIID)
             * {
             *  if (sourceBiota.PropertiesIID == null || !sourceBiota.PropertiesIID.ContainsKey((PropertyInstanceId)value.Type))
             *      context.BiotaPropertiesIID.Remove(value);
             * }
             *
             * if (sourceBiota.PropertiesInt != null)
             * {
             *  foreach (var kvp in sourceBiota.PropertiesInt)
             *      targetBiota.SetProperty(kvp.Key, kvp.Value);
             * }
             * foreach (var value in targetBiota.BiotaPropertiesInt)
             * {
             *  if (sourceBiota.PropertiesInt == null || !sourceBiota.PropertiesInt.ContainsKey((PropertyInt)value.Type))
             *      context.BiotaPropertiesInt.Remove(value);
             * }
             *
             * if (sourceBiota.PropertiesInt64 != null)
             * {
             *  foreach (var kvp in sourceBiota.PropertiesInt64)
             *      targetBiota.SetProperty(kvp.Key, kvp.Value);
             * }
             * foreach (var value in targetBiota.BiotaPropertiesInt64)
             * {
             *  if (sourceBiota.PropertiesInt64 == null || !sourceBiota.PropertiesInt64.ContainsKey((PropertyInt64)value.Type))
             *      context.BiotaPropertiesInt64.Remove(value);
             * }
             *
             * if (sourceBiota.PropertiesString != null)
             * {
             *  foreach (var kvp in sourceBiota.PropertiesString)
             *      targetBiota.SetProperty(kvp.Key, kvp.Value);
             * }
             * foreach (var value in targetBiota.BiotaPropertiesString)
             * {
             *  if (sourceBiota.PropertiesString == null || !sourceBiota.PropertiesString.ContainsKey((PropertyString)value.Type))
             *      context.BiotaPropertiesString.Remove(value);
             * }*/


            if (sourceBiota.PropertiesPosition != null)
            {
                foreach (var kvp in sourceBiota.PropertiesPosition)
                {
                    BiotaPropertiesPosition existingValue = targetBiota.BiotaPropertiesPosition.FirstOrDefault(r => r.PositionType == (ushort)kvp.Key);

                    if (existingValue == null)
                    {
                        existingValue = new BiotaPropertiesPosition {
                            ObjectId = sourceBiota.Id
                        };

                        targetBiota.BiotaPropertiesPosition.Add(existingValue);
                    }

                    existingValue.PositionType = (ushort)kvp.Key;
                    existingValue.ObjCellId    = kvp.Value.ObjCellId;
                    existingValue.OriginX      = kvp.Value.PositionX;
                    existingValue.OriginY      = kvp.Value.PositionY;
                    existingValue.OriginZ      = kvp.Value.PositionZ;
                    existingValue.AnglesW      = kvp.Value.RotationW;
                    existingValue.AnglesX      = kvp.Value.RotationX;
                    existingValue.AnglesY      = kvp.Value.RotationY;
                    existingValue.AnglesZ      = kvp.Value.RotationZ;
                }
            }
            foreach (var value in targetBiota.BiotaPropertiesPosition)
            {
                if (sourceBiota.PropertiesPosition == null || !sourceBiota.PropertiesPosition.ContainsKey((PositionType)value.PositionType))
                {
                    context.BiotaPropertiesPosition.Remove(value);
                }
            }


            if (sourceBiota.PropertiesSpellBook != null)
            {
                foreach (var kvp in sourceBiota.PropertiesSpellBook)
                {
                    BiotaPropertiesSpellBook existingValue = targetBiota.BiotaPropertiesSpellBook.FirstOrDefault(r => r.Spell == (ushort)kvp.Key);

                    if (existingValue == null)
                    {
                        existingValue = new BiotaPropertiesSpellBook {
                            ObjectId = sourceBiota.Id
                        };

                        targetBiota.BiotaPropertiesSpellBook.Add(existingValue);
                    }

                    existingValue.Spell       = kvp.Key;
                    existingValue.Probability = kvp.Value;
                }
            }
            foreach (var value in targetBiota.BiotaPropertiesSpellBook)
            {
                if (sourceBiota.PropertiesSpellBook == null || !sourceBiota.PropertiesSpellBook.ContainsKey(value.Spell))
                {
                    context.BiotaPropertiesSpellBook.Remove(value);
                }
            }


            if (sourceBiota.PropertiesAnimPart != null)
            {
                for (int i = 0; i < sourceBiota.PropertiesAnimPart.Count; i++)
                {
                    var value = sourceBiota.PropertiesAnimPart[i];

                    BiotaPropertiesAnimPart existingValue = targetBiota.BiotaPropertiesAnimPart.FirstOrDefault(r => r.Order == i);

                    if (existingValue == null)
                    {
                        existingValue = new BiotaPropertiesAnimPart {
                            ObjectId = sourceBiota.Id
                        };

                        targetBiota.BiotaPropertiesAnimPart.Add(existingValue);
                    }

                    existingValue.Index       = value.Index;
                    existingValue.AnimationId = value.AnimationId;
                    existingValue.Order       = (byte)i;
                }
            }
            foreach (var value in targetBiota.BiotaPropertiesAnimPart)
            {
                if (sourceBiota.PropertiesAnimPart == null || value.Order >= sourceBiota.PropertiesAnimPart.Count)
                {
                    context.BiotaPropertiesAnimPart.Remove(value);
                }
            }

            if (sourceBiota.PropertiesPalette != null)
            {
                foreach (var value in sourceBiota.PropertiesPalette)
                {
                    BiotaPropertiesPalette existingValue = targetBiota.BiotaPropertiesPalette.FirstOrDefault(r => r.SubPaletteId == value.SubPaletteId && r.Offset == value.Offset && r.Length == value.Length);

                    if (existingValue == null)
                    {
                        existingValue = new BiotaPropertiesPalette {
                            ObjectId = sourceBiota.Id, SubPaletteId = value.SubPaletteId, Offset = value.Offset, Length = value.Length
                        };

                        targetBiota.BiotaPropertiesPalette.Add(existingValue);
                    }
                }
            }
            foreach (var value in targetBiota.BiotaPropertiesPalette)
            {
                if (sourceBiota.PropertiesPalette == null || !sourceBiota.PropertiesPalette.Any(p => p.SubPaletteId == value.SubPaletteId && p.Offset == value.Offset && p.Length == value.Length))
                {
                    context.BiotaPropertiesPalette.Remove(value);
                }
            }

            if (sourceBiota.PropertiesTextureMap != null)
            {
                for (int i = 0; i < sourceBiota.PropertiesTextureMap.Count; i++)
                {
                    var value = sourceBiota.PropertiesTextureMap[i];

                    BiotaPropertiesTextureMap existingValue = targetBiota.BiotaPropertiesTextureMap.FirstOrDefault(r => r.Order == i);

                    if (existingValue == null)
                    {
                        existingValue = new BiotaPropertiesTextureMap {
                            ObjectId = sourceBiota.Id
                        };

                        targetBiota.BiotaPropertiesTextureMap.Add(existingValue);
                    }

                    existingValue.Index = value.PartIndex;
                    existingValue.OldId = value.OldTexture;
                    existingValue.NewId = value.NewTexture;
                    existingValue.Order = (byte)i;
                }
            }
            foreach (var value in targetBiota.BiotaPropertiesTextureMap)
            {
                if (sourceBiota.PropertiesTextureMap == null || value.Order >= sourceBiota.PropertiesTextureMap.Count)
                {
                    context.BiotaPropertiesTextureMap.Remove(value);
                }
            }


            // Properties for all world objects that typically aren't modified over the original Biota

            /*if (biota.PropertiesCreateList != null)
             * {
             *  foreach (var value in biota.PropertiesCreateList)
             *  {
             *      BiotaPropertiesCreateList existingValue = existingBiota.BiotaPropertiesCreateList.FirstOrDefault(r => r.Id == value.Id);
             *
             *      if (existingValue == null)
             *          existingBiota.BiotaPropertiesCreateList.Add(value);
             *      else
             *      {
             *          existingValue.DestinationType = value.DestinationType;
             *          existingValue.WeenieClassId = value.WeenieClassId;
             *          existingValue.StackSize = value.StackSize;
             *          existingValue.Palette = value.Palette;
             *          existingValue.Shade = value.Shade;
             *          existingValue.TryToBond = value.TryToBond;
             *      }
             *  }
             * }
             * foreach (var value in existingBiota.BiotaPropertiesCreateList)
             * {
             *  if (biota.PropertiesCreateList == null || !biota.PropertiesCreateList.Any(p => p.Id == value.Id))
             *      context.BiotaPropertiesCreateList.Remove(value);
             * }*/

            /*if (biota.PropertiesEmote != null)
             * {
             *  foreach (var value in biota.PropertiesEmote)
             *  {
             *      BiotaPropertiesEmote existingValue = existingBiota.BiotaPropertiesEmote.FirstOrDefault(r => r.Id == value.Id);
             *
             *      if (existingValue == null)
             *          existingBiota.BiotaPropertiesEmote.Add(value);
             *      else
             *      {
             *          existingValue.Category = value.Category;
             *          existingValue.Probability = value.Probability;
             *          existingValue.WeenieClassId = value.WeenieClassId;
             *          existingValue.Style = value.Style;
             *          existingValue.Substyle = value.Substyle;
             *          existingValue.Quest = value.Quest;
             *          existingValue.VendorType = value.VendorType;
             *          existingValue.MinHealth = value.MinHealth;
             *          existingValue.MaxHealth = value.MaxHealth;
             *
             *          foreach (var value2 in value.PropertiesEmoteAction)
             *          {
             *              BiotaPropertiesEmoteAction existingValue2 = existingValue.BiotaPropertiesEmoteAction.FirstOrDefault(r => r.Id == value2.Id);
             *
             *              if (existingValue2 == null)
             *                  existingValue.BiotaPropertiesEmoteAction.Add(value2);
             *              else
             *              {
             *                  //existingValue2.EmoteId = value2.EmoteId;
             *                  existingValue2.Order = (uint)value.PropertiesEmoteAction.IndexOf(value2);
             *                  existingValue2.Type = value2.Type;
             *                  existingValue2.Delay = value2.Delay;
             *                  existingValue2.Extent = value2.Extent;
             *                  existingValue2.Motion = value2.Motion;
             *                  existingValue2.Message = value2.Message;
             *                  existingValue2.TestString = value2.TestString;
             *                  existingValue2.Min = value2.Min;
             *                  existingValue2.Max = value2.Max;
             *                  existingValue2.Min64 = value2.Min64;
             *                  existingValue2.Max64 = value2.Max64;
             *                  existingValue2.MinDbl = value2.MinDbl;
             *                  existingValue2.MaxDbl = value2.MaxDbl;
             *                  existingValue2.Stat = value2.Stat;
             *                  existingValue2.Display = value2.Display;
             *                  existingValue2.Amount = value2.Amount;
             *                  existingValue2.Amount64 = value2.Amount64;
             *                  existingValue2.HeroXP64 = value2.HeroXP64;
             *                  existingValue2.Percent = value2.Percent;
             *                  existingValue2.SpellId = value2.SpellId;
             *                  existingValue2.WealthRating = value2.WealthRating;
             *                  existingValue2.TreasureClass = value2.TreasureClass;
             *                  existingValue2.TreasureType = value2.TreasureType;
             *                  existingValue2.PScript = value2.PScript;
             *                  existingValue2.Sound = value2.Sound;
             *                  existingValue2.DestinationType = value2.DestinationType;
             *                  existingValue2.WeenieClassId = value2.WeenieClassId;
             *                  existingValue2.StackSize = value2.StackSize;
             *                  existingValue2.Palette = value2.Palette;
             *                  existingValue2.Shade = value2.Shade;
             *                  existingValue2.TryToBond = value2.TryToBond;
             *                  existingValue2.ObjCellId = value2.ObjCellId;
             *                  existingValue2.OriginX = value2.OriginX;
             *                  existingValue2.OriginY = value2.OriginY;
             *                  existingValue2.OriginZ = value2.OriginZ;
             *                  existingValue2.AnglesW = value2.AnglesW;
             *                  existingValue2.AnglesX = value2.AnglesX;
             *                  existingValue2.AnglesY = value2.AnglesY;
             *                  existingValue2.AnglesZ = value2.AnglesZ;
             *              }
             *          }
             *          foreach (var value2 in value.PropertiesEmoteAction)
             *          {
             *              if (!existingValue.BiotaPropertiesEmoteAction.Any(p => p.Id == value2.Id))
             *                  context.BiotaPropertiesEmoteAction.Remove(value2);
             *          }
             *      }
             *  }
             * }
             * foreach (var value in existingBiota.BiotaPropertiesEmote)
             * {
             *  if (biota.PropertiesEmote == null || !biota.PropertiesEmote.Any(p => p.Id == value.Id))
             *      context.BiotaPropertiesEmote.Remove(value);
             * }*/

            if (sourceBiota.PropertiesEventFilter != null)
            {
                foreach (var value in sourceBiota.PropertiesEventFilter)
                {
                    BiotaPropertiesEventFilter existingValue = targetBiota.BiotaPropertiesEventFilter.FirstOrDefault(r => r.Event == value);

                    if (existingValue == null)
                    {
                        var entity = new BiotaPropertiesEventFilter {
                            ObjectId = sourceBiota.Id, Event = value
                        };

                        targetBiota.BiotaPropertiesEventFilter.Add(entity);
                    }
                }
            }
            foreach (var value in targetBiota.BiotaPropertiesEventFilter)
            {
                if (sourceBiota.PropertiesEventFilter == null || !sourceBiota.PropertiesEventFilter.Any(p => p == value.Event))
                {
                    context.BiotaPropertiesEventFilter.Remove(value);
                }
            }

            /*if (biota.PropertiesGenerator != null)
             * {
             *  foreach (var value in biota.PropertiesGenerator)
             *  {
             *      BiotaPropertiesGenerator existingValue = existingBiota.BiotaPropertiesGenerator.FirstOrDefault(r => r.Id == value.Id);
             *
             *      if (existingValue == null)
             *          existingBiota.BiotaPropertiesGenerator.Add(value);
             *      else
             *      {
             *          existingValue.Probability = value.Probability;
             *          existingValue.WeenieClassId = value.WeenieClassId;
             *          existingValue.Delay = value.Delay;
             *          existingValue.InitCreate = value.InitCreate;
             *          existingValue.MaxCreate = value.MaxCreate;
             *          existingValue.WhenCreate = value.WhenCreate;
             *          existingValue.WhereCreate = value.WhereCreate;
             *          existingValue.StackSize = value.StackSize;
             *          existingValue.PaletteId = value.PaletteId;
             *          existingValue.Shade = value.Shade;
             *          existingValue.ObjCellId = value.ObjCellId;
             *          existingValue.OriginX = value.OriginX;
             *          existingValue.OriginY = value.OriginY;
             *          existingValue.OriginZ = value.OriginZ;
             *          existingValue.AnglesW = value.AnglesW;
             *          existingValue.AnglesX = value.AnglesX;
             *          existingValue.AnglesY = value.AnglesY;
             *          existingValue.AnglesZ = value.AnglesZ;
             *      }
             *  }
             * }
             * foreach (var value in existingBiota.BiotaPropertiesGenerator)
             * {
             *  if (biota.PropertiesGenerator == null || !biota.PropertiesGenerator.Any(p => p.Id == value.Id))
             *      context.BiotaPropertiesGenerator.Remove(value);
             * }*/


            // Properties for creatures

            if (sourceBiota.PropertiesAttribute != null)
            {
                foreach (var kvp in sourceBiota.PropertiesAttribute)
                {
                    BiotaPropertiesAttribute existingValue = targetBiota.BiotaPropertiesAttribute.FirstOrDefault(r => r.Type == (ushort)kvp.Key);

                    if (existingValue == null)
                    {
                        existingValue = new BiotaPropertiesAttribute {
                            ObjectId = sourceBiota.Id
                        };

                        targetBiota.BiotaPropertiesAttribute.Add(existingValue);
                    }

                    existingValue.Type        = (ushort)kvp.Key;
                    existingValue.InitLevel   = kvp.Value.InitLevel;
                    existingValue.LevelFromCP = kvp.Value.LevelFromCP;
                    existingValue.CPSpent     = kvp.Value.CPSpent;
                }
            }
            foreach (var value in targetBiota.BiotaPropertiesAttribute)
            {
                if (sourceBiota.PropertiesAttribute == null || !sourceBiota.PropertiesAttribute.ContainsKey((PropertyAttribute)value.Type))
                {
                    context.BiotaPropertiesAttribute.Remove(value);
                }
            }

            if (sourceBiota.PropertiesAttribute2nd != null)
            {
                foreach (var kvp in sourceBiota.PropertiesAttribute2nd)
                {
                    BiotaPropertiesAttribute2nd existingValue = targetBiota.BiotaPropertiesAttribute2nd.FirstOrDefault(r => r.Type == (ushort)kvp.Key);

                    if (existingValue == null)
                    {
                        existingValue = new BiotaPropertiesAttribute2nd {
                            ObjectId = sourceBiota.Id
                        };

                        targetBiota.BiotaPropertiesAttribute2nd.Add(existingValue);
                    }

                    existingValue.Type         = (ushort)kvp.Key;
                    existingValue.InitLevel    = kvp.Value.InitLevel;
                    existingValue.LevelFromCP  = kvp.Value.LevelFromCP;
                    existingValue.CPSpent      = kvp.Value.CPSpent;
                    existingValue.CurrentLevel = kvp.Value.CurrentLevel;
                }
            }
            foreach (var value in targetBiota.BiotaPropertiesAttribute2nd)
            {
                if (sourceBiota.PropertiesAttribute2nd == null || !sourceBiota.PropertiesAttribute2nd.ContainsKey((PropertyAttribute2nd)value.Type))
                {
                    context.BiotaPropertiesAttribute2nd.Remove(value);
                }
            }

            if (sourceBiota.PropertiesBodyPart != null)
            {
                foreach (var kvp in sourceBiota.PropertiesBodyPart)
                {
                    BiotaPropertiesBodyPart existingValue = targetBiota.BiotaPropertiesBodyPart.FirstOrDefault(r => r.Key == (uint)kvp.Key);

                    if (existingValue == null)
                    {
                        existingValue = new BiotaPropertiesBodyPart {
                            ObjectId = sourceBiota.Id
                        };

                        targetBiota.BiotaPropertiesBodyPart.Add(existingValue);
                    }

                    existingValue.Key             = (ushort)kvp.Key;
                    existingValue.DType           = (int)kvp.Value.DType;
                    existingValue.DVal            = kvp.Value.DVal;
                    existingValue.DVar            = kvp.Value.DVar;
                    existingValue.BaseArmor       = kvp.Value.BaseArmor;
                    existingValue.ArmorVsSlash    = kvp.Value.ArmorVsSlash;
                    existingValue.ArmorVsPierce   = kvp.Value.ArmorVsPierce;
                    existingValue.ArmorVsBludgeon = kvp.Value.ArmorVsBludgeon;
                    existingValue.ArmorVsCold     = kvp.Value.ArmorVsCold;
                    existingValue.ArmorVsFire     = kvp.Value.ArmorVsFire;
                    existingValue.ArmorVsAcid     = kvp.Value.ArmorVsAcid;
                    existingValue.ArmorVsElectric = kvp.Value.ArmorVsElectric;
                    existingValue.ArmorVsNether   = kvp.Value.ArmorVsNether;
                    existingValue.BH  = kvp.Value.BH;
                    existingValue.HLF = kvp.Value.HLF;
                    existingValue.MLF = kvp.Value.MLF;
                    existingValue.LLF = kvp.Value.LLF;
                    existingValue.HRF = kvp.Value.HRF;
                    existingValue.MRF = kvp.Value.MRF;
                    existingValue.LRF = kvp.Value.LRF;
                    existingValue.HLB = kvp.Value.HLB;
                    existingValue.MLB = kvp.Value.MLB;
                    existingValue.LLB = kvp.Value.LLB;
                    existingValue.HRB = kvp.Value.HRB;
                    existingValue.MRB = kvp.Value.MRB;
                    existingValue.LRB = kvp.Value.LRB;
                }
            }
            foreach (var value in targetBiota.BiotaPropertiesBodyPart)
            {
                if (sourceBiota.PropertiesBodyPart == null || !sourceBiota.PropertiesBodyPart.ContainsKey((CombatBodyPart)value.Key))
                {
                    context.BiotaPropertiesBodyPart.Remove(value);
                }
            }

            if (sourceBiota.PropertiesSkill != null)
            {
                foreach (var kvp in sourceBiota.PropertiesSkill)
                {
                    BiotaPropertiesSkill existingValue = targetBiota.BiotaPropertiesSkill.FirstOrDefault(r => r.Type == (ushort)kvp.Key);

                    if (existingValue == null)
                    {
                        existingValue = new BiotaPropertiesSkill {
                            ObjectId = sourceBiota.Id
                        };

                        targetBiota.BiotaPropertiesSkill.Add(existingValue);
                    }

                    existingValue.Type                  = (ushort)kvp.Key;
                    existingValue.LevelFromPP           = kvp.Value.LevelFromPP;
                    existingValue.SAC                   = (uint)kvp.Value.SAC;
                    existingValue.PP                    = kvp.Value.PP;
                    existingValue.InitLevel             = kvp.Value.InitLevel;
                    existingValue.ResistanceAtLastCheck = kvp.Value.ResistanceAtLastCheck;
                    existingValue.LastUsedTime          = kvp.Value.LastUsedTime;
                }
            }
            foreach (var value in targetBiota.BiotaPropertiesSkill)
            {
                if (sourceBiota.PropertiesSkill == null || !sourceBiota.PropertiesSkill.ContainsKey((Skill)value.Type))
                {
                    context.BiotaPropertiesSkill.Remove(value);
                }
            }


            // Properties for books

            if (sourceBiota.PropertiesBook != null)
            {
                if (targetBiota.BiotaPropertiesBook == null)
                {
                    targetBiota.BiotaPropertiesBook = new BiotaPropertiesBook {
                        ObjectId = sourceBiota.Id,
                    }
                }
                ;

                targetBiota.BiotaPropertiesBook.MaxNumPages        = sourceBiota.PropertiesBook.MaxNumPages;
                targetBiota.BiotaPropertiesBook.MaxNumCharsPerPage = sourceBiota.PropertiesBook.MaxNumCharsPerPage;
            }
            else
            {
                if (targetBiota.BiotaPropertiesBook != null)
                {
                    context.BiotaPropertiesBook.Remove(targetBiota.BiotaPropertiesBook);
                }
            }

            if (sourceBiota.PropertiesBookPageData != null)
            {
                for (int i = 0; i < sourceBiota.PropertiesBookPageData.Count; i++)
                {
                    var value = sourceBiota.PropertiesBookPageData[i];

                    BiotaPropertiesBookPageData existingValue = targetBiota.BiotaPropertiesBookPageData.FirstOrDefault(r => r.PageId == i);

                    if (existingValue == null)
                    {
                        existingValue = new BiotaPropertiesBookPageData {
                            ObjectId = sourceBiota.Id
                        };

                        targetBiota.BiotaPropertiesBookPageData.Add(existingValue);
                    }

                    existingValue.PageId        = (uint)i;
                    existingValue.AuthorId      = value.AuthorId;
                    existingValue.AuthorName    = value.AuthorName;
                    existingValue.AuthorAccount = value.AuthorAccount;
                    existingValue.IgnoreAuthor  = value.IgnoreAuthor;
                    existingValue.PageText      = value.PageText;
                }
            }
            foreach (var value in targetBiota.BiotaPropertiesBookPageData)
            {
                if (sourceBiota.PropertiesBookPageData == null || value.PageId >= sourceBiota.PropertiesBookPageData.Count)
                {
                    context.BiotaPropertiesBookPageData.Remove(value);
                }
            }


            // Biota additions over Weenie

            if (sourceBiota.PropertiesAllegiance != null)
            {
                foreach (var kvp in sourceBiota.PropertiesAllegiance)
                {
                    BiotaPropertiesAllegiance existingValue = targetBiota.BiotaPropertiesAllegiance.FirstOrDefault(r => r.CharacterId == kvp.Key);

                    if (existingValue == null)
                    {
                        existingValue = new BiotaPropertiesAllegiance {
                            AllegianceId = sourceBiota.Id
                        };

                        targetBiota.BiotaPropertiesAllegiance.Add(existingValue);
                    }

                    existingValue.CharacterId    = kvp.Key;
                    existingValue.Banned         = kvp.Value.Banned;
                    existingValue.ApprovedVassal = kvp.Value.ApprovedVassal;
                }
            }
            foreach (var value in targetBiota.BiotaPropertiesAllegiance)
            {
                if (sourceBiota.PropertiesAllegiance == null || !sourceBiota.PropertiesAllegiance.ContainsKey(value.CharacterId))
                {
                    context.BiotaPropertiesAllegiance.Remove(value);
                }
            }

            if (sourceBiota.PropertiesEnchantmentRegistry != null)
            {
                foreach (var value in sourceBiota.PropertiesEnchantmentRegistry)
                {
                    BiotaPropertiesEnchantmentRegistry existingValue = targetBiota.BiotaPropertiesEnchantmentRegistry.FirstOrDefault(r => r.SpellId == value.SpellId && r.LayerId == value.LayerId && r.CasterObjectId == value.CasterObjectId);

                    if (existingValue == null)
                    {
                        existingValue = new BiotaPropertiesEnchantmentRegistry {
                            ObjectId = sourceBiota.Id
                        };

                        targetBiota.BiotaPropertiesEnchantmentRegistry.Add(existingValue);
                    }

                    existingValue.EnchantmentCategory = value.EnchantmentCategory;
                    existingValue.SpellId             = value.SpellId;
                    existingValue.LayerId             = value.LayerId;
                    existingValue.HasSpellSetId       = value.HasSpellSetId;
                    existingValue.SpellCategory       = (ushort)value.SpellCategory;
                    existingValue.PowerLevel          = value.PowerLevel;
                    existingValue.StartTime           = value.StartTime;
                    existingValue.Duration            = value.Duration;
                    existingValue.CasterObjectId      = value.CasterObjectId;
                    existingValue.DegradeModifier     = value.DegradeModifier;
                    existingValue.DegradeLimit        = value.DegradeLimit;
                    existingValue.LastTimeDegraded    = value.LastTimeDegraded;
                    existingValue.StatModType         = (uint)value.StatModType;
                    existingValue.StatModKey          = value.StatModKey;
                    existingValue.StatModValue        = value.StatModValue;
                    existingValue.SpellSetId          = (uint)value.SpellSetId;
                }
            }
            foreach (var value in targetBiota.BiotaPropertiesEnchantmentRegistry)
            {
                if (sourceBiota.PropertiesEnchantmentRegistry == null || !sourceBiota.PropertiesEnchantmentRegistry.Any(p => p.SpellId == value.SpellId && p.LayerId == value.LayerId && p.CasterObjectId == value.CasterObjectId))
                {
                    context.BiotaPropertiesEnchantmentRegistry.Remove(value);
                }
            }

            if (sourceBiota.HousePermissions != null)
            {
                foreach (var kvp in sourceBiota.HousePermissions)
                {
                    HousePermission existingValue = targetBiota.HousePermission.FirstOrDefault(r => r.PlayerGuid == kvp.Key);

                    if (existingValue == null)
                    {
                        existingValue = new HousePermission {
                            HouseId = sourceBiota.Id
                        };

                        targetBiota.HousePermission.Add(existingValue);
                    }

                    existingValue.PlayerGuid = kvp.Key;
                    existingValue.Storage    = kvp.Value;
                }
            }
            foreach (var value in targetBiota.HousePermission)
            {
                if (sourceBiota.HousePermissions == null || !sourceBiota.HousePermissions.ContainsKey(value.PlayerGuid))
                {
                    context.HousePermission.Remove(value);
                }
            }
        }
    }