예제 #1
0
        public static void Send_SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA(Character chr)
        {
            using (var packet = new RealmPacketOut(RealmServerOpCode.SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA, 0))
            {
				chr.Send(packet);
            }
        }
예제 #2
0
		public static void SendInBounds(Character duelist)
		{
            using (var packet = new RealmPacketOut(RealmServerOpCode.SMSG_DUEL_INBOUNDS,4))
            {
                duelist.Send(packet);
            }
		}
예제 #3
0
        public void SendSpontaneousUpdate(Character receiver, bool visible, params UpdateFieldId[] indices)
        {
            var highestIndex = 0;

            foreach (var index in indices)
            {
                if (index.RawId > highestIndex)
                {
                    highestIndex = index.RawId;
                }
            }

            var mask = new UpdateMask(highestIndex);

            using (var packet = new UpdatePacket(1024))
            {
                packet.Position = 4;                                                            // jump over header
                packet.Write(1);                                                                // Update Count
                packet.Write((byte)UpdateType.Values);
                EntityId.WritePacked(packet);
                WriteSpontaneousUpdate(mask, packet, receiver, indices, visible);

                receiver.Send(packet);
            }
        }
예제 #4
0
		public static void SendCountdown(Character duelist, uint millis)
		{
            using (var packet = new RealmPacketOut(RealmServerOpCode.SMSG_DUEL_COUNTDOWN, 4))
            {
                packet.Write(millis);

                duelist.Send(packet);
            }
		}
예제 #5
0
 public static void SendTitleEarned(Character character, CharacterTitleEntry titleEntry, bool lost)
 {
     using (var packet = new RealmPacketOut(RealmServerOpCode.SMSG_TITLE_EARNED, 4 + 4))
     {
         packet.WriteUInt((uint) titleEntry.BitIndex);
         packet.WriteUInt(lost ? 0 : 1);
         character.Send(packet);
     }
 }
예제 #6
0
		public static void SendOutOfBounds(Character duelist, uint cancelDelayMillis)
		{
            using (var packet = new RealmPacketOut(RealmServerOpCode.SMSG_DUEL_OUTOFBOUNDS, 4))
            {
                packet.Write(cancelDelayMillis);

                duelist.Send(packet);
            }
		}
예제 #7
0
        public void SendOutOfRangeUpdate(Character receiver, HashSet <WorldObject> worldObjects)
        {
            using (var packet = new UpdatePacket(1024))
            {
                packet.Position = 4;                                                            // jump over header
                packet.Write(1);                                                                // Update Count
                packet.Write((byte)UpdateType.OutOfRange);
                packet.Write(worldObjects.Count);
                foreach (var worldObject in worldObjects)
                {
                    worldObject.EntityId.WritePacked(packet);
                }

                receiver.Send(packet);
            }
        }
예제 #8
0
        /// <summary>
        /// Sends the quest update complete.
        /// </summary>
        /// <param name="chr">The character.</param>
        public static void SendQuestUpdateComplete(Character chr, uint questId)
        {
            using (var packet = new RealmPacketOut(RealmServerOpCode.SMSG_QUESTUPDATE_COMPLETE))
            {
                packet.Write(questId);

                chr.Send(packet);
            }
        }
예제 #9
0
        /// <summary>
        /// Sends the quest update failed timer.
        /// </summary>
        /// <param name="qst">The QST.</param>
        /// <param name="chr">The character</param>
        public static void SendQuestUpdateFailedTimer(Character chr, Quest qst)
        {
            using (var packet = new RealmPacketOut(RealmServerOpCode.SMSG_QUESTUPDATE_FAILEDTIMER))
            {
                packet.Write(qst.Template.Id);

                chr.Send(packet);
            }
        }
