home *** CD-ROM | disk | FTP | other *** search
/ Programming a Multiplayer FPS in DirectX / Programming a Multiplayer FPS in DirectX (Companion CD).iso / Source / Chapter 8 / Engine / Scripting.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2005-03-29  |  15.7 KB  |  529 lines

  1. //-----------------------------------------------------------------------------
  2. // Scripting.h implementation.
  3. // Refer to the Scripting.h interface for more details.
  4. //
  5. // Programming a Multiplayer First Person Shooter in DirectX
  6. // Copyright (c) 2004 Vaughan Young
  7. //-----------------------------------------------------------------------------
  8. #include "Engine.h"
  9.  
  10. //-----------------------------------------------------------------------------
  11. // The variable class constructor.
  12. //-----------------------------------------------------------------------------
  13. Variable::Variable( char *name, FILE *file )
  14. {
  15.     // Store the name of the variable
  16.     m_name = new char[strlen( name ) + 1];
  17.     strcpy( m_name, name );
  18.  
  19.     // Ensure the file pointer is valid.
  20.     if( file == NULL )
  21.         return;
  22.  
  23.     // Read the variable's type.
  24.     char buffer[MAX_PATH];
  25.     fscanf( file, "%s", buffer );
  26.     if( strcmp( buffer, "bool" ) == 0 )
  27.     {
  28.         // The variable is a boolean.
  29.         m_type = VARIABLE_BOOL;
  30.  
  31.         // Read and set the bool for the variable.
  32.         bool value;
  33.         fscanf( file, "%s", buffer );
  34.         if( strcmp( buffer, "true" ) == 0 )
  35.             value = true;
  36.         else
  37.             value = false;
  38.         m_data = new bool;
  39.         memcpy( m_data, &value, sizeof( bool ) );
  40.     }
  41.     else if( strcmp( buffer, "colour" ) == 0 )
  42.     {
  43.         // The variable is a colour.
  44.         m_type = VARIABLE_COLOUR;
  45.  
  46.         // Read and set the colour for the variable.
  47.         D3DCOLORVALUE colour;
  48.         fscanf( file, "%s", buffer );
  49.         colour.r = (float)atof( buffer );
  50.         fscanf( file, "%s", buffer );
  51.         colour.g = (float)atof( buffer );
  52.         fscanf( file, "%s", buffer );
  53.         colour.b = (float)atof( buffer );
  54.         fscanf( file, "%s", buffer );
  55.         colour.a = (float)atof( buffer );
  56.         m_data = new D3DCOLORVALUE;
  57.         memcpy( m_data, &colour, sizeof( D3DCOLORVALUE ) );
  58.     }
  59.     else if( strcmp( buffer, "float" ) == 0 )
  60.     {
  61.         // The variable is a float.
  62.         m_type = VARIABLE_FLOAT;
  63.  
  64.         // Read and set the float for the variable.
  65.         float value;
  66.         fscanf( file, "%s", buffer );
  67.         value = (float)atof( buffer );
  68.         m_data = new float;
  69.         memcpy( m_data, &value, sizeof( float ) );
  70.     }
  71.     else if( strcmp( buffer, "number" ) == 0 )
  72.     {
  73.         // The variable is a number.
  74.         m_type = VARIABLE_NUMBER;
  75.  
  76.         // Read and set the number for the variable.
  77.         long value;
  78.         fscanf( file, "%s", buffer );
  79.         value = atol( buffer );
  80.         m_data = new long;
  81.         memcpy( m_data, &value, sizeof( long ) );
  82.     }
  83.     else if( strcmp( buffer, "string" ) == 0 )
  84.     {
  85.         // The variable is a string.
  86.         m_type = VARIABLE_STRING;
  87.  
  88.         // Find the opening inverted commas.
  89.         bool commasFound = false;
  90.         ZeroMemory( buffer, MAX_PATH * sizeof( char ) );
  91.         fscanf( file, "%c", buffer );
  92.         while( true )
  93.         {
  94.             if( strcmp( buffer, "\"" ) == 0 )
  95.             {
  96.                 commasFound = true;
  97.                 break;
  98.             }
  99.  
  100.             if( strcmp( buffer, " " ) != 0 )
  101.             {
  102.                 fpos_t pos;
  103.                 fgetpos( file, &pos );
  104.                 fsetpos( file, &--pos );
  105.                 break;
  106.             }
  107.  
  108.             fscanf( file, "%c", buffer );
  109.         }
  110.  
  111.         // Read and set the string for the variable.
  112.         char completeString[MAX_PATH];
  113.         ZeroMemory( completeString, MAX_PATH * sizeof( char ) );
  114.         bool addSpacing = false;
  115.         do
  116.         {
  117.             fscanf( file, "%s", buffer );
  118.             if( strcmp( &buffer[strlen( buffer ) - 1], "\"" ) == 0 )
  119.             {
  120.                 buffer[strlen( buffer ) - 1] = 0;
  121.                 commasFound = false;
  122.             }
  123.  
  124.             if( addSpacing == false )
  125.                 addSpacing = true;
  126.             else
  127.                 strcat( completeString, " " );
  128.  
  129.             strcat( completeString, buffer );
  130.         } while( commasFound == true );
  131.  
  132.         m_data = new char[strlen( completeString ) + 1];
  133.         strcpy( (char*)m_data, completeString );
  134.     }
  135.     else if( strcmp( buffer, "vector" ) == 0 )
  136.     {
  137.         // The variable is a vector.
  138.         m_type = VARIABLE_VECTOR;
  139.  
  140.         // Read and set the vector for the variable.
  141.         D3DXVECTOR3 vector;
  142.         fscanf( file, "%s", buffer );
  143.         vector.x = (float)atof( buffer );
  144.         fscanf( file, "%s", buffer );
  145.         vector.y = (float)atof( buffer );
  146.         fscanf( file, "%s", buffer );
  147.         vector.z = (float)atof( buffer );
  148.         m_data = new D3DXVECTOR3;
  149.         memcpy( m_data, &vector, sizeof( D3DXVECTOR3 ) );
  150.     }
  151.     else
  152.     {
  153.         // The variable has an unknown type.
  154.         m_type = VARIABLE_UNKNOWN;
  155.  
  156.         // Read and set the data (same as a string) for the variable.
  157.         fscanf( file, "%s", buffer );
  158.         m_data = new char[strlen( buffer ) + 1];
  159.         strcpy( (char*)m_data, buffer );
  160.     }
  161. }
  162.  
  163. //-----------------------------------------------------------------------------
  164. // The variable class constructor.
  165. //-----------------------------------------------------------------------------
  166. Variable::Variable( char *name, char type, void *value )
  167. {
  168.     // Store the name of the variable.
  169.     m_name = new char[strlen( name ) + 1];
  170.     strcpy( m_name, name );
  171.  
  172.     // Store the type of the variable.
  173.     m_type = type;
  174.  
  175.     // Set the variable's data based on its type.
  176.     switch( m_type )
  177.     {
  178.         case VARIABLE_BOOL:
  179.             m_data = new bool;
  180.             memcpy( m_data, (bool*)value, sizeof( bool ) );
  181.             return;
  182.  
  183.         case VARIABLE_COLOUR:
  184.             m_data = new D3DCOLORVALUE;
  185.             memcpy( m_data, (D3DCOLORVALUE*)value, sizeof( D3DCOLORVALUE ) );
  186.             return;
  187.  
  188.         case VARIABLE_FLOAT:
  189.             m_data = new float;
  190.             memcpy( m_data, (float*)value, sizeof( float ) );
  191.             return;
  192.  
  193.         case VARIABLE_NUMBER:
  194.             m_data = new long;
  195.             memcpy( m_data, (long*)value, sizeof( long ) );
  196.             return;
  197.  
  198.         case VARIABLE_STRING:
  199.             m_data = new char[strlen( (char*)value ) + 1];
  200.             strcpy( (char*)m_data, (char*)value );
  201.             return;
  202.  
  203.         case VARIABLE_VECTOR:
  204.             m_data = new D3DXVECTOR3;
  205.             memcpy( m_data, (D3DXVECTOR3*)value, sizeof( D3DXVECTOR3 ) );
  206.             return;
  207.  
  208.         default:
  209.             m_data = new char[strlen( (char*)value ) + 1];
  210.             strcpy( (char*)m_data, (char*)value );
  211.             return;
  212.     }
  213. }
  214.  
  215. //-----------------------------------------------------------------------------
  216. // The variable class destructor.
  217. //-----------------------------------------------------------------------------
  218. Variable::~Variable()
  219. {
  220.     SAFE_DELETE_ARRAY( m_name );
  221.     SAFE_DELETE( m_data );
  222. }
  223.  
  224. //-----------------------------------------------------------------------------
  225. // Returns the type of the variable.
  226. //-----------------------------------------------------------------------------
  227. char Variable::GetType()
  228. {
  229.     return m_type;
  230. }
  231.  
  232. //-----------------------------------------------------------------------------
  233. // Returns the name of the variable.
  234. //-----------------------------------------------------------------------------
  235. char *Variable::GetName()
  236. {
  237.     return m_name;
  238. }
  239.  
  240. //-----------------------------------------------------------------------------
  241. // Returns the data in the variable.
  242. //-----------------------------------------------------------------------------
  243. void *Variable::GetData()
  244. {
  245.     switch( m_type )
  246.     {
  247.         case VARIABLE_BOOL:
  248.             return (bool*)m_data;
  249.  
  250.         case VARIABLE_COLOUR:
  251.             return (D3DCOLORVALUE*)m_data;
  252.  
  253.         case VARIABLE_FLOAT:
  254.             return (float*)m_data;
  255.  
  256.         case VARIABLE_NUMBER:
  257.             return (long*)m_data;
  258.  
  259.         case VARIABLE_STRING:
  260.             return (char*)m_data;
  261.  
  262.         case VARIABLE_VECTOR:
  263.             return (D3DXVECTOR3*)m_data;
  264.  
  265.         default:
  266.             return m_data;
  267.     }
  268. }
  269.  
  270. //-----------------------------------------------------------------------------
  271. // The script class constructor.
  272. //-----------------------------------------------------------------------------
  273. Script::Script( char *name, char *path ) : Resource< Script >( name, path )
  274. {
  275.     // Create the linked list that will store all of the script's variables.
  276.     m_variables = new LinkedList< Variable >;
  277.  
  278.     // Open the script file using the filename.
  279.     FILE *file = NULL;
  280.     if( ( file = fopen( GetFilename(), "r" ) ) == NULL )
  281.         return;
  282.  
  283.     // Continue reading from the file until the eof is reached.
  284.     bool read = false;
  285.     char buffer[MAX_PATH];
  286.     fscanf( file, "%s", buffer );
  287.     while( feof( file ) == 0 )
  288.     {
  289.         // Check if the file position indicator is between a #begin and #end
  290.         // statement. If so then read the data into the variable linked list.
  291.         if( read == true )
  292.         {
  293.             // Stop reading data if an #end statement has been reached.
  294.             if( strcmp( buffer, "#end" ) == 0 )
  295.                 read = false;
  296.             else
  297.                 m_variables->Add( new Variable( buffer, file ) );
  298.         }
  299.         else if( strcmp( buffer, "#begin" ) == 0 )
  300.             read = true;
  301.  
  302.         // Read the next string.
  303.         fscanf( file, "%s", buffer );
  304.     }
  305.  
  306.     // Close the script file.
  307.     fclose( file );
  308. }
  309.  
  310. //-----------------------------------------------------------------------------
  311. // The script class destructor.
  312. //-----------------------------------------------------------------------------
  313. Script::~Script()
  314. {
  315.     SAFE_DELETE( m_variables );
  316. }
  317.  
  318. //-----------------------------------------------------------------------------
  319. // Adds a new variable to the script.
  320. //-----------------------------------------------------------------------------
  321. void Script::AddVariable( char *name, char type, void *value )
  322. {
  323.     m_variables->Add( new Variable( name, type, value ) );
  324. }
  325.  
  326. //-----------------------------------------------------------------------------
  327. // Sets the value of an existing variable in the script.
  328. //-----------------------------------------------------------------------------
  329. void Script::SetVariable( char *name, void *value )
  330. {
  331.     // Find the variable.
  332.     Variable *variable = NULL;
  333.     m_variables->Iterate( true );
  334.     while( m_variables->Iterate() != NULL )
  335.     {
  336.         if( strcmp( m_variables->GetCurrent()->GetName(), name ) == 0 )
  337.         {
  338.             variable = m_variables->GetCurrent();
  339.             break;
  340.         }
  341.     }
  342.  
  343.     // Ensure the variable was found.
  344.     if( variable == NULL )
  345.         return;
  346.  
  347.     // Get the variable's type.
  348.     char type = variable->GetType();
  349.  
  350.     // Destroy the variable.
  351.     m_variables->Remove( &variable );
  352.  
  353.     // Add the variable back in with the new value.
  354.     AddVariable( name, type, value );
  355. }
  356.  
  357. //-----------------------------------------------------------------------------
  358. // Saves the script to file.
  359. //-----------------------------------------------------------------------------
  360. void Script::SaveScript( char *filename )
  361. {
  362.     FILE *file = NULL;
  363.     char output[MAX_PATH];
  364.  
  365.     // Open the given filename if available, otherwise the internal filename.
  366.     if( filename != NULL )
  367.     {
  368.         if( ( file = fopen( filename, "w" ) ) == NULL )
  369.             return;
  370.     }
  371.     else
  372.     {
  373.         if( ( file = fopen( GetFilename(), "w" ) ) == NULL )
  374.             return;
  375.     }
  376.  
  377.     // Write the #begin statement to the file.
  378.     fputs( "#begin\n", file );
  379.  
  380.     // Write each variable to the file.
  381.     m_variables->Iterate( true );
  382.     while( m_variables->Iterate() != NULL )
  383.     {
  384.         switch( m_variables->GetCurrent()->GetType() )
  385.         {
  386.             case VARIABLE_BOOL:
  387.                 if( *((bool*)m_variables->GetCurrent()->GetData()) == true )
  388.                     sprintf( output, "%s bool true", m_variables->GetCurrent()->GetName() );
  389.                 else
  390.                     sprintf( output, "%s bool false", m_variables->GetCurrent()->GetName() );
  391.                 fputs( output, file );
  392.                 fputs( "\n", file );
  393.                 continue;
  394.  
  395.             case VARIABLE_COLOUR:
  396.                 sprintf( output, "%s colour %f %f %f %f", m_variables->GetCurrent()->GetName(), ( (D3DCOLORVALUE*)m_variables->GetCurrent()->GetData() )->r, ( (D3DCOLORVALUE*)m_variables->GetCurrent()->GetData() )->g, ( (D3DCOLORVALUE*)m_variables->GetCurrent()->GetData() )->b, ( (D3DCOLORVALUE*)m_variables->GetCurrent()->GetData() )->a );
  397.                 fputs( output, file );
  398.                 fputs( "\n", file );
  399.                 continue;
  400.  
  401.             case VARIABLE_FLOAT:
  402.                 sprintf( output, "%s float %f", m_variables->GetCurrent()->GetName(), *(float*)m_variables->GetCurrent()->GetData() );
  403.                 fputs( output, file );
  404.                 fputs( "\n", file );
  405.                 continue;
  406.  
  407.             case VARIABLE_NUMBER:
  408.                 sprintf( output, "%s number %d", m_variables->GetCurrent()->GetName(), *(long*)m_variables->GetCurrent()->GetData() );
  409.                 fputs( output, file );
  410.                 fputs( "\n", file );
  411.                 continue;
  412.  
  413.             case VARIABLE_STRING:
  414.                 sprintf( output, "%s string \"%s\"", m_variables->GetCurrent()->GetName(), (char*)m_variables->GetCurrent()->GetData() );
  415.                 fputs( output, file );
  416.                 fputs( "\n", file );
  417.                 continue;
  418.  
  419.             case VARIABLE_VECTOR:
  420.                 sprintf( output, "%s vector %f %f %f", m_variables->GetCurrent()->GetName(), ( (D3DXVECTOR3*)m_variables->GetCurrent()->GetData() )->x, ( (D3DXVECTOR3*)m_variables->GetCurrent()->GetData() )->y, ( (D3DXVECTOR3*)m_variables->GetCurrent()->GetData() )->z );
  421.                 fputs( output, file );
  422.                 fputs( "\n", file );
  423.                 continue;
  424.  
  425.             default:
  426.                 sprintf( output, "%s unknown %s", m_variables->GetCurrent()->GetName(), (char*)m_variables->GetCurrent()->GetData() );
  427.                 fputs( output, file );
  428.                 fputs( "\n", file );
  429.                 continue;
  430.         }
  431.     }
  432.  
  433.     // Write the #end statement to the file.
  434.     fputs( "#end", file );
  435.  
  436.     // Close the script file.
  437.     fclose( file );
  438. }
  439.  
  440. //-----------------------------------------------------------------------------
  441. // Returns boolean data from the named variable.
  442. //-----------------------------------------------------------------------------
  443. bool *Script::GetBoolData( char *variable )
  444. {
  445.     m_variables->Iterate( true );
  446.     while( m_variables->Iterate() != NULL )
  447.         if( strcmp( m_variables->GetCurrent()->GetName(), variable ) == 0 )
  448.             return (bool*)m_variables->GetCurrent()->GetData();
  449.  
  450.     return NULL;
  451. }
  452.  
  453. //-----------------------------------------------------------------------------
  454. // Returns colour data from the named variable.
  455. //-----------------------------------------------------------------------------
  456. D3DCOLORVALUE *Script::GetColourData( char *variable )
  457. {
  458.     m_variables->Iterate( true );
  459.     while( m_variables->Iterate() != NULL )
  460.         if( strcmp( m_variables->GetCurrent()->GetName(), variable ) == 0 )
  461.             return (D3DCOLORVALUE*)m_variables->GetCurrent()->GetData();
  462.  
  463.     return NULL;
  464. }
  465.  
  466. //-----------------------------------------------------------------------------
  467. // Returns float data from the named variable.
  468. //-----------------------------------------------------------------------------
  469. float *Script::GetFloatData( char *variable )
  470. {
  471.     m_variables->Iterate( true );
  472.     while( m_variables->Iterate() != NULL )
  473.         if( strcmp( m_variables->GetCurrent()->GetName(), variable ) == 0 )
  474.             return (float*)m_variables->GetCurrent()->GetData();
  475.  
  476.     return NULL;
  477. }
  478.  
  479. //-----------------------------------------------------------------------------
  480. // Returns number data from the named variable.
  481. //-----------------------------------------------------------------------------
  482. long *Script::GetNumberData( char *variable )
  483. {
  484.     m_variables->Iterate( true );
  485.     while( m_variables->Iterate() != NULL )
  486.         if( strcmp( m_variables->GetCurrent()->GetName(), variable ) == 0 )
  487.             return (long*)m_variables->GetCurrent()->GetData();
  488.  
  489.     return NULL;
  490. }
  491.  
  492. //-----------------------------------------------------------------------------
  493. // Returns string data from the named variable.
  494. //-----------------------------------------------------------------------------
  495. char *Script::GetStringData( char *variable )
  496. {
  497.     m_variables->Iterate( true );
  498.     while( m_variables->Iterate() != NULL )
  499.         if( strcmp( m_variables->GetCurrent()->GetName(), variable ) == 0 )
  500.             return (char*)m_variables->GetCurrent()->GetData();
  501.  
  502.     return NULL;
  503. }
  504.  
  505. //-----------------------------------------------------------------------------
  506. // Returns colour data from the named variable.
  507. //-----------------------------------------------------------------------------
  508. D3DXVECTOR3 *Script::GetVectorData( char *variable )
  509. {
  510.     m_variables->Iterate( true );
  511.     while( m_variables->Iterate() != NULL )
  512.         if( strcmp( m_variables->GetCurrent()->GetName(), variable ) == 0 )
  513.             return (D3DXVECTOR3*)m_variables->GetCurrent()->GetData();
  514.  
  515.     return NULL;
  516. }
  517.  
  518. //-----------------------------------------------------------------------------
  519. // Returns unknown data from the named variable.
  520. //-----------------------------------------------------------------------------
  521. void *Script::GetUnknownData( char *variable )
  522. {
  523.     m_variables->Iterate( true );
  524.     while( m_variables->Iterate() != NULL )
  525.         if( strcmp( m_variables->GetCurrent()->GetName(), variable ) == 0 )
  526.             return m_variables->GetCurrent()->GetData();
  527.  
  528.     return NULL;
  529. }