Exemplo n.º 1
0
        public static void WritePacketLength(this SpanWriter writer)
        {
            var length = writer.Position;

            writer.Seek(1, SeekOrigin.Begin);
            writer.Write((ushort)length);
            writer.Seek(length, SeekOrigin.Begin);
        }
Exemplo n.º 2
0
        public static int CreateMessageLocalized(
            Span <byte> buffer,
            Serial serial, int graphic, MessageType type, int hue, int font, int number, string name = "", string args = ""
            )
        {
            name ??= "";
            args ??= "";

            if (hue == 0)
            {
                hue = 0x3B2;
            }

            var writer = new SpanWriter(buffer);

            writer.Write((byte)0xC1);
            writer.Seek(2, SeekOrigin.Current);
            writer.Write(serial);
            writer.Write((short)graphic);
            writer.Write((byte)type);
            writer.Write((short)hue);
            writer.Write((short)font);
            writer.Write(number);
            writer.WriteAscii(name, 30);
            writer.WriteLittleUniNull(args);

            writer.WritePacketLength();
            return(writer.Position);
        }
Exemplo n.º 3
0
        public void Terminate()
        {
            int length = _position + 4;

            if (length != _buffer.Length)
            {
                Resize(length);
            }

            var writer = new SpanWriter(_buffer);

            writer.Seek(_position, SeekOrigin.Begin);
            writer.Write(0);

            writer.Seek(11, SeekOrigin.Begin);
            writer.Write(_hash);
            writer.WritePacketLength();
        }
Exemplo n.º 4
0
        public static int CreateMessage(
            Span <byte> buffer,
            Serial serial,
            int graphic,
            MessageType type,
            int hue,
            int font,
            bool ascii,
            string lang,
            string name,
            string text
            )
        {
            if (buffer[0] != 0)
            {
                return(buffer.Length);
            }

            name ??= "";
            text ??= "";
            lang ??= "ENU";

            if (hue == 0)
            {
                hue = 0x3B2;
            }

            var writer = new SpanWriter(buffer);

            writer.Write((byte)(ascii ? 0x1C : 0xAE)); // Packet ID
            writer.Seek(2, SeekOrigin.Current);
            writer.Write(serial);
            writer.Write((short)graphic);
            writer.Write((byte)type);
            writer.Write((short)hue);
            writer.Write((short)font);
            if (ascii)
            {
                writer.WriteAscii(name, 30);
                writer.WriteAsciiNull(text);
            }
            else
            {
                writer.WriteAscii(lang, 4);
                writer.WriteAscii(name, 30);
                writer.WriteBigUniNull(text);
            }

            writer.WritePacketLength();
            return(writer.Position);
        }
Exemplo n.º 5
0
        public ObjectPropertyList(IEntity e)
        {
            Entity  = e;
            _buffer = GC.AllocateUninitializedArray <byte>(64);

            var writer = new SpanWriter(_buffer);

            writer.Write((byte)0xD6); // Packet ID
            writer.Seek(2, SeekOrigin.Current);
            writer.Write((ushort)1);
            writer.Write(e.Serial);
            writer.Write((ushort)0);
            _position = writer.Position + 4; // Hash
        }
Exemplo n.º 6
0
        private static void WritePacked(ReadOnlySpan <byte> source, ref SpanWriter writer, out int length)
        {
            var size = source.Length;
            var dest = writer.RawBuffer.Slice(writer.Position + 3);

            length = dest.Length;

            var ce = Zlib.Pack(dest, ref length, source, ZlibQuality.Default);

            if (ce != ZlibError.Okay)
            {
                Console.WriteLine("ZLib error: {0} (#{1})", ce, (int)ce);
                length = 0;
                size   = 0;
            }

            writer.Write((byte)size);
            writer.Write((byte)length);
            writer.Write((byte)(((size >> 4) & 0xF0) | ((length >> 8) & 0xF)));
            writer.Seek(length, SeekOrigin.Current);
        }
