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