Game Development Community

dev|Pro Game Development Curriculum

TGE Simplification - Part 3: Removing Module, Package, and Command-line Functionality

by Darrel Cusey · 04/11/2006 (2:02 pm) · 6 comments

I see a lot of people asking how to streamline and simplify the TGE script codebase. This third tutorial in the series shows you how to remove module, package, and command-line functionality from the script codebase. The ultimate goal of these tutorials is to get us closer and closer to having a foundation of code that can be used to build an MMO. Module functionality is being removed because you don't want clients running arbitrary code in an MMO environment. Package functionality is being removed to reduce script complexity. And finally, command-line functionality is being removed to greatly reduce the ability of clients to "tinker" with the program execution environment.


Starting Point:
---------------
This tutorial builds on the previous two tutorials in this series. You must have successfully completed both of the previous two tutorials in this series in order to start this one. Currently, I have the folder c:/mygame, and inside I have these folders and files:

/client
/creator
/server
DeleteDSOs.bat
DeletePrefs.bat
glu2d3d.dll
main.cs
MyGame.exe (This is my renamed Torque Demo App)
OpenAL32.dll
opengl2d3d.dll
wrap_oal.dll

The /client, /creator and /server folders and the mygame.exe are modified versions of the 1.4 HEAD, with all modifications completed as described in the first tutorial in this series and the second tutorial in this series.

The files opengl2d3d.dll and glu2d3d.dll are all fresh builds from the HEAD. If you are unsure how to create a new Visual C++ Project from the Torque SDK, please see this tutorial.

All other files in the project root are just copied over from the "example" folder.

If you haven't done so already, complete all the steps in the first tutorial in this series and the second tutorial in this series first before starting this one, as each tutorial builds on the previous one. Run the DeleteDSOs.bat and DeletePrefs.bat once each and you should be ready.


Third Goal:
-----------
Our next objective will be to remove module, package, and command-line functionality from the script codebase. You should be able to go through these tutorials with any of the "mods" (like starter.racing, tutorial.base or demo), but I haven't tried any of these yet -- so, you'll probably have to make in-flight adjustments if you try anything other than starter.fps.


Conventions:
------------

Throughout this tutorial, I'll be asking you to test your "Torque Demo" application (I use the name "mygame.exe" in the text below). It is important that you really do test your demo app at each of these points -- we'll be making a lot of changes and trying to make them all at once without testing at each CHECKPOINT would be a debugging nightmare.

I will use backslashes to show the path, from project root, to a C++ source code file. I'm showing the full path so that you can be absolutely sure that you are editing the correct file.

I will use forward slashes to show the path, from your game folder root (c:/mygame in my case), to a Torque Script file.



Phase 1: Removing Command-Line
------------------------------

1. Add the following line to the top of your root /main.cs:

$missionArg="client/data/missions/stronghold.mis";



2. In your root /main.cs, remove these lines of code:

//------------------------------------------------------------------------------
// Process command line arguments

for ($i = 1; $i < $Game::argc ; $i++)
{
.
.
.
not all code shown for brevity
.
.
.
      //-------------------
      default:
        $argUsed[$i]++;
        //We've removed the ability for client to run arbitrary modules
   }
}


and this...

function parseArgs()
{  
}

and this...

// Parse the command line arguments
echo("--------- Parsing Arguments ---------");
parseArgs();

and this...

// Display an error message for unused arguments
for ($i = 1; $i < $Game::argc; $i++)  {
   if (!$argUsed[$i])
      error("Error: Unknown command line argument: " @ $Game::argv[$i]);
}


CHECKPOINT --> Run DeleteDSOs.bat and DeletePrefs.bat at your game folder root, then run your Torque Demo App (c:/mygame/mygame.exe in my case) to make sure everything worked.


Phase 2: Removing Command-Line Help
-----------------------------------

1. In your root /main.cs, remove all this code:

package Help {
   function onExit() {
      // Override onExit when displaying help
   }
};

function displayHelp() {
   activatePackage(Help);

   error(
      "MyGame command line options:\n"@
      "  -log <logmode>         Logging behavior; see main.cs comments for details\n"@
      "  -console               Open a separate console\n"@
      "  -jSave  <file_name>    Record a journal\n"@
      "  -jPlay  <file_name>    Play back a journal\n"@
      "  -jDebug <file_name>    Play back a journal and issue an int3 at the end\n"@
      "  -help                  Display this help message\n"
   );
}

2. In your root /main.cs, remove this line of code:

$displayHelp = false;

3. In your root /main.cs, change this:

if (!$logModeSpecified) {
   setLogMode(6);
}


to this:


setLogMode(6);


4. In your root /main.cs, change this:

// Either display the help message or startup the app.
if ($displayHelp) {
   enableWinConsole(true);
   displayHelp();
   quit();
}
else {
  
  onStart();

}


to this:


//Start the simulation
onStart();


5. Your root /main.cs should now look something like this:

$isClient = false;
$isServer = false;
$isCreator = false;
$userMods = "client";
$modcount = 1;
$missionArg="client/data/missions/stronghold.mis";
setLogMode(6);
setModPaths($userMods);
NextToken($userMods, currentMod, ";");

//Change the next line to true if you want the server to run in dedicated mode
$isDedicated = false;

