示例#1
0
        public static void SendMapDetails(this NetState ns, MapItem map)
        {
            if (ns.CannotSendPackets())
            {
                return;
            }

            var writer = new SpanWriter(stackalloc byte[ns.NewCharacterList ? 21 : 19]);

            writer.Write((byte)(ns.NewCharacterList ? 0xF5 : 0x90)); // Packet ID
            writer.Write(map.Serial);
            writer.Write((short)0x139D);

            var bounds = map.Bounds;

            writer.Write((short)bounds.Start.X);
            writer.Write((short)bounds.Start.Y);
            writer.Write((short)bounds.End.X);
            writer.Write((short)bounds.End.Y);
            writer.Write((short)map.Width);
            writer.Write((short)map.Height);

            if (ns.NewCharacterList)
            {
                writer.Write((short)(map.Facet?.MapID ?? 0));
            }

            ns.Send(writer.Span);
        }
示例#2
0
        public static void SendArrow(this NetState ns, byte command, int x, int y, Serial s)
        {
            if (ns.CannotSendPackets())
            {
                return;
            }

            var writer = new SpanWriter(stackalloc byte[10]);

            writer.Write((byte)0xBA); // Packet ID
            writer.Write(command);

            if (ns.HighSeas)
            {
                writer.Write((short)x);
                writer.Write((short)y);
                writer.Write(s);
            }
            else if (command == 1)
            {
                writer.Write((short)x);
                writer.Write((short)y);
            }
            else
            {
                writer.Write((short)-1);
                writer.Write((short)-1);
            }

            ns.Send(writer.Span);
        }
示例#3
0
        public static void SendPartyMemberLocations(this NetState ns, Mobile from, Party party)
        {
            if (ns.CannotSendPackets())
            {
                return;
            }

            var count     = party?.Members.Count ?? 0;
            var maxLength = 9 + (count > 1 ? (count - 1) * 9 : 0);
            var writer    = new SpanWriter(stackalloc byte[maxLength]);

            writer.Write((byte)0xF0); // Packet ID
            writer.Seek(2, SeekOrigin.Current);
            writer.Write((byte)0x01); // Command

            bool sendPacket = false;

            for (var i = 0; i < count; i++)
            {
                var    pmi = party !.Members[i];
                Mobile mob = pmi?.Mobile;

                if (mob?.NetState == null || mob == from)
                {
                    continue;
                }

                if (Utility.InUpdateRange(from.Location, mob.Location) && from.CanSee(mob))
                {
                    continue;
                }

                sendPacket = true;
                writer.Write(mob.Serial);
                writer.Write((short)mob.X);
                writer.Write((short)mob.Y);
                writer.Write((byte)(mob.Map?.MapID ?? 0));
            }

            if (!sendPacket)
            {
                return;
            }

            writer.Write(0);
            writer.WritePacketLength();
            ns.Send(writer.Span);
        }
示例#4
0
        public static void SendMapCommand(this NetState ns, MapItem map, int command, int x = 0, int y = 0, bool editable = false)
        {
            if (ns.CannotSendPackets())
            {
                return;
            }

            var writer = new SpanWriter(stackalloc byte[11]);

            writer.Write((byte)0x56); // Packet ID
            writer.Write(map.Serial);
            writer.Write((byte)command);
            writer.Write(editable);
            writer.Write((short)x);
            writer.Write((short)y);

            ns.Send(writer.Span);
        }