예제 #10
0
        public static void SendQuestCompletedQueryResponse(Character chr)
        {
            using (var packet = new RealmPacketOut(RealmServerOpCode.SMSG_QUERY_QUESTS_COMPLETED_RESPONSE, 4))
            {
                packet.Write(chr.QuestLog.FinishedQuests.Count);
                foreach (var entry in chr.QuestLog.FinishedQuests)
                {
                    packet.Write(entry);
                }

                chr.Send(packet);
            }
        }
예제 #11
0
        /// <summary>
        /// Sends the quest invalid.
        /// </summary>
        /// <param name="chr">The character.</param>
        /// <param name="reason">The reason.</param>
        public static void SendQuestInvalid(Character chr, QuestInvalidReason reason)
        {
            using (var packet = new RealmPacketOut(RealmServerOpCode.SMSG_QUESTGIVER_QUEST_INVALID, 4))
            {
                packet.Write((int)reason);

                chr.Send(packet);
            }
        }
예제 #12
0
        public static void SendStatusEnqueued(Character chr,
			int index,
            BattlegroundRelation relation,
			BattlegroundQueue queue)
        {
            var status = BattlegroundStatus.Enqueued;

            using (var packet = new RealmPacketOut(RealmServerOpCode.SMSG_BATTLEFIELD_STATUS))
            {
				packet.Write(index);

                var bgId = queue.Template.Id;

                // 64-bit guid start
                packet.Write((byte)ArenaType.None);
                packet.Write((byte)1);              // affects level range calculation?
                packet.Write((uint)bgId);
                packet.Write((ushort)8080);
                // 64-bit guid stop

				packet.Write((byte)0);				// since 3.3
				packet.Write((byte)0);				// since 3.3
                packet.Write(queue.InstanceId);     // instance id
                packet.Write(false);                // bool isRatedMatch
                packet.Write((int)status);

                packet.Write(queue.AverageWaitTime);					// avg wait time for queue, in ms
                packet.Write((int)relation.QueueTime.TotalMilliseconds); // time in the queue, also in ms

                chr.Send(packet);
            }
        }
예제 #13
0
파일: NPCHandler.cs 프로젝트: NVN/WCell
		public static void SendBankSlotResult(Character chr, BuyBankBagResponse response)
		{
			using (var packet = new RealmPacketOut(RealmServerOpCode.SMSG_BUY_BANK_SLOT_RESULT, 4))
			{
				packet.Write((uint)response);
				chr.Send(packet);
			}
		}
예제 #14
0
		public static void SendPetGUIDs(Character chr)
		{
			if (chr.ActivePet == null)
			{
				using (var packet = new RealmPacketOut(RealmServerOpCode.SMSG_PET_GUIDS, 12))
				{
					packet.Write(0); // list count
					chr.Send(packet);
				}
			}
			else
			{
				using (var packet = new RealmPacketOut(RealmServerOpCode.SMSG_PET_GUIDS, 12))
				{
					packet.Write(1); // list count
					packet.Write(chr.ActivePet.EntityId);
					chr.Send(packet);
				}
			}
		}
예제 #15
0
        public static void SendDungeonDifficulty(Character chr)
        {
            using (var packet = new RealmPacketOut(RealmServerOpCode.MSG_SET_DUNGEON_DIFFICULTY, 12))
            {
                var group = chr.Group;
                if (group != null && !group.Flags.HasFlag(GroupFlags.Raid))
                {
                    packet.Write(group.DungeonDifficulty);
                    packet.Write(1); // val
                    packet.Write(1); // isingroup
                }
                else // this is wrong? one packet def should be enough
                {
                    packet.Write((int)chr.Record.DungeonDifficulty);
                    packet.Write(1);
                    packet.Write(0);
                }

                chr.Send(packet);
            }
        }
