using System; using System.Text; using System.IO; using libsecondlife; namespace mapgenerator { class mapgenerator { static void WriteFieldMember(MapField field) { string type = ""; switch (field.Type) { case FieldType.BOOL: type = "bool"; break; case FieldType.F32: type = "float"; break; case FieldType.F64: type = "double"; break; case FieldType.IPPORT: case FieldType.U16: type = "ushort"; break; case FieldType.IPADDR: case FieldType.U32: type = "uint"; break; case FieldType.LLQuaternion: type = "LLQuaternion"; break; case FieldType.LLUUID: type = "LLUUID"; break; case FieldType.LLVector3: type = "LLVector3"; break; case FieldType.LLVector3d: type = "LLVector3d"; break; case FieldType.LLVector4: type = "LLVector4"; break; case FieldType.S16: type = "short"; break; case FieldType.S32: type = "int"; break; case FieldType.S64: type = "long"; break; case FieldType.S8: type = "sbyte"; break; case FieldType.U64: type = "ulong"; break; case FieldType.U8: type = "byte"; break; case FieldType.Fixed: type = "byte[]"; break; } if (field.Type != FieldType.Variable) { Console.WriteLine(" public " + type + " " + field.Name + ";"); } else { Console.WriteLine(" private byte[] _" + field.Name.ToLower() + ";"); Console.WriteLine(" public byte[] " + field.Name + "\n {"); Console.WriteLine(" get { return _" + field.Name.ToLower() + "; }"); Console.WriteLine(" set\n {"); Console.WriteLine(" if (value == null) { _" + field.Name.ToLower() + " = null; return; }"); Console.WriteLine(" if (value.Length > " + ((field.Count == 1) ? "255" : "1024") + ") { throw new OverflowException(" + "\"Value exceeds " + ((field.Count == 1) ? "255" : "1024") + " characters\"); }"); Console.WriteLine(" else { _" + field.Name.ToLower() + " = new byte[value.Length]; Array.Copy(value, _" + field.Name.ToLower() + ", value.Length); }"); Console.WriteLine(" }\n }"); } } static void WriteFieldFromBytes(MapField field) { switch (field.Type) { case FieldType.BOOL: Console.WriteLine(" " + field.Name + " = (bytes[i++] != 0) ? (bool)true : (bool)false;"); break; case FieldType.F32: Console.WriteLine(" " + "if (!BitConverter.IsLittleEndian) Array.Reverse(bytes, i, 4);"); Console.WriteLine(" " + field.Name + " = BitConverter.ToSingle(bytes, i); i += 4;"); break; case FieldType.F64: Console.WriteLine(" " + "if (!BitConverter.IsLittleEndian) Array.Reverse(bytes, i, 8);"); Console.WriteLine(" " + field.Name + " = BitConverter.ToDouble(bytes, i); i += 8;"); break; case FieldType.Fixed: Console.WriteLine(" " + field.Name + " = new byte[" + field.Count + "];"); Console.WriteLine(" Array.Copy(bytes, i, " + field.Name + ", 0, " + field.Count + "); i += " + field.Count + ";"); break; case FieldType.IPADDR: case FieldType.U32: Console.WriteLine(" " + field.Name + " = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));"); break; case FieldType.IPPORT: case FieldType.U16: Console.WriteLine(" " + field.Name + " = (ushort)(bytes[i++] + (bytes[i++] << 8));"); break; case FieldType.LLQuaternion: Console.WriteLine(" " + field.Name + " = new LLQuaternion(bytes, i); i += 16;"); break; case FieldType.LLUUID: Console.WriteLine(" " + field.Name + " = new LLUUID(bytes, i); i += 16;"); break; case FieldType.LLVector3: Console.WriteLine(" " + field.Name + " = new LLVector3(bytes, i); i += 12;"); break; case FieldType.LLVector3d: Console.WriteLine(" " + field.Name + " = new LLVector3d(bytes, i); i += 24;"); break; case FieldType.LLVector4: Console.WriteLine(" " + field.Name + " = new LLVector4(bytes, i); i += 16;"); break; case FieldType.S16: Console.WriteLine(" " + field.Name + " = (short)(bytes[i++] + (bytes[i++] << 8));"); break; case FieldType.S32: Console.WriteLine(" " + field.Name + " = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));"); break; case FieldType.S64: Console.WriteLine(" " + field.Name + " = (long)(bytes[i++] + (bytes[i++] << 8) + " + "(bytes[i++] << 16) + (bytes[i++] << 24) + " + "(bytes[i++] << 32) + (bytes[i++] << 40) + " + "(bytes[i++] << 48) + (bytes[i++] << 56));"); break; case FieldType.S8: Console.WriteLine(" " + field.Name + " = (sbyte)bytes[i++];"); break; case FieldType.U64: Console.WriteLine(" " + field.Name + " = (ulong)(bytes[i++] + (bytes[i++] << 8) + " + "(bytes[i++] << 16) + (bytes[i++] << 24) + " + "(bytes[i++] << 32) + (bytes[i++] << 40) + " + "(bytes[i++] << 48) + (bytes[i++] << 56));"); break; case FieldType.U8: Console.WriteLine(" " + field.Name + " = (byte)bytes[i++];"); break; case FieldType.Variable: if (field.Count == 1) { Console.WriteLine(" length = (ushort)bytes[i++];"); } else { Console.WriteLine(" length = (ushort)(bytes[i++] + (bytes[i++] << 8));"); } Console.WriteLine(" _" + field.Name.ToLower() + " = new byte[length];"); Console.WriteLine(" Array.Copy(bytes, i, _" + field.Name.ToLower() + ", 0, length); i += length;"); break; } } static void WriteBlockClass(MapBlock block) { bool variableFields = false; Console.WriteLine(" public class " + block.Name + "Block\n {"); foreach (MapField field in block.Fields) { WriteFieldMember(field); if (field.Type == FieldType.Variable) { variableFields = true; } } Console.WriteLine(""); // Default constructor Console.WriteLine(" public " + block.Name + "Block() { }"); // Console.WriteLine(" public " + block.Name + "Block(byte[] bytes, ref int i)" + "\n {"); // Declare a length variable if we need it for variable fields in this constructor if (variableFields) { Console.WriteLine(" int length;"); } Console.WriteLine(" try\n {"); foreach (MapField field in block.Fields) { WriteFieldFromBytes(field); } Console.WriteLine(" }\n catch (Exception)\n" + " {\n throw new MalformedDataException();\n" + " }\n }\n"); // FIXME: Write the ToBytes() function Console.WriteLine(" public byte[] ToBytes() { return null; }"); Console.WriteLine(" }\n"); } static void WritePacketClass(MapPacket packet) { Console.WriteLine(" class " + packet.Name + "Packet\n {"); // Write out each block class foreach (MapBlock block in packet.Blocks) { WriteBlockClass(block); } // Header member Console.WriteLine(" public " + packet.Frequency.ToString() + "Header Header;"); // PacketType member Console.WriteLine(" public PacketType Type { get { return Type; } set { Type = value; } }"); // Block members foreach (MapBlock block in packet.Blocks) { Console.WriteLine(" public " + block.Name + "Block" + ((block.Count != 1) ? "[]" : "") + " " + block.Name + ";"); } Console.WriteLine(""); // Default constructor Console.WriteLine(" " + packet.Name + "Packet()\n {"); Console.WriteLine(" Type = PacketType." + packet.Name + ";"); Console.WriteLine(" Header = new " + packet.Frequency.ToString() + "Header();"); foreach (MapBlock block in packet.Blocks) { if (block.Count == 1) { // Single count block Console.WriteLine(" " + block.Name + " = new " + block.Name + "Block();"); } else if (block.Count == -1) { // Variable count block Console.WriteLine(" " + block.Name + " = new " + block.Name + "Block[0];"); } else { // Multiple count block Console.WriteLine(" " + block.Name + " = new " + block.Name + "Block[" + block.Count + "];"); } } Console.WriteLine(" }\n"); // Constructor that takes a byte array and beginning position only (no prebuilt header) bool seenVariable = false; Console.WriteLine(" " + packet.Name + "Packet(byte[] bytes, ref int i)\n {"); Console.WriteLine(" Type = PacketType." + packet.Name + ";"); Console.WriteLine(" int packetEnd = bytes.Length - 1;"); Console.WriteLine(" Header = new " + packet.Frequency.ToString() + "Header(bytes, ref i, ref packetEnd);"); foreach (MapBlock block in packet.Blocks) { if (block.Count == 1) { // Single count block Console.WriteLine(" " + block.Name + " = new " + block.Name + "Block(bytes, ref i);"); } else if (block.Count == -1) { // Variable count block if (!seenVariable) { Console.WriteLine(" int count = (int)bytes[i++];"); seenVariable = true; } else { Console.WriteLine(" count = (int)bytes[i++];"); } Console.WriteLine(" for (int j = 0; j < count; j++)"); Console.WriteLine(" { " + block.Name + "[j] = new " + block.Name + "Block(bytes, ref i); }"); } else { // Multiple count block Console.WriteLine(" for (int j = 0; j < " + block.Count + "; j++)"); Console.WriteLine(" { " + block.Name + "[j] = new " + block.Name + "Block(bytes, ref i); }"); } } Console.WriteLine(" }\n"); // Constructor that takes a byte array and a prebuilt header Console.WriteLine(" " + packet.Name + "Packet(" + packet.Frequency.ToString() + "Header header, byte[] bytes, ref int i)\n {"); Console.WriteLine(" Type = PacketType." + packet.Name + ";"); Console.WriteLine(" Header = header;"); Console.WriteLine(" //FIXME"); Console.WriteLine(" }\n"); // ToBytes() function Console.WriteLine(" public byte[] ToBytes() { return null; }"); // Closing bracket Console.WriteLine(" }\n"); } static void Main(string[] args) { SecondLife libsl = new SecondLife("keywords.txt", "message_template.msg"); TextReader reader = new StreamReader("template.cs"); Console.WriteLine(reader.ReadToEnd()); reader.Close(); Console.WriteLine(" public enum PacketType\n {"); foreach (MapPacket packet in libsl.Protocol.LowMaps) { if (packet != null) { Console.WriteLine(" " + packet.Name + ","); } } foreach (MapPacket packet in libsl.Protocol.MediumMaps) { if (packet != null) { Console.WriteLine(" " + packet.Name + ","); } } foreach (MapPacket packet in libsl.Protocol.HighMaps) { if (packet != null) { Console.WriteLine(" " + packet.Name + ","); } } Console.WriteLine(" }\n"); foreach (MapPacket packet in libsl.Protocol.LowMaps) { if (packet != null) { WritePacketClass(packet); } } foreach (MapPacket packet in libsl.Protocol.MediumMaps) { if (packet != null) { WritePacketClass(packet); } } foreach (MapPacket packet in libsl.Protocol.HighMaps) { if (packet != null) { WritePacketClass(packet); } } Console.WriteLine("}"); } } }