Creating a Command with Sub-Commands

So how do you create a new command? Creating a new command is as simple as creating a new class that inherits from the CCommand() class and executing the logic of the Execute() and OnRollBack() member functions. Some commands, such as the create login command, will not implement the OnRollBack() function because it uses sub-commands. This means that the CCommand() class will handle rolling back all of the sub-commands. Take a look at the CCreateAccountCmd() class.

<?
require_once( “CCommand.php” );
require_once( “CRenderCmd.php” );
require_once( “CLockTableCmd.php” );
require_once( “CUnlockTableCmd.php” );
require_once( “CVerifyAccountInfoCmd.php” );
require_once( “CCreateNeighborhoodCmd.php” );

class CCreateAccountCmd extends CCommand
{
    function CCreateAccountCmd( &$pParent )
    {
        parent::CCommand( $pParent );

        $this->m_arraySubCommands[0] = new CRenderCmd($this);
        $this->m_arraySubCommands[1] = new CLockTableCmd($this);
        $this->m_arraySubCommands[2] = new CVerifyAccountInfoCmd($this);
        $this->m_arraySubCommands[3] = new CCreateNeighborhoodCmd($this);
        $this->m_arraySubCommands[4] = new CUnlockTableCmd($this);
        $this->m_arraySubCommands[5] = new CRenderCmd($this);

    }
    function Execute( $args )
    {
        $result = null;

        // is it ok for us to continue on to actually creating the account?
        if ($this->m_nCurrentCommand == 0 && isset($args[‘proceed’]))
        {
            // we got our input, so let’s move to the next command
            $this->m_nCurrentCommand++;

            // we want the next “proceed” we see to be a new one.
            // so get rid of the one we have now
            unset( $args[‘proceed’] );
        }

        do
        {
            // jump to the current command and execute it
            switch ($this->m_nCurrentCommand)
            {
                case 0:
                    // render the account creation page
                    $result = $this->m_arraySubCommands[0]
                        ->Execute( “CreateAccount.html”, $args );
                    // if it was successful, then we know
                        // that we need to wait for input
                    if ($result == CMD_FINISHED)
                    {
                        $result = CMD_NEEDS_INPUT;
                    }
                    break;
                case 1:
                    // lock the database table
                    $result = $this->m_arraySubCommands[1]
                        ->Execute( $GLOBALS[‘g_DBTable’] );
                    break;
                case 2:
                    // verify the account information
                    $result = $this->m_arraySubCommands[2]
                        ->Execute($args[‘sPlayerName’],
                            $args[‘sPassword’],
                            $args[‘sPasswordRetype’],
                            $args[‘sNeighborhoodName’] );
                    // was there an error?
                    if ($result == CMD_ERROR)
                    {
                        // let the regular error
                        //handler deal with these errors
                        break;
                    }
                    // any other error?
                    else if ($result != CMD_FINISHED)
                    {
                    // undo whatever we’ve done so far
                    $this->OnRollBack();

                    // make a note of the error,
                        // so the create
                    // account page can render
                        // it to the user
                    $args[‘sError’] = $result;

                    // restart this command’s execution
                    $this->m_nCurrentCommand = 0;
                    return $this->Execute( $args );
                }

                break;
            case 3:
                // create the neighborhood
                $result = $this->m_arraySubCommands[3]
                    ->Execute($args[‘sPlayerName’],
                        $args[‘sPassword’],
                        $args[‘sNeighborhoodName’] );
                break;
            case 4:
                // unlock all locked database tables
                $result = $this->m_arraySubCommands[4]
                    ->Execute( );
                break;
            case 5:
                // render a “successful creation” page
                $result = $this->m_arraySubCommands[5]
                    ->Execute( “AccountCreationSuccess.html”, $args );
                break;
        }

        // handle the result from our sub-command
        $result = $this->HandleSubCommand($result);

    // while there are still commands to be
    // executed that don’t need human input
    } while( $result == CMD_CONTINUED )    ;
        return $result;
    }
}

?>

You’ll notice that the first six lines of the code all require other files. These other files are simply other classes that the game uses. Since this is a command, you need to require the CCommand.php file so you can inherit from it. The CRenderCmd() allows you to pass the execute function an html file to render to the browser. This command handles everything that the user sees. The CLockTableCmd() and the CUnlockTableCmd() locks and unlocks a specified table in the Kiddy Cartel database. Without these two classes there would be a chance that a user could be updating the database at the same time that another user is updating the database, and that is not good. The CVerifyAccountInfoCmd() looks in the database to make sure that the user isn’t trying to create a duplicate account. If they are, then execu-tion needs to stop and the user needs to know that the account already exists. The last required file is the file that actually creates the default neighborhood for the user.

I am not going to explain each one of these classes. There are just too many classes in this game to explain each in great detail. Please look at the CD and take a look at each class. You’ll notice that each command is structured very similarly. I will explain the CCreateAccountCmd() class and another class that doesn’t have sub-commands to execute so you can see the difference in how to code them.

All the CCreateAccountCmd() class implements is a constructor and the Execute() function. The constructor tells the CCommand() class that the CCreateAccountCmd() is the parent class. Then the class proceeds to set up an array of sub-commands. Each of these sub-com-mands will have its own logic in the Execute() function.

The Execute() function uses a do…while loop and a switch statement to determine which command it should execute. Each case in the switch statement corresponds to a sub-com-mand. The sub-command looks like this:

    $this->m_arraySubCommands[0] = new CRenderCmd($this);
    $this->m_arraySubCommands[1] = new CLockTableCmd($this);
    $this->m_arraySubCommands[2] = new CVerifyAccountInfoCmd($this);
    $this->m_arraySubCommands[3] = new CCreateNeighborhoodCmd($this);
    $this->m_arraySubCommands[4] = new CUnlockTableCmd($this);
    $this->m_arraySubCommands[5] = new CRenderCmd($this);

So that means the first case statement will contain the logic for the CRenderCmd(). The second case statement will contain the logic for the CLockTableCmd(), and so on. Once one command has finished executing, the loop starts over and moves on to the next command by incrementing the $m_nCurrentCommand variable.

The first case statement uses the CRenderCmd() class. The Execute() function of the CRenderCmd() class takes an HTML page for an argument. This will render the HTML page to the browser. Once the page is rendered to the browser, the game state switches to waiting for input. Once the user fills out the form on the CreateAccount.html page and then clicks Submit, the command executes and locks the table. After the table is locked the loop executes again, but this time it falls to the third case. This is where you verify that this user doesn’t exist. If the user does exist, then the class needs to roll back whatever you have done up to this point.

Once you have verified that the account does not exist in the database you create the neighborhood and unlock the table. Once the table is unlocked you render a message to the browser telling the user that the account has been created successfully and that they can log in and start playing, Take a look at Figures 11.2 and 11.3 to see the Create Account page and the Success page.

Figure 11.2. The Create Account page.


Figure 11.3. Successful account creation.


It’s that easy to create a command with sub-commands. Don’t worry about how you integrate the command into the game just yet. That will be covered later in this chapter. For now, take a look at how to create a command with no sub-commands.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset