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 class mapgenerator
8 {
9 static void WriteFieldMember(TextWriter writer, MapField field)
10 {
11 string type = String.Empty;
12  
13 switch (field.Type)
14 {
15 case FieldType.BOOL:
16 type = "bool";
17 break;
18 case FieldType.F32:
19 type = "float";
20 break;
21 case FieldType.F64:
22 type = "double";
23 break;
24 case FieldType.IPPORT:
25 case FieldType.U16:
26 type = "ushort";
27 break;
28 case FieldType.IPADDR:
29 case FieldType.U32:
30 type = "uint";
31 break;
32 case FieldType.LLQuaternion:
33 type = "Quaternion";
34 break;
35 case FieldType.LLUUID:
36 type = "UUID";
37 break;
38 case FieldType.LLVector3:
39 type = "Vector3";
40 break;
41 case FieldType.LLVector3d:
42 type = "Vector3d";
43 break;
44 case FieldType.LLVector4:
45 type = "Vector4";
46 break;
47 case FieldType.S16:
48 type = "short";
49 break;
50 case FieldType.S32:
51 type = "int";
52 break;
53 case FieldType.S8:
54 type = "sbyte";
55 break;
56 case FieldType.U64:
57 type = "ulong";
58 break;
59 case FieldType.U8:
60 type = "byte";
61 break;
62 case FieldType.Fixed:
63 type = "byte[]";
64 break;
65 }
66 if (field.Type != FieldType.Variable)
67 {
68 //writer.WriteLine(" /// <summary>" + field.Name + " field</summary>");
69 writer.WriteLine(" public " + type + " " + field.Name + ";");
70 }
71 else
72 {
73 writer.WriteLine(" public byte[] " + field.Name + ";");
74  
75 //writer.WriteLine(" private byte[] _" + field.Name.ToLower() + ";");
76 ////writer.WriteLine(" /// <summary>" + field.Name + " field</summary>");
77 //writer.WriteLine(" public byte[] " + field.Name + Environment.NewLine + " {");
78 //writer.WriteLine(" get { return _" + field.Name.ToLower() + "; }");
79 //writer.WriteLine(" set" + Environment.NewLine + " {");
80 //writer.WriteLine(" if (value == null) { _" +
81 // field.Name.ToLower() + " = null; return; }");
82 //writer.WriteLine(" if (value.Length > " +
83 // ((field.Count == 1) ? "255" : "1100") + ") { throw new OverflowException(" +
84 // "\"Value exceeds " + ((field.Count == 1) ? "255" : "1100") + " characters\"); }");
85 //writer.WriteLine(" else { _" + field.Name.ToLower() +
86 // " = new byte[value.Length]; Buffer.BlockCopy(value, 0, _" +
87 // field.Name.ToLower() + ", 0, value.Length); }");
88 //writer.WriteLine(" }" + Environment.NewLine + " }");
89 }
90 }
91  
92 static void WriteFieldFromBytes(TextWriter writer, MapField field)
93 {
94 switch (field.Type)
95 {
96 case FieldType.BOOL:
97 writer.WriteLine(" " +
98 field.Name + " = (bytes[i++] != 0) ? (bool)true : (bool)false;");
99 break;
100 case FieldType.F32:
101 writer.WriteLine(" " +
102 field.Name + " = Utils.BytesToFloat(bytes, i); i += 4;");
103 break;
104 case FieldType.F64:
105 writer.WriteLine(" " +
106 field.Name + " = Utils.BytesToDouble(bytes, i); i += 8;");
107 break;
108 case FieldType.Fixed:
109 writer.WriteLine(" " + field.Name + " = new byte[" + field.Count + "];");
110 writer.WriteLine(" Buffer.BlockCopy(bytes, i, " + field.Name +
111 ", 0, " + field.Count + "); i += " + field.Count + ";");
112 break;
113 case FieldType.IPADDR:
114 case FieldType.U32:
115 writer.WriteLine(" " + field.Name +
116 " = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));");
117 break;
118 case FieldType.IPPORT:
119 // IPPORT is big endian while U16/S16 are little endian. Go figure
120 writer.WriteLine(" " + field.Name +
121 " = (ushort)((bytes[i++] << 8) + bytes[i++]);");
122 break;
123 case FieldType.U16:
124 writer.WriteLine(" " + field.Name +
125 " = (ushort)(bytes[i++] + (bytes[i++] << 8));");
126 break;
127 case FieldType.LLQuaternion:
128 writer.WriteLine(" " + field.Name + ".FromBytes(bytes, i, true); i += 12;");
129 break;
130 case FieldType.LLUUID:
131 writer.WriteLine(" " + field.Name + ".FromBytes(bytes, i); i += 16;");
132 break;
133 case FieldType.LLVector3:
134 writer.WriteLine(" " + field.Name + ".FromBytes(bytes, i); i += 12;");
135 break;
136 case FieldType.LLVector3d:
137 writer.WriteLine(" " + field.Name + ".FromBytes(bytes, i); i += 24;");
138 break;
139 case FieldType.LLVector4:
140 writer.WriteLine(" " + field.Name + ".FromBytes(bytes, i); i += 16;");
141 break;
142 case FieldType.S16:
143 writer.WriteLine(" " + field.Name +
144 " = (short)(bytes[i++] + (bytes[i++] << 8));");
145 break;
146 case FieldType.S32:
147 writer.WriteLine(" " + field.Name +
148 " = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));");
149 break;
150 case FieldType.S8:
151 writer.WriteLine(" " + field.Name +
152 " = (sbyte)bytes[i++];");
153 break;
154 case FieldType.U64:
155 writer.WriteLine(" " + field.Name +
156 " = (ulong)((ulong)bytes[i++] + ((ulong)bytes[i++] << 8) + " +
157 "((ulong)bytes[i++] << 16) + ((ulong)bytes[i++] << 24) + " +
158 "((ulong)bytes[i++] << 32) + ((ulong)bytes[i++] << 40) + " +
159 "((ulong)bytes[i++] << 48) + ((ulong)bytes[i++] << 56));");
160 break;
161 case FieldType.U8:
162 writer.WriteLine(" " + field.Name +
163 " = (byte)bytes[i++];");
164 break;
165 case FieldType.Variable:
166 if (field.Count == 1)
167 {
168 writer.WriteLine(" length = bytes[i++];");
169 }
170 else
171 {
172 writer.WriteLine(" length = (bytes[i++] + (bytes[i++] << 8));");
173 }
174 writer.WriteLine(" " + field.Name + " = new byte[length];");
175 writer.WriteLine(" Buffer.BlockCopy(bytes, i, " + field.Name + ", 0, length); i += length;");
176 break;
177 default:
178 writer.WriteLine("!!! ERROR: Unhandled FieldType: " + field.Type.ToString() + " !!!");
179 break;
180 }
181 }
182  
183 static void WriteFieldToBytes(TextWriter writer, MapField field)
184 {
185 writer.Write(" ");
186  
187 switch (field.Type)
188 {
189 case FieldType.BOOL:
190 writer.WriteLine("bytes[i++] = (byte)((" + field.Name + ") ? 1 : 0);");
191 break;
192 case FieldType.F32:
193 writer.WriteLine("Utils.FloatToBytes(" + field.Name + ", bytes, i); i += 4;");
194 break;
195 case FieldType.F64:
196 writer.WriteLine("Utils.DoubleToBytes(" + field.Name + ", bytes, i); i += 8;");
197 break;
198 case FieldType.Fixed:
199 writer.WriteLine("Buffer.BlockCopy(" + field.Name + ", 0, bytes, i, " + field.Count + ");" +
200 "i += " + field.Count + ";");
201 break;
202 case FieldType.IPPORT:
203 // IPPORT is big endian while U16/S16 is little endian. Go figure
204 writer.WriteLine("bytes[i++] = (byte)((" + field.Name + " >> 8) % 256);");
205 writer.WriteLine(" bytes[i++] = (byte)(" + field.Name + " % 256);");
206 break;
207 case FieldType.U16:
208 case FieldType.S16:
209 writer.WriteLine("bytes[i++] = (byte)(" + field.Name + " % 256);");
210 writer.WriteLine(" bytes[i++] = (byte)((" + field.Name + " >> 8) % 256);");
211 break;
212 case FieldType.LLQuaternion:
213 case FieldType.LLVector3:
214 writer.WriteLine(field.Name + ".ToBytes(bytes, i); i += 12;");
215 break;
216 case FieldType.LLUUID:
217 case FieldType.LLVector4:
218 writer.WriteLine(field.Name + ".ToBytes(bytes, i); i += 16;");
219 break;
220 case FieldType.LLVector3d:
221 writer.WriteLine(field.Name + ".ToBytes(bytes, i); i += 24;");
222 break;
223 case FieldType.U8:
224 writer.WriteLine("bytes[i++] = " + field.Name + ";");
225 break;
226 case FieldType.S8:
227 writer.WriteLine("bytes[i++] = (byte)" + field.Name + ";");
228 break;
229 case FieldType.IPADDR:
230 case FieldType.U32:
231 writer.WriteLine("Utils.UIntToBytes(" + field.Name + ", bytes, i); i += 4;");
232 break;
233 case FieldType.S32:
234 writer.WriteLine("Utils.IntToBytes(" + field.Name + ", bytes, i); i += 4;");
235 break;
236 case FieldType.U64:
237 writer.WriteLine("Utils.UInt64ToBytes(" + field.Name + ", bytes, i); i += 8;");
238 break;
239 case FieldType.Variable:
240 //writer.WriteLine("if(" + field.Name + " == null) { Console.WriteLine(\"Warning: " + field.Name + " is null, in \" + this.GetType()); }");
241 //writer.Write(" ");
242 if (field.Count == 1)
243 {
244 writer.WriteLine("bytes[i++] = (byte)" + field.Name + ".Length;");
245 }
246 else
247 {
248 writer.WriteLine("bytes[i++] = (byte)(" + field.Name + ".Length % 256);");
249 writer.WriteLine(" bytes[i++] = (byte)((" +
250 field.Name + ".Length >> 8) % 256);");
251 }
252 writer.WriteLine(" Buffer.BlockCopy(" + field.Name + ", 0, bytes, i, " +
253 field.Name + ".Length); " + "i += " + field.Name + ".Length;");
254 break;
255 default:
256 writer.WriteLine("!!! ERROR: Unhandled FieldType: " + field.Type.ToString() + " !!!");
257 break;
258 }
259 }
260  
261 static int GetFieldLength(TextWriter writer, MapField field)
262 {
263 switch (field.Type)
264 {
265 case FieldType.BOOL:
266 case FieldType.U8:
267 case FieldType.S8:
268 return 1;
269 case FieldType.U16:
270 case FieldType.S16:
271 case FieldType.IPPORT:
272 return 2;
273 case FieldType.U32:
274 case FieldType.S32:
275 case FieldType.F32:
276 case FieldType.IPADDR:
277 return 4;
278 case FieldType.U64:
279 case FieldType.F64:
280 return 8;
281 case FieldType.LLVector3:
282 case FieldType.LLQuaternion:
283 return 12;
284 case FieldType.LLUUID:
285 case FieldType.LLVector4:
286 return 16;
287 case FieldType.LLVector3d:
288 return 24;
289 case FieldType.Fixed:
290 return field.Count;
291 case FieldType.Variable:
292 return 0;
293 default:
294 writer.WriteLine("!!! ERROR: Unhandled FieldType " + field.Type.ToString() + " !!!");
295 return 0;
296 }
297 }
298  
299 static void WriteBlockClass(TextWriter writer, MapBlock block, MapPacket packet)
300 {
301 int variableFieldCountBytes = 0;
302  
303 //writer.WriteLine(" /// <summary>" + block.Name + " block</summary>");
304 writer.WriteLine(" /// <exclude/>");
305 writer.WriteLine(" public sealed class " + block.Name + "Block : PacketBlock" + Environment.NewLine + " {");
306  
307 foreach (MapField field in block.Fields)
308 {
309 WriteFieldMember(writer, field);
310 if (field.Type == FieldType.Variable) { variableFieldCountBytes += field.Count; }
311 }
312  
313 // Length property
314 writer.WriteLine("");
315 //writer.WriteLine(" /// <summary>Length of this block serialized in bytes</summary>");
316 writer.WriteLine(" public override int Length" + Environment.NewLine +
317 " {" + Environment.NewLine +
318 " get" + Environment.NewLine +
319 " {");
320 int length = variableFieldCountBytes;
321  
322 // Figure out the length of this block
323 foreach (MapField field in block.Fields)
324 {
325 length += GetFieldLength(writer, field);
326 }
327  
328 if (variableFieldCountBytes == 0)
329 {
330 writer.WriteLine(" return " + length + ";");
331 }
332 else
333 {
334 writer.WriteLine(" int length = " + length + ";");
335  
336 foreach (MapField field in block.Fields)
337 {
338 if (field.Type == FieldType.Variable)
339 {
340 writer.WriteLine(" if (" + field.Name +
341 " != null) { length += " + field.Name + ".Length; }");
342 }
343 }
344  
345 writer.WriteLine(" return length;");
346 }
347  
348 writer.WriteLine(" }" + Environment.NewLine + " }" + Environment.NewLine);
349  
350 // Default constructor
351 //writer.WriteLine(" /// <summary>Default constructor</summary>");
352 writer.WriteLine(" public " + block.Name + "Block() { }");
353  
354 // Constructor for building the class from bytes
355 //writer.WriteLine(" /// <summary>Constructor for building the block from a byte array</summary>");
356 writer.WriteLine(" public " + block.Name + "Block(byte[] bytes, ref int i)" + Environment.NewLine +
357 " {" + Environment.NewLine +
358 " FromBytes(bytes, ref i);" + Environment.NewLine +
359 " }" + Environment.NewLine);
360  
361 // Initiates instance variables from a byte message
362 writer.WriteLine(" public override void FromBytes(byte[] bytes, ref int i)" + Environment.NewLine +
363 " {");
364  
365 // Declare a length variable if we need it for variable fields in this constructor
366 if (variableFieldCountBytes > 0) { writer.WriteLine(" int length;"); }
367  
368 // Start of the try catch block
369 writer.WriteLine(" try" + Environment.NewLine + " {");
370  
371 foreach (MapField field in block.Fields)
372 {
373 WriteFieldFromBytes(writer, field);
374 }
375  
376 writer.WriteLine(" }" + Environment.NewLine +
377 " catch (Exception)" + Environment.NewLine +
378 " {" + Environment.NewLine +
379 " throw new MalformedDataException();" + Environment.NewLine +
380 " }" + Environment.NewLine + " }" + Environment.NewLine);
381  
382 // ToBytes() function
383 //writer.WriteLine(" /// <summary>Serialize this block to a byte array</summary>");
384 writer.WriteLine(" public override void ToBytes(byte[] bytes, ref int i)" + Environment.NewLine +
385 " {");
386  
387 foreach (MapField field in block.Fields)
388 {
389 WriteFieldToBytes(writer, field);
390 }
391  
392 writer.WriteLine(" }" + Environment.NewLine);
393 writer.WriteLine(" }" + Environment.NewLine);
394 }
395  
396 static void WritePacketClass(TextWriter writer, MapPacket packet)
397 {
398 bool hasVariableBlocks = false;
399 string sanitizedName;
400  
401 //writer.WriteLine(" /// <summary>" + packet.Name + " packet</summary>");
402 writer.WriteLine(" /// <exclude/>");
403 writer.WriteLine(" public sealed class " + packet.Name + "Packet : Packet" + Environment.NewLine + " {");
404  
405 // Write out each block class
406 foreach (MapBlock block in packet.Blocks)
407 {
408 WriteBlockClass(writer, block, packet);
409 }
410  
411 // Length member
412 writer.WriteLine(" public override int Length" + Environment.NewLine +
413 " {" + Environment.NewLine + " get" + Environment.NewLine +
414 " {");
415  
416 int length = 0;
417 if (packet.Frequency == PacketFrequency.Low) { length = 10; }
418 else if (packet.Frequency == PacketFrequency.Medium) { length = 8; }
419 else { length = 7; }
420  
421 foreach (MapBlock block in packet.Blocks)
422 {
423 if (block.Count == -1)
424 {
425 hasVariableBlocks = true;
426 ++length;
427 }
428 }
429  
430 writer.WriteLine(" int length = " + length + ";");
431  
432 foreach (MapBlock block in packet.Blocks)
433 {
434 if (block.Name == "Header") { sanitizedName = "_" + block.Name; }
435 else { sanitizedName = block.Name; }
436  
437 if (block.Count == -1)
438 {
439 // Variable count block
440 writer.WriteLine(" for (int j = 0; j < " + sanitizedName + ".Length; j++)");
441 writer.WriteLine(" length += " + sanitizedName + "[j].Length;");
442 }
443 else if (block.Count == 1)
444 {
445 writer.WriteLine(" length += " + sanitizedName + ".Length;");
446 }
447 else
448 {
449 // Multiple count block
450 writer.WriteLine(" for (int j = 0; j < " + block.Count + "; j++)");
451 writer.WriteLine(" length += " + sanitizedName + "[j].Length;");
452 }
453 }
454 writer.WriteLine(" return length;");
455 writer.WriteLine(" }" + Environment.NewLine + " }");
456  
457 // Block members
458 foreach (MapBlock block in packet.Blocks)
459 {
460 // TODO: More thorough name blacklisting
461 if (block.Name == "Header") { sanitizedName = "_" + block.Name; }
462 else { sanitizedName = block.Name; }
463  
464 //writer.WriteLine(" /// <summary>" + block.Name + " block</summary>");
465 writer.WriteLine(" public " + block.Name + "Block" +
466 ((block.Count != 1) ? "[]" : "") + " " + sanitizedName + ";");
467 }
468  
469 writer.WriteLine("");
470  
471 // Default constructor
472 //writer.WriteLine(" /// <summary>Default constructor</summary>");
473 writer.WriteLine(" public " + packet.Name + "Packet()" + Environment.NewLine + " {");
474 writer.WriteLine(" HasVariableBlocks = " + hasVariableBlocks.ToString().ToLowerInvariant() + ";");
475 writer.WriteLine(" Type = PacketType." + packet.Name + ";");
476 writer.WriteLine(" Header = new Header();");
477 writer.WriteLine(" Header.Frequency = PacketFrequency." + packet.Frequency + ";");
478 writer.WriteLine(" Header.ID = " + packet.ID + ";");
479 writer.WriteLine(" Header.Reliable = true;"); // Turn the reliable flag on by default
480 if (packet.Encoded) { writer.WriteLine(" Header.Zerocoded = true;"); }
481 foreach (MapBlock block in packet.Blocks)
482 {
483 if (block.Name == "Header") { sanitizedName = "_" + block.Name; }
484 else { sanitizedName = block.Name; }
485  
486 if (block.Count == 1)
487 {
488 // Single count block
489 writer.WriteLine(" " + sanitizedName + " = new " + block.Name + "Block();");
490 }
491 else if (block.Count == -1)
492 {
493 // Variable count block
494 writer.WriteLine(" " + sanitizedName + " = null;");
495 }
496 else
497 {
498 // Multiple count block
499 writer.WriteLine(" " + sanitizedName + " = new " + block.Name + "Block[" + block.Count + "];");
500 }
501 }
502 writer.WriteLine(" }" + Environment.NewLine);
503  
504 // Constructor that takes a byte array and beginning position only (no prebuilt header)
505 bool seenVariable = false;
506 //writer.WriteLine(" /// <summary>Constructor that takes a byte array and beginning position (no prebuilt header)</summary>");
507 writer.WriteLine(" public " + packet.Name + "Packet(byte[] bytes, ref int i) : this()" + Environment.NewLine +
508 " {" + Environment.NewLine +
509 " int packetEnd = bytes.Length - 1;" + Environment.NewLine +
510 " FromBytes(bytes, ref i, ref packetEnd, null);" + Environment.NewLine +
511 " }" + Environment.NewLine);
512  
513 writer.WriteLine(" override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)" + Environment.NewLine + " {");
514 writer.WriteLine(" Header.FromBytes(bytes, ref i, ref packetEnd);");
515 writer.WriteLine(" if (Header.Zerocoded && zeroBuffer != null)");
516 writer.WriteLine(" {");
517 writer.WriteLine(" packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;");
518 writer.WriteLine(" bytes = zeroBuffer;");
519 writer.WriteLine(" }");
520  
521 foreach (MapBlock block in packet.Blocks)
522 {
523 if (block.Name == "Header") { sanitizedName = "_" + block.Name; }
524 else { sanitizedName = block.Name; }
525  
526 if (block.Count == 1)
527 {
528 // Single count block
529 writer.WriteLine(" " + sanitizedName + ".FromBytes(bytes, ref i);");
530 }
531 else if (block.Count == -1)
532 {
533 // Variable count block
534 if (!seenVariable)
535 {
536 writer.WriteLine(" int count = (int)bytes[i++];");
537 seenVariable = true;
538 }
539 else
540 {
541 writer.WriteLine(" count = (int)bytes[i++];");
542 }
543 writer.WriteLine(" if(" + sanitizedName + " == null || " + sanitizedName + ".Length != " + block.Count + ") {");
544 writer.WriteLine(" " + sanitizedName + " = new " + block.Name + "Block[count];");
545 writer.WriteLine(" for(int j = 0; j < count; j++)");
546 writer.WriteLine(" { " + sanitizedName + "[j] = new " + block.Name + "Block(); }");
547 writer.WriteLine(" }");
548 writer.WriteLine(" for (int j = 0; j < count; j++)");
549 writer.WriteLine(" { " + sanitizedName + "[j].FromBytes(bytes, ref i); }");
550 }
551 else
552 {
553 // Multiple count block
554 writer.WriteLine(" if(" + sanitizedName + " == null || " + sanitizedName + ".Length != " + block.Count + ") {");
555 writer.WriteLine(" " + sanitizedName + " = new " + block.Name + "Block[" + block.Count + "];");
556 writer.WriteLine(" for(int j = 0; j < " + block.Count + "; j++)");
557 writer.WriteLine(" { " + sanitizedName + "[j] = new " + block.Name + "Block(); }");
558 writer.WriteLine(" }");
559 writer.WriteLine(" for (int j = 0; j < " + block.Count + "; j++)");
560 writer.WriteLine(" { " + sanitizedName + "[j].FromBytes(bytes, ref i); }");
561 }
562 }
563 writer.WriteLine(" }" + Environment.NewLine);
564  
565 seenVariable = false;
566  
567 // Constructor that takes a byte array and a prebuilt header
568 //writer.WriteLine(" /// <summary>Constructor that takes a byte array and a prebuilt header</summary>");
569 writer.WriteLine(" public " + packet.Name + "Packet(Header head, byte[] bytes, ref int i): this()" + Environment.NewLine +
570 " {" + Environment.NewLine +
571 " int packetEnd = bytes.Length - 1;" + Environment.NewLine +
572 " FromBytes(head, bytes, ref i, ref packetEnd);" + Environment.NewLine +
573 " }" + Environment.NewLine);
574  
575 writer.WriteLine(" override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)" + Environment.NewLine +
576 " {");
577 writer.WriteLine(" Header = header;");
578 foreach (MapBlock block in packet.Blocks)
579 {
580 if (block.Name == "Header") { sanitizedName = "_" + block.Name; }
581 else { sanitizedName = block.Name; }
582  
583 if (block.Count == 1)
584 {
585 // Single count block
586 writer.WriteLine(" " + sanitizedName + ".FromBytes(bytes, ref i);");
587 }
588 else if (block.Count == -1)
589 {
590 // Variable count block
591 if (!seenVariable)
592 {
593 writer.WriteLine(" int count = (int)bytes[i++];");
594 seenVariable = true;
595 }
596 else
597 {
598 writer.WriteLine(" count = (int)bytes[i++];");
599 }
600 writer.WriteLine(" if(" + sanitizedName + " == null || " + sanitizedName + ".Length != count) {");
601 writer.WriteLine(" " + sanitizedName + " = new " + block.Name + "Block[count];");
602 writer.WriteLine(" for(int j = 0; j < count; j++)");
603 writer.WriteLine(" { " + sanitizedName + "[j] = new " + block.Name + "Block(); }");
604 writer.WriteLine(" }");
605 writer.WriteLine(" for (int j = 0; j < count; j++)");
606 writer.WriteLine(" { " + sanitizedName + "[j].FromBytes(bytes, ref i); }");
607 }
608 else
609 {
610 // Multiple count block
611 writer.WriteLine(" if(" + sanitizedName + " == null || " + sanitizedName + ".Length != " + block.Count + ") {");
612 writer.WriteLine(" " + sanitizedName + " = new " + block.Name + "Block[" + block.Count + "];");
613 writer.WriteLine(" for(int j = 0; j < " + block.Count + "; j++)");
614 writer.WriteLine(" { " + sanitizedName + "[j] = new " + block.Name + "Block(); }");
615 writer.WriteLine(" }");
616 writer.WriteLine(" for (int j = 0; j < " + block.Count + "; j++)");
617 writer.WriteLine(" { " + sanitizedName + "[j].FromBytes(bytes, ref i); }");
618 }
619 }
620 writer.WriteLine(" }" + Environment.NewLine);
621  
622 #region ToBytes() Function
623  
624 //writer.WriteLine(" /// <summary>Serialize this packet to a byte array</summary><returns>A byte array containing the serialized packet</returns>");
625 writer.WriteLine(" public override byte[] ToBytes()" + Environment.NewLine + " {");
626  
627 writer.Write(" int length = ");
628 if (packet.Frequency == PacketFrequency.Low) { writer.WriteLine("10;"); }
629 else if (packet.Frequency == PacketFrequency.Medium) { writer.WriteLine("8;"); }
630 else { writer.WriteLine("7;"); }
631  
632 foreach (MapBlock block in packet.Blocks)
633 {
634 if (block.Name == "Header") { sanitizedName = "_" + block.Name; }
635 else { sanitizedName = block.Name; }
636  
637 if (block.Count == 1)
638 {
639 // Single count block
640 writer.WriteLine(" length += " + sanitizedName + ".Length;");
641 }
642 }
643  
644 foreach (MapBlock block in packet.Blocks)
645 {
646 if (block.Name == "Header") { sanitizedName = "_" + block.Name; }
647 else { sanitizedName = block.Name; }
648  
649 if (block.Count == -1)
650 {
651 writer.WriteLine(" length++;");
652 writer.WriteLine(" for (int j = 0; j < " + sanitizedName +
653 ".Length; j++) { length += " + sanitizedName + "[j].Length; }");
654 }
655 else if (block.Count > 1)
656 {
657 writer.WriteLine(" for (int j = 0; j < " + block.Count +
658 "; j++) { length += " + sanitizedName + "[j].Length; }");
659 }
660 }
661  
662 writer.WriteLine(" if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }");
663 writer.WriteLine(" byte[] bytes = new byte[length];");
664 writer.WriteLine(" int i = 0;");
665 writer.WriteLine(" Header.ToBytes(bytes, ref i);");
666 foreach (MapBlock block in packet.Blocks)
667 {
668 if (block.Name == "Header") { sanitizedName = "_" + block.Name; }
669 else { sanitizedName = block.Name; }
670  
671 if (block.Count == -1)
672 {
673 // Variable count block
674 writer.WriteLine(" bytes[i++] = (byte)" + sanitizedName + ".Length;");
675 writer.WriteLine(" for (int j = 0; j < " + sanitizedName +
676 ".Length; j++) { " + sanitizedName + "[j].ToBytes(bytes, ref i); }");
677 }
678 else if (block.Count == 1)
679 {
680 writer.WriteLine(" " + sanitizedName + ".ToBytes(bytes, ref i);");
681 }
682 else
683 {
684 // Multiple count block
685 writer.WriteLine(" for (int j = 0; j < " + block.Count +
686 "; j++) { " + sanitizedName + "[j].ToBytes(bytes, ref i); }");
687 }
688 }
689  
690 writer.WriteLine(" if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }");
691 writer.WriteLine(" return bytes;" + Environment.NewLine + " }" + Environment.NewLine);
692  
693 #endregion ToBytes() Function
694  
695 WriteToBytesMultiple(writer, packet);
696  
697 writer.WriteLine(" }" + Environment.NewLine);
698 }
699  
700 static void WriteToBytesMultiple(TextWriter writer, MapPacket packet)
701 {
702 writer.WriteLine(
703 " public override byte[][] ToBytesMultiple()" + Environment.NewLine +
704 " {");
705  
706 // Check if there are any variable blocks
707 bool hasVariable = false;
708 bool cannotSplit = false;
709 foreach (MapBlock block in packet.Blocks)
710 {
711 if (block.Count == -1)
712 {
713 hasVariable = true;
714 }
715 else if (hasVariable)
716 {
717 // A fixed or single block showed up after a variable count block.
718 // Our automatic splitting algorithm won't work for this packet
719 cannotSplit = true;
720 break;
721 }
722 }
723  
724 if (hasVariable && !cannotSplit)
725 {
726 writer.WriteLine(
727 " System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();");
728 writer.WriteLine(
729 " int i = 0;");
730 writer.Write(
731 " int fixedLength = ");
732 if (packet.Frequency == PacketFrequency.Low) { writer.WriteLine("10;"); }
733 else if (packet.Frequency == PacketFrequency.Medium) { writer.WriteLine("8;"); }
734 else { writer.WriteLine("7;"); }
735 writer.WriteLine();
736  
737 // ACK serialization
738 writer.WriteLine(" byte[] ackBytes = null;");
739 writer.WriteLine(" int acksLength = 0;");
740 writer.WriteLine(" if (Header.AckList != null && Header.AckList.Length > 0) {");
741 writer.WriteLine(" Header.AppendedAcks = true;");
742 writer.WriteLine(" ackBytes = new byte[Header.AckList.Length * 4 + 1];");
743 writer.WriteLine(" Header.AcksToBytes(ackBytes, ref acksLength);");
744 writer.WriteLine(" }");
745 writer.WriteLine();
746  
747 // Count fixed blocks
748 foreach (MapBlock block in packet.Blocks)
749 {
750 string sanitizedName;
751 if (block.Name == "Header") { sanitizedName = "_" + block.Name; }
752 else { sanitizedName = block.Name; }
753  
754 if (block.Count == 1)
755 {
756 // Single count block
757 writer.WriteLine(" fixedLength += " + sanitizedName + ".Length;");
758 }
759 else if (block.Count > 0)
760 {
761 // Fixed count block
762 writer.WriteLine(" for (int j = 0; j < " + block.Count + "; j++) { fixedLength += " + sanitizedName + "[j].Length; }");
763 }
764 }
765  
766 // Serialize fixed blocks
767 writer.WriteLine(
768 " byte[] fixedBytes = new byte[fixedLength];");
769 writer.WriteLine(
770 " Header.ToBytes(fixedBytes, ref i);");
771 foreach (MapBlock block in packet.Blocks)
772 {
773 string sanitizedName;
774 if (block.Name == "Header") { sanitizedName = "_" + block.Name; }
775 else { sanitizedName = block.Name; }
776  
777 if (block.Count == 1)
778 {
779 // Single count block
780 writer.WriteLine(" " + sanitizedName + ".ToBytes(fixedBytes, ref i);");
781 }
782 else if (block.Count > 0)
783 {
784 // Fixed count block
785 writer.WriteLine(" for (int j = 0; j < " + block.Count + "; j++) { " + sanitizedName + "[j].ToBytes(fixedBytes, ref i); }");
786 }
787 }
788  
789 int variableCountBlock = 0;
790 foreach (MapBlock block in packet.Blocks)
791 {
792 string sanitizedName;
793 if (block.Name == "Header") { sanitizedName = "_" + block.Name; }
794 else { sanitizedName = block.Name; }
795  
796 if (block.Count == -1)
797 {
798 // Variable count block
799 ++variableCountBlock;
800 }
801 }
802 writer.WriteLine(" fixedLength += " + variableCountBlock + ";");
803 writer.WriteLine();
804  
805 foreach (MapBlock block in packet.Blocks)
806 {
807 string sanitizedName;
808 if (block.Name == "Header") { sanitizedName = "_" + block.Name; }
809 else { sanitizedName = block.Name; }
810  
811 if (block.Count == -1)
812 {
813 // Variable count block
814 writer.WriteLine(" int " + sanitizedName + "Start = 0;");
815 }
816 }
817  
818 writer.WriteLine(" do");
819 writer.WriteLine(" {");
820  
821 // Count how many variable blocks can go in this packet
822 writer.WriteLine(" int variableLength = 0;");
823  
824 foreach (MapBlock block in packet.Blocks)
825 {
826 string sanitizedName;
827 if (block.Name == "Header") { sanitizedName = "_" + block.Name; }
828 else { sanitizedName = block.Name; }
829  
830 if (block.Count == -1)
831 {
832 // Variable count block
833 writer.WriteLine(" int " + sanitizedName + "Count = 0;");
834 }
835 }
836 writer.WriteLine();
837  
838 foreach (MapBlock block in packet.Blocks)
839 {
840 string sanitizedName;
841 if (block.Name == "Header") { sanitizedName = "_" + block.Name; }
842 else { sanitizedName = block.Name; }
843  
844 if (block.Count == -1)
845 {
846 // Variable count block
847 writer.WriteLine(" i = " + sanitizedName + "Start;");
848 writer.WriteLine(" while (fixedLength + variableLength + acksLength < Packet.MTU && i < " + sanitizedName + ".Length) {");
849 writer.WriteLine(" int blockLength = " + sanitizedName + "[i].Length;");
850 writer.WriteLine(" if (fixedLength + variableLength + blockLength + acksLength <= MTU) {");
851 writer.WriteLine(" variableLength += blockLength;");
852 writer.WriteLine(" ++" + sanitizedName + "Count;");
853 writer.WriteLine(" }");
854 writer.WriteLine(" else { break; }");
855 writer.WriteLine(" ++i;");
856 writer.WriteLine(" }");
857 writer.WriteLine();
858 }
859 }
860  
861 // Create the packet
862 writer.WriteLine(" byte[] packet = new byte[fixedLength + variableLength + acksLength];");
863 writer.WriteLine(" int length = fixedBytes.Length;");
864 writer.WriteLine(" Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);");
865 // Remove the appended ACKs flag from subsequent packets
866 writer.WriteLine(" if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }");
867 writer.WriteLine();
868  
869 foreach (MapBlock block in packet.Blocks)
870 {
871 string sanitizedName;
872 if (block.Name == "Header") { sanitizedName = "_" + block.Name; }
873 else { sanitizedName = block.Name; }
874  
875 if (block.Count == -1)
876 {
877 writer.WriteLine(" packet[length++] = (byte)" + sanitizedName + "Count;");
878 writer.WriteLine(" for (i = " + sanitizedName + "Start; i < " + sanitizedName + "Start + "
879 + sanitizedName + "Count; i++) { " + sanitizedName + "[i].ToBytes(packet, ref length); }");
880 writer.WriteLine(" " + sanitizedName + "Start += " + sanitizedName + "Count;");
881 writer.WriteLine();
882 }
883 }
884  
885 // ACK appending
886 writer.WriteLine(" if (acksLength > 0) {");
887 writer.WriteLine(" Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);");
888 writer.WriteLine(" acksLength = 0;");
889 writer.WriteLine(" }");
890 writer.WriteLine();
891  
892 writer.WriteLine(" packets.Add(packet);");
893  
894 writer.WriteLine(" } while (");
895 bool first = true;
896 foreach (MapBlock block in packet.Blocks)
897 {
898 string sanitizedName;
899 if (block.Name == "Header") { sanitizedName = "_" + block.Name; }
900 else { sanitizedName = block.Name; }
901  
902 if (block.Count == -1)
903 {
904 if (first) first = false;
905 else writer.WriteLine(" ||");
906  
907 // Variable count block
908 writer.Write(" " + sanitizedName + "Start < " + sanitizedName + ".Length");
909 }
910 }
911 writer.WriteLine(");");
912 writer.WriteLine();
913 writer.WriteLine(" return packets.ToArray();");
914 writer.WriteLine(" }");
915 }
916 else
917 {
918 writer.WriteLine(" return new byte[][] { ToBytes() };");
919 writer.WriteLine(" }");
920 }
921 }
922  
923 static int Main(string[] args)
924 {
925 ProtocolManager protocol;
926 List<string> unused = new List<string>();
927 TextWriter writer;
928  
929 try
930 {
931 if (args.Length != 4)
932 {
933 Console.WriteLine("Usage: [message_template.msg] [template.cs] [unusedpackets.txt] [_Packets_.cs]");
934 return -1;
935 }
936  
937 writer = new StreamWriter(args[3]);
938 protocol = new ProtocolManager(args[0]);
939  
940 // Build a list of unused packets
941 using (StreamReader unusedReader = new StreamReader(args[2]))
942 {
943 while (unusedReader.Peek() >= 0)
944 {
945 unused.Add(unusedReader.ReadLine().Trim());
946 }
947 }
948  
949 // Read in the template.cs file and write it to our output
950 TextReader reader = new StreamReader(args[1]);
951 writer.WriteLine(reader.ReadToEnd());
952 reader.Close();
953 }
954 catch (Exception e)
955 {
956 Console.WriteLine(e.ToString());
957 return -2;
958 }
959  
960  
961 // Prune all of the unused packets out of the protocol
962 int i = 0;
963 foreach (MapPacket packet in protocol.LowMaps)
964 {
965 if (packet != null && unused.Contains(packet.Name))
966 protocol.LowMaps[i] = null;
967 i++;
968 }
969 i = 0;
970 foreach (MapPacket packet in protocol.MediumMaps)
971 {
972 if (packet != null && unused.Contains(packet.Name))
973 protocol.MediumMaps[i] = null;
974 i++;
975 }
976 i = 0;
977 foreach (MapPacket packet in protocol.HighMaps)
978 {
979 if (packet != null && unused.Contains(packet.Name))
980 protocol.HighMaps[i] = null;
981 i++;
982 }
983  
984  
985 // Write the PacketType enum
986 writer.WriteLine(" public enum PacketType" + Environment.NewLine + " {" + Environment.NewLine +
987 " /// <summary>A generic value, not an actual packet type</summary>" + Environment.NewLine +
988 " Default,");
989 foreach (MapPacket packet in protocol.LowMaps)
990 if (packet != null)
991 writer.WriteLine(" " + packet.Name + " = " + (0x10000 | packet.ID) + ",");
992 foreach (MapPacket packet in protocol.MediumMaps)
993 if (packet != null)
994 writer.WriteLine(" " + packet.Name + " = " + (0x20000 | packet.ID) + ",");
995 foreach (MapPacket packet in protocol.HighMaps)
996 if (packet != null)
997 writer.WriteLine(" " + packet.Name + " = " + (0x30000 | packet.ID) + ",");
998 writer.WriteLine(" }" + Environment.NewLine);
999  
1000 // Write the base Packet class
1001 writer.WriteLine(
1002 " public abstract partial class Packet" + Environment.NewLine + " {" + Environment.NewLine +
1003 " public const int MTU = 1200;" + Environment.NewLine +
1004 Environment.NewLine +
1005 " public Header Header;" + Environment.NewLine +
1006 " public bool HasVariableBlocks;" + Environment.NewLine +
1007 " public PacketType Type;" + Environment.NewLine +
1008 " public abstract int Length { get; }" + Environment.NewLine +
1009 " public abstract void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer);" + Environment.NewLine +
1010 " public abstract void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd);" + Environment.NewLine +
1011 " public abstract byte[] ToBytes();" + Environment.NewLine +
1012 " public abstract byte[][] ToBytesMultiple();"
1013 );
1014 writer.WriteLine();
1015  
1016 // Write the Packet.GetType() function
1017 writer.WriteLine(
1018 " public static PacketType GetType(ushort id, PacketFrequency frequency)" + Environment.NewLine +
1019 " {" + Environment.NewLine +
1020 " switch (frequency)" + Environment.NewLine +
1021 " {" + Environment.NewLine +
1022 " case PacketFrequency.Low:" + Environment.NewLine +
1023 " switch (id)" + Environment.NewLine +
1024 " {");
1025 foreach (MapPacket packet in protocol.LowMaps)
1026 if (packet != null)
1027 writer.WriteLine(" case " + packet.ID + ": return PacketType." + packet.Name + ";");
1028 writer.WriteLine(" }" + Environment.NewLine +
1029 " break;" + Environment.NewLine +
1030 " case PacketFrequency.Medium:" + Environment.NewLine +
1031 " switch (id)" + Environment.NewLine + " {");
1032 foreach (MapPacket packet in protocol.MediumMaps)
1033 if (packet != null)
1034 writer.WriteLine(" case " + packet.ID + ": return PacketType." + packet.Name + ";");
1035 writer.WriteLine(" }" + Environment.NewLine +
1036 " break;" + Environment.NewLine +
1037 " case PacketFrequency.High:" + Environment.NewLine +
1038 " switch (id)" + Environment.NewLine + " {");
1039 foreach (MapPacket packet in protocol.HighMaps)
1040 if (packet != null)
1041 writer.WriteLine(" case " + packet.ID + ": return PacketType." + packet.Name + ";");
1042 writer.WriteLine(" }" + Environment.NewLine +
1043 " break;" + Environment.NewLine + " }" + Environment.NewLine + Environment.NewLine +
1044 " return PacketType.Default;" + Environment.NewLine + " }" + Environment.NewLine);
1045  
1046 // Write the Packet.BuildPacket(PacketType) function
1047 writer.WriteLine(" public static Packet BuildPacket(PacketType type)");
1048 writer.WriteLine(" {");
1049 foreach (MapPacket packet in protocol.HighMaps)
1050 if (packet != null)
1051 writer.WriteLine(" if(type == PacketType." + packet.Name + ") return new " + packet.Name + "Packet();");
1052 foreach (MapPacket packet in protocol.MediumMaps)
1053 if (packet != null)
1054 writer.WriteLine(" if(type == PacketType." + packet.Name + ") return new " + packet.Name + "Packet();");
1055 foreach (MapPacket packet in protocol.LowMaps)
1056 if (packet != null)
1057 writer.WriteLine(" if(type == PacketType." + packet.Name + ") return new " + packet.Name + "Packet();");
1058 writer.WriteLine(" return null;" + Environment.NewLine);
1059 writer.WriteLine(" }");
1060  
1061 // Write the Packet.BuildPacket() function
1062 writer.WriteLine(@"
1063 public static Packet BuildPacket(byte[] packetBuffer, ref int packetEnd, byte[] zeroBuffer)
1064 {
1065 byte[] bytes;
1066 int i = 0;
1067 Header header = Header.BuildHeader(packetBuffer, ref i, ref packetEnd);
1068 if (header.Zerocoded)
1069 {
1070 packetEnd = Helpers.ZeroDecode(packetBuffer, packetEnd + 1, zeroBuffer) - 1;
1071 bytes = zeroBuffer;
1072 }
1073 else
1074 {
1075 bytes = packetBuffer;
1076 }
1077 Array.Clear(bytes, packetEnd + 1, bytes.Length - packetEnd - 1);
1078  
1079 switch (header.Frequency)
1080 {
1081 case PacketFrequency.Low:
1082 switch (header.ID)
1083 {");
1084 foreach (MapPacket packet in protocol.LowMaps)
1085 if (packet != null)
1086 writer.WriteLine(" case " + packet.ID + ": return new " + packet.Name + "Packet(header, bytes, ref i);");
1087 writer.WriteLine(@"
1088 }
1089 break;
1090 case PacketFrequency.Medium:
1091 switch (header.ID)
1092 {");
1093 foreach (MapPacket packet in protocol.MediumMaps)
1094 if (packet != null)
1095 writer.WriteLine(" case " + packet.ID + ": return new " + packet.Name + "Packet(header, bytes, ref i);");
1096 writer.WriteLine(@"
1097 }
1098 break;
1099 case PacketFrequency.High:
1100 switch (header.ID)
1101 {");
1102 foreach (MapPacket packet in protocol.HighMaps)
1103 if (packet != null)
1104 writer.WriteLine(" case " + packet.ID + ": return new " + packet.Name + "Packet(header, bytes, ref i);");
1105 writer.WriteLine(@"
1106 }
1107 break;
1108 }
1109  
1110 throw new MalformedDataException(""Unknown packet ID "" + header.Frequency + "" "" + header.ID);
1111 }
1112 }");
1113  
1114 // Write the packet classes
1115 foreach (MapPacket packet in protocol.LowMaps)
1116 if (packet != null) { WritePacketClass(writer, packet); }
1117 foreach (MapPacket packet in protocol.MediumMaps)
1118 if (packet != null) { WritePacketClass(writer, packet); }
1119 foreach (MapPacket packet in protocol.HighMaps)
1120 if (packet != null) { WritePacketClass(writer, packet); }
1121  
1122  
1123 // Finish up
1124 writer.WriteLine("}");
1125 writer.Close();
1126 return 0;
1127 }
1128 }
1129 }