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; } }
public async Task WriteBinaryResponse(List <DbStructure> structures) { //Binary mode writes out structures in binary structs //HEADER FORMAT: // 4 static Signature, says "DWMS" // 4 int32 File type version, should be 3 // 4 int32 Metadata version // 4 int32 Structure count // 4 int32 Saved epoch // 4 int32 RESERVED // 4 int32 RESERVED // 4 int32 RESERVED //TOTAL: 32 bytes //Struct format: // 2 short Metadata Index // 1 byte Rotation (in degrees, 0-360, but scaled so that 256=360) // 1 byte Flags (SEE BELOW) // 4 float Position X // 4 float Position Y // 4 int32 ID // 4 float Position Z // 4 int32 Tribe ID //TOTAL: 24 bytes each //FLAGS //0: Has inventory //1: Is remove //2: RESERVED //3: RESERVED //4: RESERVED //5: RESERVED //6: RESERVED //7: RESERVED //Set headers e.Response.ContentLength = (24 * structures.Count) + 32; e.Response.ContentType = "application/octet-stream"; e.Response.StatusCode = 200; //Create and send file header byte[] buf = new byte[32]; buf[0] = 0x44; buf[1] = 0x57; buf[2] = 0x4D; buf[3] = 0x53; BinaryTool.WriteInt32(buf, 4, 3); //Version tag BinaryTool.WriteInt32(buf, 8, 0); BinaryTool.WriteInt32(buf, 12, structures.Count); BinaryTool.WriteInt32(buf, 16, 0); //Was epoch, now unused BinaryTool.WriteInt32(buf, 20, 0); BinaryTool.WriteInt32(buf, 24, 0); BinaryTool.WriteInt32(buf, 28, 0); await e.Response.Body.WriteAsync(buf, 0, 32); //Loop through structures and find where they are foreach (var t in structures) { //Get data StructureMetadata metadata = Program.structureMetadata.Where(x => x.names.Contains(t.classname)).FirstOrDefault(); int index = Program.structureMetadata.IndexOf(metadata); //Produce flags byte flags = 0; if (t.has_inventory) { flags |= 0x01 << 0; } //Write parts BinaryTool.WriteInt16(buf, 0, (short)index); buf[2] = (byte)(t.location.yaw * 0.70833333333333333333333333333333f); //Scales this to fit the 0-360 degrees into 0-255 buf[3] = flags; BinaryTool.WriteFloat(buf, 4, t.location.x); BinaryTool.WriteFloat(buf, 8, t.location.y); BinaryTool.WriteInt32(buf, 12, t.structure_id); BinaryTool.WriteFloat(buf, 16, t.location.z); BinaryTool.WriteInt32(buf, 20, t.tribe_id); //Write to stream await e.Response.Body.WriteAsync(buf, 0, 24); } }