Skip to content
shakty edited this page Apr 6, 2023 · 4 revisions
  • status: incomplete
  • version: 7.x

Overview

All logic client types have access to the Game Room object in which they are instantiated. This object, in turn, contains a reference to the Channel object in which it is embedded.

Below some of the main properties and methods of these objects are described.

GameRoom

Properties

  • treatmentName: The name of the treatment chosen by the waiting room (or 'standard' if no treatment is defined in the game).

  • settings: The settings for the treatment.

  • clientTypes = this.gameLevel ? this.game.levels[this.gameLevel].clientTypes : this.game.clientTypes;

  • dataDir: Path to the directory where the data is saved.

  • node: Reference to the logic node.

  • channel: Reference to the channel to which the room belongs.

Methods

  • updateWin(id, update, opts):

    Updates the current winning value of a client in the registry.

    • string id The id of the client
    • number win The update to be added to current winning
    • object opts Configuration options:
      • clear: If TRUE, it overwrites current value
      • winProperty: The name of the winning property, default 'win'

    Returns number|boolean The updated value or FALSE if the client is not found.

  • computeBonus(options):

    Computes, sends, and dumps to file system the total bonus of each player in the room.

    object options Configuration options. Example:

{

    // If TRUE, console.log each bonus object
    // Default: false
    print: true,

    // If TRUE, sends the computed bonus to each client
    // Default: TRUE
    say: true,

    // It TRUE, it writes a `bonus.csv` file. Default: TRUE.
    dump: true,

    // If TRUE, it appends to existing `bonus.csv` files. Default: FALSE.
    append: false,

    // The names of the columns in `bonus.csv`.

    // The values for  each column are extracted from the
    // client objects in the registry, property names are matched exactly.
    //
    // Furthermore, it is possible to
    // specify a different property name by passing an array,
    // instead of a string, where the first element is the
    // name of the column in the dump file, and the second
    // element is the name of the property in the client object.
    // It is also possible to pass a function as second
    // element, and in this case the return value is written
    // to file.
    //
    // Default: [ 'id' 'type', 'bonus' ].
    //
    // Other options can modify the default value.
    //
    // If `amt` option is true or AMT information is found,
    // the following fields are added:
    //
    // [ 'workerid', 'hitid', 'assignmentid', 'access',
    //   'exit', 'approve', 'reject' ];
    //
    // If `addDisconnected` option is true, the following
    // fields are added:
    //
    // [ 'disconnected', 'disconnectedStage' ].
    //
    header: [
        'id', [ 'type', 'clientType' ], 'win',
        [ 'approve', item => !item.disconnected ]
    ],

    // DEPRECATED 5.8.0+
    // The name of the keys in the registry object from which
    // the values for the dump file are taken.
    // Default: equal to header.
    //
    headerKeys: [ 'id', 'clientType', 'WorkerId',
                  'HITId', 'AssignmentId', 'ExitCode', 'win' ],


    // If different from 1, the bonus is multiplied by the exchange
    // rate, and a new property named (winProperty+'Raw') is added.
    // Default: (settings.EXCHANGE_RATE || 1)
    exchangeRate: 1,

    // The name of the property holding the bonus.
    // Default: 'win'
    winProperty: 'win',

    // The decimals included in the bonus (-1 = no rounding)
    // Default: 2
    winDecimals: 2,

    // If a property is missing, this value is used instead.
    // Default: 'NA'
    missing: 'NA'

    // If set, this callback can manipulate the bonus object
    // before sending it.
    // Default: undefined
    cb: function(o) { o.win = o.win + 1 },


    // An optional callback function to filter out clients
    // Default: undefined
    filter: function(client) {
        return true; // keeps the client (else skips it).
    },

    // An array of client objects or ids that overwrites the clients
    // in the game room.
    // Default: undefined
    clients: [ client1, client2 ]

    // If TRUE, currently diconnected players are added to the
    // printout and dump file.
    // Default: false
    addDisconnected: true,

    // If TRUE, it forces writing AMT columns into dump file,
    // if FALSE, it prevents it.
    // Default: undefined.
    amt: true

}

Channel

The channel contains all clients (connected and disconnected), the rooms (game rooms, waiting rooms, requirement rooms, etc.) and offer methods to move clients into rooms, to create new ones, and to connect bots and phantoms.

Properties

  • defaultChannel: TRUE, if this is the default channel.

  • gameName: The name of the game associated with the channel.

  • gameInfo: Reference to the game information, including treatments and client types.

  • registy: The registry of all connected and disconnected clients.

  • waitingRoom: Reference to the main waiting room of the game (if any).

  • requirementsRoom: Reference to the main requirements room of the game (if any).

  • gameRooms: Collection of instantiated game rooms.

  • maxRooms: Max number of rooms that can be created (default: -1 no limit).

  • gameLevels: Collection of game levels for the game (if any).

  • bots: Collection of node instances of bot client type, indexed by client id.

  • phantoms: Collection of node instances of phantom client type, indexed by phantom js pid.

Methods

  • moveClient(id, toRoom, fromRoom): Moves a client into a different room and sends notification clients in old and new room.

string id Client id or alias. string toRoom New room name (must exist). string fromRoom Optional. The name of the current room, to avoid further lookup (if given, must exist).

  • moveClientToGameLevel(id, toLevel, fromRoom): Moves a client to the entry room of the chosen game level.