예제 #16
0
		/// <summary>
		/// Sends spell modifier update
		/// </summary>
		public static void SendSpellModifier(Character chr, byte groupBitNumber, SpellModifierType type, int amount, bool isPercent)
		{
			var opcode = isPercent ? RealmServerOpCode.SMSG_SET_PCT_SPELL_MODIFIER :
				RealmServerOpCode.SMSG_SET_FLAT_SPELL_MODIFIER;
			using (var packet = new RealmPacketOut(opcode, 6))
			{
				packet.Write(groupBitNumber);
				packet.Write((byte) type);
				packet.Write(amount);

				chr.Send(packet);
			}
		}
예제 #17
0
		/// <summary>
		/// Parses any incoming whispers.
		/// </summary>
		/// <param name="type">the type of chat message indicated by the client</param>
		/// <param name="language">the chat language indicated by the client</param>
		/// <param name="packet">the actual chat message packet</param>
		private static void WhisperParser(Character sender, ChatMsgType type, ChatLanguage language, RealmPacketIn packet)
		{
			var recipient = packet.ReadCString();
			var msg = ReadMessage(packet);

			if (msg.Length == 0)
				return;

			if (RealmCommandHandler.HandleCommand(sender, msg, sender.Target as Character))
				return;

			var targetChr = World.GetCharacter(recipient, false);
			if (targetChr == null)
			{
				SendChatPlayerNotFoundReply(sender.Client, recipient);
				return;
			}

			if (targetChr.Faction.Group != sender.Faction.Group)
			{
				SendChatPlayerWrongTeamReply(sender.Client);
				return;
			}

			if (targetChr.IsIgnoring(sender))
			{
				using (var packetOut = CreateCharChatMessage(ChatMsgType.Ignored, ChatLanguage.Universal, targetChr, sender, null, msg))
				{
					sender.Send(packetOut);
				}
			}
			else
			{
				using (var packetOut = CreateCharChatMessage(ChatMsgType.Whisper, ChatLanguage.Universal, sender, targetChr, null, msg))
				{
					targetChr.Send(packetOut);
				}
			}

			using (var packetOut = CreateCharChatMessage(ChatMsgType.MsgReply, ChatLanguage.Universal, targetChr, targetChr, null, msg, sender.ChatTag))
			{
				sender.Send(packetOut);
			}

			// handle afk/dnd situations
			if (targetChr.IsAFK)
			{
				using (var packetOut = CreateCharChatMessage(ChatMsgType.AFK, ChatLanguage.Universal, targetChr, sender, null, targetChr.AFKReason, targetChr.ChatTag))
				{
					sender.Send(packetOut);
				}
			}

			if (targetChr.IsDND)
			{
				using (var packetOut = CreateCharChatMessage(ChatMsgType.DND, ChatLanguage.Universal, targetChr, sender, null, string.Empty, targetChr.ChatTag))
				{
					sender.Send(packetOut);
				}
			}
		}
예제 #18
0
		/// <summary>
		/// Forces the client to start or update a cooldown timer on the given single spell
		/// (mostly important for certain talents and item spells that don't automatically start cooling down)
		/// </summary>
		public static void SendCooldownUpdate(Character chr, SpellId spellId)
		{
			using (var packet = new RealmPacketOut(RealmServerOpCode.SMSG_COOLDOWN_EVENT, 12))
			{
				packet.WriteUInt((uint)spellId);
				chr.EntityId.WritePacked(packet);

				chr.Send(packet);
			}
		}
