Comrades in Arms Discussion Board

Full Version: FHQ multiplayer framework
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Comrades,

I've decided to release the framework I use for our missions here in the hope that it might be useful.

What is it ?

The FHQ Multiplayer Framework (FHQ MP) is a system for creating multiplayer missions, specifically handling distributed events. In that respect, it's structure is similar to that of CBA. You can define events that are executed on local machines, remote machines, all machines, or the server.

In addition, it also handles reading of parameters in single and multiplayer.

Defining events

Events are defined either in description.ext, or added dynamically during the mission. Here's an example of a few events defined in description.ext:

Code:
class FHQ_MultiplayerFramework
{
    class Options
    {
        Options[] = {"fhq_mp_oneevent"};
    };
    
    class JoinEvents
    {
        // List of events that should be automatically fired on joining clients.
        // Events listed here always get the player as parameter, and a boolean indicating
        // whether it was a join in progress or not.
        Events[] = {"viewDistance"};
    };
    
    class Events
    {
        // On JIP clients, set view distance
        class viewDistance
        {
            code = "setViewDistance (_this * 100);};";
        };
        

        // This event is called on all clients to end the mission,
        //parameters [end, text, delay]
        class missionEnd
        {
            // Mission end
            code = "_this execVM 'library\endMission.sqf'";
        };

        // kbTell a sentence, should be called with speaker local
        // Example:
        // ["TellTo", leader FHQ_playerGroup, [leader FHQ_playerGroup, [HQ, "speech", "done1"]]]
        //                     call FHQ_MP_specificEvent;
        class TellTo
        {
            // Paramters: [speaker, [receiver, topic, sentenceId]]
            code = "(_this select 0) kbTell (_this select 1);";
        };
    };
};

The code searches for class FHQ_MultiplayerFramework in description.ext, so this name is fixed. The same applies to Options, JoinEvents, and Events.

Options define options for FHQ MP. Currently, only fhq_mp_oneevent is present, which tells the code to stop searching for additional events of the same name when it's encountered the first one.

JoinEvents lists all events that should be executed on JIP clients. In the example, every new client executes the "viewDistance" event.

Events are always composed of a name and a code field. The code is simply the code that is executed when the event runs.

Initialization

The script file has to be called once on every client. preferably in init.sqf.:

Code:
call compile preProcessFileLineNumbers "fhqmp.sqf";
waitUntil {!(isNil "FHQ_MP_InitDone")};

This initializes the system and pre-loads a number of variables with code that can be called later throughout the mission.

It also iterates through the Params section in description.ext and reads the defined parameters, creating variables who's name is the class name of the parameter, and the value is the selected value, or the default value in single player. For example:

Code:
class Params
{
    class FHQ_ViewDistance
    {
        title = "View Distance";
        values[] = {10, 15, 20, 25, 30, 40, 50, 60, 70, 80, 90, 100};
        texts[] = {"1000m", "1500m", "2000m", "2500m", "3000m", "4000m", "5000m", "6000m", "7000m", "8000m", "9000m", "10000m"};
        default = 25;
    };
};

FHQ MP would create a (public) variable "FHQ_ViewDistance" with the selected value, or 25 in single player.
Adding events during runtime

Events can be added at runtime. Events are only known on clients that defined them.

Events are added via FHQ_MP_addEvent:

Code:
_handle = [_name, _code] call FHQ_MP_addEvent;

The viewDistance example above would look like this:

Code:
["viewDistance", compile "setViewDistance (_this * 100);"] call FHQ_MP_addEvent

Events are removed viy FHQ_MP_remEvent:

Code:
[_handle] call FHQ_MP_remEvent
Calling events

Events are executed by one of six functions:

FHQ_MP_localEvent: The event is only invoked on this machine
FHQ_MP_globalEvent: The event is invoked on all machines (including this one)
FHQ_MP_remoteEvent: The event is invoked on all machines but the caller
FHQ_MP_specificEvent: The event is invoked on the machine where the given object is local
FHQ_MP_serverEcvent: The event is only executed on the server
FHQ_MP_clientEvent: The event is only executed on the client matching the client ID

NOTE: _parameterArray is always passed as "_this" to code executed as event.


FHQ_MP_localEvent

This event only executes on the client it is issued on.  Calling the function works like this:

Code:
[_name, _parameterArray] call FHQ_MP_localEvent;
.

For example, to use the example viewDistance event to set the view distance on the caller's machine to 2000, use

Code:
["viewDistance", 20] call FHQ_MP_localEvent;


FHQ_MP_globalEvent

This event executes on all machines, including the server (regardless of whether it is a dedicated server, or a hosted game).

Code:
[_name, _parameterArray] call FHQ_MP_globalEvent;
.

For example, to set the view distance on all machines to 2000, use

Code:
["viewDistance", 20] call FHQ_MP_globalEvent;


FHQ_MP_remoteEvent

Similar to the local and global events, just executes on all machines except the one calling the event.

Code:
[_name, _parameterArray] call FHQ_MP_remoteEvent;
.


FHQ_MP_specificEvent

Calling this event requires an additional parameter, and object that is tested for locality on every machine. The code executes on the machine that the object is local to.

Code:
[_name, _object, _parameterArray] call FHQ_MP_specificEvent;
.

For example, the following code executes an event on the machine that leader FHQ_playerGroup is local on and has him speak a sentence:

Code:
["TellTo", leader FHQ_playerGroup, [leader FHQ_playerGroup, [HQ, "speech", "done1"]]] call FHQ_MP_specificEvent;


FHQ_MP_serverEvent

This event needs Arma 2 patch 1.62 or later. It currently does not work on Iron Front.

An event called by this function only executes on the server.

Code:
[_eventName, _eventParameters] call FHQ_MP_serverEvent;


FHQ_MP_clientEvent

This event is only executed on the client specified by it's client id:

Code:
[_eventName, _clientId, _eventParameters] call FHQ_MP_specificEvent;

_clientId is the ID of the client, which can be obtained by different means. One simple means is the owner script command. It returns the id of the client where an object is local.

Code:
["TellTo", owner (leader FHQ_playerGroup), [leader FHQ_playerGroup, [HQ, "speech", "done1"]]] call FHQ_MP_clientEvent;

The difference to specificEvent is that the event is directly send to the specified client, and ONLY to this client. This reduces network traffic, since the locality check of specificEvent would have to be performed on each client. As such, this is currently the preferred solution to sending events. Use this instead of specificEvent on Arma 2 and Arma 3 (Iron Front does not support it).
Attached download is corrupted
try again, re-uploaded.

I guess this was the same problem that also corrupted some avatars