Jump to content

[Release] Andre Safe Zones


Donnovan

Recommended Posts

Main post updated on how to exec the script in init.sqf:

You must run from the root (not inside a isServer or !isServer or any other condition):

execVM "andre_safezone.sqf"; //exec it on the root on init.sqf

if (isServer) then {
    //code 1...
    //code 2...
    //code 3...
    //DO NOT EXEC IT HERE!
} else {
    //code 4...`
    //code 5...
    //code 6...
    //DO NOT EXEC IT HERE!
};
Link to comment
Share on other sites

Ok, call compiling something that anybody can set its bad. As you provide an Remote Execution exploit.
 

This trader protection thing can be done allot neater with Triggers and not to have 4+ spawned loops on EVERY player.
I have no doubt code actually works but its not all in that. Its really not optimized, and RE potential in it is really bad.

Suggestion:

Remake it with Triggers. As well there is no need to PV anything here. Maybe an array of objects in a trader but i dont really thing server needs to do anything with it.
And please dont spawn 4+ threads with while{true} in them. even if you have a sleep its a bad practice to do so. 

Link to comment
Share on other sites

Ok, call compiling something that anybody can set its bad. As you provide an Remote Execution exploit.

<snip>

 

 

ok this went overboard...

 

call compile format ['don_%1 = nil;', don_player_veh getVariable ['don_ownerity_code', 0]];
don_player_veh setVariable ['don_ownerity_code', nil, true];

do you see an issue here?

 

Call compiling allows easy manipulation (and querying) of variably-named variables; from a new scripter's perspective it's easy and it works.

If a security issue would be good to use a better method of course.

 

What's the better method though?

Can you give us any references how to handle this better?

Link to comment
Share on other sites

Thankyou for the help mgm,

 

This code set on the client a variable with the initial time of the 480 seconds countdown for each protected vehicle the client have tried to invade in the safezone. The suggestion for the variable name is in a variable set on the vehicle when its gained protection. This variable is set on the client, with the suggested unique name, and have the client diag_tickTime time of the first invasion try.

 

BTW...

 

I believe it can be done this other way:

 

Only one timer per vehicle, on the server side.

 

Client:

When the client try to invade a protected vehicle, he, the client, send to the server (publicVariableServer) the ask to iniciate the 480 seconds counter to liberate the vehicle.

 

Server:

The server spawn a thread that waits for 480 seconds and then clean the vehicles variables related to protection. With those variables cleaned, the vehicle have no more protection.

Link to comment
Share on other sites

Thankyou for the help mgm,

 

This code it to set on the client a variable with the initial time of the 480 seconds countdown for each protected vehicle the client have tried to invade in the safezone. The suggestion for the variable name is in a variable set on the vehicle when its gained protection. This variable is set on the client, with the suggested unique name, and have the client diag_tickTime time of the first invasion try.

 

BTW...

 

I believe it can be done this other way:

 

Only one timer per vehicle, on the server side.

 

Client:

When the client try to invade a protected vehicle, he, the client, send to the server (publicVariableServer) the ask to iniciate the 480 seconds counter to liberate the vehicle.

 

Server:

The server spawn a thread that waits for 480 seconds and then clean the vehicles variables related to protection. With those variables cleaned, the vehicle have no more protection.

spawn-and-forget is a quick and easy way to write things what you just said in the last line looks good to me.

 

Experienced scripters don't seem to be a big fan of spawning things though. They want scripter to juggle 50 things like a pro from within same thread.

Link to comment
Share on other sites

Ok, here is a quick sum up of all the bad things in this code. Do with it whatever you see fit.

 

  • Creating MANY spawns (threads) when a single one could do all the work (clientside)
  • Multiple levels of indentation, breaking it up into smaller functions would help everyone (maintain the code, understand it and edit it if needed).
  • Call compile anything is dangerous!
  • Creating multiple loops, could be replace with a single loop or use triggers. (if your heart is set on loops :P)
  • Using while instead of waituntil. You can put code inside a waituntil, just needs to return a bool.
  • Using many global variables. Good practice in programming, you should avoid polluting the global namespace, potentially introduction name collisions.