示例#5
0
        public static void SendExtendedShardStats(
            this NetState ns, string name, int age, int clients, int items, int mobiles, int mem
            )
        {
            if (ns.CannotSendPackets())
            {
                return;
            }

            var str =
                $"ModernUO, Name={name}, Age={age}, Clients={clients}, Items={items}, Chars={mobiles}, Mem={mem}K, Ver=2";

            var length = Encoding.UTF8.GetMaxByteCount(str.Length);

            Span <byte> span = stackalloc byte[length + 1];

            Encoding.UTF8.GetBytes(str, span);
            span[^ 1] = 0; // Terminator
示例#6
0
        public static void SendCorpseEquip(this NetState ns, Mobile beholder, Corpse beheld)
        {
            if (ns.CannotSendPackets())
            {
                return;
            }

            var list = beheld.EquipItems;

            var maxLength = 8 + (list.Count + 2) * 5;
            var writer    = new SpanWriter(stackalloc byte[maxLength]);

            writer.Write((byte)0x89);
            writer.Seek(2, SeekOrigin.Current);
            writer.Write(beheld.Serial);

            for (var i = 0; i < list.Count; ++i)
            {
                var item = list[i];

                if (!item.Deleted && beholder.CanSee(item) && item.Parent == beheld)
                {
                    writer.Write((byte)(item.Layer + 1));
                    writer.Write(item.Serial);
                }
            }

            if (beheld.Hair?.ItemID > 0)
            {
                writer.Write((byte)(Layer.Hair + 1));
                writer.Write(HairInfo.FakeSerial(beheld.Owner.Serial) - 2);
            }

            if (beheld.FacialHair?.ItemID > 0)
            {
                writer.Write((byte)(Layer.FacialHair + 1));
                writer.Write(FacialHairInfo.FakeSerial(beheld.Owner.Serial) - 2);
            }

            writer.Write((byte)Layer.Invalid);

            writer.WritePacketLength();
            ns.Send(writer.Span);
        }
示例#7
0
        public static void SendCompactShardStats(
            this NetState ns, uint age, int clients, int items, int mobiles, long mem
            )
        {
            if (ns.CannotSendPackets())
            {
                return;
            }

            var writer = new SpanWriter(stackalloc byte[27]);

            writer.Write((byte)0x51); // Packet ID
            writer.Write((ushort)27); // Length
            writer.Write(clients);
            writer.Write(items);
            writer.Write(mobiles);
            writer.Write(age);
            writer.Write(mem);

            ns.Send(writer.Span);
        }
示例#8
0
        public static void SendBBDisplayBoard(this NetState ns, BaseBulletinBoard board)
        {
            if (ns.CannotSendPackets())
            {
                return;
            }

            var writer = new SpanWriter(stackalloc byte[38]);

            writer.Write((byte)0x71); // Packet ID
            writer.Write((ushort)38);
            writer.Write((byte)0x00); // Command
            writer.Write(board.Serial);

            var text = board.BoardName ?? "";

            var         textChars  = text.AsSpan(0, Math.Min(text.Length, 30));
            Span <byte> textBuffer = stackalloc byte[TextEncoding.UTF8.GetMaxByteCount(textChars.Length)]; // Max 30 * 3 (90 bytes)

            // We are ok with the string being cut-off mid character. The alternative is very slow.
            var byteLength = Math.Min(29, TextEncoding.UTF8.GetBytes(textChars, textBuffer));

            writer.Write(textBuffer[..byteLength]);
示例#9
0
        public static void SendGuildMemberLocations(this NetState ns, Mobile from, Guild guild, bool sendLocations)
        {
            if (ns.CannotSendPackets())
            {
                return;
            }

            var count     = guild?.Members.Count ?? 0;
            var maxLength = 9 + (count > 1 ? (count - 1) * (sendLocations ? 10 : 4) : 0);
            var writer    = new SpanWriter(stackalloc byte[maxLength]);

            writer.Write((byte)0xF0); // Packet ID
            writer.Seek(2, SeekOrigin.Current);
            writer.Write((byte)0x02); // Command
            writer.Write(count > 0 && sendLocations);

            bool sendPacket = false;

            for (var i = 0; i < count; i++)
            {
                var m = guild !.Members[i];

                if (m?.NetState == null || m == from)
                {
                    continue;
                }

                if (sendLocations && Utility.InUpdateRange(from.Location, m.Location) && from.CanSee(m))
                {
                    continue;
                }

                sendPacket = true;
                writer.Write(m.Serial);

                if (sendLocations)
                {
                    writer.Write((short)m.X);
                    writer.Write((short)m.Y);
                    writer.Write((byte)(m.Map?.MapID ?? 0));

                    if (m.Alive)
                    {
                        writer.Write((byte)(m.Hits * 100 / Math.Max(m.HitsMax, 1)));
                    }
                    else
                    {
                        writer.Write((byte)0);
                    }
                }
            }

            if (!sendPacket)
            {
                return;
            }

            writer.Write(0);
            writer.WritePacketLength();
            ns.Send(writer.Span);
        }
示例#10
0
        public static void SendCorpseContent(this NetState ns, Mobile beholder, Corpse beheld)
        {
            if (ns.CannotSendPackets())
            {
                return;
            }

            var list             = beheld.EquipItems;
            var hairItemID       = beheld.Hair?.ItemID ?? 0;
            var facialHairItemID = beheld.FacialHair?.ItemID ?? 0;
            var count            = list.Count;

            if (hairItemID > 0)
            {
                count++;
            }

            if (facialHairItemID > 0)
            {
                count++;
            }

            var maxLength = 5 + count * (ns.ContainerGridLines ? 20 : 19);
            var writer    = new SpanWriter(stackalloc byte[maxLength]);

            writer.Write((byte)0x3C);
            writer.Seek(4, SeekOrigin.Current); // Length and Count

            var written = 0;

            for (var i = 0; i < list.Count; ++i)
            {
                var child = list[i];

                if (!child.Deleted && child.Parent == beheld && beholder.CanSee(child))
                {
                    writer.Write(child.Serial);
                    writer.Write((ushort)child.ItemID);
                    writer.Write((byte)0); // signed, itemID offset
                    writer.Write((ushort)child.Amount);
                    writer.Write((short)child.X);
                    writer.Write((short)child.Y);
                    if (ns.ContainerGridLines)
                    {
                        writer.Write((byte)0); // Grid Location?
                    }
                    writer.Write(beheld.Serial);
                    writer.Write((ushort)child.Hue);

                    ++written;
                }
            }

            if (hairItemID > 0)
            {
                writer.Write(HairInfo.FakeSerial(beheld.Owner.Serial) - 2);
                writer.Write((ushort)hairItemID);
                writer.Write((byte)0); // signed, itemID offset
                writer.Write((ushort)1);
                writer.Write(0);       // X/Y
                if (ns.ContainerGridLines)
                {
                    writer.Write((byte)0); // Grid Location?
                }
                writer.Write(beheld.Serial);
                writer.Write((ushort)beheld.Hair !.Hue);

                ++written;
            }

            if (facialHairItemID > 0)
            {
                writer.Write(FacialHairInfo.FakeSerial(beheld.Owner.Serial) - 2);
                writer.Write((ushort)facialHairItemID);
                writer.Write((byte)0); // signed, itemID offset
                writer.Write((ushort)1);
                writer.Write(0);       // X/Y
                if (ns.ContainerGridLines)
                {
                    writer.Write((byte)0); // Grid Location?
                }
                writer.Write(beheld.Serial);
                writer.Write((ushort)beheld.FacialHair !.Hue);

                ++written;
            }

            writer.Seek(1, SeekOrigin.Begin);
            writer.Write((ushort)writer.BytesWritten);
            writer.Write((ushort)written);
            writer.Seek(0, SeekOrigin.End);
            ns.Send(writer.Span);
        }