Jump to content
Sign in to follow this  
1para{god-father}

Help on script after removal of processInitCommands

Recommended Posts

Yes, PublicVariable is fine. Just it's ability to send code isn't. That's all. You can update your markers fine, because you've no reason to have to PublicVariable the code to do so....

Alright, but what about addPublicVariableEventHandler? Is that 100% client based once the map is loaded or does the server send the ENTIRE thing every single time? (I updated the post you replied to while you were replying). I mean the wiki says it's the EH doing it, but which one? client, server, my grandma's?

Share this post


Link to post
Share on other sites
Alright, but what about addPublicVariableEventHandler? Is that 100% client based once the map is loaded or does the server send the ENTIRE thing every single time? (I updated the post you replied to while you were replying). I mean the wiki says it's the EH doing it, but which one? client, server, my grandma's?

Doing what exactly?

The publicvariableEH runs on whatever client/server instance it's defined on. It's a local object, so having one doesn't pass it's existence over the network.

BIS_fnc_MP does NOT pass entire code blocks across the network. It only passes the function name, which is called on all clients/target client. So thus, you MUST have the function defined on the target first, or it wont work.

For updating marker locations, if it's for showing where players are on the map etc, you can do that locally, without any need for any public variables. Just put all the player slot object names into an array, and every second or so, update each object's marker.

Share this post


Link to post
Share on other sites
Something I don't understand.

You need publicVariable to make sure some things update on clients, and at the same time it seems everyone agrees that it screws people over (and is a bandwidth hog). How the heck would you update markers on a map for a MPMission without telling all clients to update it for example? I mean, no matter what, at SOME POINT, you need to send stuff to clients and force them to update...

createMarker is global it will automatically exist on all machines, if you want local marker you should use createMarkeLocal.

As for the traffic, makes no difference you remove one traffic and create another instead of it, only this time your traffic is better shaped as it has no code in it just params and function names.

You can still do that with the createUnit command i believe.

This should also be addressed. I would much prefer these exploits removed or made optional with mission config.

Share this post


Link to post
Share on other sites

createMarker might be global, but setMarkerPos isn't so if you want to move your markers dynamically (new mission appear, etc), you need to update them on clients with setMarkerPosLocal, at least that's how I understand it.

Usually I do things like this:

1) Update setMarkerPos server side

2) PV a variable like markerPosUpdated or whatever

3) Have a client side PVHE on that variable run setMarkerPosLocal.

My question was related to WHICH HE is doing what and from what Radioman just posted, if you define the HE client side, it's ONLY the clients doing it, which is fine for me. That means when I PV, only the variable is sent (which is ridicule), all the rest is done 100% client side. If this is indeed true, I don't really see the problem with doing SHITTONS of stuff on clients, just using flags variable that you PV here and there on the server (apart from core server stuff of course).

I'm still wondering if it's more efficient to pack all that you can into an array and send that over once, or to have tons of little independant variable that you PV as you go. I'm guessing arrays is the way to go but that would mean sending bigger chunks to everyone at the same time...

For updating marker locations, if it's for showing where players are on the map etc, you can do that locally, without any need for any public variables. Just put all the player slot object names into an array, and every second or so, update each object's marker.

Yea, for that it works because the server doesn't give a damn about any of that. You can't do that with dynamically updated markers that are results of server side scripts (missions, etc).

BIS_fnc_MP does NOT pass entire code blocks across the network

Ah, thanks for clearing that up!

As you said though, you NEED to send that stuff to the client, one way or the other. All you can do is find the "best" way, I agree. But in the end, it needs to send something :)

In any case, thanks for the patience in trying to explain stuff like this. Some concepts are not easy to grasp without the basics (especially the entire networking bit) and some questions must appear completely stupid.

Edited by Twix

Share this post


Link to post
Share on other sites
createMarker might be global, but setMarkerPos isn't so if you want to move your markers dynamically, you need to update them on clients with setMarkerPosLocal, at least that's how I understand it.

Usually I do things like this:

1) Update setMarkerPos server side

2) PV a variable like markerPosUpdated or whatever

3) Have a client side PVHE on that variable run setMarkerPosLocal.

My question was related to WHICH HE is doing what and from what Radioman just posted, if you define the HE client side, it's ONLY the clients doing it, which is fine for me. That means when I PV, only the variable is sent (which is ridicule), all the rest is done 100% client side. If this is indeed true, I don't really see the problem with doing SHITTONS of stuff on clients, just using flags variable that you PV here and there on the server (apart from core server stuff of course).

