/// <summary> /// Notifies the User about the new page. /// </summary> void NotifyUserOfNewPage() { if (_dialogItem == null) { // Dialog has ended using (var pw = ServerPacket.EndChatDialog()) { _user.Send(pw, ServerMessageType.GUI); } } else { // New page using (var pw = ServerPacket.SetChatDialogPage(_dialogItem.ID, GetResponsesToSkip())) { _user.Send(pw, ServerMessageType.GUI); } } }
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 RecvGetFriends(IIPSocket conn, BitStream r) { var account = TryGetAccount(conn); if (account == null) { return; } User user; if ((user = TryGetUser(conn)) == null) { return; } string FriendsString = account.Friends; List <string> FriendsList = FriendsString.Split(',').ToList <string>(); string OnlineFriendsString = ""; string FriendsMap = ""; var OnlineMembers = Server.World.GetUsers(); foreach (var Member in OnlineMembers) { if (FriendsList.Contains(Member.Name)) { OnlineFriendsString += Member.Name + ","; var parentMap = World.GetMap(Member.Map.ParentMapID); FriendsMap += parentMap.Name + ","; } } using (var pw = ServerPacket.ReceiveFriends(OnlineFriendsString, FriendsMap, FriendsString)) { user.Send(pw, ServerMessageType.GUI); } }
/// <summary> /// When overridden in the derived class, allows for handling when the status of an <see cref="IIPSocket"/> changes. /// </summary> /// <param name="sender">The <see cref="IIPSocket"/> who's status has changed.</param> /// <param name="status">The new status.</param> /// <param name="reason">The reason for the status change.</param> protected override void OnReceiveStatusChanged(IIPSocket sender, NetConnectionStatus status, string reason) { base.OnReceiveStatusChanged(sender, status, reason); switch (status) { case NetConnectionStatus.Disconnected: // If there was an account on the socket, destroy it var acc = World.GetUserAccount(sender, false); if (acc != null) { acc.Dispose(); } break; case NetConnectionStatus.Connected: // Send the server time to the client using (var pw = ServerPacket.SetGameTime(DateTime.Now)) { sender.Send(pw, ServerMessageType.GUI); } break; } }
/// <summary> /// Updates the client with the changes that have been made to the UserInventory. /// </summary> public void Update() { // Don't actually grab the PacketWriter from the pool until we know we will need it PacketWriter pw = null; try { // Loop through all slots for (var slot = 0; slot < GameData.MaxInventorySize; slot++) { // Skip unchanged slots if (!_slotChanged[slot]) { continue; } // Get the item in the slot var invSlot = new InventorySlot(slot); var item = UserInventory[invSlot]; // Get the values to send, which depends on if the slot is empty (item == null) or not GrhIndex sendItemGraphic; byte sendItemAmount; if (item == null) { sendItemGraphic = GrhIndex.Invalid; sendItemAmount = 0; } else { sendItemGraphic = item.GraphicIndex; sendItemAmount = item.Amount; } // Grab the PacketWriter if we have not already, or clear it if we have if (pw == null) { pw = ServerPacket.GetWriter(); } else { pw.Reset(); } // Pack the data and send it ServerPacket.SetInventorySlot(pw, invSlot, sendItemGraphic, sendItemAmount); OwnerUser.Send(pw, ServerMessageType.GUIItems); } } finally { // If we grabbed a PacketWriter, make sure we dispose of it! if (pw != null) { pw.Dispose(); } } // Changes complete _slotChanged.SetAll(false); }
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 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); } } } }
/// <summary> /// Tells the skill user to start using the given <paramref name="skill"/>. This is more of a suggestion than a /// request since the skill user does not actually have to start casting the skill. If this skill user decides /// to use the skill, the CurrentCastingSkill must be set to the <paramref name="skill"/>. /// </summary> /// <param name="skill">The skill to be used.</param> /// <param name="target">The optional character to use the skill on. Can be null.</param> /// <returns>True if the <paramref name="skill"/> started being casted; otherwise false. This does not indicate /// whether or not the skill was or will be successfully used, just that it was attempted to be used. Common /// times this will return false is if there is a skill already being casted, or if the skill that was /// attempted to be used still needs to cool down.</returns> public bool TryStartCastingSkill(ISkill <SkillType, StatType, Character> skill, Character target) { if (!_character.IsAlive) { return(false); } // Check that the character knows the skill if (!_character.KnownSkills.Knows(skill.SkillType)) { return(false); } // Don't interrupt a skill that the character is already casting if (IsCastingSkill) { return(false); } // Check that the group is available for usage if (_cooldownManager.IsCoolingDown(skill.CooldownGroup, _character.GetTime())) { return(false); } // Only allow immediate-usage skills when moving if (_character.Velocity != Vector2.Zero && skill.CastingTime > 0) { return(false); } if (skill.CastingTime == 0) { // The skill to use has no usage delay, so use it immediately UseSkill(skill, target, true); } else { // The skill does have a delay, so queue it for usage _currentCastingSkill = skill; _castingSkillTarget = target; var castingTime = skill.CastingTime; _castingSkillUsageTime = _character.GetTime() + castingTime; // Tell the character the details about the skill they are casting if (_character is INetworkSender) { using (var pw = ServerPacket.SkillStartCasting_ToUser(skill.SkillType, castingTime)) { ((INetworkSender)_character).Send(pw, ServerMessageType.GUIUserStatus); } } // Tell the users on the map that the character is casting using (var pw = ServerPacket.SkillStartCasting_ToMap(_character.MapEntityIndex, skill.SkillType)) { _character.Map.Send(pw, ServerMessageType.MapDynamicEntityProperty); } } return(true); }
protected void SynchronizePercentage() { const int _updatePercentDiff = 2; // Check if the percentage has changed int maxHP = _character.ModStats[StatType.MaxHP]; int maxMP = _character.ModStats[StatType.MaxMP]; if (maxHP < 1) { const string errmsg = "MaxHP is less than 1 for Character `{0}`!"; if (log.IsErrorEnabled) { log.ErrorFormat(errmsg, _character); } Debug.Fail(string.Format(errmsg, _character)); return; } var newHPPercent = (byte)(((float)_character.HP / maxHP) * 100.0f); byte newMPPercent = 100; if (maxMP > 0) { newMPPercent = (byte)(((float)_character.MP / maxMP) * 100.0f); } var updateHP = Math.Abs(newHPPercent - _lastSentHPPercent) >= _updatePercentDiff; var updateMP = Math.Abs(newMPPercent - _lastSentMPPercent) >= _updatePercentDiff; if (!updateHP && !updateMP) { return; } _lastSentHPPercent = newHPPercent; _lastSentMPPercent = newMPPercent; // Get the map var map = _character.Map; if (map == null) { return; } // Get the users to send the update to (excluding this character) var users = map.Users; if (_isUser) { users = users.Where(x => x != _character); } if (users.Count() == 0) { return; } // Send the updates using (var pw = ServerPacket.GetWriter()) { if (updateHP) { pw.Reset(); ServerPacket.SetCharacterHPPercent(pw, _character.MapEntityIndex, newHPPercent); foreach (var user in users) { user.Send(pw, ServerMessageType.MapCharacterSP); } } if (updateMP) { pw.Reset(); ServerPacket.SetCharacterMPPercent(pw, _character.MapEntityIndex, newMPPercent); foreach (var user in users) { user.Send(pw, ServerMessageType.MapCharacterSP); } } } }