Exemplo n.º 7
0
        public void Add(int number, string arguments = null)
        {
            if (number == 0)
            {
                return;
            }

            arguments ??= "";

            if (Header == 0)
            {
                Header     = number;
                HeaderArgs = arguments;
            }

            AddHash(number);
            if (arguments.Length > 0)
            {
                AddHash(arguments.GetHashCode(StringComparison.Ordinal));
            }

            int strLength = Utility.Unicode.GetByteCount(arguments);

            int length = _position + 6 + strLength;

            while (length > _buffer.Length)
            {
                Flush();
            }

            var writer = new SpanWriter(_buffer);

            writer.Seek(_position, SeekOrigin.Begin);
            writer.Write(number);
            writer.Write((ushort)strLength);
            writer.WriteBigUni(arguments);
        }
Exemplo n.º 8
0
 public static void WritePacketLength(this SpanWriter writer)
 {
     writer.Seek(1, SeekOrigin.Begin);
     writer.Write((ushort)writer.BytesWritten);
     writer.Seek(0, SeekOrigin.End);
 }
Exemplo n.º 9
0
            (Zlib.MaxPackSize(stairsPerBuffer * stairsLength) + 4) * stairsCount; // 22602

        public static byte[] CreateHouseDesignStateDetailed(uint serial, int revision, MultiComponentList components)
        {
            var xMin  = components.Min.X;
            var yMin  = components.Min.Y;
            var xMax  = components.Max.X;
            var yMax  = components.Max.Y;
            var tiles = components.List;

            const int totalPlaneLength   = planeLength * planeCount;
            const int stairsBufferLength = stairsPerBuffer * stairsLength;
            const int maxUnpackedSize    = totalPlaneLength + stairsBufferLength * stairsCount;

            using var inflatedWriter = new SpanWriter(maxUnpackedSize);

            Span <bool> planesUsed      = stackalloc bool[9];
            var         index           = 0;
            var         stairsIndex     = totalPlaneLength;
            var         totalStairsUsed = 0;
            var         width           = xMax - xMin + 1;
            var         height          = yMax - yMin + 1;

            for (var i = 0; i < tiles.Length; ++i)
            {
                var mte   = tiles[i];
                var x     = mte.OffsetX - xMin;
                var y     = mte.OffsetY - yMin;
                int z     = mte.OffsetZ;
                var floor = TileData.ItemTable[mte.ItemId & TileData.MaxItemValue].Height <= 0;

                int plane = z switch
                {
                    0 => 0,
                    7 => 1,
                    27 => 2,
                    47 => 3,
                    67 => 4,
                    _ => - 1
                };

                if (plane > -1)
                {
                    int size;
                    if (plane == 0)
                    {
                        size = height;
                    }
                    else if (floor)
                    {
                        size = height - 2;
                        x   -= 1;
                        y   -= 1;
                    }
                    else
                    {
                        size   = height - 1;
                        plane += 4;
                    }

                    index = (x * size + y) * 2;
                    if (x >= 0 && y >= 0 && y < size && index + 1 < 0x400)
                    {
                        var planeUsed = planesUsed[plane];
                        if (!planeUsed)
                        {
                            inflatedWriter.Seek(plane * planeLength, SeekOrigin.Begin);
                            inflatedWriter.Clear(planeLength);
                            planesUsed[plane] = true;
                        }

                        inflatedWriter.Seek(index, SeekOrigin.Begin);
                        inflatedWriter.Write(mte.ItemId);
                        continue;
                    }
                }

                inflatedWriter.Seek(stairsIndex, SeekOrigin.Begin);
                inflatedWriter.Write(mte.ItemId);
                inflatedWriter.Write((byte)mte.OffsetX);
                inflatedWriter.Write((byte)mte.OffsetY);
                inflatedWriter.Write((byte)mte.OffsetZ);
                stairsIndex = inflatedWriter.Position;
                totalStairsUsed++;
            }

            var buffer = GC.AllocateUninitializedArray <byte>(maxPacketLength);
            var writer = new SpanWriter(buffer);

            writer.Write((byte)0xD8);           // Packet ID
            writer.Seek(2, SeekOrigin.Current); // Length

            writer.Write((byte)0x03);           // Compression Type
            writer.Write((byte)0x00);           // Unknown
            writer.Write(serial);
            writer.Write(revision);
            writer.Write((short)tiles.Length);
            writer.Seek(3, SeekOrigin.Current); // Buffer Length, Plane Count

            var totalPlanes = 0;
            var totalLength = 1; // includes plane count

            for (var i = 0; i < planeCount; i++)
            {
                if (!planesUsed[i])
                {
                    inflatedWriter.Seek(planeCount, SeekOrigin.Current);
                    continue;
                }

                int size = i switch
                {
                    0 => width * height * 2,
                    < 5 => (width - 1) * (height - 2) * 2,
                    _ => width * (height - 1) * 2
                };

                var source = inflatedWriter.RawBuffer.Slice(i * planeLength, size);

                writer.Write((byte)(0x20 | i));
                WritePacked(source, ref writer, out int destLength);

                totalLength += 4 + destLength;
                totalPlanes++;
            }

            index = 0;
            while (totalStairsUsed > 0)
            {
                var count = Math.Min(stairsPerBuffer, totalStairsUsed);
                totalStairsUsed -= count;

                var start  = totalPlaneLength + index * stairsLength;
                var size   = count * 5;
                var source = inflatedWriter.RawBuffer.Slice(start, size);

                writer.Write((byte)(9 + index++));
                WritePacked(source, ref writer, out int destLength);
                totalLength += 4 + destLength;
                totalPlanes++;
            }

            writer.Seek(15, SeekOrigin.Begin);
            writer.Write((short)totalLength);
            writer.Write((byte)totalPlanes);
            writer.WritePacketLength();

            // TODO: Avoid this somehow.
            Array.Resize(ref buffer, writer.BytesWritten);
            return(buffer);
        }