I'm still wondering if it's more efficient to pack all that you can into an array and send that over once, or to have tons of little independant variable that you PV as you go. I'm guessing arrays is the way to go but that would mean sending bigger chunks to everyone at the same time...

As you said though, you NEED to send that stuff to the client, one way or the other. All you can do is find the "best" way, I agree. But in the end, it needs to send something :)

You can break up PVs without much issue. As long as you're not sending hundreds at a time. Optimisation is key, and there's not been any specific findings on whether PV packing is faster or not.

PVClient and PVServer can help slim things up.

Share this post


Link to post
Share on other sites

Thanks and thanks for the PVclient/PVserver thing, didn't know about it yet.

Damn, the more I learn the more I want to start everything from scratch :)

Share this post


Link to post
Share on other sites

Another question about using BIS_fnc_MP, can I make the function in one script, and then call it from another, and if so how do I link them?

I want a function to remove an action, but I don't want to put it in the script that is executed by the addAction as then the function will only be defined on the client who uses the action. So do I need to make the function in another script and then only call it through the addAction script e.g.

function defined in main script:

CF_removeActionMP =

		{

		private["_object","_actName"];
		_object = objectFromNetID (_this select 0);
		_actName = _this select 1;

		if(isNull _object) exitWith {};

	_object removeAction _actName;

	};

function executed in external addAction script:

[[netid _veh,action1],"CF_removeActionMP",nil,true] call BIS_fnc_MP;

Is there anything else I need to do or will that call just auto detect the function already exists as that main script has already been run?

Edited by clydefrog

Share this post


Link to post
Share on other sites
Another question about using BIS_fnc_MP, can I make the function in one script, and then call it from another, and if so how do I link them?

Yes, as long as the the function name is global and loaded into memory on all machines (or at least desired ones) they can be in different scripts.

Also, you do not have to create a function at all, you can use BIS_fnc_MP to execute a .sqf script file (just like execVM) as long as the script file is already on the machine. See my second example in #29 in this thread. That way you can put your code in a script and not have to worry about creating a function.

Edited by Loyalguard
post link not working

Share this post


Link to post
Share on other sites

Ok thanks.

No, that wont fix the problem. I've told you how to fix the problem.... Exactly how. Do that, and it's fixed.

It doesn't work, it actually broke it and doesn't show the action at all using that netID stuff. I'm going to try it later without it if I can get somebody to help me test it.

Share this post


Link to post
Share on other sites

clydefrog - i should be about laters if you want to pm me - also send me what you have done :)

Share this post


Link to post
Share on other sites
clydefrog - i should be about laters if you want to pm me - also send me what you have done :)

Alright thanks Mikie. I've actually got the addAction with the condition working by the way, it just had to be a string when calling the function but not when defining it so I've put it back to that, it's working for me in the editor but I'm yet to to test it with somebody when local hosting. I'll PM you the script.

Edited by clydefrog

Share this post


Link to post
Share on other sites
Better they fixed the hole that allows clients to inject their own scripts in the first place.

Since a mission script can overwrite BIS missions in a way that persists between missions, you don't even need any kind of hack/mod/whatever. You just need to create a mission that overwrites the relevant BIS functions, and then every server you join will explode, as the game engine itself seems to call at least one of the "offending" functions.

Basically, if the game's default features use a function, that function should not be possible to modify in a mission in a way that will persist outside of that mission (if it should be possible to modify at all).

Don't think you got the concept of BIS_fnc_MP

BIS_fnc_MP doesn't send the function across the network, but allows a function set across the network to be executed without the client ever seeing that code before. So basically, a client might never define the offending function, but still run it via BIS_fnc_MP because the offending function was sent via publicVariable. Of course, I'm more against the bad practice of sending code across the network than I am against a function that can execute anything (including code not defined in advance by the client), but they're both pretty bad IMO.

While allowing you to broadcast scripts/functions across the network does give added functionality, it really is a workaround for something that should have already been in game (aka mod synchronization, making sure everyone have the required mods, which is currently only achieve-able by using Play withSIX and playing on a properly configured server), and using something like that on a regular basis is pretty terrible coding IMO. I mean, every time you want to jump you need to broadcast an entire string and have all clients compile it? Terribly inefficient. Either force the mod or implement its scripts into the server's missions. I don't think it's too wrong of BIS to require you to choose one of these 2 options.