Good Luck :D

Link to comment
Share on other sites

You is not helping in anything nor contributing. Those changes demands a completelly new script. My idea can't be done with less threads. May be about global variables i can save something from your post.

 

And about name colisions, don't you noticed i put a donn_ on the global variables?

 

You is a intelligent poerson, at least a smart person, but talking like a journal horoscope with tips for life sound really idiot.

Link to comment
Share on other sites

  • Using while instead of waituntil. You can put code inside a waituntil, just needs to return a bool.

If you look the code you will see that waitUntil {sleep 0.25;speed player > 1};. Its not a big code, but enough to you understand that i'm not using while due to lack of knowledge about how waitUntil works.

Link to comment
Share on other sites

easy donn. he is only trying to help. if you don't like his tips that's fine but don't call him an idiot for that lol

keep up the good work and chill

Ok.

Thankyou for you help, maca134.

Why triggers are better than spawn? Triggers are a secondary thread, like spawn.

How a trigger run code? With something very similar, if not a spawn.

What is a trigger if not a spawn loop with regular check?

So about having a spawn or a trigger, i see no difference at all. It's a personal preference until tests are done, and i don't believe those tests worth to do for me. Its my opinion. But i never will deprecate others works because it's not done in the way i believe is better.

At the end, the number of threads will be the same. There is no "everything in a single thread". The engine will generate its threads, if not by sqf spawn, by sensors.

Link to comment
Share on other sites

Code within triggers gets executes in the non-scheduled environment so doesnt create any threads

So another approach, maybe have 1 spawn running the code needed for the safezone stuff (maybe 2 if absolutely necessary).

Use a waitUntil {uiSleep 1; SOME_GLOBAL_VAR};
Use local triggers to set/unset on/off vars when the player enters and leaves the safezone.

 

Something like this, only creates 1-2 spawns.

Link to comment
Share on other sites

Ok.

Thankyou for you help, maca134.

Why triggers are better than spawn? Triggers are a secondary thread, like spawn.

How a trigger run code? With something very similar, if not a spawn.

What is a trigger if not a spawn loop with regular check?

So about having a spawn or a trigger, i see no difference at all. It's a personal preference until tests are done, and i don't believe those tests worth to do for me. Its my opinion. But i never will deprecate others works because it's not done in the way i believe is better.

At the end, the number of threads will be the same. There is no "everything in a single thread". The engine will generate its threads, if not by sqf spawn, by sensors.

Hey Don,

 

How are you doin. I was on the forums at BI and read about a security improvement. I remembered your code had the same so I came here now to share with you my finding. The last guy tried to help you still recovering in hospital but I am adventureous like that so let's see how you'll take this information share lol

 

In summary, your code has call compile format and all these guys (also here) saying that it's generally not a good thing and it's definitely slower than its drop-in replacement so there's no reason to use call compile and should be replaced with missionnamespace getvariable. something along the same lines about 5 weeks ago but at the time I couldn't comprehend what he was talking about (i see now).

so my improvement suggestion to you is, change it as per above.

 

 

 

Here is a live example, I just moved my call compile code 2 seconds ago and tested it's working as expected.

 

old code

_SUCurrentTaskAgeInSecondsNumber = call compile format ["mgmTfA_gv_PV_SU%1SUCurrentTaskAgeInSecondsNumber", _myGUSUIDNumber];

new code

_SUCurrentTaskAgeInSecondsNumber = missionnamespace getvariable [format ["mgmTfA_gv_PV_SU%1SUCurrentTaskAgeInSecondsNumber",_myGUSUIDNumber], []];

hope this helps...

Link to comment
Share on other sites

