Jump to content
code34

Bus message exchange (BME) scripts

Recommended Posts

Bus message exchange



This package builds a main BUS messages between clients & server and optimize data transfert between clients & server

28mk75l.jpg

Feature:

- build one main bus message exchange that is better against the red chain

- Mp & SP compatible

- send & listener oriented

Information:

This script is a part of the handler modules from WIT - ARMA2. All modules/functions of handler modules from WIT are not distribute in this package.

Download:

https://www.dropbox.com/s/s80fd7xi8df7dif/bus_message_exchange.Altis.zip?dl=0

Github:

https://github.com/code34/bus_message_exchange.Altis

Licence:

Under Gpl, you can share, modify, distribute this script but don't remove the licence and the name of the original author

Readme:

/*

Author: code34 nicolas_boiteux@yahoo.fr

Copyright © 2013 Nicolas BOITEUX

Bus Message Exchange (BME)

This program is free software: you can redistribute it and/or modify

it under the terms of the GNU General Public License as published by

the Free Software Foundation, either version 3 of the License, or

(at your option) any later version.

This program is distributed in the hope that it will be useful,

but WITHOUT ANY WARRANTY; without even the implied warranty of

MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the

GNU General Public License for more details.

You should have received a copy of the GNU General Public License

along with this program. If not, see <http://www.gnu.org/licenses/>.

*/

Create a main bus message between clients & server

Usage:

put the directory BEM in your mission directory

put this code into your mission init.sqf

call compilefinal preprocessFileLineNumbers "BME\init.sqf";

See example mission in directory: bus_exchange_message.Altis

Licence:

You can share, modify, distribute this script but don't remove the licence and the name of the original author

logs:

0.3 - Fix:

- fix mp handler call

- fix reset code

0.2 - Fix:

- add performance improvement of @Prodavec

- add private variable declaration

- fix iteration call

- add logs

- change calling line

0.1 - BUS message Exchange original from A2 - Warcontext

Documentation

V 0.3 : BME by code34 - nicolas_boiteux@yahoo.fr

V 0.2 : BME by code34 - nicolas_boiteux@yahoo.fr

V 0.1 : BME by code34 - nicolas_boiteux@yahoo.fr

Messages are variables that contains value, and are send to destination host.

How to send message:

--------------------

Usage:

[message, destination] call BME_fnc_publicvariable;

Send a message to all client

["variablename", "client"] call BME_fnc_publicvariable;

Send a message to a specific client

["variablename", "client", clientid] call BME_fnc_publicvariable;

Send a message to server

["variablename", "server"] call BME_fnc_publicvariable;

Send a message to everybody

["variablename", "all"] call BME_fnc_publicvariable;

How to receive message:

-----------------------

The message are handle by listeners on client or server side. Listeners are specific functions that are executed on destination host, when message is distributed.

Message is distributed as a parameter of the function like eventhandler do.

There is tow kind of listeners:

- server listeners

- client listerners

The listener declaration must respect this syntax:

BME_netcode_server_nameofyourvariable = { code to execute on server side };

BME_netcode_nameofyourvariable = { code to execute on client side };

You can declare thoses listeners directly on your code, but it's more simple to use the default location:

client side:

- declare by default in BME_clienthandler.sqf

server side:

- declare by default in BME_serverhandler.sqf

exemple to hint a message to all client (listener already exists :) )

bme_message = "Hello folks!";

["bme_message", "client"] call BME_fnc_publicvariable;

Example of server listener to init a variable on server side

client side:

myvariable = "Hello folks!";

["myvariable", "server"] call BME_fnc_publicvariable;

server side

BME_netcode_server_myvariable = {

myvariable = _this select 0;

};

Example of client listener to init a variable on client side

server side:

myvariable = "Hello folks!";

["myvariable", "client"] call BME_fnc_publicvariable;

client side

BME_netcode_myvariable = {

myvariable = _this select 0;

};

Edited by code34

Share this post


Link to post
Share on other sites

I don't know cause i don't use packaged BIS functions since Arma: too much side effect and we don't have access to all the code.

This system works since A2, BIS certainly decided to copy it and generalize it in A3, as they already did with other modules like Alice, etc in A2 :)

I release thoses scripts cause i had to make them standalone for my other missions. :D

Note: i developped this script as workaround cause there is a lack with the MP DATA transfert/refresh design in main game, and also with publicvariable function in local.

Edited by code34

Share this post


Link to post
Share on other sites