Basically, the remote execution of scripts the other guy doesn't have is one big workaround for important missing features and a big ugly hole to be exploited or just used inefficiently. Instead, I want to see BIS working on the issues that these commands are used to work around.

Though the real security problem is modifying game functions in a out-of-mission-persistent way rather than the remote execution. But remote execution is pretty ugly in itself when you are actually broadcasting the entire code across the network.

As for optional mods, I think with the exception of a few client-side mods (aka sthud, stance indicator), I think it hurts the overall experience more than it helps, compared to a situation where mods are automatically synchronized and you run the same stuff as the server. If the game forced that kind of thing, so many people would have so much trouble saved for them. Right now the only way they can get that is if they close their game and use Play withSIX to connect. Basically, insisting on allowing people to play with different mods is mostly coming from the lack of ability to synchronize them in an easy an automatic way.

As for local executing of scripting commands with global effect, well, that's the entire problem with being able to modify BIS functions in a mission and have them stay modified when you go play other missions, thus allowing you to hack without actually doing anything "hacky" (as in, you're not modifying memory or finding ways to run mods without signatures or whatever the "real hackers" are doing). As long as a mission script can destroy the game's (or even a mod's) functionality in every other mission - We're going to have problems.

Running code on each client just by creating a vehicle is not possible unless the client already had that code, as long as setVehicleInit is removed.