Exemplo n.º 10
0
        public static void SendDisplayGump(this NetState ns, Gump gump, out int switches, out int entries)
        {
            switches = 0;
            entries  = 0;

            if (ns == null)
            {
                return;
            }

            var packed = ns.Unpack;

            var writer = new SpanWriter(512, true);

            writer.Write((byte)(packed ? 0xDD : 0xB0)); // Packet ID
            writer.Seek(2, SeekOrigin.Current);

            writer.Write(gump.Serial);
            writer.Write(gump.TypeID);
            writer.Write(gump.X);
            writer.Write(gump.Y);

            var spanWriter = new SpanWriter(512, true);

            if (!gump.Draggable)
            {
                spanWriter.Write(Gump.NoMove);
            }

            if (!gump.Closable)
            {
                spanWriter.Write(Gump.NoClose);
            }

            if (!gump.Disposable)
            {
                spanWriter.Write(Gump.NoDispose);
            }

            if (!gump.Resizable)
            {
                spanWriter.Write(Gump.NoResize);
            }

            var stringsList = new OrderedHashSet <string>(11);

            foreach (var entry in gump.Entries)
            {
                entry.AppendTo(ref spanWriter, stringsList, ref entries, ref switches);
            }

            if (packed)
            {
                spanWriter.Write((byte)0); // Layout text terminator
                WritePacked(ref writer, spanWriter.Span);
            }
            else
            {
                writer.Write((ushort)spanWriter.BytesWritten);
                writer.Write(spanWriter.Span);
            }

            if (packed)
            {
                writer.Write(stringsList.Count);
            }
            else
            {
                writer.Write((ushort)stringsList.Count);
            }

            spanWriter.Seek(0, SeekOrigin.Begin);

            foreach (var str in stringsList)
            {
                var s = str ?? "";
                spanWriter.Write((ushort)s.Length);
                spanWriter.WriteBigUni(s);
            }

            if (packed)
            {
                WritePacked(ref writer, spanWriter.Span);
            }
            else
            {
                writer.Write(spanWriter.Span);
            }

            writer.WritePacketLength();

            ns.Send(writer.Span);
            spanWriter.Dispose(); // Can't use using and refs, so we dispose manually
        }