예제 #19
0
파일: NPCHandler.cs 프로젝트: NVN/WCell
		public static void SendTrainerList(this NPC trainer, Character chr, IEnumerable<TrainerSpellEntry> spells,
										   string msg)
		{
			using (
				var packet = new RealmPacketOut(RealmServerOpCode.SMSG_TRAINER_LIST, 8 + 4 + 4 + (30 * 38) + msg.Length + 1))
			{
				packet.Write(trainer.EntityId);
				packet.Write((uint)trainer.TrainerEntry.TrainerType);

				var countPos = packet.Position;
				packet.Position += 4;

				var spellCount = 0;
				foreach (var trainerSpell in spells)
				{
					if (!chr.CanLearn(trainerSpell))
					{
						continue;
					}

					var spell = trainerSpell.Spell;
					if (spell.IsTeachSpell)
					{
						spell = spell.LearnSpell;
					}

					//packet.Position = offset  + (spell.Index * entryLength);
					packet.Write(trainerSpell.Spell.Id);
					packet.Write((byte)trainerSpell.GetTrainerSpellState(chr));
					packet.Write(trainerSpell.GetDiscountedCost(chr, trainer));
					packet.Write(spell.Talent != null ? 1u : 0u);						// talent cost
					packet.Write(trainerSpell.Spell.IsProfession && trainerSpell.Spell.TeachesApprenticeAbility ? 1 : 0);	// Profession cost
					packet.Write((byte)trainerSpell.RequiredLevel);
					packet.Write((uint)trainerSpell.RequiredSkillId);
					packet.Write(trainerSpell.RequiredSkillAmount);
					packet.Write((uint)trainerSpell.RequiredSpellId);

					// The following are infrequent Ids of some sort - Possibly spell replacements?
					packet.Write(0u);
					packet.Write(0u);
					++spellCount;
				}

				packet.Write(msg);

				packet.Position = countPos;
				packet.Write(spellCount);

				chr.Send(packet);
			}
		}
예제 #20
0
파일: NPCHandler.cs 프로젝트: NVN/WCell
		/// <summary>
		/// Send the vendor's list of items for sale to the client. 
		/// *All allowable race and class checks should be done prior to calling this method.
		/// *All checks on number-limited items should also be done prior to calling this method.
		/// *This method can handle up to 256 items per vendor. If you try to send more items than that, 
		/// this method will send only the first 256. 
		/// </summary>
		/// <param name="client">The client to send the packet to.</param>
		/// <param name="itemsForSale">An array of items to send to the client.</param>
		public static void SendVendorInventoryList(Character buyer, NPC vendor, List<VendorItemEntry> itemsForSale)
		{
			var numItems = (itemsForSale.Count <= 0xFF) ? itemsForSale.Count : 0xFF;

			using (var packet = new RealmPacketOut(RealmServerOpCode.SMSG_LIST_INVENTORY, 10 + (28 * numItems)))
			{
				packet.Write(vendor.EntityId);
				packet.Write((byte)numItems);
				if (numItems == 0)
				{
					packet.Write((byte)VendorInventoryError.NoInventory);
				}
				else
				{
					for (var i = 0; i < numItems; ++i)
					{
						// Write in the item number (1 - 256)
						packet.Write(i + 1);

						var item = itemsForSale[i];
						var price = buyer.Reputations.GetDiscountedCost(vendor.Faction.ReputationIndex, item.Template.BuyPrice);

						packet.Write(item.Template.Id);
						packet.Write(item.Template.DisplayId);
						packet.Write(item.RemainingStockAmount);
						packet.Write(price);
						packet.Write(item.Template.MaxDurability);
						packet.Write(item.BuyStackSize);
						packet.Write(item.ExtendedCostId);
					}
				}
				buyer.Send(packet);
			}
		}
예제 #21
0
 public static void SendQuestLogFull(Character chr)
 {
     using (var pckt = new RealmPacketOut(RealmServerOpCode.SMSG_QUESTLOG_FULL))
     {
         chr.Send(pckt);
     }
 }