For markers, setMarkerPos is actually global, but has some bugs for JIP players, or at least had (haven't got the chance to test if it was ever actually fixed, I use local markers most of the time and just update them locally to save network traffic, as they usually can simply be updated locally, or are only updated on events I need to publicVariable regardless of the marker update).

Share this post


Link to post
Share on other sites

Basically, if the game's default features use a function, that function should not be possible to modify in a mission in a way that will persist outside of that mission (if it should be possible to modify at all).

They just fixed it.. with compileFinal

Share this post


Link to post
Share on other sites
They just fixed it.. with compileFinal

Yes, I know. I think this is a good step. Should be enough to stop people from hacking without needing to actually hack anything.

Share this post


Link to post
Share on other sites
Yes, I know. I think this is a good step. Should be enough to stop people from hacking without needing to actually hack anything.

Though, there's a flaw in this, in that there's some dynamic variables that are called by BIS functions, that players can compileFinal, and inject code in that way. >.> I'm yet to test this however, but I'll give it a try and find out if BIS made a fancy way for just their function library to be able to overwrite 'final' variables/functions.

Edited by Radioman

Share this post


Link to post
Share on other sites
Though, there's a flaw in this, in that there's some dynamic variables that are called by BIS functions, that players can compileFinal, and inject code in that way. >.>

Please elaborate. Output of compileFinal is fixed code, how do you compileFinal a variable?

Share this post


Link to post
Share on other sites
Please elaborate. Output of compileFinal is fixed code, how do you compileFinal a variable?

BIS could have somewhere in their library, that pulls a variable from the UINamespace, and 'call compile's it. You could compileFinal something into that variable, and then the function will recompile it again. But this isn't very probable, because of the fact that call compile doesn't take 'code' as a parameter, so thus would probably just error out instead.

When I say variable, I mean it loosely. As, in SQF a function is just a variable that contains code, so, they're quite related.

There could be some parts of the library that dynamically create functions and then run them later, so thus, aren't compileFinal. Again, I'll have to do some digging to be sure....

Share this post


Link to post
Share on other sites
BIS could have somewhere in their library, that pulls a variable from the UINamespace, and 'call compile's it. You could compileFinal something into that variable, and then the function will recompile it again. But this isn't very probable, because of the fact that call compile doesn't take 'code' as a parameter, so thus would probably just error out instead.

When I say variable, I mean it loosely. As, in SQF a function is just a variable that contains code, so, they're quite related.

There could be some parts of the library that dynamically create functions and then run them later, so thus, aren't compileFinal. Again, I'll have to do some digging to be sure....

The only times I've seen dynamic call compile used is when people try to dynamically access existing public variable name. This http://killzonekid.com/arma-scripting-tutorials-variables-part-2/ explains about namespaces and why you dont need to do call compile like that. Dynamic on the fly function creation? I wonder under what circumstances you would need it.

Share this post


Link to post
Share on other sites
The only time I've seen dynamic call compile used is when people try to dynamically access existing public variable name. This http://killzonekid.com/arma-scripting-tutorials-variables-part-2/ explains about namespaces and why you dont need to do call compile like that. Dynamic on the fly function creation? I wonder under what circumstances you would need it.

Well exactly, there's no REAL reason to do it that way, but, with BIS, there's no surprises there.

I mean, considering that this virus thing could even happen, I'm not surprised anymore by this mandatory library and how insecure it is....

I'd never do something like what I described, but I've yet to go through ALL these functions and check them.

Share this post


Link to post
Share on other sites
Well exactly, there's no REAL reason to do it that way, but, with BIS, there's no surprises there.

You see I would have agreed with you there months ago when I was deciphering dayz code and looking up BIS_fnc functions. Oh the horror of ArmA 2 BIS library. ArmA 3 BIS library is actually very well written, so something must have drastically changed between then and now. Also the fact that we now have all commands read only and compileFinal says a lot about the direction BIS taking.

Share this post


Link to post
Share on other sites
You see I would have agreed with you there months ago when I was deciphering dayz code and looking up BIS_fnc functions. Oh the horror of ArmA 2 BIS library. ArmA 3 BIS library is actually very well written, so something must have drastically changed between then and now. Also the fact that we now have all commands read only and compileFinal says a lot about the direction BIS taking.

Yes, a newly adopted direction.

Also, the A2 functions are still in A3, so that's still something to worry about.

Share this post


Link to post
Share on other sites

Hello

I read all of this but I'm still a begeinner. After removing processInitCommands and setVehicleInit script simple vehicle respawn (which I use to respawn vehicles) isn't working properly. How should I change this lines of code by BIS_fnc_MP function to make a script working properly.

if (_haveinit) then 
				{_unit setVehicleInit format ["%1;", _unitinit];
				processInitCommands;};
	if (_hasname) then 
				{_unit setVehicleInit format ["%1 = this; this setVehicleVarName ""%1""",_unitname];
				processInitCommands;};
	_dead = false;

I can delete this lines and script will work properly for vehicles without the name, but I need name some vehicles for special functions.

vhole script if it's needed

if (!isServer) exitWith {};

// Define variables
_unit = _this select 0;
_delay = if (count _this > 1) then {_this select 1} else {30};
_deserted = if (count _this > 2) then {_this select 2} else {120};
_respawns = if (count _this > 3) then {_this select 3} else {0};
_explode = if (count _this > 4) then {_this select 4} else {false};
_dynamic = if (count _this > 5) then {_this select 5} else {false};
_unitinit = if (count _this > 6) then {_this select 6} else {};
_haveinit = if (count _this > 6) then {true} else {false};

_hasname = false;
_unitname = vehicleVarName _unit;
if (isNil _unitname) then {_hasname = false;} else {_hasname = true;};
_noend = true;
_run = true;
_rounds = 0;

if (_delay < 0) then {_delay = 0};
if (_deserted < 0) then {_deserted = 0};
if (_respawns <= 0) then {_respawns= 0; _noend = true;};
if (_respawns > 0) then {_noend = false};

_dir = getDir _unit;
_position = getPosASL _unit;
_type = typeOf _unit;
_dead = false;
_nodelay = false;


// Start monitoring the vehicle
while {_run} do 
{	
sleep (2 + random 10);
     if ((getDammage _unit > 0.8) and ({alive _x} count crew _unit == 0)) then {_dead = true};

// Check if the vehicle is deserted.
if (_deserted > 0) then
{
	if ((getPosASL _unit distance _position > 10) and ({alive _x} count crew _unit == 0) and (getDammage _unit < 0.8)) then 
	{
		_timeout = time + _deserted;
		sleep 0.1;
	 	waitUntil {_timeout < time or !alive _unit or {alive _x} count crew _unit > 0};
		if ({alive _x} count crew _unit > 0) then {_dead = false}; 
		if ({alive _x} count crew _unit == 0) then {_dead = true; _nodelay =true}; 
		if !(alive _unit) then {_dead = true; _nodelay = false}; 
	};
};

// Respawn vehicle
     if (_dead) then 
{	
	if (_nodelay) then {sleep 0.1; _nodelay = false;} else {sleep _delay;};
	if (_dynamic) then {_position = getPosASL _unit; _dir = getDir _unit;};
	if (_explode) then {_effect = "M_AT" createVehicle getPosASL _unit; _effect setPosASL getPosASL _unit;};
	sleep 0.1;

	deleteVehicle _unit;
	sleep 2;
	_unit = _type createVehicle _position;
	_unit setPosASL _position;
	_unit setDir _dir;

	if (_haveinit) then 
				{_unit setVehicleInit format ["%1;", _unitinit];
				processInitCommands;};
	if (_hasname) then 
				{_unit setVehicleInit format ["%1 = this; this setVehicleVarName ""%1""",_unitname];
				processInitCommands;};
	_dead = false;

	// Check respawn amount
	if !(_noend) then {_rounds = _rounds + 1};
	if ((_rounds == _respawns) and !(_noend)) then {_run = false;};
};
};

I think missionmakers need solution for this.

Share this post


Link to post
Share on other sites
Hello

I read all of this but I'm still a begeinner. After removing processInitCommands and setVehicleInit script simple vehicle respawn (which I use to respawn vehicles) isn't working properly. How should I change this lines of code by BIS_fnc_MP function to make a script working properly.

if (_haveinit) then 
				{_unit setVehicleInit format ["%1;", _unitinit];
				processInitCommands;};
	if (_hasname) then 
				{_unit setVehicleInit format ["%1 = this; this setVehicleVarName ""%1""",_unitname];
				processInitCommands;};
	_dead = false;

I can delete this lines and script will work properly for vehicles without the name, but I need name some vehicles for special functions.

vhole script if it's needed

if (!isServer) exitWith {};

// Define variables
_unit = _this select 0;
_delay = if (count _this > 1) then {_this select 1} else {30};
_deserted = if (count _this > 2) then {_this select 2} else {120};
_respawns = if (count _this > 3) then {_this select 3} else {0};
_explode = if (count _this > 4) then {_this select 4} else {false};
_dynamic = if (count _this > 5) then {_this select 5} else {false};
_unitinit = if (count _this > 6) then {_this select 6} else {};
_haveinit = if (count _this > 6) then {true} else {false};

_hasname = false;
_unitname = vehicleVarName _unit;
if (isNil _unitname) then {_hasname = false;} else {_hasname = true;};
_noend = true;
_run = true;
_rounds = 0;

if (_delay < 0) then {_delay = 0};
if (_deserted < 0) then {_deserted = 0};
if (_respawns <= 0) then {_respawns= 0; _noend = true;};
if (_respawns > 0) then {_noend = false};

_dir = getDir _unit;
_position = getPosASL _unit;
_type = typeOf _unit;
_dead = false;
_nodelay = false;


// Start monitoring the vehicle
while {_run} do 
{	
sleep (2 + random 10);
     if ((getDammage _unit > 0.8) and ({alive _x} count crew _unit == 0)) then {_dead = true};

// Check if the vehicle is deserted.
if (_deserted > 0) then
{
	if ((getPosASL _unit distance _position > 10) and ({alive _x} count crew _unit == 0) and (getDammage _unit < 0.8)) then 
	{
		_timeout = time + _deserted;
		sleep 0.1;
	 	waitUntil {_timeout < time or !alive _unit or {alive _x} count crew _unit > 0};
		if ({alive _x} count crew _unit > 0) then {_dead = false}; 
		if ({alive _x} count crew _unit == 0) then {_dead = true; _nodelay =true}; 
		if !(alive _unit) then {_dead = true; _nodelay = false}; 
	};
};

// Respawn vehicle
     if (_dead) then 
{	
	if (_nodelay) then {sleep 0.1; _nodelay = false;} else {sleep _delay;};
	if (_dynamic) then {_position = getPosASL _unit; _dir = getDir _unit;};
	if (_explode) then {_effect = "M_AT" createVehicle getPosASL _unit; _effect setPosASL getPosASL _unit;};
	sleep 0.1;

	deleteVehicle _unit;
	sleep 2;
	_unit = _type createVehicle _position;
	_unit setPosASL _position;
	_unit setDir _dir;

	if (_haveinit) then 
				{_unit setVehicleInit format ["%1;", _unitinit];
				processInitCommands;};
	if (_hasname) then 
				{_unit setVehicleInit format ["%1 = this; this setVehicleVarName ""%1""",_unitname];
				processInitCommands;};
	_dead = false;

	// Check respawn amount
	if !(_noend) then {_rounds = _rounds + 1};
	if ((_rounds == _respawns) and !(_noend)) then {_run = false;};
};
};

I think missionmakers need solution for this.

Simple Vehicle Respawn Script v1.81 for Arma 3 by Tophe

It is fixed see :-

http://forums.bistudio.com/showthread.php?147890-Simple-Vehicle-Respawn-Script-Arma3/page5

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  

×