Beispiel #1
0
        /// <summary>
        /// Writes a standard response: the only thing this will ever respond with
        /// </summary>
        /// <param name="index"></param>
        /// <param name="opcode"></param>
        /// <returns></returns>
        private async Task WriteResponse(ulong index, ushort opcode)
        {
            //This includes just 10 bytes:
            //  8 bytes: The index of the request
            //  2 bytes: The response opcode. 0 means that all is good

            //Create payload
            byte[] payload = new byte[10];
            BinaryTool.WriteUInt64(payload, 0, index);
            BinaryTool.WriteUInt16(payload, 8, opcode);

            //Send
            await SendData(payload);
        }
        public async Task WriteBinaryResponse(List <DbInventory> inventories)
        {
            //Binary mode writes out structures in binary structs
            //In format header, name table, inventory struct

            //HEADER FORMAT:
            //  4   static  Signature, says "DWMI"
            //  4   int32   File type version, should be 1
            //  4   int32   RESERVED
            //  4   int32   Inventory count

            //  4   int32   Saved epoch
            //  4   int32   Name table entry count
            //  4   int32   RESERVED
            //  4   int32   RESERVED
            //TOTAL: 32 bytes

            //The name table comes next, and is just a list of classnames, with a byte indicating their length before

            //Inventory Struct format:
            //  8   int64   Holder ID
            //  1   byte    Holder type
            //  2   int16   Item count
            //  4   int32   Tribe ID
            //  ?   Item[]  Items
            //TOTAL: VARIABLE

            //Item struct format:
            //  8   int64   Item ID
            //  4   int32   Name table classname index
            //  4   float   Durability
            //  2   int16   Stack size
            //  2   int16   Flags
            //  1   byte    Custom data count
            //  ?   CD[]    Custom datas, number specified above
            //Total: VARIABLE

            //CD (Custom Data) format:
            //  2   int16   Tag
            //  2   int16   String length
            //  ?   string  Data

            //Set headers
            e.Response.ContentType = "application/octet-stream";
            e.Response.StatusCode  = 200;

            //Create name table
            List <string> names = new List <string>();

            foreach (var i in inventories)
            {
                foreach (var ii in i.items)
                {
                    if (!names.Contains(ii.classname))
                    {
                        names.Add(ii.classname);
                    }
                }
            }

            //Create and send file header
            byte[] buf = new byte[32768];
            buf[0] = 0x44;
            buf[1] = 0x57;
            buf[2] = 0x4D;
            buf[3] = 0x49;
            BinaryTool.WriteInt32(buf, 4, 2); //Version tag
            BinaryTool.WriteInt32(buf, 8, 0);
            BinaryTool.WriteInt32(buf, 12, inventories.Count);
            BinaryTool.WriteInt32(buf, 16, 0); //Was epoch, now unused
            BinaryTool.WriteInt32(buf, 20, names.Count);
            BinaryTool.WriteInt32(buf, 24, 0);
            BinaryTool.WriteInt32(buf, 28, 0);
            await e.Response.Body.WriteAsync(buf, 0, 32);

            //Send name table
            foreach (var name in names)
            {
                //Write to buffer
                byte[] d = Encoding.UTF8.GetBytes(name);
                buf[0] = (byte)d.Length;
                if (d.Length > byte.MaxValue)
                {
                    throw new Exception("Encoding failed, name is too long!");
                }
                Array.Copy(d, 0, buf, 1, d.Length);

                //Send on network
                await e.Response.Body.WriteAsync(buf, 0, d.Length + 1);
            }

            //Send inventories
            foreach (var inventory in inventories)
            {
                //Create header
                BinaryTool.WriteUInt64(buf, 0, inventory.holder_id);
                buf[8] = (byte)inventory.holder_type;
                BinaryTool.WriteInt16(buf, 9, (short)inventory.items.Length);
                BinaryTool.WriteInt32(buf, 11, inventory.tribe_id);
                int offset = 15;

                //Add items
                foreach (var i in inventory.items)
                {
                    //Create header
                    BinaryTool.WriteUInt64(buf, offset, i.item_id);
                    BinaryTool.WriteInt32(buf, offset + 8, names.IndexOf(i.classname));
                    BinaryTool.WriteFloat(buf, offset + 12, i.durability);
                    BinaryTool.WriteInt16(buf, offset + 16, (short)i.stack_size);
                    BinaryTool.WriteInt16(buf, offset + 18, (short)i.flags);
                    buf[offset + 20] = (byte)i.custom_data.Count;
                    offset          += 21;

                    //Write custom datas
                    foreach (var c in i.custom_data)
                    {
                        //Write key
                        byte[] d = Encoding.UTF8.GetBytes(c.Key);
                        BinaryTool.WriteInt16(buf, offset, (short)d.Length);
                        Array.Copy(d, 0, buf, offset + 2, d.Length);
                        offset += 2 + d.Length;

                        //Write value
                        d = Encoding.UTF8.GetBytes(c.Value);
                        BinaryTool.WriteInt16(buf, offset, (short)d.Length);
                        Array.Copy(d, 0, buf, offset + 2, d.Length);
                        offset += 2 + d.Length;
                    }
                }

                //Send data
                await e.Response.Body.WriteAsync(buf, 0, offset);

                offset = 0;
            }
        }