예제 #22
0
		/// <summary>
		/// Sends any kind of extra command-bar to control other entities, such as NPCs, vehicles etc
		/// </summary>
		/// <param name="owner"></param>
		//public static void SendSpells(Character owner, NPC npc, uint duration,
		//    PetAttackMode attackMode, PetAction action, PetFlags flags,
		//    PetActionEntry[] petActions,
		//    PetSpell[] spells)

		public static void SendSpells(Character owner, NPC pet, PetAction currentAction)
		{
			// TODO: Cooldowns
			var record = pet.PetRecord;
            var mode = pet.Entry.Type == CreatureType.NonCombatPet ? PetAttackMode.Passive : PetAttackMode.Defensive;
		    var flags = PetFlags.None;
		    uint[] actions = null;
            if(record != null)
            {
                mode = record.AttackMode;
                flags = record.Flags;
                actions = record.ActionButtons;
            }
            if (actions == null)
                actions = pet.BuildPetActionBar();

		    using (var packet = new RealmPacketOut(RealmServerOpCode.SMSG_PET_SPELLS, 20 + (PetConstants.PetActionCount * 4) + 1 + (pet.Spells.Count) + 1 + (0)))
			{
				packet.Write(pet.EntityId);
				packet.Write((ushort)pet.Entry.FamilyId);
				packet.Write(pet.RemainingDecayDelayMillis);			// duration
				packet.Write((byte)mode);
				packet.Write((byte)currentAction);
				packet.Write((ushort)flags);

				for (var i = 0; i < PetConstants.PetActionCount; i++)
				{
					var action = actions[i];
					packet.Write(action);
				}

				var spellPos = packet.Position;
				++packet.Position;
				var spellCount = 0;
				foreach (var spell in pet.Spells)
				{
					if (!spell.IsPassive)
					{
						packet.Write((ushort)spell.Id);
                        packet.Write((ushort)PetSpellState.Enabled);
						++spellCount;
					}
				}

				packet.Write((byte)0);		// TODO: Cooldowns

				packet.Position = spellPos;
				packet.Write((byte)spellCount);

				owner.Send(packet);
			}
		}
예제 #23
0
 public static void SendQuestPushResult(Character receiver, QuestPushResponse qpr, Character giver)
 {
     using (var pckt = new RealmPacketOut(RealmServerOpCode.MSG_QUEST_PUSH_RESULT))
     {
         pckt.Write(receiver.EntityId);
         pckt.Write((byte)qpr);
         giver.Send(pckt);
     }
 }
예제 #24
0
        public static void SendStatusActive(Character chr, Battleground bg, int queueIndex)
        {
            var status = BattlegroundStatus.Active;
            var side = chr.FactionGroup.GetBattlegroundSide();

            using (var packet = new RealmPacketOut(RealmServerOpCode.SMSG_BATTLEFIELD_STATUS))
            {
				packet.Write(queueIndex);

                var bgId = bg.Template.Id;

                // 64-bit guid start
                packet.Write((byte)ArenaType.None);
                packet.Write((byte)1); // affects level range calculation?
                packet.Write((uint)bgId);
                packet.Write((ushort)8080);
                // 64-bit guid stop

				packet.Write((byte)0);				// since 3.3
				packet.Write((byte)0);				// since 3.3
                packet.Write(bg.InstanceId); // instance id
                packet.Write((byte)0); // bool isRatedMatch
                packet.Write((int)status);

                packet.Write((int)bg.Id);

                // the number of milliseconds before the Battlefield will close after a battle is finished.
                // This is 0 before the battle is finished
                packet.Write(bg.RemainingShutdownDelay);

                // start time, in ms. clientGetTickCount - this = instance runtime
                packet.Write(bg.RuntimeMillis);
                packet.Write((byte)side); // arena faction - 0 or 1
                chr.Send(packet);
            }
        }
예제 #25
0
        public static void SendBattlefieldList(Character chr, GlobalBattlegroundQueue queue)
        {
            using (var packet = new RealmPacketOut(RealmServerOpCode.SMSG_BATTLEFIELD_LIST))
            {
                var fromGUI = true;

                packet.Write((long)0);
                packet.Write(fromGUI);							// since 3.1.1
				packet.Write((uint)queue.Template.Id);
				packet.Write((byte)queue.BracketId);			// BracketId
				packet.Write((byte)0);							// since 3.3

                var pos = packet.Position;
                packet.Position += 4;

                var count = 0;
                for (var i = 0; i < queue.Instances.Count; i++)
                {
                    var bg = queue.Instances[i];
                    if (chr.Role.IsStaff || bg.CanEnter(chr))
                    {
                        packet.Write(bg.InstanceId);
                        count++;
                    }
                }

                packet.Position = pos;
                packet.Write(count);

                chr.Send(packet);
            }
        }