Release frontpaged on the Armaholic homepage.

================================================

We have also "connected" these pages to your account on Armaholic.

This means in the future you will be able to maintain these pages yourself if you wish to do so. Once this new feature is ready we will contact you about it and explain how things work and what options you have.

When you have any questions already feel free to PM or email me!

Share this post


Link to post
Share on other sites

Can you explain a bit more about what this actually is, and where it should be used?

Share this post


Link to post
Share on other sites

Looks good!

How can I monitor, not necessarily with this tool, the data transfer performance within a mission/server? I'm concerned with the use of publicVariables, in particular.

Share this post


Link to post
Share on other sites
Can you explain a bit more about what this actually is, and where it should be used?

Hi,

I think the best exemple is the hello world ;)

this code on server part:

myvariable = "Hello folks!";

["myvariable", "client"] call BME_fnc_publicvariable;

print hello world on all the client, this function should be declare on client part:

BME_netcode_myvariable = {

myvariable = _this select 0;

hint myvariable;

};

same thing but inverse way

this code on client side:

myvariable = "Hello folks!";

["myvariable", "server"] call BME_fnc_publicvariable;

this code on server side to print into logs

BME_netcode_server_myvariable = {

myvariable = _this select 0;

diag_log myvariable;

};

---------- Post added at 17:16 ---------- Previous post was at 17:12 ----------

Looks good!

How can I monitor, not necessarily with this tool, the data transfer performance within a mission/server? I'm concerned with the use of publicVariables, in particular.

You can not monitor the data transfert performance with this tool ;(

Share this post


Link to post
Share on other sites

OMG, this is ONE MORE Client <-> Server exchanging system. I thought there's REALY some optimizing code but not.

1. init.sqf

[] execVM "BME\init.sqf";

Using execVM may cause loading order issues, like it was in Warfare by Benny for example. And it's better to send null-pointer instead of empty array if you don't want to send eny kind of arguments:

objNull call compile preprocessFileLineNumbers "BME\init.sqf";

It guarantees loading order before any user script which are using that system.

2. BME\init.sqf

_garbage = [] spawn BME_fnc_queue;
_garbage = [] call BME_fnc_eventhandler;
_garbage = [] call BME_fnc_serverhandler;

Same: use objNull.

And... where is local var privatization? If you create local var _myvar, always add it to private block:

private "_myvar";

It'll be very bad if someone will create "_garbage" var and BME will be loaded between user scripts. _garbage variable value will be overrided with a script handle.

Should be fixed with:

private "_garbage";

3. \BME\BME_queue.sqf

waituntil {(count bme_queue) > 0};

WOW! ARE YOU KIDDING ME? Oh yeah, I know the idea: LAGS FOR EVERYONE FOR FREE :)))) Not realy. And then people would curse BIS for laggy scripts / low FPS / etc. Very "nice" solution for ArmA servers.

First off you MUST to know: waitUntil works on full speed 1 check per frame in non-scheduled environment but may be delayed. If you're using waitUntil with no delay it completely loads VM with useless work (most of loops have very low efficiency by design) in most of time. The VM's script scheduler will allocate its time between useless FAST loop and other scripts. Is it good?

That part of the code should be recoded with no loop.

4. \BME\BME_queue.sqf

if((_type == "server") or (_type == "all")) then

It's much better to compare vars by float/double values instead of strings.

So

if ("aaaa" == "bbbb") then {...};
if ("someshit" == "someshit") then {...};

works much slower (depending on the strings size) than this:

if (var1 == var2) then {...};
if (_shit1 == _shit2) then {...};

and it'll be better way to use macro instead creating local var for comparing:

#define DO_SOME_SHIT  100
#define DO_OTHER_SHIT 101

switch (_input) do
{
   case DO_SOME_SHIT:
   {
       // ...
   };
   case DO_OTHER_SHIT 101:
   {
       // ...
   };
};

// ...

["Hello World!", DO_SOME_SHIT] call fnc_MyShit;

5. \BME\BME_queue.sqf

call compile format["wcgarbage = [_variable] spawn BME_netcode_server_%1;", _variablename];

OMG!

You're using slow dynamic compilation instead of getting direct access to the var! Why?

objNull spawn (missionNamespace getVariable (format ["BME_netcode_server_%1", _variablename]));

Is wcgarbage var used elsewhere?

bme_queue select 0
bme_queue select 0
bme_queue select 0

Any reason to extract the array entry three times instead of using single-time extraction and storing it in local var?