Some few changes are needed to make it compatible with infiStar: remove custom Fired Event Handlers and use infiStar variable inSafeZone = true and inSafeZone = false.

 

Thankyou Ace22 for the help on tests.

 

infiStar version: if some problem is found, please tell me.

//===============
// KONFIGURATION
//===============

//Altis Safezones
donn_traders = [
	["Altis Trader City 1",[13323,14527,0]],
	["Altis Trader City 2",[6177,16835,0]],
	["Altis Trader City 3",[18460,14259,0]]
];

//====================
// CLIENT SIDE SCRIPT
//====================

if (hasInterface) then {
	//SENSORS
	donn_notSafe = true;
	donn_safeZone_name = "(nothing)";
	{
		_x spawn {
			private ["_dist","_tPos","_tName","_maxVel","_tRad"];
			_tName = _this select 0;
			_tPos = _this select 1;
			_maxVel = 100;
			_tRad = 250;
			waitUntil {sleep 0.25;speed player > 1};
			while {true} do {
				_dist = player distance _tPos;
				while {_dist > 150} do {
					sleep ((((_dist - _tRad)/_maxVel) max 0.25) min 5);
					_dist = player distance  _tPos;
				};
				donn_notSafe = false;
				inSafeZone = true; //NEW LINE 1
				donn_safeZone_name = _tName;
				systemChat ("You are in safezone city: " + _tName);
				while {_dist < 150} do {
					sleep 0.25;
					_dist = player distance _tPos;
				};
				donn_notSafe = true;
				inSafeZone = false; //NEW LINE 2
				donn_safeZone_name = "(nenhuma)";
				systemChat ("You leaved safezone city: " + _tName);
			};
		};
	} forEach donn_traders;

	//Safe zone Functions
	donn_avoidGearAccess = {
		_protecting = [];
		_toProtect = donn_pv_protected_veh select 1;
		_toUnprotect = [];
		_protectVersion = donn_pv_protected_veh select 0;
		while {!donn_notSafe} do {
			{
				_x addEventHandler ["ContainerOpened", {
					_veh = _this select 0;
					_player = _this select 1;
					_veh_crew = _veh getVariable ['don_crew', nil];
					if (isNil '_veh_crew') then {_veh_crew = [getPlayerUID _player];};
					_groupUnits = units _player;
					_canAccess = false;
					{
						if (getPlayerUID _x in _veh_crew) then {
							_canAccess = true;
						};
					} forEach _groupUnits;
					if (!_canAccess)then {
						systemChat format ['%1, you cant access this gear.', name _player];
						_player action ["Gear", objNull];
					};
				}];
			} forEach _toProtect;
			{
				_x removeAllEventHandlers "ContainerOpened";
			} forEach _toUnprotect;
			_protecting = _protecting + _toProtect - _toUnprotect;
			waitUntil {sleep 0.2;donn_pv_protected_veh select 0 > _protectVersion};
			_toProtect = (donn_pv_protected_veh select 1) - _protecting;
			_toUnprotect = _protecting - (donn_pv_protected_veh select 1);
		};
		{
			_x removeAllEventHandlers "ContainerOpened";
		} forEach _protecting;
	};
	
	//Safezone
	don_incar = false;
	donn_godMode = false;
	[] spawn {
		private ['_runOneTime','_donn_notSafe','_don_passengers','_don_veh_crew','_don_player_veh','_don_veh_driver'];
		waitUntil {!(isNil 'donn_notSafe')};
		_runOneTime = false;
		_donn_notSafe = donn_notSafe;
		while {true} do {
			waitUntil {!((_donn_notSafe && donn_notSafe) || (!_donn_notSafe && !donn_notSafe)) || !_runOneTime};
			_donn_notSafe = donn_notSafe;
			if (!_donn_notSafe) then {
				//Player God Mode
				player allowDamage false;
				donn_godMode = true;
				
				//Protect Player Gear
				donn_pv_protected_veh_add = player;
				publicVariableServer "donn_pv_protected_veh_add";
				
				//Avoid player to access other Gears (turn off is automatic)
				[] spawn donn_avoidGearAccess;
			};
			if (_donn_notSafe && _runOneTime) then {
				//Player God Mode Off
				player allowDamage true;
				donn_godMode = false;
				
				//Clear Player Gear Protection
				donn_pv_protected_veh_sub = player;
				publicVariableServer "donn_pv_protected_veh_sub";
			};
			if (!_donn_notSafe && don_incar) then {
				
				//Get Info
				_don_player_veh = don_player_veh;
				don_veh_crew = crew _don_player_veh;
				_don_veh_driver = driver _don_player_veh;
				
				if (player == _don_veh_driver) then {
					//Car God Mode
					_don_player_veh allowDamage false;
					_don_player_veh removeAllEventHandlers 'handleDamage';
					_don_player_veh addEventHandler ['handleDamage', {0}];
					_don_player_veh removeAllEventHandlers 'Fired';
					_don_player_veh addEventHandler ['Fired',{deleteVehicle (_this select 6);}];
					
					//Passenger Names
					_don_passengers = '';
					{if (alive _x) then {_don_passengers = _don_passengers + format [' %1',name _x];};} forEach don_veh_crew;
					
					//Passenger PlayerUID
					_don_veh_crew = [];
					{if (alive _x) then {_don_veh_crew = _don_veh_crew + [getPlayerUID _x];};} forEach don_veh_crew;

					//Put info on Vehicle
					_don_player_veh setVariable ['don_ownerity_code', format ['%1_%2', getPlayerUID player, round diag_tickTime], true];
					_don_player_veh setVariable ['don_crew', _don_veh_crew, true];
					_don_player_veh setVariable ['don_passengers', _don_passengers, true];

					//Protect Vehicle Gear
					donn_pv_protected_veh_add = _don_player_veh;
					publicVariable "donn_pv_protected_veh_add";
				};
				
			};
			if (_donn_notSafe && don_incar && _runOneTime) then {
				
				//Get Info
				_don_player_veh = don_player_veh;
				_don_veh_driver = driver _don_player_veh;			
				
				if (player == _don_veh_driver) then {
					//Clear Vehicle Protection Variables
					_don_player_veh setVariable ['don_ownerity_code', nil, true];
					_don_player_veh setVariable ['don_crew', nil, true];
					_don_player_veh setVariable ['don_passengers', nil, true];
				
					//Car God Mode Off
					_don_player_veh allowDamage true;
					_don_player_veh removeAllEventHandlers 'handleDamage';
					_don_player_veh removeAllEventHandlers 'Fired';
					
					//Clear Vehicle Gear Protection
					donn_pv_protected_veh_sub = _don_player_veh;
					publicVariableServer "donn_pv_protected_veh_sub";
				};
			};
			_runOneTime = true;
		};
	};
	[] spawn {
		private ['_don_veh_crew','_wait_time','_last_mark','_max_time'];
		while {true} do {
			_max_time = 480;
			waitUntil {sleep 0.0625; vehicle player != player};
			don_player_veh = vehicle player;
			don_incar = true;
			if (!donn_notSafe) then {
				_don_veh_crew = don_player_veh getVariable ['don_crew', nil];
				if (isNil '_don_veh_crew') then {_don_veh_crew = [getPlayerUID player];};
				_groupUnits = units player;
				_canAccess = false;
				{
					if (getPlayerUID _x in _don_veh_crew) then {
						_canAccess = true;
					};
				} forEach _groupUnits;
				if (!_canAccess) then {
					call compile format ['if (isNil ''don_%1'') then {don_%1 = diag_tickTime;}; _last_mark = don_%1;', don_player_veh getVariable ['don_ownerity_code', 0]];
					_wait_time = diag_tickTime - _last_mark;
					if (_wait_time < _max_time) then {
						while {player != vehicle player} do {
							player action ['getOut', don_player_veh];
							uiSleep 0.01;
						};
						cuttext [format ['Owners:%1. %2 seconds to liberate.', don_player_veh getVariable ['don_passengers','Owners not found'], round (_max_time - _wait_time)], 'PLAIN DOWN'];
						cad_pvar_smessage = [format ['%1 is messing with your vehicle! %2 seconds to liberate!', name player, round (_max_time - _wait_time)], _don_veh_crew];
						publicVariable 'cad_pvar_smessage';
					} else {
						call compile format ['don_%1 = nil;', don_player_veh getVariable ['don_ownerity_code', 0]];
						don_player_veh setVariable ['don_ownerity_code', nil, true];
						don_player_veh setVariable ['don_crew', nil, true];
						don_player_veh setVariable ['don_passengers', nil, true];
						cuttext [format ['Vehicle is now free for all!'], 'PLAIN DOWN'];
						cad_pvar_smessage = [format ['Vehicle invaded by %1!', name player], _don_veh_crew];
						publicVariable 'cad_pvar_smessage';
					};
				};
				don_player_veh allowDamage false;
				don_player_veh removeAllEventHandlers 'handleDamage';
				don_player_veh addEventHandler ['handleDamage', {0}];
				don_player_veh removeAllEventHandlers 'Fired';
				don_player_veh addEventHandler ['Fired',{deleteVehicle (_this select 6);}];
			};
			if (donn_notSafe) then {
				don_player_veh allowDamage true;
				don_player_veh removeAllEventHandlers 'handleDamage';
				don_player_veh removeAllEventHandlers 'Fired';
				if (player == driver don_player_veh) then {
					don_player_veh setVariable ['don_ownerity_code', nil, true];
					don_player_veh setVariable ['don_crew', nil, true];
					don_player_veh setVariable ['don_passengers', nil, true];
				};
			};
			waitUntil {sleep 0.0625; vehicle player == player};
			don_incar = false;
			don_player_veh = nil;
		};
	};
	//Remote Mensages
	'cad_pvar_smessage' addPublicVariableEventHandler {
		private ['_message', '_receivers'];
		_message = (_this select 1) select 0; _receivers = (_this select 1) select 1;
		if (getPlayerUID player in _receivers) then {cutText [_message, 'PLAIN DOWN'];};
	};
	diag_log "! SAZON OK !";
};