//-----------------------------------------------------------------------------
function onStart()
{     
   setRandomSeed();

   echo("\n\n--------- Game Initialization ---------\n\n");
   
      if (isFile("client/init.cs")){
        // Client Startup
        exec("client/canvas.cs");
        exec("client/audio.cs");
        exec("client/defaults.cs");
        exec("client/prefs.cs");
        exec("client/init.cs");
        exec("client/data/init.cs");
        $isClient = true;
      } 
      else {
        error("\n\n ERROR: /client/init.cs not found.  The client directory is required for all distributions.");
        quit();
      }
      
      if (isFile("server/init.cs")) {
        //Server Startup
        exec("server/defaults.cs");
        exec("server/prefs.cs");
        exec("server/init.cs");
        $isServer = true;
      }
      
      if (isFile("creator/init.cs")){
        exec("creator/init.cs");
        $isCreator = true;
      }
      
      if ($isServer) {
        initServer();
        if ($isDedicated){
         initDedicated();
        }
      }
      
      if (!$isDedicated && $isClient) {
        initClient();
        if ($isCreator){
          initCreator();
        }
      }
      
   echo("\n\n--------- Engine Initialization Complete ---------\n\n");
}
//-----------------------------------------------------------------------------
function onExit()
{  
   if ($isServer){
      echo("Exporting server prefs");
      export("$Pref::Server::*", "server/prefs.cs", false);
      
      echo("Exporting server banlist");
      BanList::Export("server/banlist.cs");
   }
   
   if ($isClient) {
      echo("Exporting client prefs");
      export("$Pref::*", "client/prefs.cs", false);

      echo("Exporting client config");
      if (isObject(moveMap))
         moveMap.save("client/config.cs", false); 
    
   }  
}

//-----------------------------------------------------------------------------
// MAIN

onStart();


CHECKPOINT --> Run DeleteDSOs.bat and DeletePrefs.bat at your game folder root, then run your Torque Demo App (c:/mygame/mygame.exe in my case) to make sure everything worked.


Phase 3: Removing the Last Remnants of Module Functionality
-----------------------------------------------------------

As you can see from the main.cs, the script code still needs a few module-related variables: $userMods, and $modcount. There are also the two functions setModPaths() and NextToken(). None of these variables or functions are used anywhere else in the script codebase. The setModPaths() is a console function that takes the semi-colon delimnited list, and executes this C++ code for each token after doing some validation:

// Copy this path to the validPaths list
      validPaths.push_back(paths[i]);

The validPaths list is used by, well... the whole engine more or less. A more appropriate title for this function might be "setValidPath()". If you wanted to, you could go into the source code, and change the function "setModPath" to "setValidPath" and then change all calls to that function as well (and the header file) - but, for now, we'll just leave well-enough alone. However, we can still get rid of the rest -- since none of it is used anymore except "setModPaths()"

1. In your root /main.cs, change this:


$userMods = "client";
   $modcount = 1;
   $missionArg="client/data/missions/stronghold.mis";
   setLogMode(6);
   setModPaths("client");
   NextToken($userMods, currentMod, ";");


to this:


$missionArg="client/data/missions/stronghold.mis";
   setLogMode(6);
   setModPaths("client");


CHECKPOINT --> Run DeleteDSOs.bat and DeletePrefs.bat at your game folder root, then run your Torque Demo App (c:/mygame/mygame.exe in my case) to make sure everything worked.


Congratulations!!! You have successfully streamlined and simplified the TGE 1.4 codebase! You now have a clear path to all your scripts from your root /main.cs, and following the path of execution is now incredibly simple. I hope you have enjoyed this series of tutorials as much as I enjoyed writing them.

Edit: Updated Paths to the first 2 tutorials

#1
04/12/2006 (8:36 am)
I've actually been looking to do these steps for a while now. Thanks for laying it all out.
#2
06/26/2006 (11:50 pm)
while i was coding, i always redefined functions which already were defined in common mod.
or i had to change the codes in common mod, then common mod is not common anymore.
when i'm debugging, i always confused that i redefined or not.

i tried this resource and it works better this way for my project. and it's much simple.

while i'm doing this, i found that you can pass first command line arg as root main script.
so i decide to use two root script, main.cs for game, dedicated.cs only for dedicated server.
and then run dedicated server like "mygame.exe dedicated.cs"

this way, you can run dedicated server and client at the same time more easier for testing,
without modifying $isDedicated.

in dedicated.cs, onStart() would be something like this.

function onStart()
{
//Server Startup
exec("server/defaults.cs");
exec("server/prefs.cs");
exec("server/init.cs");

initServer();
initDedicated();
echo("\n\n--------- Engine Initialization Complete ---------\n\n");
}


thanks Darrel for your great resource!
#3
01/26/2007 (11:42 am)
I just got this working in TGEA. Took some editing, but it works now. Wonderful resource.
#4
02/11/2007 (8:45 am)
@Aaryna: That's great news - I'm glad it's working well for you :)
#5
01/18/2008 (11:03 am)
I've just applied your tutorial series to TGE 1.5 and it seems to work without problems.

Thanks for this great ressource!
#6
03/20/2008 (6:54 pm)
Would be great to see one of these for the new TGEA 1.7.