corrade-vassal – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 1 using System;
2 using System.Collections.Generic;
3 using System.IO;
4  
5 namespace mapgenerator
6 {
7 /// <summary>
8 ///
9 /// </summary>
10 public enum PacketFrequency
11 {
12 /// <summary></summary>
13 Low,
14 /// <summary></summary>
15 Medium,
16 /// <summary></summary>
17 High
18 }
19  
20 /// <summary>
21 ///
22 /// </summary>
23 public enum FieldType
24 {
25 /// <summary></summary>
26 U8,
27 /// <summary></summary>
28 U16,
29 /// <summary></summary>
30 U32,
31 /// <summary></summary>
32 U64,
33 /// <summary></summary>
34 S8,
35 /// <summary></summary>
36 S16,
37 /// <summary></summary>
38 S32,
39 /// <summary></summary>
40 F32,
41 /// <summary></summary>
42 F64,
43 /// <summary></summary>
44 LLUUID,
45 /// <summary></summary>
46 BOOL,
47 /// <summary></summary>
48 LLVector3,
49 /// <summary></summary>
50 LLVector3d,
51 /// <summary></summary>
52 LLVector4,
53 /// <summary></summary>
54 LLQuaternion,
55 /// <summary></summary>
56 IPADDR,
57 /// <summary></summary>
58 IPPORT,
59 /// <summary></summary>
60 Variable,
61 /// <summary></summary>
62 Fixed,
63 /// <summary></summary>
64 Single,
65 /// <summary></summary>
66 Multiple
67 }
68  
69 /// <summary>
70 ///
71 /// </summary>
72 public class MapField : IComparable
73 {
74 /// <summary></summary>
75 public int KeywordPosition;
76 /// <summary></summary>
77 public string Name;
78 /// <summary></summary>
79 public FieldType Type;
80 /// <summary></summary>
81 public int Count;
82  
83 /// <summary>
84 ///
85 /// </summary>
86 /// <param name="obj"></param>
87 /// <returns></returns>
88 public int CompareTo(object obj)
89 {
90 MapField temp = (MapField)obj;
91  
92 if (this.KeywordPosition > temp.KeywordPosition)
93 {
94 return 1;
95 }
96 else
97 {
98 if(temp.KeywordPosition == this.KeywordPosition)
99 {
100 return 0;
101 }
102 else
103 {
104 return -1;
105 }
106 }
107 }
108 }
109  
110 /// <summary>
111 ///
112 /// </summary>
113 public class MapBlock : IComparable
114 {
115 /// <summary></summary>
116 public int KeywordPosition;
117 /// <summary></summary>
118 public string Name;
119 /// <summary></summary>
120 public int Count;
121 /// <summary></summary>
122 public List<MapField> Fields;
123  
124 /// <summary>
125 ///
126 /// </summary>
127 /// <param name="obj"></param>
128 /// <returns></returns>
129 public int CompareTo(object obj)
130 {
131 MapBlock temp = (MapBlock)obj;
132  
133 if (this.KeywordPosition > temp.KeywordPosition)
134 {
135 return 1;
136 }
137 else
138 {
139 if(temp.KeywordPosition == this.KeywordPosition)
140 {
141 return 0;
142 }
143 else
144 {
145 return -1;
146 }
147 }
148 }
149 }
150  
151 /// <summary>
152 ///
153 /// </summary>
154 public class MapPacket
155 {
156 /// <summary></summary>
157 public ushort ID;
158 /// <summary></summary>
159 public string Name;
160 /// <summary></summary>
161 public PacketFrequency Frequency;
162 /// <summary></summary>
163 public bool Trusted;
164 /// <summary></summary>
165 public bool Encoded;
166 /// <summary></summary>
167 public List<MapBlock> Blocks;
168 }
169  
170 /// <summary>
171 ///
172 /// </summary>
173 public class ProtocolManager
174 {
175 /// <summary></summary>
176 public Dictionary<FieldType, int> TypeSizes;
177 /// <summary></summary>
178 public Dictionary<string, int> KeywordPositions;
179 /// <summary></summary>
180 public MapPacket[] LowMaps;
181 /// <summary></summary>
182 public MapPacket[] MediumMaps;
183 /// <summary></summary>
184 public MapPacket[] HighMaps;
185  
186 /// <summary>
187 ///
188 /// </summary>
189 /// <param name="keywordFile"></param>
190 /// <param name="mapFile"></param>
191 /// <param name="client"></param>
192 public ProtocolManager(string mapFile)
193 {
194 // Initialize the map arrays
195 LowMaps = new MapPacket[65536];
196 MediumMaps = new MapPacket[256];
197 HighMaps = new MapPacket[256];
198  
199 // Build the type size hash table
200 TypeSizes = new Dictionary<FieldType,int>();
201 TypeSizes.Add(FieldType.U8, 1);
202 TypeSizes.Add(FieldType.U16, 2);
203 TypeSizes.Add(FieldType.U32, 4);
204 TypeSizes.Add(FieldType.U64, 8);
205 TypeSizes.Add(FieldType.S8, 1);
206 TypeSizes.Add(FieldType.S16, 2);
207 TypeSizes.Add(FieldType.S32, 4);
208 TypeSizes.Add(FieldType.F32, 4);
209 TypeSizes.Add(FieldType.F64, 8);
210 TypeSizes.Add(FieldType.LLUUID, 16);
211 TypeSizes.Add(FieldType.BOOL, 1);
212 TypeSizes.Add(FieldType.LLVector3, 12);
213 TypeSizes.Add(FieldType.LLVector3d, 24);
214 TypeSizes.Add(FieldType.LLVector4, 16);
215 TypeSizes.Add(FieldType.LLQuaternion, 16);
216 TypeSizes.Add(FieldType.IPADDR, 4);
217 TypeSizes.Add(FieldType.IPPORT, 2);
218 TypeSizes.Add(FieldType.Variable, -1);
219 TypeSizes.Add(FieldType.Fixed, -2);
220  
221 KeywordPositions = new Dictionary<string, int>();
222 LoadMapFile(mapFile);
223 }
224  
225 /// <summary>
226 ///
227 /// </summary>
228 /// <param name="command"></param>
229 /// <returns></returns>
230 public MapPacket Command(string command)
231 {
232 foreach (MapPacket map in HighMaps)
233 {
234 if (map != null)
235 {
236 if (command == map.Name)
237 {
238 return map;
239 }
240 }
241 }
242  
243 foreach (MapPacket map in MediumMaps)
244 {
245 if (map != null)
246 {
247 if (command == map.Name)
248 {
249 return map;
250 }
251 }
252 }
253  
254 foreach (MapPacket map in LowMaps)
255 {
256 if (map != null)
257 {
258 if (command == map.Name)
259 {
260 return map;
261 }
262 }
263 }
264  
265 throw new Exception("Cannot find map for command \"" + command + "\"");
266 }
267  
268 /// <summary>
269 ///
270 /// </summary>
271 /// <param name="data"></param>
272 /// <returns></returns>
273 public MapPacket Command(byte[] data)
274 {
275 ushort command;
276  
277 if (data.Length < 5)
278 {
279 return null;
280 }
281  
282 if (data[4] == 0xFF)
283 {
284 if ((byte)data[5] == 0xFF)
285 {
286 // Low frequency
287 command = (ushort)(data[6] * 256 + data[7]);
288 return Command(command, PacketFrequency.Low);
289 }
290 else
291 {
292 // Medium frequency
293 command = (ushort)data[5];
294 return Command(command, PacketFrequency.Medium);
295 }
296 }
297 else
298 {
299 // High frequency
300 command = (ushort)data[4];
301 return Command(command, PacketFrequency.High);
302 }
303 }
304  
305 /// <summary>
306 ///
307 /// </summary>
308 /// <param name="command"></param>
309 /// <param name="frequency"></param>
310 /// <returns></returns>
311 public MapPacket Command(ushort command, PacketFrequency frequency)
312 {
313 switch (frequency)
314 {
315 case PacketFrequency.High:
316 return HighMaps[command];
317 case PacketFrequency.Medium:
318 return MediumMaps[command];
319 case PacketFrequency.Low:
320 return LowMaps[command];
321 }
322  
323 throw new Exception("Cannot find map for command \"" + command + "\" with frequency \"" + frequency + "\"");
324 }
325  
326 /// <summary>
327 ///
328 /// </summary>
329 public void PrintMap(TextWriter writer)
330 {
331 PrintOneMap(writer, LowMaps, "Low ");
332 PrintOneMap(writer, MediumMaps, "Medium");
333 PrintOneMap(writer, HighMaps, "High ");
334 }
335  
336 /// <summary>
337 ///
338 /// </summary>
339 /// <param name="map"></param>
340 /// <param name="frequency"></param>
341 private void PrintOneMap(TextWriter writer, MapPacket[] map, string frequency) {
342 int i;
343  
344 for (i = 0; i < map.Length; ++i)
345 {
346 if (map[i] != null)
347 {
348 writer.WriteLine("{0} {1,5} - {2} - {3} - {4}", frequency, i, map[i].Name,
349 map[i].Trusted ? "Trusted" : "Untrusted",
350 map[i].Encoded ? "Zerocoded" : "Unencoded");
351  
352 foreach (MapBlock block in map[i].Blocks)
353 {
354 if (block.Count == -1)
355 {
356 writer.WriteLine("\t{0,4} {1} (Variable)", block.KeywordPosition, block.Name);
357 }
358 else
359 {
360 writer.WriteLine("\t{0,4} {1} ({2})", block.KeywordPosition, block.Name, block.Count);
361 }
362  
363 foreach (MapField field in block.Fields)
364 {
365 writer.WriteLine("\t\t{0,4} {1} ({2} / {3})", field.KeywordPosition, field.Name,
366 field.Type, field.Count);
367 }
368 }
369 }
370 }
371 }
372  
373 /// <summary>
374 ///
375 /// </summary>
376 /// <param name="mapFile"></param>
377 /// <param name="outputFile"></param>
378 public static void DecodeMapFile(string mapFile, string outputFile)
379 {
380 byte magicKey = 0;
381 byte[] buffer = new byte[2048];
382 int nread;
383 BinaryReader map;
384 BinaryWriter output;
385  
386 try
387 {
388 map = new BinaryReader(new FileStream(mapFile, FileMode.Open));
389 }
390 catch(Exception e)
391 {
392 throw new Exception("Map file error", e);
393 }
394  
395 try
396 {
397 output = new BinaryWriter(new FileStream(outputFile, FileMode.CreateNew));
398 }
399 catch(Exception e)
400 {
401 throw new Exception("Map file error", e);
402 }
403  
404 while ((nread = map.Read(buffer, 0, 2048)) != 0)
405 {
406 for (int i = 0; i < nread; ++i)
407 {
408 buffer[i] ^= magicKey;
409 magicKey += 43;
410 }
411  
412 output.Write(buffer, 0, nread);
413 }
414  
415 map.Close();
416 output.Close();
417 }
418  
419 /// <summary>
420 ///
421 /// </summary>
422 /// <param name="mapFile"></param>
423 private void LoadMapFile(string mapFile)
424 {
425 FileStream map;
426  
427 // Load the protocol map file
428 try
429 {
430 map = new FileStream(mapFile, FileMode.Open, FileAccess.Read);
431 }
432 catch(Exception e)
433 {
434 throw new Exception("Map file error", e);
435 }
436  
437 try
438 {
439 StreamReader r = new StreamReader(map);
440 r.BaseStream.Seek(0, SeekOrigin.Begin);
441 string newline;
442 string trimmedline;
443 bool inPacket = false;
444 bool inBlock = false;
445 MapPacket currentPacket = null;
446 MapBlock currentBlock = null;
447 char[] trimArray = new char[] {' ', '\t'};
448  
449 // While not at the end of the file
450 while (r.Peek() > -1)
451 {
452 #region ParseMap
453  
454 newline = r.ReadLine();
455 trimmedline = System.Text.RegularExpressions.Regex.Replace(newline, @"\s+", " ");
456 trimmedline = trimmedline.Trim(trimArray);
457  
458 if (!inPacket)
459 {
460 // Outside of all packet blocks
461  
462 if (trimmedline == "{")
463 {
464 inPacket = true;
465 }
466 }
467 else
468 {
469 // Inside of a packet block
470  
471 if (!inBlock)
472 {
473 // Inside a packet block, outside of the blocks
474  
475 if (trimmedline == "{")
476 {
477 inBlock = true;
478 }
479 else if (trimmedline == "}")
480 {
481 // Reached the end of the packet
482 // currentPacket.Blocks.Sort();
483 inPacket = false;
484 }
485 else
486 {
487 // Skip comments
488 if (trimmedline.StartsWith("//")) continue;
489  
490 // The packet header
491 #region ParsePacketHeader
492  
493 // Splice the string in to tokens
494 string[] tokens = trimmedline.Split(new char[] {' ', '\t'});
495  
496 if (tokens.Length > 3)
497 {
498 //Hash packet name to insure correct keyword ordering
499 KeywordPosition(tokens[0]);
500  
501 uint packetID;
502  
503 // Remove the leading "0x"
504 if (tokens[2].Length > 2 && tokens[2].Substring(0, 2) == "0x")
505 {
506 tokens[2] = tokens[2].Substring(2, tokens[2].Length - 2);
507 packetID = UInt32.Parse(tokens[2], System.Globalization.NumberStyles.HexNumber);
508 } else {
509 packetID = UInt32.Parse(tokens[2]);
510 }
511  
512  
513 if (tokens[1] == "Fixed")
514 {
515  
516 // Truncate the id to a short
517 packetID &= 0xFFFF;
518 LowMaps[packetID] = new MapPacket();
519 LowMaps[packetID].ID = (ushort)packetID;
520 LowMaps[packetID].Frequency = PacketFrequency.Low;
521 LowMaps[packetID].Name = tokens[0];
522 LowMaps[packetID].Trusted = (tokens[3] == "Trusted");
523 LowMaps[packetID].Encoded = (tokens[4] == "Zerocoded");
524 LowMaps[packetID].Blocks = new List<MapBlock>();
525  
526 currentPacket = LowMaps[packetID];
527 }
528 else if (tokens[1] == "Low")
529 {
530 LowMaps[packetID] = new MapPacket();
531 LowMaps[packetID].ID = (ushort)packetID;
532 LowMaps[packetID].Frequency = PacketFrequency.Low;
533 LowMaps[packetID].Name = tokens[0];
534 LowMaps[packetID].Trusted = (tokens[2] == "Trusted");
535 LowMaps[packetID].Encoded = (tokens[4] == "Zerocoded");
536 LowMaps[packetID].Blocks = new List<MapBlock>();
537  
538 currentPacket = LowMaps[packetID];
539  
540 }
541 else if (tokens[1] == "Medium")
542 {
543 MediumMaps[packetID] = new MapPacket();
544 MediumMaps[packetID].ID = (ushort)packetID;
545 MediumMaps[packetID].Frequency = PacketFrequency.Medium;
546 MediumMaps[packetID].Name = tokens[0];
547 MediumMaps[packetID].Trusted = (tokens[2] == "Trusted");
548 MediumMaps[packetID].Encoded = (tokens[4] == "Zerocoded");
549 MediumMaps[packetID].Blocks = new List<MapBlock>();
550  
551 currentPacket = MediumMaps[packetID];
552  
553 }
554 else if (tokens[1] == "High")
555 {
556 HighMaps[packetID] = new MapPacket();
557 HighMaps[packetID].ID = (ushort)packetID;
558 HighMaps[packetID].Frequency = PacketFrequency.High;
559 HighMaps[packetID].Name = tokens[0];
560 HighMaps[packetID].Trusted = (tokens[2] == "Trusted");
561 HighMaps[packetID].Encoded = (tokens[4] == "Zerocoded");
562 HighMaps[packetID].Blocks = new List<MapBlock>();
563  
564 currentPacket = HighMaps[packetID];
565  
566 }
567 else
568 {
569 //Client.Log("Unknown packet frequency", Helpers.LogLevel.Error);
570 throw new Exception("Unknown packet frequency");
571 }
572 }
573  
574 #endregion
575 }
576 }
577 else
578 {
579 if (trimmedline.Length > 0 && trimmedline.Substring(0, 1) == "{")
580 {
581 // A field
582 #region ParseField
583  
584 MapField field = new MapField();
585  
586 // Splice the string in to tokens
587 string[] tokens = trimmedline.Split(new char[] {' ', '\t'});
588  
589 field.Name = tokens[1];
590 field.KeywordPosition = KeywordPosition(field.Name);
591 field.Type = (FieldType)Enum.Parse(typeof(FieldType), tokens[2], true);
592  
593 if (tokens[3] != "}")
594 {
595 field.Count = Int32.Parse(tokens[3]);
596 }
597 else
598 {
599 field.Count = 1;
600 }
601  
602 // Save this field to the current block
603 currentBlock.Fields.Add(field);
604  
605 #endregion
606 }
607 else if (trimmedline == "}")
608 {
609 // currentBlock.Fields.Sort();
610 inBlock = false;
611 }
612 else if (trimmedline.Length != 0 && trimmedline.Substring(0, 2) != "//")
613 {
614 // The block header
615 #region ParseBlockHeader
616  
617 currentBlock = new MapBlock();
618  
619 // Splice the string in to tokens
620 string[] tokens = trimmedline.Split(new char[] {' ', '\t'});
621  
622 currentBlock.Name = tokens[0];
623 currentBlock.KeywordPosition = KeywordPosition(currentBlock.Name);
624 currentBlock.Fields = new List<MapField>();
625 currentPacket.Blocks.Add(currentBlock);
626  
627 if (tokens[1] == "Single")
628 {
629 currentBlock.Count = 1;
630 }
631 else if (tokens[1] == "Multiple")
632 {
633 currentBlock.Count = Int32.Parse(tokens[2]);
634 }
635 else if (tokens[1] == "Variable")
636 {
637 currentBlock.Count = -1;
638 }
639 else
640 {
641 //Client.Log("Unknown block frequency", Helpers.LogLevel.Error);
642 throw new Exception("Unknown block frequency");
643 }
644  
645 #endregion
646 }
647 }
648 }
649  
650 #endregion
651 }
652  
653 r.Close();
654 map.Close();
655 }
656 catch (Exception e)
657 {
658 throw e;
659 }
660 }
661  
662 private int KeywordPosition(string keyword)
663 {
664 if (KeywordPositions.ContainsKey(keyword))
665 {
666 return KeywordPositions[keyword];
667 }
668  
669 int hash = 0;
670 for (int i = 1; i < keyword.Length; i++)
671 {
672 hash = (hash + (int)(keyword[i])) * 2;
673 }
674 hash *= 2;
675 hash &= 0x1FFF;
676  
677 int startHash = hash;
678  
679 while (KeywordPositions.ContainsValue(hash))
680 {
681 hash++;
682 hash &= 0x1FFF;
683 if (hash == startHash)
684 {
685 //Give up looking, went through all values and they were all taken.
686 throw new Exception("All hash values are taken. Failed to add keyword: " + keyword);
687 }
688 }
689  
690 KeywordPositions[keyword] = hash;
691 return hash;
692 }
693 }
694 }