//=============
// SERVER SIDE
//=============
if (isServer) then {
	//DONN SaZon Protected Veh
	donn_pv_protected_veh = [0,[]];
	publicVariable "donn_pv_protected_veh";
	"donn_pv_protected_veh_add" addPublicVariableEventHandler {
		donn_pv_protected_veh set [0,(donn_pv_protected_veh select 0) + 1];
		donn_pv_protected_veh set [1,(donn_pv_protected_veh select 1) + [_this select 1]];
		publicVariable "donn_pv_protected_veh";
		diag_log ("[SAZON] Added veh to protection: " + str (_this select 1));
	};
	"donn_pv_protected_veh_sub" addPublicVariableEventHandler {
		donn_pv_protected_veh set [0,(donn_pv_protected_veh select 0) + 1];
		donn_pv_protected_veh set [1,(donn_pv_protected_veh select 1) - [_this select 1]];
		publicVariable "donn_pv_protected_veh";
		diag_log ("[SAZON] Deadded veh to protection: " + str (_this select 1));
	};
};
Link to comment
Share on other sites

Next change, thanks to Ace(11+11). He gave me the function for that: Avoid vehicles to be stolen by rope.

no idea how this 'rope' works but sure sounds good to be protected against it! you're doing a good job with constant updates.
Link to comment
Share on other sites

Thanks to Donavan for letting TeamPlayerGaming help him test this. He helped Ace 22 get this tested out and ready to go. It has been running on our server for almost a week with no noticable loss in performance.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...