6. \BME\BME_eventhandler.sqf

if!(tolower(_type) in ["client", "server", "all"]) exitwith {hint "BME: wrong destination parameter should be client|server|all"};
...
switch (tolower(_type)) do {
		case "server": {

_variablevalue 	=  call compile format["%1", _variablename];

See above. If you will use macros, toLower will not be used.

(((bme_addqueue select 2) == "server") or ((bme_addqueue select 2) == "all")))
(((bme_addqueue select 2) == "client") or ((bme_addqueue select 2) == "all")))

Cool. "bme_addqueue select 2" is used FOUR times instead of ONE.

bme_queue = bme_queue + [bme_addqueue];

Why would you use binary addition instead of set?

bme_queue set [count bme_queue, bme_addqueue];

Also there's no something revolutionary to decrease network traffic, something like serializing arrays (I hope you know about arrays trasfered via net ;) click).

Thanks for your time, that was a nice try, but for actual use it should be completely rewritten from the scratch. For mission/addon makers I dont recommend to use it because of explained reasons. Use BIS_fnc_MP instead or create new one with no gross errors in simple code.

Also that article is very usefull for novices: http://community.bistudio.com/wiki/Code_Optimisation

Edited by Prodavec

Share this post


Link to post
Share on other sites

Well provadec you spend a lot of energy to wrote this thread. You did some good remarks(that i will integrate in next release) and some wrongs cause you are not looking all the problem.

But i think your global interest is about performance and how increase performance execution. First you must don't forget BME was developped on A2. Must of the execution time problem that your are talking about like array serialization happen at a low level design. Fix them by script is simply workaround, but it's not the good way to adress thoses kind of problem. Unfortunately, it's the way that BIS took for a lot of problem, but it made some shits over shit.

My personnal thinking is about to produce a understandable code for me(as you did) that can be modify by other for their own purpose (you) that is most important than produce a code that win 0.000001ms at execution.

Moreover, you must don't forget that messages transmist between client & servers happen at a low frequency that why it's not make sens to improve queue performance as it could be interesting to fix the array serialization you are talking about.

Just for my personnal information cause you compare BIS_fnc_MP to BME, where do you find the BIS server side code of BIS_fnc_MP ?

Edited by code34

Share this post


Link to post
Share on other sites
OMG, this is ONE MORE Client <-> Server exchanging system. I thought there's REALY some optimizing code but not.

WOW! ARE YOU KIDDING ME?

You're using slow dynamic compilation instead of getting direct access to the var! Why?

Use BIS_fnc_MP instead or create new one with no gross errors in simple code.

Using tact is always good. Other than that, thanks for the insights.

Share this post


Link to post
Share on other sites

Updated version frontpaged on the Armaholic homepage.

================================================

We have also "connected" these pages to your account on Armaholic.

This means in the future you will be able to maintain these pages yourself if you wish to do so. Once this new feature is ready we will contact you about it and explain how things work and what options you have.

When you have any questions already feel free to PM or email me!

Share this post


Link to post
Share on other sites

@code34 - nice work mate - MP coding is a bitch to start off with, so nice one on trying to simplify it for other users. I can see this being a big advantage for the wider audience with less coding knowledge.

Found that many people in the Arma world want to make MP games straight away with little understanding, so hopefully this will assist them.

Prodavec made one or two valid points about performance which hopefully you updated in your newest code.

So all in all - nice work, and hopefully you can keep updating and simplifying for others.

Share this post


Link to post
Share on other sites

Updated version frontpaged on the Armaholic homepage.

================================================

We have also "connected" these pages to your account on Armaholic.

This means soon you will be able to maintain these pages yourself if you wish to do so. Once this new feature is ready we will contact you about it and explain how things work and what options you have.

When you have any questions already feel free to PM or email me!

Share this post


Link to post
Share on other sites

Ive been staring at this for 2 days. I can't make it work with my dedicated server. Can we get some doco explaining EXACTLY what one needs to do to make it work to a single client.

For example. Send a location and direction to a single player onplayerconnected. Any help would be EXTREMELY appreciated.

Share this post


Link to post
Share on other sites

hi :)

I reverse the example of first page

example of client listener to init a variable on client side

server side:

myvariable = [[16000, 16000], 0];

["myvariable", "client"] call BME_fnc_publicvariable;

client side

BME_netcode_myvariable = {

_myvariable = _this select 0;

_position = _myvariable select 0;

_dir = _myvariable select 1;

};

Edited by code34

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

×