예제 #26
0
		public void SendOutOfRangeUpdate(Character receiver, HashSet<WorldObject> worldObjects)
		{
			using (var packet = new UpdatePacket(1024))
			{
				packet.Position = 4;						// jump over header
				packet.Write(1);							// Update Count
				packet.Write((byte)UpdateType.OutOfRange);
				packet.Write(worldObjects.Count);
				foreach (var worldObject in worldObjects)
				{
					worldObject.EntityId.WritePacked(packet);
				}

				receiver.Send(packet);
			}
		}
예제 #27
0
        public static void SendStatusInvited(Character chr, int inviteTimeout)
        {
            var status = BattlegroundStatus.Preparing;
            var invite = chr.Battlegrounds.Invitation;

            using (var packet = new RealmPacketOut(RealmServerOpCode.SMSG_BATTLEFIELD_STATUS))
            {
                packet.Write(invite.QueueIndex);

                var bg = invite.Team.Battleground;
                var bgId = bg.Template.Id;

                // 64-bit guid start
                packet.Write((byte)ArenaType.None);
                packet.Write((byte)1); // affects level range calculation?
                packet.Write((uint)bgId);
                packet.Write((ushort)8080);
                // 64-bit guid stop

				packet.Write((byte)0);				// since 3.3
				packet.Write((byte)0);				// since 3.3
                packet.Write(bg.InstanceId); // instance id
                packet.Write((byte)chr.FactionGroup.GetBattlegroundSide()); // bool isRatedMatch
                packet.Write((int)status);

				packet.Write((int)bg.Id);
                packet.Write(inviteTimeout);

                chr.Send(packet);
            }
        }
예제 #28
0
파일: PetHandler.cs 프로젝트: MeaNone/WCell
		/// <summary>
		/// Sends any kind of extra command-bar to control other entities, such as NPCs, vehicles etc
		/// </summary>
		/// <param name="owner"></param>
		//public static void SendSpells(Character owner, NPC npc, uint duration,
		//    PetAttackMode attackMode, PetAction action, PetFlags flags,
		//    PetActionEntry[] petActions,
		//    PetSpell[] spells)

		public static void SendSpells(Character owner, NPC pet, PetAction currentAction)
		{
			// TODO: Cooldowns
			var record = pet.PetRecord;
			using (var packet = new RealmPacketOut(RealmServerOpCode.SMSG_PET_SPELLS, 20 + (PetConstants.PetActionCount * 4) + 1 + (pet.Spells.Count) + 1 + (0)))
			{
				packet.Write(pet.EntityId);
				packet.Write((ushort)pet.Entry.FamilyId);
				//packet.Write((ushort)0);
				packet.Write(pet.RemainingDecayDelayMillis);			// duration
				packet.Write((byte)record.AttackMode);
				packet.Write((byte)currentAction);
				packet.Write((ushort)record.Flags);

				var actions = record.ActionButtons;
				for (var i = 0; i < PetConstants.PetActionCount; i++)
				{
					var action = actions[i];
					packet.Write(action);
				}

				var spellPos = packet.Position;
				++packet.Position;
				var spellCount = 0;
				foreach (var spell in pet.Spells)
				{
					if (!spell.IsPassive)
					{
						packet.Write(spell.Id | ((uint)PetSpellState.Enabled << 24));
						++spellCount;
					}
				}

				packet.Write((byte)0);		// TODO: Cooldowns

				packet.Position = spellPos;
				packet.Write((byte)spellCount);

				owner.Send(packet);
			}
		}
