void RecvUpdateVelocityAndPosition(IIPSocket conn, BitStream r)
        {
            var mapEntityIndex = r.ReadMapEntityIndex();
            DynamicEntity dynamicEntity = null;

            // Grab the DynamicEntity
            // The map can be null if the spatial updates come very early (which isn't uncommon)
            if (Map != null)
                dynamicEntity = _objGrabber.GetDynamicEntity<DynamicEntity>(mapEntityIndex);

            // Deserialize
            if (dynamicEntity != null)
            {
                // Read the value into the DynamicEntity
                dynamicEntity.DeserializePositionAndVelocity(r);
            }
            else
            {
                // DynamicEntity was null, so just flush the values from the reader
                DynamicEntity.FlushPositionAndVelocity(r);
            }
        }
        void RecvStartShopping(IIPSocket conn, BitStream r)
        {
            var entityIndex = r.ReadMapEntityIndex();

            User user;
            Map map;
            if (!TryGetMap(conn, out user, out map))
                return;

            if (user.IsPeerTrading)
                return;

            var shopkeeper = map.GetDynamicEntity<Character>(entityIndex);
            if (shopkeeper == null)
                return;

            user.ShoppingState.TryStartShopping(shopkeeper);
        }
        void RecvUseWorld(IIPSocket conn, BitStream r)
        {
            var useEntityIndex = r.ReadMapEntityIndex();

            // Get the map and user
            User user;
            Map map;
            if (!TryGetMap(conn, out user, out map))
                return;

            if (user.IsPeerTrading)
                return;

            if (!user.IsAlive)
            {
                const string errmsg = "User `{0}` tried to use world entity while dead.";
                if (log.IsInfoEnabled)
                    log.InfoFormat(errmsg, user);
                return;
            }

            // Grab the DynamicEntity to use
            var useEntity = map.GetDynamicEntity(useEntityIndex);
            if (useEntity == null)
            {
                const string errmsg = "UseEntity received but usedEntityIndex `{0}` is not a valid DynamicEntity.";
                Debug.Fail(string.Format(errmsg, useEntityIndex));
                if (log.IsErrorEnabled)
                    log.ErrorFormat(errmsg, useEntityIndex);
                return;
            }

            // Ensure the used DynamicEntity is even usable
            var asUsable = useEntity as IUsableEntity;
            if (asUsable == null)
            {
                const string errmsg =
                    "UseEntity received but useByIndex `{0}` refers to DynamicEntity `{1}` which does " +
                    "not implement IUsableEntity.";
                Debug.Fail(string.Format(errmsg, useEntityIndex, useEntity));
                if (log.IsErrorEnabled)
                    log.WarnFormat(errmsg, useEntityIndex, useEntity);
                return;
            }

            // Use it
            if (asUsable.Use(user))
            {
                // Notify everyone in the map it was used
                if (asUsable.NotifyClientsOfUsage)
                {
                    using (var pw = ServerPacket.UseEntity(useEntity.MapEntityIndex, user.MapEntityIndex))
                    {
                        map.Send(pw, ServerMessageType.Map);
                    }
                }
            }
        }
        void RecvAttack(IIPSocket conn, BitStream r)
        {
            User user;
            MapEntityIndex? targetIndex = null;

            var hasTarget = r.ReadBool();
            if (hasTarget)
                targetIndex = r.ReadMapEntityIndex();

            if ((user = TryGetUser(conn)) != null)
            {
                if (user.IsPeerTrading)
                    return;

                user.Attack(GetTargetCharacter(user, targetIndex));
            }
        }
        void RecvRequestMapEntityIndex(IIPSocket conn, BitStream r)
        {
            var index = r.ReadMapEntityIndex();

            // Get the user and their map
            User user;
            if ((user = TryGetUser(conn)) == null)
                return;

            Map map;
            if (!TryGetMap(user, out map))
                return;

            // Get the DynamicEntity
            var de = map.GetDynamicEntity(index);

            if (de == null)
            {
                // The DynamicEntity for the index was null, so tell the client to delete whatever is at that index
                using (var pw = ServerPacket.RemoveDynamicEntity(index))
                {
                    conn.Send(pw, ServerMessageType.Map);
                }
            }
            else
            {
                // A DynamicEntity does exist at that index, so tell the client to create it
                using (var pw = ServerPacket.CreateDynamicEntity(de))
                {
                    conn.Send(pw, ServerMessageType.Map);
                }
            }
        }
        void RecvSkillStopCasting_ToMap(IIPSocket conn, BitStream r)
        {
            var casterEntityIndex = r.ReadMapEntityIndex();

            // Get the entity
            var casterEntity = _objGrabber.GetDynamicEntity<Character>(casterEntityIndex);
            if (casterEntity == null)
                return;

            // Set the entity as not casting
            casterEntity.IsCastingSkill = false;
        }
        void RecvStartChatDialog(IIPSocket conn, BitStream r)
        {
#pragma warning disable 168
            var npcIndex = r.ReadMapEntityIndex();
#pragma warning restore 168
            var dialogIndex = r.ReadNPCChatDialogID();

            var dialog = ClientNPCChatManager.Instance[dialogIndex];
            GameplayScreen.ChatDialogForm.StartDialog(dialog);
        }
 void RecvSynchronizeDynamicEntity(IIPSocket conn, BitStream r)
 {
     var mapEntityIndex = r.ReadMapEntityIndex();
     DynamicEntity e = Map.GetDynamicEntity(mapEntityIndex);
     e.Deserialize(r);
 }
        void RecvEmote(IIPSocket conn, BitStream r)
        {
            var mapEntityIndex = r.ReadMapEntityIndex();
            var emoticon = r.ReadEnum<Emoticon>();

            var entity = Map.GetDynamicEntity(mapEntityIndex);
            if (entity == null)
                return;

            EmoticonDisplayManager.Instance.Add(entity, emoticon, GetTime());
        }
        void RecvChatSay(IIPSocket conn, BitStream r)
        {
            var name = r.ReadString(GameData.MaxServerSayNameLength);
            var mapEntityIndex = r.ReadMapEntityIndex();
            var text = r.ReadString(GameData.MaxServerSayLength);

            var chatText = CreateChatText(name, text);
            GameplayScreen.AppendToChatOutput(chatText);

            var entity = Map.GetDynamicEntity(mapEntityIndex);
            if (entity == null)
                return;

            GameplayScreen.AddChatBubble(entity, text);
        }
        void RecvCreateDynamicEntity(IIPSocket conn, BitStream r)
        {
            var mapEntityIndex = r.ReadMapEntityIndex();
            var dynamicEntity = _dynamicEntityFactory.Read(r);
            Map.AddDynamicEntity(dynamicEntity, mapEntityIndex);

            var character = dynamicEntity as Character;
            if (character != null)
            {
                // HACK: Having to call this .Initialize() and pass these parameters seems hacky
                character.Initialize(Map, GameplayScreen.SkeletonManager);
            }

            if (log.IsInfoEnabled)
                log.InfoFormat("Created DynamicEntity with index `{0}` of type `{1}`", dynamicEntity.MapEntityIndex,
                    dynamicEntity.GetType());
        }
        void RecvCharDamage(IIPSocket conn, BitStream r)
        {
            var mapCharIndex = r.ReadMapEntityIndex();
            var damage = r.ReadInt();

            var chr = _objGrabber.GetDynamicEntity<Character>(mapCharIndex);
            if (chr == null)
                return;

            GameplayScreen.DamageTextPool.Create(damage, chr, GetTime());
        }
        void RecvCharAttack(IIPSocket conn, BitStream r)
        {
            // Read the values
            var attackerID = r.ReadMapEntityIndex();

            MapEntityIndex? attackedID;
            if (r.ReadBool())
                attackedID = r.ReadMapEntityIndex();
            else
                attackedID = null;

            ActionDisplayID? actionDisplayIDNullable;
            if (r.ReadBool())
                actionDisplayIDNullable = r.ReadActionDisplayID();
            else
                actionDisplayIDNullable = null;

            // Get the object references using the IDs provided
            var attacker = _objGrabber.GetDynamicEntity<Character>(attackerID);
            if (attacker == null)
                return;

            DynamicEntity attacked = attackedID.HasValue ? Map.GetDynamicEntity(attackedID.Value) : null;

            // Use the default ActionDisplayID if we were provided with a null value
            ActionDisplayID actionDisplayID = !actionDisplayIDNullable.HasValue ? GameData.DefaultActionDisplayID : actionDisplayIDNullable.Value;

            // Get the ActionDisplay to use and, if valid, execute it
            var actionDisplay = ActionDisplayScripts.ActionDisplays[actionDisplayID];
            if (actionDisplay != null)
                actionDisplay.Execute(Map, attacker, attacked);
        }
        void RecvUseEntity(IIPSocket conn, BitStream r)
        {
            var usedEntityIndex = r.ReadMapEntityIndex();
            var usedByIndex = r.ReadMapEntityIndex();

            // Grab the used DynamicEntity
            var usedEntity = _objGrabber.GetDynamicEntity<IUsableEntity>(usedEntityIndex);
            if (usedEntity == null)
                return;

            // Grab the one who used this DynamicEntity (we can still use it, we'll just pass null)
            var usedBy = Map.GetDynamicEntity(usedByIndex);
            if (usedBy == null)
                return;

            // Use it
            usedEntity.Use(usedBy);
        }
        void RecvCreateActionDisplayAtEntity(IIPSocket conn, BitStream r)
        {
            ActionDisplayID actionDisplayId = r.ReadActionDisplayID();
            MapEntityIndex sourceEntityIndex = r.ReadMapEntityIndex();
            bool hasTarget = r.ReadBool();
            MapEntityIndex? targetEntityIndex = hasTarget ? r.ReadMapEntityIndex() : (MapEntityIndex?)null;

            // Get the entities
            var sourceEntity = _objGrabber.GetDynamicEntity<Character>(sourceEntityIndex);
            if (sourceEntity == null)
                return;

            var targetEntity = targetEntityIndex.HasValue ? _objGrabber.GetDynamicEntity<Character>(targetEntityIndex.Value) : null;

            // Get the action display
            var ad = ActionDisplayScripts.ActionDisplays[actionDisplayId];
            if (ad == null)
                return;

            // Create
            ad.Execute(Map, sourceEntity, targetEntity);
        }
        void RecvNotifyLevel(IIPSocket conn, BitStream r)
        {
            var mapCharIndex = r.ReadMapEntityIndex();

            var chr = _objGrabber.GetDynamicEntity<Character>(mapCharIndex);
            if (chr == null)
                return;

            var message = GameMessageCollection.CurrentLanguage.GetMessage(GameMessage.CombatSelfLevelUp, UserInfo.Level.ToString());

            if (chr == World.UserChar)
                GameplayScreen.InfoBox.Add(message);
        }
        void RecvSkillStartCasting_ToMap(IIPSocket conn, BitStream r)
        {
            var casterEntityIndex = r.ReadMapEntityIndex();
            var skillType = r.ReadEnum<SkillType>();

            // Get the SkillInfo for the skill being used
            var skillInfo = _objGrabber.GetSkillInfo(skillType);
            if (skillInfo == null)
                return;

            // Get the entity
            var casterEntity = _objGrabber.GetDynamicEntity<Character>(casterEntityIndex);
            if (casterEntity == null)
                return;

            // If an ActionDisplay is available for this skill, display it
            if (skillInfo.StartCastingActionDisplay.HasValue)
            {
                var ad = ActionDisplayScripts.ActionDisplays[skillInfo.StartCastingActionDisplay.Value];
                if (ad != null)
                {
                    casterEntity.IsCastingSkill = true;
                    ad.Execute(Map, casterEntity, null);
                }
            }
        }
        void RecvPlaySoundAtEntity(IIPSocket conn, BitStream r)
        {
            var soundID = r.ReadSoundID();
            var index = r.ReadMapEntityIndex();

            var entity = Map.GetDynamicEntity(index);
            if (entity == null)
                return;

            if (!SoundManager.Play(soundID, entity))
                LogFailPlaySound(soundID);
        }
        void RecvSkillUse(IIPSocket conn, BitStream r)
        {
            var casterEntityIndex = r.ReadMapEntityIndex();
            var hasTarget = r.ReadBool();
            MapEntityIndex? targetEntityIndex = null;
            if (hasTarget)
                targetEntityIndex = r.ReadMapEntityIndex();
            var skillType = r.ReadEnum<SkillType>();

            var casterEntity = _objGrabber.GetDynamicEntity<CharacterEntity>(casterEntityIndex);
            CharacterEntity targetEntity = null;
            if (targetEntityIndex.HasValue)
                targetEntity = _objGrabber.GetDynamicEntity<CharacterEntity>(targetEntityIndex.Value);

            if (casterEntity == null)
                return;

            // Get the SkillInfo for the skill being used
            var skillInfo = _objGrabber.GetSkillInfo(skillType);
            if (skillInfo == null)
                return;

            // If an ActionDisplay is available for this skill, display it
            if (skillInfo.CastActionDisplay.HasValue)
            {
                var ad = ActionDisplayScripts.ActionDisplays[skillInfo.CastActionDisplay.Value];
                if (ad != null)
                    ad.Execute(Map, casterEntity, targetEntity);
            }
        }
        void RecvRemoveDynamicEntity(IIPSocket conn, BitStream r)
        {
            var mapEntityIndex = r.ReadMapEntityIndex();
            var dynamicEntity = Map.GetDynamicEntity(mapEntityIndex);

            if (dynamicEntity == null)
                return;

            Map.RemoveEntity(dynamicEntity);

            if (log.IsInfoEnabled)
                log.InfoFormat("Removed DynamicEntity with index `{0}`", mapEntityIndex);

            dynamicEntity.Dispose();
        }
        void RecvStartQuestChatDialog(IIPSocket conn, BitStream r)
        {
            var npcIndex = r.ReadMapEntityIndex();

            // Available quests
            var numAvailableQuests = r.ReadByte();
            var availableQuests = new QuestID[numAvailableQuests];
            for (var i = 0; i < availableQuests.Length; i++)
            {
                availableQuests[i] = r.ReadQuestID();
            }

            // Quests that can be turned in
            var numTurnInQuests = r.ReadByte();
            var turnInQuests = new QuestID[numTurnInQuests];
            for (var i = 0; i < turnInQuests.Length; i++)
            {
                turnInQuests[i] = r.ReadQuestID();
            }

            // For the quests that are available, make sure we set their status to not being able to be turned in (just in case)
            foreach (var id in availableQuests)
            {
                UserInfo.HasFinishQuestRequirements.SetRequirementsStatus(id, false);
            }

            // For the quests that were marked as being able to turn in, set their status to being able to be finished
            foreach (var id in turnInQuests)
            {
                UserInfo.HasFinishQuestRequirements.SetRequirementsStatus(id, true);
            }

            // Grab the descriptions for both the available quests and quests we can turn in
            var qds = availableQuests.Concat(turnInQuests).Distinct().Select(x => _questDescriptions.GetOrDefault(x)).ToArray();

            // Display the form
            GameplayScreen.AvailableQuestsForm.Display(qds, npcIndex);
        }
        void RecvSetCharacterMPPercent(IIPSocket conn, BitStream r)
        {
            var mapEntityIndex = r.ReadMapEntityIndex();
            var percent = r.ReadByte();

            var character = _objGrabber.GetDynamicEntity<Character>(mapEntityIndex);
            if (character == null)
                return;

            character.MPPercent = percent;
        }
        void RecvPickupItem(IIPSocket conn, BitStream r)
        {
            var mapEntityIndex = r.ReadMapEntityIndex();

            User user;
            Map map;
            if (!TryGetMap(conn, out user, out map))
                return;

            // Get the item
            var item = map.GetDynamicEntity<ItemEntityBase>(mapEntityIndex);
            if (item == null)
                return;

            // Ensure the distance is valid
            if (!GameData.IsValidPickupDistance(user, item))
            {
                const string errmsg = "User `{0}` failed to pick up item `{1}` - distance was too great.";
                if (log.IsInfoEnabled)
                    log.InfoFormat(errmsg, user, item);
                return;
            }

            // Pick it up
            item.Pickup(user);
        }
        void RecvSetCharacterPaperDoll(IIPSocket conn, BitStream r)
        {
            var mapEntityIndex = r.ReadMapEntityIndex();
            var count = r.ReadByte();

            var layers = new string[count];
            for (var i = 0; i < layers.Length; i++)
            {
                layers[i] = r.ReadString();
            }

            var character = _objGrabber.GetDynamicEntity<Character>(mapEntityIndex);
            if (character == null)
                return;

            character.CharacterSprite.SetPaperDollLayers(layers);
        }
        void RecvStartNPCChatDialog(IIPSocket conn, BitStream r)
        {
            var npcIndex = r.ReadMapEntityIndex();
            var forceSkipQuestDialog = r.ReadBool();

            User user;
            Map map;
            if (!TryGetMap(conn, out user, out map))
                return;

            if (user.IsPeerTrading)
                return;

            var npc = map.GetDynamicEntity<NPC>(npcIndex);
            if (npc == null)
                return;

            // Check the distance and state
            if (user.Map != npc.Map || user.Map == null || !npc.IsAlive || npc.IsDisposed || user.GetDistance(npc) > GameData.MaxNPCChatDistance)
                return;

            // If the NPC provides any quests that this user can do or turn in, show that instead
            if (!forceSkipQuestDialog && !npc.Quests.IsEmpty())
            {
                IQuest<User>[] availableQuests;
                IQuest<User>[] turnInQuests;
                QuestHelper.GetAvailableQuests(user, npc, out availableQuests, out turnInQuests);

                if (availableQuests.Length > 0 || turnInQuests.Length > 0)
                {
                    using (var pw = ServerPacket.StartQuestChatDialog(npcIndex, availableQuests.Select(x => x.QuestID), turnInQuests.Select(x => x.QuestID)))
                    {
                        user.Send(pw, ServerMessageType.GUI);
                    }
                    return;
                }
            }

            // Force-skipped the quest dialog, or there was no available quests, so start the chat dialog
            user.ChatState.StartChat(npc);
        }
        void RecvSetProvidedQuests(IIPSocket conn, BitStream r)
        {
            var mapEntityIndex = r.ReadMapEntityIndex();
            var count = r.ReadByte();
            var questIDs = new QuestID[count];
            for (var i = 0; i < count; i++)
            {
                questIDs[i] = r.ReadQuestID();
            }

            var character = _objGrabber.GetDynamicEntity<Character>(mapEntityIndex);
            if (character != null)
                character.ProvidedQuests = questIDs;
        }
        void RecvUseSkill(IIPSocket conn, BitStream r)
        {
            SkillType skillType;
            MapEntityIndex? targetIndex = null;

            // Get the SkillType to use
            try
            {
                skillType = r.ReadEnum<SkillType>();
            }
            catch (InvalidCastException)
            {
                const string errmsg = "Failed to read SkillType from stream.";
                if (log.IsWarnEnabled)
                    log.Warn(errmsg);
                Debug.Fail(errmsg);
                r.ReadBool();
                return;
            }

            // Check for a target
            var hasTarget = r.ReadBool();
            if (hasTarget)
                targetIndex = r.ReadMapEntityIndex();

            // Get the user
            User user;
            if ((user = TryGetUser(conn)) != null)
            {
                // Check that they know the skill
                if (!user.KnownSkills.Knows(skillType))
                    user.Send(GameMessage.SkillNotKnown, ServerMessageType.GUIChat);
                else
                {
                    // Use the skill
                    user.UseSkill(skillType, GetTargetCharacter(user, targetIndex));
                }
            }
        }
 void RecvSetUserChar(IIPSocket conn, BitStream r)
 {
     var mapCharIndex = r.ReadMapEntityIndex();
     World.UserCharIndex = mapCharIndex;
 }
        void RecvAcceptOrTurnInQuest(IIPSocket conn, BitStream r)
        {
            var providerIndex = r.ReadMapEntityIndex();
            var questID = r.ReadQuestID();

            // Get the user
            User user;
            if ((user = TryGetUser(conn)) == null || user.Map == null)
                return;

            if (user.IsPeerTrading)
                return;

            // Get the provider
            var npc = user.Map.GetDynamicEntity<Character>(providerIndex);
            var provider = npc as IQuestProvider<User>;
            if (provider == null)
                return;

            // Check the distance and state
            if (user.Map != npc.Map || user.Map == null || !npc.IsAlive || npc.IsDisposed ||
                user.GetDistance(npc) > GameData.MaxNPCChatDistance)
                return;

            // Get the quest
            var quest = _questManager.GetQuest(questID);
            if (quest == null)
                return;

            // Ensure this provider even provides this quest
            if (!provider.Quests.Contains(quest))
                return;

            // If the user already has the quest, try to turn it in
            if (user.ActiveQuests.Contains(quest))
            {
                // Quest already started, try to turn in
                var success = user.TryFinishQuest(quest);
                using (var pw = ServerPacket.AcceptOrTurnInQuestReply(questID, success, false))
                {
                    user.Send(pw, ServerMessageType.GUI);
                }
            }
            else
            {
                // Quest not started yet, try to add it
                var success = user.TryAddQuest(quest);
                using (var pw = ServerPacket.AcceptOrTurnInQuestReply(questID, success, true))
                {
                    user.Send(pw, ServerMessageType.GUI);
                }
            }
        }
        void RecvStartShopping(IIPSocket conn, BitStream r)
        {
            var shopOwnerIndex = r.ReadMapEntityIndex();
            var canBuy = r.ReadBool();
            var name = r.ReadString();
            var itemCount = r.ReadByte();

            var items = new IItemTemplateTable[itemCount];
            for (var i = 0; i < itemCount; i++)
            {
                var value = new ItemTemplateTable();
                value.ReadState(r);
                items[i] = value;
            }

            var shopOwner = Map.GetDynamicEntity(shopOwnerIndex);
            var shopInfo = new ShopInfo<IItemTemplateTable>(shopOwner, name, canBuy, items);

            GameplayScreen.ShopForm.DisplayShop(shopInfo);
        }