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); }
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); }
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); }
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); }
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
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); }
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); }
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]);
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); }
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); }