예제 #29
0
		public static void SendAttackSwingNotInRange(Character chr)
		{
			using (var packet = new RealmPacketOut(RealmServerOpCode.SMSG_ATTACKSWING_NOTINRANGE))
			{
				chr.Send(packet);
			}
		}
예제 #30
0
		public void SendSpontaneousUpdate(Character receiver, bool visible, params UpdateFieldId[] indices)
		{
			var highestIndex = 0;
			foreach (var index in indices)
			{
				if (index.RawId > highestIndex)
				{
					highestIndex = index.RawId;
				}
			}

			var mask = new UpdateMask(highestIndex);
			using (var packet = new UpdatePacket(1024))
			{
				packet.Position = 4;						// jump over header
				packet.Write(1);							// Update Count
				packet.Write((byte)UpdateType.Values);
				EntityId.WritePacked(packet);
				WriteSpontaneousUpdate(mask, packet, receiver, indices, visible);

				receiver.Send(packet);
			}
		}
예제 #31
0
        public static void SendPlayerPossessedPetSpells(Character owner, Character possessed)
        {

            using (var packet = new RealmPacketOut(RealmServerOpCode.SMSG_PET_SPELLS, 20 + (PetConstants.PetActionCount * 4) + 1 + (0) + 1 + (0)))
            {
                packet.Write(possessed.EntityId);
                packet.Write((ushort) CreatureFamilyId.None);
                packet.Write(0); // duration
                packet.Write((byte) PetAttackMode.Passive);
                packet.Write((byte) PetAction.Stay);
                packet.Write((ushort) PetFlags.None);

                var action = new PetActionEntry
                                 {
                                     Action = PetAction.Attack,
                                     Type = PetActionType.SetAction
                                 }.Raw;

                packet.Write(action);

                for (var i = 1; i < PetConstants.PetActionCount; i++)
                {
                    action = new PetActionEntry
                                 {
                                     Type = PetActionType.SetAction
                                 }.Raw;
                    packet.Write(action);
                }

                packet.Write((byte) 0); // No Spells

                packet.Write((byte) 0); // No Cooldowns

                owner.Send(packet);
            }
        }
예제 #32
0
        /// <summary>
        /// Sends the Item's PushResult (required after adding items).
        /// </summary>
        public static void SendItemPushResult(Character owner, Item item, ItemTemplate templ, int amount, ItemReceptionType reception)
        {
            bool isStacked;
            int contSlot;
            uint propertySeed, randomPropid;
            if (item != null)
            {
                contSlot = item.Container.Slot;
                isStacked = item.Amount != amount; // item.Amount == amount means that it was not added to an existing stack
                propertySeed = item.PropertySeed;
                randomPropid = item.RandomPropertiesId;
            }
            else
            {
                contSlot = BaseInventory.INVALID_SLOT;
                isStacked = true;													// we did not have an item -> stacked
                propertySeed = 0;
                randomPropid = 0;
            }

            using (var packet = new RealmPacketOut(RealmServerOpCode.SMSG_ITEM_PUSH_RESULT, 45))
            {
                packet.Write(owner.EntityId);
                packet.Write((ulong)reception);

                //packet.Write(received ? 1 : 0);										// 0 = "You looted...", 1 = "You received..."
                //packet.Write(isNew ? 1 : 0);										// 0 = "You received/looted...", 1 = "You created..."

                packet.Write(1);													// log message
                packet.Write((byte)contSlot);
                packet.Write(isStacked ? -1 : item.Slot);
                packet.Write(templ.Id);
                packet.Write(propertySeed);
                packet.Write(randomPropid);
                packet.Write(amount);												// amount added
                packet.Write(owner.Inventory.GetAmount(templ.ItemId));				// amount of that type of item in inventory

                owner.Send(packet);
            }
        }