diff --git a/libsecondlife-cs/mapgenerator/ProtocolManager.cs b/libsecondlife-cs/mapgenerator/ProtocolManager.cs
new file mode 100644
index 00000000..71505121
--- /dev/null
+++ b/libsecondlife-cs/mapgenerator/ProtocolManager.cs
@@ -0,0 +1,701 @@
+using System;
+using System.Collections;
+using System.IO;
+
+namespace libsecondlife
+{
+ ///
+ ///
+ ///
+ public enum PacketFrequency
+ {
+ ///
+ Low,
+ ///
+ Medium,
+ ///
+ High
+ }
+
+ ///
+ ///
+ ///
+ public enum FieldType
+ {
+ ///
+ U8,
+ ///
+ U16,
+ ///
+ U32,
+ ///
+ U64,
+ ///
+ S8,
+ ///
+ S16,
+ ///
+ S32,
+ ///
+ F32,
+ ///
+ F64,
+ ///
+ LLUUID,
+ ///
+ BOOL,
+ ///
+ LLVector3,
+ ///
+ LLVector3d,
+ ///
+ LLVector4,
+ ///
+ LLQuaternion,
+ ///
+ IPADDR,
+ ///
+ IPPORT,
+ ///
+ Variable,
+ ///
+ Fixed,
+ ///
+ Single,
+ ///
+ Multiple
+ }
+
+ ///
+ ///
+ ///
+ public class MapField : IComparable
+ {
+ ///
+ public int KeywordPosition;
+ ///
+ public string Name;
+ ///
+ public FieldType Type;
+ ///
+ public int Count;
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public int CompareTo(object obj)
+ {
+ MapField temp = (MapField)obj;
+
+ if (this.KeywordPosition > temp.KeywordPosition)
+ {
+ return 1;
+ }
+ else
+ {
+ if(temp.KeywordPosition == this.KeywordPosition)
+ {
+ return 0;
+ }
+ else
+ {
+ return -1;
+ }
+ }
+ }
+ }
+
+ ///
+ ///
+ ///
+ public class MapBlock : IComparable
+ {
+ ///
+ public int KeywordPosition;
+ ///
+ public string Name;
+ ///
+ public int Count;
+ ///
+ public ArrayList Fields;
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public int CompareTo(object obj)
+ {
+ MapBlock temp = (MapBlock)obj;
+
+ if (this.KeywordPosition > temp.KeywordPosition)
+ {
+ return 1;
+ }
+ else
+ {
+ if(temp.KeywordPosition == this.KeywordPosition)
+ {
+ return 0;
+ }
+ else
+ {
+ return -1;
+ }
+ }
+ }
+ }
+
+ ///
+ ///
+ ///
+ public class MapPacket
+ {
+ ///
+ public ushort ID;
+ ///
+ public string Name;
+ ///
+ public PacketFrequency Frequency;
+ ///
+ public bool Trusted;
+ ///
+ public bool Encoded;
+ ///
+ public ArrayList Blocks;
+ }
+
+ ///
+ ///
+ ///
+ public class ProtocolManager
+ {
+ ///
+ public Hashtable TypeSizes;
+ ///
+ public Hashtable KeywordPositions;
+ ///
+ public MapPacket[] LowMaps;
+ ///
+ public MapPacket[] MediumMaps;
+ ///
+ public MapPacket[] HighMaps;
+
+ private int i = 0;
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public ProtocolManager(string keywordFile, string mapFile)
+ {
+ // Initialize the map arrays
+ LowMaps = new MapPacket[65536];
+ MediumMaps = new MapPacket[256];
+ HighMaps = new MapPacket[256];
+
+ // Build the type size hash table
+ TypeSizes = new Hashtable();
+ TypeSizes.Add(FieldType.U8, 1);
+ TypeSizes.Add(FieldType.U16, 2);
+ TypeSizes.Add(FieldType.U32, 4);
+ TypeSizes.Add(FieldType.U64, 8);
+ TypeSizes.Add(FieldType.S8, 1);
+ TypeSizes.Add(FieldType.S16, 2);
+ TypeSizes.Add(FieldType.S32, 4);
+ TypeSizes.Add(FieldType.F32, 4);
+ TypeSizes.Add(FieldType.F64, 8);
+ TypeSizes.Add(FieldType.LLUUID, 16);
+ TypeSizes.Add(FieldType.BOOL, 1);
+ TypeSizes.Add(FieldType.LLVector3, 12);
+ TypeSizes.Add(FieldType.LLVector3d, 24);
+ TypeSizes.Add(FieldType.LLVector4, 16);
+ TypeSizes.Add(FieldType.LLQuaternion, 16);
+ TypeSizes.Add(FieldType.IPADDR, 4);
+ TypeSizes.Add(FieldType.IPPORT, 2);
+ TypeSizes.Add(FieldType.Variable, -1);
+ TypeSizes.Add(FieldType.Fixed, -2);
+
+ LoadKeywordFile(keywordFile);
+ LoadMapFile(mapFile);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public MapPacket Command(string command)
+ {
+ foreach (MapPacket map in HighMaps)
+ {
+ if (map != null)
+ {
+ if (command == map.Name)
+ {
+ return map;
+ }
+ }
+ }
+
+ foreach (MapPacket map in MediumMaps)
+ {
+ if (map != null)
+ {
+ if (command == map.Name)
+ {
+ return map;
+ }
+ }
+ }
+
+ foreach (MapPacket map in LowMaps)
+ {
+ if (map != null)
+ {
+ if (command == map.Name)
+ {
+ return map;
+ }
+ }
+ }
+
+ throw new Exception("Cannot find map for command \"" + command + "\"");
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public MapPacket Command(byte[] data)
+ {
+ ushort command;
+
+ if (data.Length < 5)
+ {
+ return null;
+ }
+
+ if (data[4] == 0xFF)
+ {
+ if ((byte)data[5] == 0xFF)
+ {
+ // Low frequency
+ command = (ushort)(data[6] * 256 + data[7]);
+ return Command(command, PacketFrequency.Low);
+ }
+ else
+ {
+ // Medium frequency
+ command = (ushort)data[5];
+ return Command(command, PacketFrequency.Medium);
+ }
+ }
+ else
+ {
+ // High frequency
+ command = (ushort)data[4];
+ return Command(command, PacketFrequency.High);
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public MapPacket Command(ushort command, PacketFrequency frequency)
+ {
+ switch (frequency)
+ {
+ case PacketFrequency.High:
+ return HighMaps[command];
+ case PacketFrequency.Medium:
+ return MediumMaps[command];
+ case PacketFrequency.Low:
+ return LowMaps[command];
+ }
+
+ throw new Exception("Cannot find map for command \"" + command + "\" with frequency \"" + frequency + "\"");
+ }
+
+ ///
+ ///
+ ///
+ public void PrintMap()
+ {
+ PrintOneMap(LowMaps, "Low ");
+ PrintOneMap(MediumMaps, "Medium");
+ PrintOneMap(HighMaps, "High ");
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ private void PrintOneMap(MapPacket[] map, string frequency) {
+ int i;
+
+ for (i = 0; i < map.Length; ++i)
+ {
+ if (map[i] != null)
+ {
+ Console.WriteLine("{0} {1,5} - {2} - {3} - {4}", frequency, i, map[i].Name,
+ map[i].Trusted ? "Trusted" : "Untrusted",
+ map[i].Encoded ? "Unencoded" : "Zerocoded");
+
+ foreach (MapBlock block in map[i].Blocks)
+ {
+ if (block.Count == -1)
+ {
+ Console.WriteLine("\t{0,4} {1} (Variable)", block.KeywordPosition, block.Name);
+ }
+ else
+ {
+ Console.WriteLine("\t{0,4} {1} ({2})", block.KeywordPosition, block.Name, block.Count);
+ }
+
+ foreach (MapField field in block.Fields)
+ {
+ Console.WriteLine("\t\t{0,4} {1} ({2} / {3})", field.KeywordPosition, field.Name,
+ field.Type, field.Count);
+ }
+ }
+ }
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ private void LoadKeywordFile(string keywordFile)
+ {
+ string line;
+ StreamReader file;
+
+ KeywordPositions = new Hashtable();
+
+ // Load the keyword file
+ try
+ {
+ file = File.OpenText(keywordFile);
+ }
+ catch(Exception e)
+ {
+ //Client.Log("Error opening \"" + keywordFile + "\": " + e.Message, Helpers.LogLevel.Error);
+ throw new Exception("Keyword file error", e);
+ }
+
+ while((line = file.ReadLine()) != null)
+ {
+ KeywordPositions.Add(line.Trim(), i++);
+ }
+
+ file.Close();
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static void DecodeMapFile(string mapFile, string outputFile)
+ {
+ byte magicKey = 0;
+ byte[] buffer = new byte[2048];
+ int nread;
+ BinaryReader map;
+ BinaryWriter output;
+
+ try
+ {
+ map = new BinaryReader(new FileStream(mapFile, FileMode.Open));
+ }
+ catch(Exception e)
+ {
+ throw new Exception("Map file error", e);
+ }
+
+ try
+ {
+ output = new BinaryWriter(new FileStream(outputFile, FileMode.CreateNew));
+ }
+ catch(Exception e)
+ {
+ throw new Exception("Map file error", e);
+ }
+
+ while ((nread = map.Read(buffer, 0, 2048)) != 0)
+ {
+ for (int i = 0; i < nread; ++i)
+ {
+ buffer[i] ^= magicKey;
+ magicKey += 43;
+ }
+
+ output.Write(buffer, 0, nread);
+ }
+
+ map.Close();
+ output.Close();
+ }
+
+ ///
+ ///
+ ///
+ ///
+ private void LoadMapFile(string mapFile)
+ {
+ FileStream map;
+ ushort low = 1;
+ ushort medium = 1;
+ ushort high = 1;
+
+ // Load the protocol map file
+ try
+ {
+ map = new FileStream(mapFile, FileMode.Open, FileAccess.Read);
+ }
+ catch(Exception e)
+ {
+ throw new Exception("Map file error", e);
+ }
+
+ try
+ {
+ StreamReader r = new StreamReader(map);
+ r.BaseStream.Seek(0, SeekOrigin.Begin);
+ string newline;
+ string trimmedline;
+ bool inPacket = false;
+ bool inBlock = false;
+ MapPacket currentPacket = null;
+ MapBlock currentBlock = null;
+ char[] trimArray = new char[] {' ', '\t'};
+
+ // While not at the end of the file
+ while (r.Peek() > -1)
+ {
+ #region ParseMap
+
+ newline = r.ReadLine();
+ trimmedline = System.Text.RegularExpressions.Regex.Replace(newline, @"\s+", " ");
+ trimmedline = trimmedline.Trim(trimArray);
+
+ if (!inPacket)
+ {
+ // Outside of all packet blocks
+
+ if (trimmedline == "{")
+ {
+ inPacket = true;
+ }
+ }
+ else
+ {
+ // Inside of a packet block
+
+ if (!inBlock)
+ {
+ // Inside a packet block, outside of the blocks
+
+ if (trimmedline == "{")
+ {
+ inBlock = true;
+ }
+ else if (trimmedline == "}")
+ {
+ // Reached the end of the packet
+ currentPacket.Blocks.Sort();
+ inPacket = false;
+ }
+ else
+ {
+ // The packet header
+ #region ParsePacketHeader
+
+ // Splice the string in to tokens
+ string[] tokens = trimmedline.Split(new char[] {' ', '\t'});
+
+ if (tokens.Length > 3)
+ {
+ if (tokens[1] == "Fixed")
+ {
+ // Remove the leading "0x"
+ if (tokens[2].Substring(0, 2) == "0x")
+ {
+ tokens[2] = tokens[2].Substring(2, tokens[2].Length - 2);
+ }
+
+ uint fixedID = UInt32.Parse(tokens[2], System.Globalization.NumberStyles.HexNumber);
+ // Truncate the id to a short
+ fixedID ^= 0xFFFF0000;
+ LowMaps[fixedID] = new MapPacket();
+ LowMaps[fixedID].ID = (ushort)fixedID;
+ LowMaps[fixedID].Frequency = PacketFrequency.Low;
+ LowMaps[fixedID].Name = tokens[0];
+ LowMaps[fixedID].Trusted = (tokens[3] == "Trusted");
+ LowMaps[fixedID].Encoded = (tokens[4] == "Zerocoded");
+ LowMaps[fixedID].Blocks = new ArrayList();
+
+ currentPacket = LowMaps[fixedID];
+ }
+ else if (tokens[1] == "Low")
+ {
+ LowMaps[low] = new MapPacket();
+ LowMaps[low].ID = low;
+ LowMaps[low].Frequency = PacketFrequency.Low;
+ LowMaps[low].Name = tokens[0];
+ LowMaps[low].Trusted = (tokens[2] == "Trusted");
+ LowMaps[low].Encoded = (tokens[3] == "Zerocoded");
+ LowMaps[low].Blocks = new ArrayList();
+
+ currentPacket = LowMaps[low];
+
+ low++;
+ }
+ else if (tokens[1] == "Medium")
+ {
+ MediumMaps[medium] = new MapPacket();
+ MediumMaps[medium].ID = medium;
+ MediumMaps[medium].Frequency = PacketFrequency.Medium;
+ MediumMaps[medium].Name = tokens[0];
+ MediumMaps[medium].Trusted = (tokens[2] == "Trusted");
+ MediumMaps[medium].Encoded = (tokens[3] == "Zerocoded");
+ MediumMaps[medium].Blocks = new ArrayList();
+
+ currentPacket = MediumMaps[medium];
+
+ medium++;
+ }
+ else if (tokens[1] == "High")
+ {
+ HighMaps[high] = new MapPacket();
+ HighMaps[high].ID = high;
+ HighMaps[high].Frequency = PacketFrequency.High;
+ HighMaps[high].Name = tokens[0];
+ HighMaps[high].Trusted = (tokens[2] == "Trusted");
+ HighMaps[high].Encoded = (tokens[3] == "Zerocoded");
+ HighMaps[high].Blocks = new ArrayList();
+
+ currentPacket = HighMaps[high];
+
+ high++;
+ }
+ else
+ {
+ //Client.Log("Unknown packet frequency", Helpers.LogLevel.Error);
+ throw new Exception("Unknown packet frequency");
+ }
+ }
+
+ #endregion
+ }
+ }
+ else
+ {
+ if (trimmedline.Length > 0 && trimmedline.Substring(0, 1) == "{")
+ {
+ // A field
+ #region ParseField
+
+ MapField field = new MapField();
+
+ // Splice the string in to tokens
+ string[] tokens = trimmedline.Split(new char[] {' ', '\t'});
+
+ field.Name = tokens[1];
+ field.KeywordPosition = KeywordPosition(field.Name);
+ field.Type = (FieldType)Enum.Parse(typeof(FieldType), tokens[2], true);
+
+ if (tokens[3] != "}")
+ {
+ field.Count = Int32.Parse(tokens[3]);
+ }
+ else
+ {
+ field.Count = 1;
+ }
+
+ // Save this field to the current block
+ currentBlock.Fields.Add(field);
+
+ #endregion
+ }
+ else if (trimmedline == "}")
+ {
+ currentBlock.Fields.Sort();
+ inBlock = false;
+ }
+ else if (trimmedline.Length != 0 && trimmedline.Substring(0, 2) != "//")
+ {
+ // The block header
+ #region ParseBlockHeader
+
+ currentBlock = new MapBlock();
+
+ // Splice the string in to tokens
+ string[] tokens = trimmedline.Split(new char[] {' ', '\t'});
+
+ currentBlock.Name = tokens[0];
+ currentBlock.KeywordPosition = KeywordPosition(currentBlock.Name);
+ currentBlock.Fields = new ArrayList();
+ currentPacket.Blocks.Add(currentBlock);
+
+ if (tokens[1] == "Single")
+ {
+ currentBlock.Count = 1;
+ }
+ else if (tokens[1] == "Multiple")
+ {
+ currentBlock.Count = Int32.Parse(tokens[2]);
+ }
+ else if (tokens[1] == "Variable")
+ {
+ currentBlock.Count = -1;
+ }
+ else
+ {
+ //Client.Log("Unknown block frequency", Helpers.LogLevel.Error);
+ throw new Exception("Unknown block frequency");
+ }
+
+ #endregion
+ }
+ }
+ }
+
+ #endregion
+ }
+
+ r.Close();
+ map.Close();
+ }
+ catch (Exception e)
+ {
+ throw e;
+ }
+ }
+
+ private int KeywordPosition(string keyword)
+ {
+ if (KeywordPositions.ContainsKey(keyword))
+ {
+ return (int)KeywordPositions[keyword];
+ }
+ else
+ {
+ //Client.Log("Couldn't find keyword: " + keyword, Helpers.LogLevel.Warning);
+ throw new Exception("Couldn't find keyword " + keyword);
+ }
+ }
+ }
+}
diff --git a/libsecondlife-cs/mapgenerator/mapgenerator.cs b/libsecondlife-cs/mapgenerator/mapgenerator.cs
index 20668d26..f446d79a 100644
--- a/libsecondlife-cs/mapgenerator/mapgenerator.cs
+++ b/libsecondlife-cs/mapgenerator/mapgenerator.cs
@@ -706,12 +706,21 @@ namespace mapgenerator
static void Main(string[] args)
{
- SecondLife libsl = new SecondLife();
- ProtocolManager protocol = new ProtocolManager("keywords.txt", "message_template.msg", libsl);
+ ProtocolManager protocol;
- TextReader reader = new StreamReader("template.cs");
- Console.WriteLine(reader.ReadToEnd());
- reader.Close();
+ try
+ {
+ protocol = new ProtocolManager("keywords.txt", "message_template.msg");
+
+ TextReader reader = new StreamReader("template.cs");
+ Console.WriteLine(reader.ReadToEnd());
+ reader.Close();
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e.ToString());
+ return;
+ }
// Write the PacketType enum
Console.WriteLine(" /// Used to identify the type of a packet");
diff --git a/libsecondlife-cs/mapgenerator/mapgenerator.csproj b/libsecondlife-cs/mapgenerator/mapgenerator.csproj
index 925ca7e0..c4f07708 100644
--- a/libsecondlife-cs/mapgenerator/mapgenerator.csproj
+++ b/libsecondlife-cs/mapgenerator/mapgenerator.csproj
@@ -35,12 +35,7 @@
-
-
-
- {D9CDEDFB-8169-4B03-B57F-0DF638F044EC}
- libsecondlife
-
+