static Path ReadPath(BinaryReader br)
        {
            Path path = new Path
            {
                Name      = br.ReadFixedLengthString(Encoding.ASCII, 128),
                Type      = br.ReadFixedLengthString(Encoding.ASCII, 128),
                Direction = (PathDirection)br.ReadInt32()
            };
            int numNodes = br.ReadInt32();

            for (int i = 0; i < numNodes; i++)
            {
                PathNode node = new PathNode
                {
                    Position = br.ReadVector3(),
                    ID       = br.ReadInt32(),
                    Name     = br.ReadFixedLengthString(Encoding.ASCII, 128)
                };

                int numProps = br.ReadInt32();
                for (int j = 0; j < numProps; j++)
                {
                    string key   = br.ReadCString();
                    string value = br.ReadCString();
                    node.Properties[key] = value;
                }
                path.Nodes.Add(node);
            }
            return(path);
        }
        static Path ReadPath(BinaryReader br)
        {
            Path path = new Path
            {
                Type      = ReadString(br),
                Name      = ReadString(br),
                Direction = (PathDirection)br.ReadInt32()
            };

            br.ReadInt32();      // flags
            br.ReadRGBAColour(); // colour

            int numNodes = br.ReadInt32();

            for (int i = 0; i < numNodes; i++)
            {
                string   name = ReadString(br);
                string   fire = ReadString(br); // fire on pass
                PathNode node = new PathNode
                {
                    Name     = name,
                    Position = br.ReadVector3()
                };

                if (!string.IsNullOrWhiteSpace(fire))
                {
                    node.Properties["message"] = fire;
                }

                Vector3 angles = br.ReadVector3();
                node.Properties["angles"] = $"{angles.X} {angles.Y} {angles.Z}";

                node.Properties["spawnflags"] = br.ReadInt32().ToString();

                br.ReadRGBAColour(); // colour

                int numProps = br.ReadInt32();
                for (int j = 0; j < numProps; j++)
                {
                    string key   = ReadString(br);
                    string value = ReadString(br);
                    if (key != null && value != null)
                    {
                        node.Properties[key] = value;
                    }
                }

                path.Nodes.Add(node);
            }
            return(path);
        }
 static void WritePath(BinaryWriter bw, Path path)
 {
     bw.WriteFixedLengthString(Encoding.ASCII, 128, path.Name);
     bw.WriteFixedLengthString(Encoding.ASCII, 128, path.Type);
     bw.Write((int)path.Direction);
     bw.Write(path.Nodes.Count);
     foreach (PathNode node in path.Nodes)
     {
         bw.WriteVector3(node.Position);
         bw.Write(node.ID);
         bw.WriteFixedLengthString(Encoding.ASCII, 128, node.Name);
         bw.Write(node.Properties.Count);
         foreach (KeyValuePair <string, string> property in node.Properties)
         {
             bw.WriteCString(property.Key, MaxVariableStringLength);
             bw.WriteCString(property.Value, MaxVariableStringLength);
         }
     }
 }