/// <summary> /// Adds a new npc to the character's client. /// </summary> /// <param name="character">The client to add npc for.</param> /// <param name="npc">The npc to add.</param> /// <param name="mainPacket">The packet composer to append bits to.</param> public static void AddNewNpc(Character character, Npc npc, PacketComposer mainPacket) { mainPacket.AppendBits(15, npc.Index); mainPacket.AppendBits(14, npc.CacheIndex); mainPacket.AppendBits(1, npc.UpdateFlags.UpdateRequired ? 1 : 0); int xPos = npc.Location.X - character.Location.X; int yPos = npc.Location.Y - character.Location.Y; if (xPos < 0) { xPos += 32; } if (yPos < 0) { yPos += 32; } mainPacket.AppendBits(5, yPos); mainPacket.AppendBits(5, xPos); mainPacket.AppendBits(3, 0); mainPacket.AppendBits(1, 1); }
/// <summary> /// Constructs the npc rendering packet. /// </summary> /// <param name="character">Character to send rendered npcs to.</param> /// <param name="allNpcs">A list of npcs that are spawned on the server.</param> public NpcRenderingPacketComposer(Character character, List <Npc> allNpcs) { SetOpcode(222); SetType(PacketType.Short); InitializeBit(); // The update block. Any updates that are pending will be added to this block. GenericPacketComposer updateBlock = new GenericPacketComposer(); AppendBits(8, character.LocalNpcs.Count); // A bin of npcs that have been removed during local npc updating. List <Npc> npcBin = new List <Npc>(); character.LocalNpcs.ForEach((npc) => { if (GameEngine.World.NpcManager.Spawns.Values.Contains(npc) && npc.Location.WithinDistance(character.Location) && !character.UpdateFlags.Teleporting) { UpdateMovement(npc, this); // Update the npc is required, since it is conditionally valid. if (npc.UpdateFlags.UpdateRequired) { RenderMasks.AppendMasks(npc, updateBlock); } } else { // Remove this npc, as it doesn't meet local standards. npcBin.Add(npc); // Signify the client that this npc needs to be removed. AppendBits(1, 1); AppendBits(2, 3); } }); // Remove all binned npcs. npcBin.ForEach((npc) => character.LocalNpcs.Remove(npc)); // Search for npcs that may qualify for locality. foreach (Npc npc in allNpcs) { // We cannot have more than 255 npcs in the client simultaneously. if (character.LocalNpcs.Count >= 255) { break; } if (character.LocalNpcs.Contains(npc) || !npc.Location.WithinDistance(character.Location)) { continue; } character.LocalNpcs.Add(npc); AddNewNpc(character, npc, this); // Update the npc if required. if (npc.UpdateFlags.UpdateRequired) { RenderMasks.AppendMasks(npc, updateBlock); } } // Finalize the composition. if (updateBlock.Position >= 3) { AppendBits(15, 32767); } FinishBit(); if (updateBlock.Position > 0) { AppendBytes(updateBlock.SerializeBuffer()); } }