string id Client id or alias. string toLevel New room name (must exist). string fromRoom Optional. The name of the current room, to avoid further lookup (if given, must exist).

  • placeClient(clientObject inRoom): Places a client into a room for the first time (client must not be found in any other room, otherwise an error is raised).

object clientObj An object representing the client string inRoom Room ID (must exist)

Returns boolean Whether the placement was valid and performed

  • require(path, exports, nocache): Special require statement to share objects with the required files.

string path The path to the required file object exports Optional. Object literals with properties shared with the required file. boolean nocache If TRUE, deletes the cached path and forces re-reading from file system. Default: FALSE.

Returns mixed The export from the required file.

  • getGameDir: Returns the path to the current game directory.

  • hasGameTreatment(treatmentName): Returns TRUE if the treatment is found in the game.

string treatmentName The treatment to check

  • getLiveInfo(): Returns an object containing information about currently connected clients. EXPERIMENTAL

Bots and Phantoms

Note: Phantoms are no longer supported.

There are two types of bot clients that can be set up to play a game, either as a replacement for human players or for testing purposes.

The first kind, instantiated using ServerChannel.connectBot, resides directly on the server, giving it a SocketDirect connection and thus admin privileges.

The second kind, created by ServerChannel.connectPhantom, uses PhantomJS to emulate a browser connection. This way, the environment of the bot is very similar to that of a human player which makes it useful for testing.

Bots

To connect a bot of client type equal to 'bot' to the waiting room:

channel.connectBot();

To connect a bot with custom configuration, and place it in any given room:

channel.connectBot({


    // Room and Client Type:

    room:       'roomId', // Room id Or room object itself.
    clientType: 'bot2',   // Client type name, if different from 'bot'.


    // Id of the Bot:

    id:        'newId', // The id of the bot, must be unique. Cannot be set
                        // if replaceId is also set.
    replaceId: 'oldId'  // The id of a previously disconneceted
                        // client to be replaced. The bot will automatically:
                        //
                        // - receive the role and the partner of  replaced
                        //   client (the partner is _not_ notified),
                        // - updae all all remaining matches (if any),
                        // - be set to DONE, if disconnected client was DONE,
                        // - have step timer set with remaining time left.
                        //
                        // These options can be changed by `gotoStepOptions`.


    // Custom Logger:

    logger: myLogger, // A custom logging function. Default: 'clients'
                      // logger of the channel.


    // Init/start of the game:

    init: true,            // If FALSE, the client will not be inited,
                           // and will not start/step. Default: TRUE.
    start: true,           // If FASLE, the game will not start after
                           // being inited. Cannot be set if `gotoStep` is set.
    gotoStep: myGameStage, // If set, after inited, the game will start from
                           // this step. Cannot be set if `start` is  set.
    gotoStepOptions: obj,  // If set, it will be mixed-in with default options.


    // Events:

    ready: readyCb, // A callback function to be executed as soon as the
                    // bot has connected and received an ID, but before
                    // the init function has been called.

    // Setup:

    // This object is passed to `node.setup`, see Client-Configuration-v7.
    setup: {
       // This also updates settings object passed in client type function.
       settings: { foo: 'bar' } // node.game.settings.foo = 'bar'.
    }
});

Phantoms

Note: Phantoms are no longer supported.

To connect a phantom of client type equal to 'autoplay' to the requirements room:

channel.connectPhantom();

To connect a custom phantom with or without authorization:

channel.connectPhantom({
    // Sets custom client type.
    clientType: 'phantom',
    // Passes additional parameters to the query string.
    queryString: 'foo="bar"',
    // Passes authorization credentials (id only).
    auth: 'myId',
    // Passes authorization credentials (id and password).
    auth: {
        id: 'myId',
        pwd: 'myPassword'
    },
    // Creates new valid credentials automatically.
    auth: 'createNew',
    // Uses the next available credentials (if any).
    auth: 'nextAvailable'    
});

See the documentation of ServerChannel for a full description of the two methods.

Server Messages

The nodeGame servers can be controlled and queried via messages.

Some of the commands accepted by the AdminServer include:

  • SERVERCOMMAND_ROOMCOMMAND
    Instructs clients in a room to be setup, started, paused, resumed or stopped.
  • SERVERCOMMAND_INFO
    Queries the server for information about channels, rooms, clients or games.
  • SERVERCOMMAND_STARTBOT
    Starts a PhantomJS instance connected to the server, using clientType 'autoplay'.

For more information, refer to the implementation of AdminServer.

Examples:

// Pause all players in a given room.
node.socket.send(node.msg.create({
    target: 'SERVERCOMMAND',
    text:   'ROOMCOMMAND',
    data: {
        type:    'PAUSE',
        roomId:  roomId,  // roomId must be defined
        doLogic: false,
        clients: 'players',
        force:   false
    }
}));

// Start a PhantomJS bot.
node.socket.send(node.msg.create({
    target: 'SERVERCOMMAND',
    text:   'STARTBOT'
}));

// Get a list of channels.
node.socket.send(node.msg.create({
    target: 'SERVERCOMMAND',
    text:   'INFO',
    data: {
        type:      'CHANNELS',
        extraInfo: true
    }
}));
// Listen for the response.
node.on.data('INFO_CHANNELS', function(msg) {
    Object.keys(msg.data).forEach(function(channel) {
        console.log(msg.data[channel].name);
    });
});
Clone this wiki locally