private void WriteEventBody()
        {
            var propertyFlags    = DescriptionPropertyFlag.None;
            var propertyFlagsPos = Writer.BaseStream.Position;

            Writer.Write(0u);
            Writer.Write((uint)Session.Player.WeenieType);

            var propertiesInt = Session.Player.GetAllPropertyInt().Where(x => SendOnLoginProperties.PropertiesInt.Contains((ushort)x.Key)).ToList();

            if (propertiesInt.Count != 0)
            {
                propertyFlags |= DescriptionPropertyFlag.PropertyInt32;

                Writer.Write((ushort)propertiesInt.Count);
                Writer.Write((ushort)0x40);

                foreach (var property in propertiesInt)
                {
                    Writer.Write((uint)property.Key);
                    Writer.Write(property.Value);
                }
            }

            var propertiesInt64 = Session.Player.GetAllPropertyInt64().Where(x => ClientProperties.PropertiesInt64.Contains((ushort)x.Key)).ToList();

            if (propertiesInt64.Count != 0)
            {
                propertyFlags |= DescriptionPropertyFlag.PropertyInt64;

                Writer.Write((ushort)propertiesInt64.Count);
                Writer.Write((ushort)0x40);

                foreach (var property in propertiesInt64)
                {
                    Writer.Write((uint)property.Key);
                    Writer.Write(property.Value);
                }
            }

            var propertiesBool = Session.Player.GetAllPropertyBools().Where(x => SendOnLoginProperties.PropertiesBool.Contains((ushort)x.Key)).ToList();

            if (propertiesBool.Count != 0)
            {
                propertyFlags |= DescriptionPropertyFlag.PropertyBool;

                Writer.Write((ushort)propertiesBool.Count);
                Writer.Write((ushort)0x20);

                foreach (var property in propertiesBool)
                {
                    Writer.Write((uint)property.Key);
                    Writer.Write(Convert.ToUInt32(property.Value)); // just as fast as inlining
                }
            }

            var propertiesDouble = Session.Player.GetAllPropertyFloat().Where(x => SendOnLoginProperties.PropertiesDouble.Contains((ushort)x.Key)).ToList();

            if (propertiesDouble.Count != 0)
            {
                propertyFlags |= DescriptionPropertyFlag.PropertyDouble;

                Writer.Write((ushort)propertiesDouble.Count);
                Writer.Write((ushort)0x20);

                foreach (var property in propertiesDouble)
                {
                    Writer.Write((uint)property.Key);
                    Writer.Write(property.Value);
                }
            }

            var propertiesString = Session.Player.GetAllPropertyString().Where(x => SendOnLoginProperties.PropertiesString.Contains((ushort)x.Key)).ToList();

            if (propertiesString != null && propertiesString.Count != 0)
            {
                propertyFlags |= DescriptionPropertyFlag.PropertyString;

                Writer.Write((ushort)propertiesString.Count);
                Writer.Write((ushort)0x10);

                foreach (var property in propertiesString)
                {
                    Writer.Write((uint)property.Key);
                    if (property.Key == PropertyString.Name)
                    {
                        if (Session.Player.IsPlussed && Session.Player.CloakStatus < CloakStatus.Player)
                        {
                            Writer.WriteString16L("+" + property.Value);
                        }
                        else
                        {
                            Writer.WriteString16L(property.Value);
                        }
                    }
                    else
                    {
                        Writer.WriteString16L(property.Value);
                    }
                }
            }

            var propertiesDid = Session.Player.GetAllPropertyDataId().Where(x => SendOnLoginProperties.PropertiesDataId.Contains((ushort)x.Key)).ToList();

            if (propertiesDid != null && propertiesDid.Count != 0)
            {
                propertyFlags |= DescriptionPropertyFlag.PropertyDid;

                Writer.Write((ushort)propertiesDid.Count);
                Writer.Write((ushort)0x20);

                foreach (var property in propertiesDid)
                {
                    Writer.Write((uint)property.Key);
                    Writer.Write(property.Value);
                }
            }

            var propertiesIid = Session.Player.GetAllPropertyInstanceId().Where(x => SendOnLoginProperties.PropertiesInstanceId.Contains((ushort)x.Key)).ToList();

            if (propertiesIid != null && propertiesIid.Count != 0)
            {
                propertyFlags |= DescriptionPropertyFlag.PropertyIid;

                Writer.Write((ushort)propertiesIid.Count);
                Writer.Write((ushort)0x20);

                foreach (var property in propertiesIid)
                {
                    Writer.Write((uint)property.Key);
                    Writer.Write(property.Value);
                }
            }

            /*if ((propertyFlags & DescriptionPropertyFlag.Resource) != 0)
             * {
             * }*/

            /*if ((propertyFlags & DescriptionPropertyFlag.Link) != 0)
             * {
             * }*/

            var lastOutsideDeath = Session.Player.GetPosition(PositionType.LastOutsideDeath);

            if (lastOutsideDeath != null)
            {
                propertyFlags |= DescriptionPropertyFlag.Position;

                Writer.Write((ushort)1);
                Writer.Write((ushort)0x20);

                Writer.Write((uint)PositionType.LastOutsideDeath);
                lastOutsideDeath.Serialize(Writer);
            }

            Writer.WritePosition((uint)propertyFlags, propertyFlagsPos);

            DescriptionVectorFlag vectorFlags = DescriptionVectorFlag.Attribute | DescriptionVectorFlag.Skill;

            if (Session.Player.Biota.BiotaPropertiesSpellBook.Count > 0)
            {
                vectorFlags |= DescriptionVectorFlag.Spell;
            }
            if (Session.Player.EnchantmentManager.HasEnchantments)
            {
                vectorFlags |= DescriptionVectorFlag.Enchantment;
            }

            Writer.Write((uint)vectorFlags);

            Writer.Write(Convert.ToUInt32(Session.Player.Health != null));

            if ((vectorFlags & DescriptionVectorFlag.Attribute) != 0)
            {
                var attributeFlags = AttributeCache.Full;
                Writer.Write((uint)attributeFlags);

                if ((attributeFlags & AttributeCache.Strength) != 0)
                {
                    Writer.Write(Session.Player.Strength.Ranks);           // ranks
                    Writer.Write(Session.Player.Strength.StartingValue);
                    Writer.Write(Session.Player.Strength.ExperienceSpent); // xp spent
                }

                if ((attributeFlags & AttributeCache.Endurance) != 0)
                {
                    Writer.Write(Session.Player.Endurance.Ranks);           // ranks
                    Writer.Write(Session.Player.Endurance.StartingValue);
                    Writer.Write(Session.Player.Endurance.ExperienceSpent); // xp spent
                }

                if ((attributeFlags & AttributeCache.Quickness) != 0)
                {
                    Writer.Write(Session.Player.Quickness.Ranks);           // ranks
                    Writer.Write(Session.Player.Quickness.StartingValue);
                    Writer.Write(Session.Player.Quickness.ExperienceSpent); // xp spent
                }

                if ((attributeFlags & AttributeCache.Coordination) != 0)
                {
                    Writer.Write(Session.Player.Coordination.Ranks);           // ranks
                    Writer.Write(Session.Player.Coordination.StartingValue);
                    Writer.Write(Session.Player.Coordination.ExperienceSpent); // xp spent
                }

                if ((attributeFlags & AttributeCache.Focus) != 0)
                {
                    Writer.Write(Session.Player.Focus.Ranks);           // ranks
                    Writer.Write(Session.Player.Focus.StartingValue);
                    Writer.Write(Session.Player.Focus.ExperienceSpent); // xp spent
                }

                if ((attributeFlags & AttributeCache.Self) != 0)
                {
                    Writer.Write(Session.Player.Self.Ranks);           // ranks
                    Writer.Write(Session.Player.Self.StartingValue);
                    Writer.Write(Session.Player.Self.ExperienceSpent); // xp spent
                }

                if ((attributeFlags & AttributeCache.Health) != 0)
                {
                    Writer.Write(Session.Player.Health.Ranks);           // ranks
                    Writer.Write(Session.Player.Health.StartingValue);   // init_level - always appears to be 0
                    Writer.Write(Session.Player.Health.ExperienceSpent); // xp spent
                    Writer.Write(Session.Player.Health.Current);         // current value
                }

                if ((attributeFlags & AttributeCache.Stamina) != 0)
                {
                    Writer.Write(Session.Player.Stamina.Ranks);           // ranks
                    Writer.Write(Session.Player.Stamina.StartingValue);   // init_level - always appears to be 0
                    Writer.Write(Session.Player.Stamina.ExperienceSpent); // xp spent
                    Writer.Write(Session.Player.Stamina.Current);         // current value
                }

                if ((attributeFlags & AttributeCache.Mana) != 0)
                {
                    Writer.Write(Session.Player.Mana.Ranks);           // ranks
                    Writer.Write(Session.Player.Mana.StartingValue);   // init_level - always appears to be 0
                    Writer.Write(Session.Player.Mana.ExperienceSpent); // xp spent
                    Writer.Write(Session.Player.Mana.Current);         // current value
                }
            }

            if ((vectorFlags & DescriptionVectorFlag.Skill) != 0)
            {
                Writer.Write((ushort)Session.Player.Skills.Count);
                Writer.Write((ushort)0x20); // unknown

                foreach (var kvp in Session.Player.Skills)
                {
                    // TODO: Network.Structure.Skill

                    Writer.Write((uint)kvp.Key);                    // skill id
                    Writer.Write(kvp.Value.Ranks);                  // points raised
                    Writer.Write((ushort)1u);
                    Writer.Write((uint)kvp.Value.AdvancementClass); // skill state
                    Writer.Write(kvp.Value.ExperienceSpent);        // xp spent on this skill
                    Writer.Write(kvp.Value.InitLevel);              // init_level, for training/specialized bonus from character creation
                    Writer.Write(0u);                               // task difficulty, aka "resistance_of_last_check"
                    Writer.Write(0d);                               // last_time_used
                }
            }

            if ((vectorFlags & DescriptionVectorFlag.Spell) != 0)
            {
                Writer.Write((ushort)Session.Player.Biota.BiotaPropertiesSpellBook.Count);
                Writer.Write((ushort)64);

                foreach (var spell in Session.Player.Biota.BiotaPropertiesSpellBook)
                {
                    Writer.Write(spell.Spell);
                    // This sets a flag to use new spell configuration always 2
                    Writer.Write(2f);
                }
            }

            if ((vectorFlags & DescriptionVectorFlag.Enchantment) != 0)
            {
                Session.Player.EnchantmentManager.SendRegistry(Writer);
            }

            // TODO: Refactor this to set all of these flags based on data. Og II
            CharacterOptionDataFlag optionFlags = CharacterOptionDataFlag.CharacterOptions2;

            optionFlags |= CharacterOptionDataFlag.SpellLists8;

            var shortcuts = Session.Player.GetShortcuts();

            if (shortcuts.Count > 0)
            {
                optionFlags |= CharacterOptionDataFlag.Shortcut;
            }

            if (Session.Player.Character.GameplayOptions != null && Session.Player.Character.GameplayOptions.Length > 0)
            {
                optionFlags |= CharacterOptionDataFlag.GameplayOptions;
            }

            var fillComps = Session.Player.Character.GetFillComponents(Session.Player.CharacterDatabaseLock);

            if (fillComps.Count > 0)
            {
                optionFlags |= CharacterOptionDataFlag.DesiredComps;
            }

            optionFlags |= CharacterOptionDataFlag.SpellbookFilters;

            Writer.Write((uint)optionFlags);
            Writer.Write(Session.Player.Character.CharacterOptions1);

            if (shortcuts.Count > 0)
            {
                Writer.Write(shortcuts);
            }

            if ((optionFlags & CharacterOptionDataFlag.SpellLists8) != 0)
            {
                for (int i = 0; i <= 7; i++)
                {
                    var spells = Session.Player.GetSpellsInSpellBar(i);

                    Writer.Write(spells.Count);
                    foreach (var spell in spells)
                    {
                        Writer.Write(spell.SpellId);
                    }
                }
            }
            else
            {
                Writer.Write(0u);
            }

            if ((optionFlags & CharacterOptionDataFlag.DesiredComps) != 0)
            {
                Writer.Write(fillComps);
            }

            //if ((optionFlags & CharacterOptionDataFlag.SpellbookFilters) != 0)
            Writer.Write(Session.Player.Character.SpellbookFilters);

            if ((optionFlags & CharacterOptionDataFlag.CharacterOptions2) != 0)
            {
                Writer.Write(Session.Player.Character.CharacterOptions2);
            }

            /*if ((optionFlags & DescriptionOptionFlag.Unk100) != 0)
             * {
             * }*/

            if ((optionFlags & CharacterOptionDataFlag.GameplayOptions) != 0)
            {
                Writer.Write(Session.Player.Character.GameplayOptions);
            }

            /*if ((optionFlags & DescriptionOptionFlag.Unk400) != 0)
             * {
             * }*/

            // Write total count.
            Writer.Write((uint)Session.Player.Inventory.Count);
            // write out all of the non-containers and foci
            foreach (var item in Session.Player.Inventory.Values.Where(i => !i.UseBackpackSlot).OrderBy(i => i.PlacementPosition))
            {
                Writer.Write(item.Guid.Full);
                Writer.Write((uint)ContainerType.NonContainer);
            }
            // Containers and foci go in side slots, they come last with their own placement order.
            foreach (var item in Session.Player.Inventory.Values.Where(i => i.UseBackpackSlot).OrderBy(i => i.PlacementPosition))
            {
                Writer.Write(item.Guid.Full);
                if (item.WeenieType == WeenieType.Container)
                {
                    Writer.Write((uint)ContainerType.Container);
                }
                else
                {
                    Writer.Write((uint)ContainerType.Foci);
                }
            }

            Writer.Write((uint)Session.Player.EquippedObjects.Values.Count);
            foreach (var item in Session.Player.EquippedObjects.Values)
            {
                Writer.Write(item.Guid.Full);
                Writer.Write((uint)(item.CurrentWieldedLocation ?? 0));
                Writer.Write((uint)(item.ClothingPriority ?? 0));
            }
        }
        /// <summary>
        /// TODO: convert this to serialize AceCharacter rather than do all this session.Player garbage
        /// </summary>
        private void WriteEventBody()
        {
            var propertyFlags    = DescriptionPropertyFlag.None;
            var propertyFlagsPos = Writer.BaseStream.Position;

            Writer.Write(0u);
            Writer.Write(0x0Au);

            var aceObj = Session.Player.GetAceObject() as AceCharacter;

            var propertiesInt = aceObj?.IntProperties.Where(x => ClientProperties.PropertiesInt.Contains((ushort)x.PropertyId)).ToList();

            if (propertiesInt != null && propertiesInt.Count != 0)
            {
                propertyFlags |= DescriptionPropertyFlag.PropertyInt32;

                Writer.Write((ushort)propertiesInt.Count);
                Writer.Write((ushort)0x40);

                var notNull = propertiesInt.Where(x => x != null);
                foreach (var uintProperty in notNull)
                {
                    Writer.Write((uint)uintProperty.PropertyId);
                    Debug.Assert(uintProperty.PropertyValue != null, "uintProperty.PropertyValue != null");
                    Writer.Write(uintProperty.PropertyValue.Value);
                }
            }

            var propertiesInt64 = aceObj?.Int64Properties.Where(x => ClientProperties.PropertiesInt64.Contains((ushort)x.PropertyId)).ToList();

            if (propertiesInt64 != null && propertiesInt64.Count != 0)
            {
                propertyFlags |= DescriptionPropertyFlag.PropertyInt64;

                Writer.Write((ushort)propertiesInt64.Count);
                Writer.Write((ushort)0x40);

                var notNull = propertiesInt64.Where(x => x != null);
                foreach (var uint64Property in notNull)
                {
                    Writer.Write((uint)uint64Property.PropertyId);
                    Debug.Assert(uint64Property.PropertyValue != null, "uint64Property.PropertyValue != null");
                    Writer.Write(uint64Property.PropertyValue.Value);
                }
            }

            var propertiesBool = aceObj?.BoolProperties.Where(x => ClientProperties.PropertiesBool.Contains((ushort)x.PropertyId)).ToList();

            if (propertiesBool != null && propertiesBool.Count != 0)
            {
                propertyFlags |= DescriptionPropertyFlag.PropertyBool;

                Writer.Write((ushort)propertiesBool.Count);
                Writer.Write((ushort)0x20);

                foreach (var boolProperty in propertiesBool)
                {
                    Writer.Write((uint)boolProperty.PropertyId);
                    Writer.Write(Convert.ToUInt32(boolProperty.PropertyValue)); // just as fast as inlining
                }
            }

            var propertiesDouble = aceObj?.DoubleProperties.Where(x => ClientProperties.PropertiesDouble.Contains(x.PropertyId)).ToList();

            if (propertiesDouble != null && propertiesDouble.Count != 0)
            {
                propertyFlags |= DescriptionPropertyFlag.PropertyDouble;

                Writer.Write((ushort)propertiesDouble.Count);
                Writer.Write((ushort)0x20);

                var notNull = propertiesDouble.Where(x => x != null);
                foreach (var doubleProperty in notNull)
                {
                    Writer.Write((uint)doubleProperty.PropertyId);
                    Debug.Assert(doubleProperty.PropertyValue != null, "doubleProperty.PropertyValue != null");
                    Writer.Write(doubleProperty.PropertyValue.Value);
                }
            }

            var propertiesString = aceObj?.StringProperties.Where(x => ClientProperties.PropertiesString.Contains(x.PropertyId)).ToList();

            if (propertiesString != null && propertiesString.Count != 0)
            {
                propertyFlags |= DescriptionPropertyFlag.PropertyString;

                Writer.Write((ushort)propertiesString.Count);
                Writer.Write((ushort)0x10);

                foreach (var stringProperty in propertiesString)
                {
                    Writer.Write((uint)stringProperty.PropertyId);
                    Writer.WriteString16L(stringProperty.PropertyValue);
                }
            }

            var propertiesDid = aceObj?.DataIdProperties.Where(x => ClientProperties.PropertiesDataId.Contains((ushort)x.PropertyId)).ToList();

            if (propertiesDid != null && propertiesDid.Count != 0)
            {
                propertyFlags |= DescriptionPropertyFlag.PropertyDid;

                Writer.Write((ushort)propertiesDid.Count);
                Writer.Write((ushort)0x20);

                foreach (var didProperty in propertiesDid)
                {
                    Writer.Write(didProperty.PropertyId);
                    Debug.Assert(didProperty.PropertyValue != null, "didProperty.PropertyValue != null");
                    Writer.Write(didProperty.PropertyValue.Value);
                }
            }

            var propertiesIid = aceObj?.InstanceIdProperties.Where(x => ClientProperties.PropertiesInstanceId.Contains((ushort)x.PropertyId)).ToList();

            if (propertiesIid != null && propertiesIid.Count != 0)
            {
                propertyFlags |= DescriptionPropertyFlag.PropertyIid;

                Writer.Write((ushort)propertiesIid.Count);
                Writer.Write((ushort)0x20);

                foreach (var iidProperty in propertiesIid)
                {
                    Writer.Write(iidProperty.PropertyId);
                    Debug.Assert(iidProperty.PropertyValue != null, "iidProperty.PropertyValue != null");
                    Writer.Write(iidProperty.PropertyValue.Value);
                }
            }

            /*if ((propertyFlags & DescriptionPropertyFlag.Resource) != 0)
             * {
             * }*/

            /*if ((propertyFlags & DescriptionPropertyFlag.Link) != 0)
             * {
             * }*/

            /*if ((propertyFlags & DescriptionPropertyFlag.Position) != 0)
             * {
             * }*/

            Writer.WritePosition((uint)propertyFlags, propertyFlagsPos);

            DescriptionVectorFlag vectorFlags = DescriptionVectorFlag.Attribute | DescriptionVectorFlag.Skill;

            var propertiesSpells = aceObj.SpellIdProperties.ToList();

            if (propertiesSpells.Count > 0)
            {
                vectorFlags |= DescriptionVectorFlag.Spell;
            }

            Writer.Write((uint)vectorFlags);
            Writer.Write(1u);

            if ((vectorFlags & DescriptionVectorFlag.Attribute) != 0)
            {
                var attributeFlags = Ability.Full;
                Writer.Write((uint)attributeFlags);

                if ((attributeFlags & Ability.Strength) != 0)
                {
                    Writer.Write(this.Session.Player.Strength.Ranks);           // ranks
                    Writer.Write(this.Session.Player.Strength.Base);
                    Writer.Write(this.Session.Player.Strength.ExperienceSpent); // xp spent
                }

                if ((attributeFlags & Ability.Endurance) != 0)
                {
                    Writer.Write(this.Session.Player.Endurance.Ranks);           // ranks
                    Writer.Write(this.Session.Player.Endurance.Base);
                    Writer.Write(this.Session.Player.Endurance.ExperienceSpent); // xp spent
                }

                if ((attributeFlags & Ability.Quickness) != 0)
                {
                    Writer.Write(this.Session.Player.Quickness.Ranks);           // ranks
                    Writer.Write(this.Session.Player.Quickness.Base);
                    Writer.Write(this.Session.Player.Quickness.ExperienceSpent); // xp spent
                }

                if ((attributeFlags & Ability.Coordination) != 0)
                {
                    Writer.Write(this.Session.Player.Coordination.Ranks);           // ranks
                    Writer.Write(this.Session.Player.Coordination.Base);
                    Writer.Write(this.Session.Player.Coordination.ExperienceSpent); // xp spent
                }

                if ((attributeFlags & Ability.Focus) != 0)
                {
                    Writer.Write(this.Session.Player.Focus.Ranks);           // ranks
                    Writer.Write(this.Session.Player.Focus.Base);
                    Writer.Write(this.Session.Player.Focus.ExperienceSpent); // xp spent
                }

                if ((attributeFlags & Ability.Self) != 0)
                {
                    Writer.Write(this.Session.Player.Self.Ranks);           // ranks
                    Writer.Write(this.Session.Player.Self.Base);
                    Writer.Write(this.Session.Player.Self.ExperienceSpent); // xp spent
                }

                if ((attributeFlags & Ability.Health) != 0)
                {
                    Writer.Write(this.Session.Player.Health.Ranks);           // ranks
                    Writer.Write(0u);                                         // init_level - always appears to be 0
                    Writer.Write(this.Session.Player.Health.ExperienceSpent); // xp spent
                    Writer.Write(this.Session.Player.Health.Current);         // current value
                }

                if ((attributeFlags & Ability.Stamina) != 0)
                {
                    Writer.Write(this.Session.Player.Stamina.Ranks);           // ranks
                    Writer.Write(0u);                                          // init_level - always appears to be 0
                    Writer.Write(this.Session.Player.Stamina.ExperienceSpent); // xp spent
                    Writer.Write(this.Session.Player.Stamina.Current);         // current value
                }

                if ((attributeFlags & Ability.Mana) != 0)
                {
                    Writer.Write(this.Session.Player.Mana.Ranks);           // ranks
                    Writer.Write(0u);                                       // init_level - always appears to be 0
                    Writer.Write(this.Session.Player.Mana.ExperienceSpent); // xp spent
                    Writer.Write(this.Session.Player.Mana.Current);         // current value
                }
            }

            if ((vectorFlags & DescriptionVectorFlag.Skill) != 0)
            {
                // FIXME(ddevec): This should be a property of the player -- the AceObject does not track buffs.
                var skills = aceObj.GetSkills();

                Writer.Write((ushort)skills.Count);
                Writer.Write((ushort)0x20); // unknown

                foreach (var skill in skills)
                {
                    Writer.Write((uint)skill.Skill);           // skill id
                    Writer.Write((ushort)skill.Ranks);         // points raised
                    Writer.Write((ushort)1u);
                    Writer.Write((uint)skill.Status);          // skill state
                    Writer.Write((uint)skill.ExperienceSpent); // xp spent on this skill
                    if (skill.Status == SkillStatus.Specialized)
                    {
                        Writer.Write(10u);  // init_level, for specialization bonus -- buffs are not part of this message
                    }
                    else
                    {
                        Writer.Write(0u); // no init_level
                    }
                    Writer.Write(0u);     // task difficulty, aka "resistance_of_last_check"
                    Writer.Write(0d);     // last_time_used
                }
            }

            if ((vectorFlags & DescriptionVectorFlag.Spell) != 0)
            {
                Writer.Write((ushort)propertiesSpells.Count);
                Writer.Write((ushort)64);

                {
                    foreach (AceObjectPropertiesSpell spell in propertiesSpells)
                    {
                        Writer.Write(spell.SpellId);
                        // This sets a flag to use new spell configuration always 2
                        Writer.Write(2f);
                    }
                }
            }

            /*if ((vectorFlags & DescriptionVectorFlag.Enchantment) != 0)
             * {
             * }*/

            // FIXME(ddevec): We have duplicated data everywhere.  There is an AceObject CharacterOption flag, and a Player.CharacterOptions...
            //    Which one is right?  I have no idea.  Right now the aceObject works...  we should probably do a refactoring once we've restored functionality

            // TODO: Refactor this to set all of these flags based on data. Og II
            CharacterOptionDataFlag optionFlags = CharacterOptionDataFlag.CharacterOptions2;

            if (Session.Player.SpellsInSpellBars.Exists(x => x.AceObjectId == aceObj.AceObjectId))
            {
                optionFlags |= CharacterOptionDataFlag.SpellLists8;
            }

            Writer.Write((uint)optionFlags);

            /*
             * Writer.Write(this.Session.Player.CharacterOptions.GetCharacterOptions1Flag());
             */
            Writer.Write(aceObj.CharacterOptions1Mapping);

            /*if ((optionFlags & DescriptionOptionFlag.Shortcut) != 0)
             * {
             * }*/
            if ((optionFlags & CharacterOptionDataFlag.SpellLists8) != 0)
            {
                for (int i = 0; i <= 7; i++)
                {
                    var sorted =
                        Session.Player.SpellsInSpellBars.FindAll(x => x.AceObjectId == aceObj.AceObjectId && x.SpellBarId == i)
                        .OrderBy(s => s.SpellBarPositionId);
                    Writer.Write(sorted.Count());
                    foreach (AceObjectPropertiesSpellBarPositions spells in sorted)
                    {
                        Writer.Write(spells.SpellId);
                    }
                }
            }
            else
            {
                Writer.Write(0u);
            }

            /*if ((optionFlags & DescriptionOptionFlag.Component) != 0)
             * {
             * }*/

            if ((optionFlags & CharacterOptionDataFlag.SpellbookFilters) != 0)
            {
                Writer.Write(0u);
            }

            if ((optionFlags & CharacterOptionDataFlag.CharacterOptions2) != 0)
            {
                // Writer.Write(this.Session.Player.CharacterOptions.GetCharacterOptions2Flag());
                Writer.Write(aceObj.CharacterOptions2Mapping);
            }

            /*if ((optionFlags & DescriptionOptionFlag.Unk100) != 0)
             * {
             * }*/

            /*if ((optionFlags & DescriptionOptionFlag.WindowLayout) != 0)
             * {
             * }*/

            /*if ((optionFlags & DescriptionOptionFlag.Unk400) != 0)
             * {
             * }*/

            // Write total count.
            Writer.Write((uint)aceObj.Inventory.Count);
            // write out all of the non-containers and foci
            foreach (var inv in aceObj.Inventory.Where(i => !i.Value.UseBackpackSlot))
            {
                Writer.Write(inv.Value.AceObjectId);
                Writer.Write((uint)ContainerType.NonContainer);
            }
            // Containers and foci go in side slots, they come last with their own placement order.
            foreach (var inv in aceObj.Inventory.Where(i => i.Value.UseBackpackSlot))
            {
                Writer.Write(inv.Value.AceObjectId);
                if ((WeenieType)inv.Value.WeenieType == WeenieType.Container)
                {
                    Writer.Write((uint)ContainerType.Container);
                }
                else
                {
                    Writer.Write((uint)ContainerType.Foci);
                }
            }

            // TODO: This is where what we have equipped is sent.
            Writer.Write((uint)aceObj.WieldedItems.Count);
            foreach (var wieldedItem in aceObj.WieldedItems)
            {
                Writer.Write(wieldedItem.Value.AceObjectId);
                Writer.Write((uint)wieldedItem.Value.CurrentWieldedLocation);
                Writer.Write(wieldedItem.Value.ClothingPriority ?? 0u);
            }
        }
        private void WriteEventBody()
        {
            var propertyFlags    = DescriptionPropertyFlag.None;
            var propertyFlagsPos = Writer.BaseStream.Position;

            Writer.Write(0u);
            Writer.Write(0x0Au);

            var propertiesInt = Session.Player.GetAllPropertyInt().Where(x => ClientProperties.PropertiesInt.Contains((ushort)x.Key)).ToList();

            if (propertiesInt.Count != 0)
            {
                propertyFlags |= DescriptionPropertyFlag.PropertyInt32;

                Writer.Write((ushort)propertiesInt.Count);
                Writer.Write((ushort)0x40);

                foreach (var property in propertiesInt)
                {
                    Writer.Write((uint)property.Key);
                    Writer.Write(property.Value);
                }
            }

            var propertiesInt64 = Session.Player.GetAllPropertyInt64().Where(x => ClientProperties.PropertiesInt64.Contains((ushort)x.Key)).ToList();

            if (propertiesInt64.Count != 0)
            {
                propertyFlags |= DescriptionPropertyFlag.PropertyInt64;

                Writer.Write((ushort)propertiesInt64.Count);
                Writer.Write((ushort)0x40);

                foreach (var property in propertiesInt64)
                {
                    Writer.Write((uint)property.Key);
                    Writer.Write(property.Value);
                }
            }

            var propertiesBool = Session.Player.GetAllPropertyBools().Where(x => ClientProperties.PropertiesBool.Contains((ushort)x.Key)).ToList();

            if (propertiesBool.Count != 0)
            {
                propertyFlags |= DescriptionPropertyFlag.PropertyBool;

                Writer.Write((ushort)propertiesBool.Count);
                Writer.Write((ushort)0x20);

                foreach (var property in propertiesBool)
                {
                    Writer.Write((uint)property.Key);
                    Writer.Write(Convert.ToUInt32(property.Value)); // just as fast as inlining
                }
            }

            var propertiesDouble = Session.Player.GetAllPropertyFloat().Where(x => ClientProperties.PropertiesDouble.Contains((ushort)x.Key)).ToList();

            if (propertiesDouble.Count != 0)
            {
                propertyFlags |= DescriptionPropertyFlag.PropertyDouble;

                Writer.Write((ushort)propertiesDouble.Count);
                Writer.Write((ushort)0x20);

                foreach (var property in propertiesDouble)
                {
                    Writer.Write((uint)property.Key);
                    Writer.Write(property.Value);
                }
            }

            var propertiesString = Session.Player.GetAllPropertyString().Where(x => ClientProperties.PropertiesString.Contains((ushort)x.Key)).ToList();

            if (propertiesString != null && propertiesString.Count != 0)
            {
                propertyFlags |= DescriptionPropertyFlag.PropertyString;

                Writer.Write((ushort)propertiesString.Count);
                Writer.Write((ushort)0x10);

                foreach (var property in propertiesString)
                {
                    Writer.Write((uint)property.Key);
                    Writer.WriteString16L(property.Value);
                }
            }

            var propertiesDid = Session.Player.GetAllPropertyDataId().Where(x => ClientProperties.PropertiesDataId.Contains((ushort)x.Key)).ToList();

            if (propertiesDid != null && propertiesDid.Count != 0)
            {
                propertyFlags |= DescriptionPropertyFlag.PropertyDid;

                Writer.Write((ushort)propertiesDid.Count);
                Writer.Write((ushort)0x20);

                foreach (var property in propertiesDid)
                {
                    Writer.Write((uint)property.Key);
                    Writer.Write(property.Value);
                }
            }

            var propertiesIid = Session.Player.GetAllPropertyInstanceId().Where(x => ClientProperties.PropertiesInstanceId.Contains((ushort)x.Key)).ToList();

            if (propertiesIid != null && propertiesIid.Count != 0)
            {
                propertyFlags |= DescriptionPropertyFlag.PropertyIid;

                Writer.Write((ushort)propertiesIid.Count);
                Writer.Write((ushort)0x20);

                foreach (var property in propertiesIid)
                {
                    Writer.Write((uint)property.Key);
                    Writer.Write(property.Value);
                }
            }

            /*if ((propertyFlags & DescriptionPropertyFlag.Resource) != 0)
             * {
             * }*/

            /*if ((propertyFlags & DescriptionPropertyFlag.Link) != 0)
             * {
             * }*/

            /*if ((propertyFlags & DescriptionPropertyFlag.Position) != 0)
             * {
             * }*/

            Writer.WritePosition((uint)propertyFlags, propertyFlagsPos);

            DescriptionVectorFlag vectorFlags = DescriptionVectorFlag.Attribute | DescriptionVectorFlag.Skill;

            if (Session.Player.Biota.BiotaPropertiesSpellBook.Count > 0)
            {
                vectorFlags |= DescriptionVectorFlag.Spell;
            }

            Writer.Write((uint)vectorFlags);
            Writer.Write(1u);

            if ((vectorFlags & DescriptionVectorFlag.Attribute) != 0)
            {
                var attributeFlags = AttributeCache.Full;
                Writer.Write((uint)attributeFlags);

                if ((attributeFlags & AttributeCache.Strength) != 0)
                {
                    Writer.Write(Session.Player.Strength.Ranks);           // ranks
                    Writer.Write(Session.Player.Strength.StartingValue);
                    Writer.Write(Session.Player.Strength.ExperienceSpent); // xp spent
                }

                if ((attributeFlags & AttributeCache.Endurance) != 0)
                {
                    Writer.Write(Session.Player.Endurance.Ranks);           // ranks
                    Writer.Write(Session.Player.Endurance.StartingValue);
                    Writer.Write(Session.Player.Endurance.ExperienceSpent); // xp spent
                }

                if ((attributeFlags & AttributeCache.Quickness) != 0)
                {
                    Writer.Write(Session.Player.Quickness.Ranks);           // ranks
                    Writer.Write(Session.Player.Quickness.StartingValue);
                    Writer.Write(Session.Player.Quickness.ExperienceSpent); // xp spent
                }

                if ((attributeFlags & AttributeCache.Coordination) != 0)
                {
                    Writer.Write(Session.Player.Coordination.Ranks);           // ranks
                    Writer.Write(Session.Player.Coordination.StartingValue);
                    Writer.Write(Session.Player.Coordination.ExperienceSpent); // xp spent
                }

                if ((attributeFlags & AttributeCache.Focus) != 0)
                {
                    Writer.Write(Session.Player.Focus.Ranks);           // ranks
                    Writer.Write(Session.Player.Focus.StartingValue);
                    Writer.Write(Session.Player.Focus.ExperienceSpent); // xp spent
                }

                if ((attributeFlags & AttributeCache.Self) != 0)
                {
                    Writer.Write(Session.Player.Self.Ranks);           // ranks
                    Writer.Write(Session.Player.Self.StartingValue);
                    Writer.Write(Session.Player.Self.ExperienceSpent); // xp spent
                }

                if ((attributeFlags & AttributeCache.Health) != 0)
                {
                    Writer.Write(Session.Player.Health.Ranks);           // ranks
                    Writer.Write(Session.Player.Health.StartingValue);   // init_level - always appears to be 0
                    Writer.Write(Session.Player.Health.ExperienceSpent); // xp spent
                    Writer.Write(Session.Player.Health.Current);         // current value
                }

                if ((attributeFlags & AttributeCache.Stamina) != 0)
                {
                    Writer.Write(Session.Player.Stamina.Ranks);           // ranks
                    Writer.Write(Session.Player.Stamina.StartingValue);   // init_level - always appears to be 0
                    Writer.Write(Session.Player.Stamina.ExperienceSpent); // xp spent
                    Writer.Write(Session.Player.Stamina.Current);         // current value
                }

                if ((attributeFlags & AttributeCache.Mana) != 0)
                {
                    Writer.Write(Session.Player.Mana.Ranks);           // ranks
                    Writer.Write(Session.Player.Mana.StartingValue);   // init_level - always appears to be 0
                    Writer.Write(Session.Player.Mana.ExperienceSpent); // xp spent
                    Writer.Write(Session.Player.Mana.Current);         // current value
                }
            }

            if ((vectorFlags & DescriptionVectorFlag.Skill) != 0)
            {
                Writer.Write((ushort)Session.Player.Skills.Count);
                Writer.Write((ushort)0x20); // unknown

                foreach (var kvp in Session.Player.Skills)
                {
                    Writer.Write((uint)kvp.Key);                   // skill id
                    Writer.Write((ushort)kvp.Value.Ranks);         // points raised
                    Writer.Write((ushort)1u);
                    Writer.Write((uint)kvp.Value.Status);          // skill state
                    Writer.Write((uint)kvp.Value.ExperienceSpent); // xp spent on this skill
                    if (kvp.Value.Status == SkillStatus.Specialized)
                    {
                        Writer.Write(10u);  // init_level, for specialization bonus -- buffs are not part of this message
                    }
                    else
                    {
                        Writer.Write(0u); // no init_level
                    }
                    Writer.Write(0u);     // task difficulty, aka "resistance_of_last_check"
                    Writer.Write(0d);     // last_time_used
                }
            }

            if ((vectorFlags & DescriptionVectorFlag.Spell) != 0)
            {
                Writer.Write((ushort)Session.Player.Biota.BiotaPropertiesSpellBook.Count);
                Writer.Write((ushort)64);

                foreach (var spell in Session.Player.Biota.BiotaPropertiesSpellBook)
                {
                    Writer.Write(spell.Spell);
                    // This sets a flag to use new spell configuration always 2
                    Writer.Write(2f);
                }
            }

            /*if ((vectorFlags & DescriptionVectorFlag.Enchantment) != 0)
             * {
             * }*/

            // TODO: Refactor this to set all of these flags based on data. Og II
            CharacterOptionDataFlag optionFlags = CharacterOptionDataFlag.CharacterOptions2;

            optionFlags |= CharacterOptionDataFlag.SpellLists8;

            Writer.Write((uint)optionFlags);
            Writer.Write((int)(Session.Player.GetProperty(PropertyInt.CharacterOptions1) ?? 0));

            /*if ((optionFlags & DescriptionOptionFlag.Shortcut) != 0)
             * {
             * }*/

            if ((optionFlags & CharacterOptionDataFlag.SpellLists8) != 0)
            {
                for (int i = 0; i <= 7; i++)
                {
                    var spells = Session.Player.GetSpellsInSpellBar(i);

                    Writer.Write(spells.Count);
                    foreach (var spell in spells)
                    {
                        Writer.Write(spell.SpellId);
                    }
                }
            }
            else
            {
                Writer.Write(0u);
            }

            /*if ((optionFlags & DescriptionOptionFlag.Component) != 0)
             * {
             * }*/

            if ((optionFlags & CharacterOptionDataFlag.SpellbookFilters) != 0)
            {
                Writer.Write(0u);
            }

            if ((optionFlags & CharacterOptionDataFlag.CharacterOptions2) != 0)
            {
                Writer.Write((int)(Session.Player.GetProperty(PropertyInt.CharacterOptions2) ?? 0));
            }

            /*if ((optionFlags & DescriptionOptionFlag.Unk100) != 0)
             * {
             * }*/

            /*if ((optionFlags & DescriptionOptionFlag.WindowLayout) != 0)
             * {
             * }*/

            /*if ((optionFlags & DescriptionOptionFlag.Unk400) != 0)
             * {
             * }*/

            // Write total count.
            Writer.Write((uint)Session.Player.Inventory.Count);
            // write out all of the non-containers and foci
            foreach (var item in Session.Player.Inventory.Values.Where(i => !i.UseBackpackSlot).OrderBy(i => i.PlacementPosition))
            {
                Writer.Write(item.Guid.Full);
                Writer.Write((uint)ContainerType.NonContainer);
            }
            // Containers and foci go in side slots, they come last with their own placement order.
            foreach (var item in Session.Player.Inventory.Values.Where(i => i.UseBackpackSlot).OrderBy(i => i.PlacementPosition))
            {
                Writer.Write(item.Guid.Full);
                if (item.WeenieType == WeenieType.Container)
                {
                    Writer.Write((uint)ContainerType.Container);
                }
                else
                {
                    Writer.Write((uint)ContainerType.Foci);
                }
            }

            Writer.Write((uint)Session.Player.EquippedObjects.Values.Count);
            foreach (var item in Session.Player.EquippedObjects.Values)
            {
                Writer.Write(item.Guid.Full);
                Writer.Write((uint)item.CurrentWieldedLocation);
                Writer.Write((uint)(item.Priority ?? 0));
            }
        }