Jump to content
Sign in to follow this  
Tankbuster

Multiplayer Framework. Insight, documentation, discussion. :)

Recommended Posts

And sorry TankBuster, I would gladly provide examples/support on how to handle it with PV/PVEH or with CBA's event system. I do not support things I do not believe in, like the MP Framework :)

No apologies required. I don't support things I don't believe in, nor things I'm expected to understand by extra sensory perception, like this.

Share this post


Link to post
Share on other sites

One more argument against MPF: It does not support new commands (as far as I know it requires each command to be handled by a script as part of MPF - as the MPF is no longer developed by BI for a long time, all the new commands should not be supported).

Share this post


Link to post
Share on other sites
So the options for this are:

Use MPF (very carefully)

Use CBA (if SB falls under a bus tomorrow can he name a successor in a will?)

Make your own system (if you have the skills, I don't)

The alternative is to adapt the system that Xeno uses in Domination. Now, if we could persuade him to make it JIP compatible, we'd be in!

Share this post


Link to post
Share on other sites
The alternative is to adapt the system that Xeno uses in Domination. Now, if we could persuade him to make it JIP compatible, we'd be in!

I do not think JIP should be integrated into an event based message system. Consider MPF, what exactly happens when you use the "per" parameter. Are all these call stored in a public var? How large does that become when you use for stuff like move or change the color of a marker? Will JIPs then process all those events on connect even though only the last one is relevant?

By separating them you can deal with JIP in a more sane manner. I use CBA events and I just add an extra event handler on the server to register any events that is somehow related to JIP players.

Share this post


Link to post
Share on other sites

What I'd like to see is an example of CBA and not-CBA for a situation like this: Tasks given to do something at a randomly placed marker which will be marked as completed when done along with text feedback or task hints and a new marker set for the next in a series of tasks part of which is playing a sound on a unit at the location that nearby players will hear. Tasks, markers and sounds are all complicated and stupid in MP, so... how would the experts do them? :)

Share this post


Link to post
Share on other sites

In a not-CBA situation I will make a small library that does the same. Really quick and dirty example that mimicks some of the CBA functions (not tested probably some syntax errors etc..):



// call compile preprocess in init.sqf or similar

#define QUOTE(X_NAME) #X_NAME
#define PV_VAR nw_var
#define HANDLERS nw_handlers

QUOTE(PV_VAR) addPublicVariableEventHandler {
(_this select 1) call receivedEvent;
};

//This doesn't have to be an array
HANDLERS = [];

//Returns index used to remove
addHandler = {
private ["_event", "_code","_setIndex"];
_event = _this select 0;
_code = _this select 1;
_setIndex = _numHandlers;
for "_i" from 0 to (_setIndex-1) do {
	if (isNil {HANDLERS select _i) exitWith {
		_setIndex = _i;
	};
};
HANDLERS set [_setIndex, [_event, _code]];
_setIndex
};

//Removes the handler pass in [_handlerIndex].
removeHandler = {
private ["_id","_numHandlers"];
_id = _this select 0;
_numHandlers = count HANDLERS;
if (_id < _numHandlers) exitWith {
	HANDLERS set [_id, nil];
};
};

//Raises on other machines.
remoteEvent = {
PV_VAR = _this;
publicVariable QUOTE(PV_VAR);
};

//Publicvar handlers are not run on local machine.
globalEvent = {
_this call removeEvent;
_this call localEvent;
};

localEvent = {
_this call receivedEvent;
};

//called when a event is received or to be run locally.
receivedEvent = {
private ["_event", "_params","_handlers"];
_event = _this select 0;
_params = _this select 1;
_handlers = [];
{
	if (_event == (_x select 0)) then {
		_handlers set [count _handlers, _x select 1];
	};
} forEach HANDLERS;

{
	//Uses spawn so earlier events don't error out later events.
	_params spawn _x;
} forEach _handlers;
};

Share this post


Link to post
Share on other sites
What I'd like to see is an example of CBA and not-CBA for a situation like this: Tasks given to do something at a randomly placed marker which will be marked as completed when done along with text feedback or task hints and a new marker set for the next in a series of tasks part of which is playing a sound on a unit at the location that nearby players will hear. Tasks, markers and sounds are all complicated and stupid in MP, so... how would the experts do them? :)

Here is some working code that I am working on for a random mission system, similar to side missions in domi. It is still a work in progress and I have not commented it to well, but you should get the picture.(Im sure sickboy or xeno could provide some better examples, as I am still a little new to scripting with CBA events.) I have done some things with MPF in the past, addactions, messages and markers. But I find the CBA events to be much more powerful and easier to work with. To top if off they create less net traffic.

The only downside to the way im doing JIP is that it is sending the the array of data for each mission twice over the network, once from the cba event and once for the PV. But I don't know of a better way to do this, and I have tried to limit the amount of data being sent.

I have three init's one for the server, one for the player, and one for jip.

server init:

sidemissioncomplete = true;
sd_mission_cleanup_done = true;
sd_mission_cleanup_array = [];
[] execVM "s_server\spawnRandomMissions.sqf";



// This takes the events and saves them into an array and pv them so that jips can get it when they join.
if (isServer) then 
{
   ["SideMisnMkr", 
   { 
       sidemsnmkrary = [(_this select 0) ,(_this select 1) ,(_this select 2) ,(_this select 3) ,(_this select 4) ];
       publicVariable "sidemsnmkrary"; 
   }
   ] call CBA_fnc_addEventHandler;  


   ["SideMisnMkr2", 
   {     
      sidemsnmkrary2 = [(_this select 0) ,(_this select 1) ,(_this select 2) ,(_this select 3) ,(_this select 4) ];
      publicVariable "sidemsnmkrary2"; 
   }
   ] call CBA_fnc_addEventHandler;  


       ["SideMisnMkr3", 
   {
       sidemsnmkrary3 = [(_this select 0) ,(_this select 1) ,(_this select 2) ,(_this select 3) ,(_this select 4) ];
       publicVariable "sidemsnmkrary3"; 
   }
   ] call CBA_fnc_addEventHandler;  

   ["SideMisnTask", 
   { 
       sidemsntaskary = [(_this select 0) ,(_this select 1) ,(_this select 2) ,(_this select 3) ,(_this select 4) ];
       publicVariable "sidemsntaskary"; 
   }
   ] call CBA_fnc_addEventHandler;  

};

player init:


// All the local commands that need to run for markers,tasks and messages. The dynamic data for each mission is passed in the array with the cba event.
if (!isServer) then 
{
   ["SideMisnMkr", 
   { 
       COMMAND=[West,"HQ"];COMMAND sideChat (_this select 1) ;

       _marker = createMarkerLocal[(_this select 2),(_this select 3)];
       _marker setMarkerShapeLocal "Ellipse";
       _marker setMarkerTypeLocal "mil_circle";
       _marker setMarkerTextLocal (_this select 4);
       _marker setMarkerSizeLocal [200, 200];


   }
   ] call CBA_fnc_addEventHandler;  


   ["SideMisnMkr2", 
   { 
       COMMAND=[West,"HQ"];COMMAND sideChat (_this select 1) ;

       _marker = createMarkerLocal[(_this select 2),(_this select 3)];
       _marker setMarkerShapeLocal "icon";
       _marker setMarkerTypeLocal "start";
       _marker setMarkerTextLocal (_this select 4);
       _marker setMarkerSizeLocal [1, 1];


   }
   ] call CBA_fnc_addEventHandler;  


       ["SideMisnMkr3", 
   { 
       COMMAND=[West,"HQ"];COMMAND sideChat (_this select 1) ;

       _marker = createMarkerLocal[(_this select 2),(_this select 3)];
       _marker setMarkerShapeLocal "icon";
       _marker setMarkerTypeLocal "end";
       _marker setMarkerTextLocal (_this select 4);
       _marker setMarkerSizeLocal [1, 1];


   }
   ] call CBA_fnc_addEventHandler;  

   ["SideMisnTask", 
   { 
       tsk1 = player createSimpleTask [(_this select 0)];
       tsk1 setSimpleTaskDescription [(_this select 0), (_this select 1), (_this select 2)];
       tsk1 setSimpleTaskDestination (_this select 3);
       tsk1 setTaskState "Assigned";
       player setCurrentTask tsk1;
       taskhint [(_this select 0), [1, 1, 1, 1], "taskCurrent"]; 


   }
   ] call CBA_fnc_addEventHandler;  




   ["SideMisnDelTask", 
   { 
       tsk1 setTaskState "Succeeded";
       taskhint [(_this select 0), [0, 1, 0, 1], "taskDone"];
       deletemarker (_this select 1);
       player removesimpletask tsk1;
       COMMAND=[West,"HQ"];COMMAND sideChat (_this select 2) ;
   }
   ] call CBA_fnc_addEventHandler;  
};


playerinit = true;

Player Jip:

.


// Make sure the commands don't run twice.
if (playerinit) exitWith {};

// Set up the events to get the Jip mission events.
["SideMisnMkrjip", 
   { 
       COMMAND=[West,"HQ"];COMMAND sideChat (_this select 1) ;

       _marker = createMarkerLocal[(_this select 2),(_this select 3)];
       _marker setMarkerShapeLocal "Ellipse";
       _marker setMarkerTypeLocal "mil_circle";
       _marker setMarkerTextLocal (_this select 4);
       _marker setMarkerSizeLocal [200, 200];
   }
] call CBA_fnc_addEventHandler;




["SideMisnMkr2jip", 
   {        
       _marker = createMarkerLocal[(_this select 2),(_this select 3)];
       _marker setMarkerShapeLocal "icon";
       _marker setMarkerTypeLocal "start";
       _marker setMarkerTextLocal (_this select 4);
       _marker setMarkerSizeLocal [1, 1];


   }
] call CBA_fnc_addEventHandler;




["SideMisnMkr3jip", 
   {         
       _marker = createMarkerLocal[(_this select 2),(_this select 3)];
       _marker setMarkerShapeLocal "icon";
       _marker setMarkerTypeLocal "end";
       _marker setMarkerTextLocal (_this select 4);
       _marker setMarkerSizeLocal [1, 1];


   }
] call CBA_fnc_addEventHandler;




["SideMisnTaskjip", 
   { 
       tsk1 = player createSimpleTask [(_this select 0)];
       tsk1 setSimpleTaskDescription [(_this select 0), (_this select 1), (_this select 2)];
       tsk1 setSimpleTaskDestination (_this select 3);
       tsk1 setTaskState "Assigned";
       player setCurrentTask tsk1;
       taskhint [(_this select 0), [1, 1, 1, 1], "taskCurrent"]; 


   }
] call CBA_fnc_addEventHandler;

// Raise the local jip events if they are active.
if (count sidemsnmkrary > 0) then {
   _nop = ["SideMisnMkrjip",sidemsnmkrary] call CBA_fnc_localEvent;
};


if (count sidemsnmkrary2 > 0) then {
   _nop = ["SideMisnMkr2jip",sidemsnmkrary2] call CBA_fnc_localEvent;
};


if (count sidemsnmkrary3 > 0) then {
   _nop = ["SideMisnMkr3jip",sidemsnmkrary3] call CBA_fnc_localEvent;
};




if (count sidemsntaskary  > 0) then {
   _nop = ["SideMisnTaskjip",sidemsntaskary] call CBA_fnc_localEvent;
};


// Set up the normal events so the player can get any new missions after they can join.    
if (!isServer) then 
{
   ["SideMisnMkr", 
   { 
       COMMAND=[West,"HQ"];COMMAND sideChat (_this select 1) ;

       _marker = createMarkerLocal[(_this select 2),(_this select 3)];
       _marker setMarkerShapeLocal "Ellipse";
       _marker setMarkerTypeLocal "mil_circle";
       _marker setMarkerTextLocal (_this select 4);
       _marker setMarkerSizeLocal [200, 200];


   }
   ] call CBA_fnc_addEventHandler;  


   ["SideMisnMkr2", 
   { 
       COMMAND=[West,"HQ"];COMMAND sideChat (_this select 1) ;

       _marker = createMarkerLocal[(_this select 2),(_this select 3)];
       _marker setMarkerShapeLocal "icon";
       _marker setMarkerTypeLocal "start";
       _marker setMarkerTextLocal (_this select 4);
       _marker setMarkerSizeLocal [1, 1];


   }
   ] call CBA_fnc_addEventHandler;  


       ["SideMisnMkr3", 
   { 
       COMMAND=[West,"HQ"];COMMAND sideChat (_this select 1) ;

       _marker = createMarkerLocal[(_this select 2),(_this select 3)];
       _marker setMarkerShapeLocal "icon";
       _marker setMarkerTypeLocal "end";
       _marker setMarkerTextLocal (_this select 4);
       _marker setMarkerSizeLocal [1, 1];


   }
   ] call CBA_fnc_addEventHandler;  

   ["SideMisnTask", 
   { 
       tsk1 = player createSimpleTask [(_this select 0)];
       tsk1 setSimpleTaskDescription [(_this select 0), (_this select 1), (_this select 2)];
       tsk1 setSimpleTaskDestination (_this select 3);
       tsk1 setTaskState "Assigned";
       player setCurrentTask tsk1;
       taskhint [(_this select 0), [1, 1, 1, 1], "taskCurrent"]; 


   }
   ] call CBA_fnc_addEventHandler;  




   ["SideMisnDelTask", 
   { 
       tsk1 setTaskState "Succeeded";
       taskhint [(_this select 0), [0, 1, 0, 1], "taskDone"];
       deletemarker (_this select 1);
       player removesimpletask tsk1;
       COMMAND=[West,"HQ"];COMMAND sideChat (_this select 2) ;
   }
   ] call CBA_fnc_addEventHandler;  
};  

Edited by Riouken

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
Sign in to follow this  

×