Dev/script

From CubeiaWiki

Jump to: navigation, search

Contents

Firebase Script Support

It is possible to write games in Firebase using script languages instead of Java on the server. This page outlines how the script support for Firebase games works.

 NB:  The script support is currently a Release Candidate and not in a Final Release state.

Requirements

A basic understanding of Cubeia Firebase is needed to understand this page. To run scripts an installed Firebase server is also needed.

Installation

You will need to download a script UAR and deploy into a Firebase server. The script UAR consists of a script game and a supporting service, both wich are mandatory. You can download the latest script support artefacts here:

Configuration

For the moment, the only way to configure the script is do drop a "script.properties" in $FIRBASE_HOME/conf. The following properties are available, shown with defaults:

# the name of the script for the game activator
game-activator-script=script-game-activator 

# the interval in seconds the activator script
# schould be called
game-activator-script-interval=60

# the name of the script for the game
game-script=script-game

Currently the suport only covers a single script file for a game.

Script Game

This section discusses the script for the game itself.

Bound Variables

The following variables are bound before execution:

_method // corresponds to a script game interface method name, see below
_args // object array of arguments to the method above, see below
_support // a com.cubeia.firebase.script.api.ScriptSupport object (see below)
_log // a log4j logger 

The "_method" and "_args" are used only if the script is not invocable, in which case they can be used to determine the action for the script. More of which below.

ScriptSupport

There's a helper object bound for all game evaluations. This can be used to convert binary data to strings, create Java objects and even to extend the evaluation context with another file. It correponds to the following Java interface:

/**
 * This is a Java representation of a helper object bound as a
 * global variable for the script execution as "_support". It contains
 * helpful methods for creating Java objects needed in the interfaces
 * and to perform string/byte conversions.
 * 
 * @author larsan
 */
public interface ScriptSupport {
	
    /**
     * This method imports another script file into the 
     * current evaluation context. Primarily meant for JavaScript
     * and other languages without explicit file import 
     * functionality.
     * 
     * @param file File to import, path from server root
     */
    public void importScript(String file);
	
    /**
     * @return The current game context, never null
     */
    public GameContext getGameContext();

    /**
     * Given an action, return the action data as a string
     * interpreted in UTF-8.
     * 
     * @param action The current action, should not be null
     * @return The data as a UTF-8 string, never null
     */
    public String getActionDataAsUTF8(GameDataAction action);
	
    /**
     * Given an action, return the action data as a string
     * interpreted in "encoding".
     * 
     * @param action The current action, should not be null
     * @param encoding The encoding to use for the string, should not be null
     * @return The data as an "encoding" string, never null
     */
    public String getActionDataAsString(GameDataAction action, String encoding);

    /**
     * Given an action, set the action data as a string
     * interpreted in "encoding".
     * 
     * @param action The current action, should not be null
     * @param value String value to set, should not be null
     * @param encoding The encoding to use for the string, should not be null
     */
    public void setActionDataAsString(GameDataAction action, String value, String encoding);
	
    /**
     * Given an action, set the action data as a string
     * interpreted in UTF-8.
     * 
     * @param action The current action, should not be null
     * @param value String value to set, should not be null
     */
	public void setActionDataAsUTF8(GameDataAction action, String value);
	
    /**
     * Create a new game data action. 
     * 
     * @param playerId Player the action should have
     * @param table Table the action is sent from , should not be null
     * @return A new game data action with table and player ID set, never null
     */
    public GameDataAction newGameDataAction(int playerId, Table table);
	
    /**
     * Create a new game object action. 
     * 
     * @param table Table the action is sent from , should not be null
     * @return A new game object action with table ID set, never null
     */
    public GameObjectAction newGameObjectAction(Table table);
		
    /**
     * Create new interception response.
     * 
     * @param allow True for allowing the action, false otherwise
     * @param code Reponse code of the action
     */
    public InterceptionResponse newInterceptionResponse(boolean allow, int code);
	
}

Execution

The execution always takes two steps:

  1. Script evaluation. If the script is not invocable, this is the only step the execution takes.
  2. Method invocation. If the script is invocable, the script support will attempt to invoke a function corresponding to a method on the ScriptGame interface (see below).

Invocable Scripts

If the script is invocable, the support will call a method, corresponding to methods on the ScriptGame interface:

/**
 * This is a Java representation of the interface the script game
 * should implement. 
 * 
 * @author larsan
 */
public interface ScriptGame extends TableListener, TableInterceptor {

    /**
     * This method is equivalent to one of the "handle" methods of
     * the GameProcessor interface.
     * 
     * @param action Action to handle, never null
     * @param table Current table, never null
     */
    public void handleDataAction(GameDataAction action, Table table);

    /**
     * This method is equivalent to one of the "handle" methods of
     * the GameProcessor interface.
     * 
     * @param action Action to handle, never null
     * @param table Current table, never null
     */
    public void handleObjectAction(GameObjectAction action, Table table);

    /**
     * This method is equivalent to the start method of
     * the TournamentGame interface.
     * 
     * @param table Current table, never null
     */
    public void startTournamentRound(Table table);

    /**
     * This method is equivalent to the start method of
     * the TournamentGame interface.
     * 
     * @param table Current table, never null
     */
    public void stopTournamentRound(Table table);

}

Please note that the interface above extends both table listener and interceptor. Ie. in a script game the table processor, listener and interceptor is written in the same script. So as an example, to dissalow player with id 666 to join a table (since that's usually the devil anyway), you can add the following to a JavaScript game:

function allowJoin(table, req) {
    // if player is the devil
    if(req.getPlayerId() == 666) {
	return _support.newInterceptionResponse(false, 666);
    } else {
	return _support.newInterceptionResponse(true, 0);
    }
}

For more information on the TableListener and TableInterceptor please refere to the Java API documentation:

Non-Invocable Scripts

If the script is not invocable, or you do not which to use functions, you can rely on stage one in the execution only. In that case you'd have to to something like this:

if(_method == 'handleDataAction') {

    var table = _args[1];
    var action = _args[0];

    _log.debug('Entering handleDataAction');
 
    // etc...

} else {

   _log.warn('Unknown method: ' + _method);

}

Script Game Activation

You can supply a game activation script. This script will be executed in intervals, configured in the "game-activator-script-interval" property.

Bound Variables

_log // a log4j logger 
_context // an activator context

Execution

The execution always takes two steps:

  1. Script evaluation. If the script is not invocable, this is the only step the execution takes.
  2. Method invocation. If the script is invocable, the script support will attempt to invoke a function corresponding to a method on the ScriptActivator interface (see below).

Invocable Scripts

If the script is invocable, the support will call a method, corresponding to methods on the ScriptActivator interface:

public interface ScriptActivator {

    public void checkTables(TableFactory fact);
	
}

Non-Invocable Scripts

If the script is not invocable, or you do not which to use functions, you can rely on stage one in the execution only.

Example Invocable Activator Script

Here a small JavaScript example of an activator:

function checkTables(fact) {

    // logging is good form
    _log.debug('Script checking tables...');

    // all tables as an array
    var list = fact.listTables();

    // if we have less than 10 tables
    if(list.length < 10) {
        
        // tables to create
	var rem = 10 - list.length;

        // logging is good form
	_log.debug('Found ' + list.length + ' tables, will create ' + rem);

        // create tables
	fact.createTables(rem, 10, null);

    }
}

Additional Languages

Ruby

To install JRuby in Firebase, please download the "JRuby 1.6.7 Complete.jar" file and drop into $FIREBASE_HOME/lib/common and restart Firebase.

Personal tools