Jump to content

[TuT] Removing Unnecessary updates and functions in server_updateObject.sqf


Guest

Recommended Posts

Introducion

 

I was looking into a Problem, where the FPS drops, when players enter a City or any Place with a large amount of Objects placed. After fushing around a while i have noticed, that actually ALL Objects are being updated. This includes houses, cras cutters, bins and fences, as also Modular Buildings like Wooden Walls. So my thought was, that counting and updating all of those Objects may result in a massive Server Load. For testing purposes i made up an array with all arma2 Buildings and a check to not Update those. Result: All of these Objects where un-breakable, can't be killed or damaged anymore. Also a slight FPS increase, but nothing really "breaking".

 

 

Before we Start

 

You must notice, that these changes make all Objects invincible. Also it is highly recommended to create a Backup, before you start editing.

Requierements:
- PBO Manager (For editing Server Files)
- A custom "variables.sqf" in you Mission Folder

 

 

 

Setting up the Variable for Objects that should not be updated (Client side)

 

These Changes are made in the variables.sqf, located in your Mission Folder.

 

What you want to find and where we add our array is in the if(isServer) then {}; - section.

Find:

needUpdate_objects = [];

And place under that:

dontUpdate_objects = ["ClutterCutter_EP1","Desk","FoldChair","FoldTable","Park_bench1","Park_bench2","Park_bench2_noRoad","SmallTable","WoodChair","Axe_woodblock","Barrel1","Barrel4","Barrel5","Barrels","Fuel_can","Garbage_can","Garbage_container","Haystack","Haystack_small",
						  "HeliH","HeliHCivil","HeliHRescue","Land_Barrel_empty","Land_Barrel_sand","Land_Barrel_water","Land_Ind_BoardsPack1","Land_Ind_BoardsPack2","Land_Pneu","Land_ladder","Land_ladder_half","Misc_TyreHeap","Misc_concrete_High","Misc_palletsfoiled","Misc_palletsfoiled_heap",
						  "Notice_board","Paleta1","Paleta2","Pile_of_wood","Satelit","Sr_border","BMP2Wreck","BRDMWreck","HMMWVWreck","LADAWreck","Land_BoatSmall_1","Land_BoatSmall_2a","Land_BoatSmall_2b","Mi8Wreck","SKODAWreck","T72Wreck","T72WreckTurret","UAZWreck","UH1Wreck","UralWreck",
						  "datsun01Wreck","datsun02Wreck","hiluxWreck","Baseball","Can_small","EvDogTags","EvKobalt","EvMap","EvMoney","EvMoscow","EvPhoto","Explosive","FloorMop","Loudspeaker","MetalBucket","Misc_Videoprojektor","Misc_Videoprojektor_platno","Misc_Wall_lamp","Notebook",
						  "Radio","SatPhone","SkeetDisk","SkeetMachine","SmallTV","Suitcase","bomb","Body","Grave","Hanged","Hanged_MD","Mass_grave","Land_Bench_EP1","Land_Cabinet_EP1","Land_Carpet_2_EP1","Land_Carpet_EP1","Land_Chair_EP1","Land_Chest_EP1","Dirtmount_EP1","Land_Crates_EP1",
						  "Land_Dirthump01_EP1","Land_Dirthump02_EP1","Land_Dirthump03_EP1","Land_Misc_Coil_EP1","Land_bags_EP1","C130J_wreck_EP1","UH60_wreck_EP1","Land_Bag_EP1","Land_Basket_EP1","Land_Blankets_EP1","Land_Boots_EP1","Land_Bowl_EP1","Land_Bucket_EP1","Land_Canister_EP1",
						  "Land_Pillow_EP1","Land_Rack_EP1","Land_Reservoir_EP1","Land_Sack_EP1","Land_Shelf_EP1","Land_Table_EP1","Land_Table_small_EP1","Land_Teapot_EP1","Land_Urn_EP1","Land_Vase_EP1","Land_Vase_loam_2_EP1","Land_Vase_loam_3_EP1","Land_Vase_loam_EP1","Land_Water_pipe_EP1",
						  "Land_Wheel_cart_EP1","Land_Wicker_basket_EP1","Land_stand_waterl_EP1","Land_sunshade_EP1","Land_tires_EP1","Microphone1_ep1","Microphone2_ep1","Microphone3_ep1","Misc_Backpackheap_EP1","Misc_TyreHeapEP1","Sign_sphere100cm_EP1","Sign_sphere10cm_EP1","Sign_sphere25cm_EP1"];

 

 

 

Changing server_updateObject.sqf

These changes are made in dayz_server.pbo\compiles\server_updateObject.sqf - This does not effect any custom mods you might have installed, for example the Vehicle Key (thanks, sir - that thing is awesome).

 

 

The very first to do, if not done already is: Create a Backup!

 

Now we're going to add our array, so these objects don't take damage, won't get killed and will never be updated. (If you have Plot Maintainance on, do not use Modular Buildings in your dont_update array.

Find (for me Line 52):

_lastUpdate = _object getVariable ["lastUpdate",time];

And place under that:

if (_object in dontUpdate_objects) then {_needUpdate = false;};

Well that was simple, wasn't it? If interested in removing unneccessary functions, proceed to the next Spoiler. If not, just leave as is and save / upload. This is finished already

 

 

 

Removing unnecessary Functions

 

This is yet still not effecting any mods (not so far i know) - but will result in a faster update of objects, because first of all we'll be using "if", instead of "switch" (If is concidered to be much faster, then switch) and secondary, we will use one function for all Hitpoint actions such as "killed", "damage" or "repair".

 

 

This is requirering a little bit of commenting out certain functions with /** and **/. If you wish so, you can delete the whole functions. I will not go further into this, as this requieres a total of 12 Characters being placed and, if you can't manage that sorry but then you should not run a server.

 

Find the Function "_object_damage" and comment it out to (including) "_object_repair". If you now did not comment out 3 Functions, search for the functions mentioned above, also for "_object_killed" and comment them out.

Next comment out the whole switch located at your bottom. If this is not a total of 31 Lines, you might have a custom mod installed, i will only cover the vehicle key in this, so you might have to add a few lines manually.

Above the switch, IF USE VEHICLE KEY, paste:

/** We're using IF, instead of SWITCH... **/
/** We shall Update all Object Parts **/
if (_type == "all") then {
	call _object_position;
	call _object_inventory;
	[_type] call _object_hitpoints;
};

/** We shall Update the Position **/
if (_type == "position") then {
	if (!(_object in needUpdate_objects)) then {
		//diag_log format["DEBUG Position: Added to NeedUpdate=%1",_object];
		needUpdate_objects set [count needUpdate_objects, _object];
	};
};

/** We shall Update the Gear **/
if (_type == "gear") then {
	call _object_inventory;
};

/** We shall Update the Damage **/
if (_type == "damage") then {
	if ( (time - _lastUpdate) > 5) then {
		[_type] call _object_hitpoints;
	} else {
		if (!(_object in needUpdate_objects)) then {
			//diag_log format["DEBUG Damage: Added to NeedUpdate=%1",_object];
			needUpdate_objects set [count needUpdate_objects, _object];
		};
	};
};

/** We can use one function for this **/
if (_type == "killed" || _type == "repair") then {
	[_type] call _object_hitpoints;
};

/** We shall Update the Vehicle Key **/
if (_type == "vehiclekey") then {
	_activatingPlayer = _this select 2;
	_vehicleClassname = _this select 3;
	_toKey = _this select 4;
	_toKeyName = _this select 5;
	_vehicle_ID = _this select 6;
	_vehicle_UID = _this select 7;
	[_activatingPlayer, _vehicleClassname, _toKey, _toKeyName, _vehicle_ID, _vehicle_UID] call _object_vehicleKey; //One Semicolon to much?
};

Note: If this is not under "_object setVariable ["lastUpdate",time,true];" you have done something wrong. If not using vehicle key, then just remove the last IF.

 

 

Now go to the functions you commented out and place above them:

_object_hitpoints = {
	private["_hitpoints","_array","_hit","_selection","_key","_damage","_updateType"];
	
	_updateType = _this select 0;
	_hitpoints = _object call vehicle_getHitpoints;
	if (_updateType != "killed") then {_damage = damage _object;} else {_damage = 1;};
	_array = [];
	{
		_hit = [_object,_x] call object_getHit;
		_selection = getText (configFile >> "CfgVehicles" >> (typeOf _object) >> "HitPoints" >> _x >> "name");
		if (_hit > 0) then {_array set [count _array,[_selection,_hit]]};
		if (_updateType == "killed") then {_hit = 1;};
		_object setHit ["_selection", _hit]
	} forEach _hitpoints;
		
	if (_objectID == "0") then {
		_key = format["CHILD:306:%1:%2:%3:",_uid,_array,_damage];
	} else {
		_key = format["CHILD:306:%1:%2:%3:",_objectID,_array,_damage];
	};
	
	_key call server_hiveWrite;
	_object setVariable ["needUpdate",false,true];
		
};



Keep in mind, that you can customize the array of object, that should not be updated by simply adding or removing an object, but please note: DO NOT, AT NO TIME, NEVER put Objects like Doors, Safes or other Objects that requiere some sort of action - in that array. Reason: As you for example open a Door, the State well more likely the "position" of the door is being updated, forcing the door to actually open. If you forbid this, you obviously can't open Doors anymore. This does not effect Objects like for example Loot, Stairs, Ladders, etc..

Link to comment
Share on other sites

With special thanks to Schwede, i also found, that Objects are being updated, even if an update i not needed at all. Due to his logs (Thank you very much!) i came up with a new way to update the Objects, by comparing, if the Object really needs an Update or not.

Note: This is absolutely untested, i do not know, if this works!

//EDIT: This seems to fix an issue, where you have to Unlock vehicles twice, but that could be only me and is tested on 2 vehicles only..

 

Updating server_updateObject.sqf to set new Variables for comparison

 

This will simply create new Variables and attach them to the Object, as this seems to be the best way to compare, if old or new.

 

 

Under "// TODO ----------------------" find:

_object setVariable ["lastUpdate",time,true];

And replace with:

_object setVariable ["lastUpdate",time,true];
_object setVariable ["lastPosition",(getPosATL _object),true];
_object setVariable ["lastHitpoints",(_object call vehicle_getHitpoints),true];

Note: Those variables ar found UNDER the Functions (_object_inventory, _object_hitpoints etc)..

 

 

 

Updating the server_functions.sqf, to check if an Update is actually needed

 

This will effect Zupa's single Currency if installed. Also this is completely untested and i did not remove the Logs out of this..

 

Find "vehicle_handleInteract" and, if using ZSC replace the whole function with this:

/** This function Updates all - Damage, Position and Gear. - Is this really necessary?? **/
vehicle_handleInteract = {
	private["_object","_lastPosition","_lastInventory","_lastHitpoints","_inventory","_position","_hitpoints"];
	_object = _this select 0;
	
	/** Let's get the last Updates in Inventory and Position **/
	_lastPosition = _object getVariable ["lastPosition"];
	_lastInventory = _object getVariable ["lastInventory",[]];
	_lastHitpoints = _object getVariable ["lastHitpoints"];
	
	/** Getting the current Inventory and Position, for comparison **/ 
	_inventory = [
			getWeaponCargo _object,
			getMagazineCargo _object,
			getBackpackCargo _object,
			_object getVariable["bankMoney",0]
			];
			
	_position = getPosATL _object;
	
	_hitpoints = _object call vehicle_getHitpoints;
	
	
	/** Let's remove the Object from the List outside the IF, to prevent "double" removing, when 2 IF's a true.. **/
	/** Also this must happen before we check, because otherwise it will be doubled, when calling server_updateObject **/
	diag_log format["Removed Object %1 from List", _object];
	needUpdate_objects = needUpdate_objects - [_object];
	
	/** Next we compare our results and check, if a Update is really required. **/
	/** Compare Position **/
	if (!(_lastPosition == _position)) then {
		diag_log format["Updating Position of %1", _object];
		[_object, "position"] call server_updateObject;
	};
	
	/** Compare Inventory **/
	if (!(_lastInventory == _inventory)) then {
		diag_log format["Updating Gear of %1", _object];
		[_object, "gear"] call server_updateObject;
	};
	
	/** Compare Hitpoints **/
	if (!(_lastHitpoints == _hitpoints)) then {
		diag_log format["Updating Hitpoints of %1", _object];
		[_object, "damage"] call server_updateObject;
	};
	
	//needUpdate_objects = needUpdate_objects - [_object];
	//[_object, "all"] call server_updateObject;
};

IF NOT using ZSC, replace with this:
 

/** This function Updates all - Damage, Position and Gear. - Is this really necessary?? **/
vehicle_handleInteract = {
	private["_object","_lastPosition","_lastInventory","_lastHitpoints","_inventory","_position","_hitpoints"];
	_object = _this select 0;
	
	/** Let's get the last Updates in Inventory and Position **/
	_lastPosition = _object getVariable ["lastPosition"];
	_lastInventory = _object getVariable ["lastInventory",[]];
	_lastHitpoints = _object getVariable ["lastHitpoints"];
	
	/** Getting the current Inventory and Position, for comparison **/ 
	_inventory = [
			getWeaponCargo _object,
			getMagazineCargo _object,
			getBackpackCargo _object
			];
			
	_position = getPosATL _object;
	
	_hitpoints = _object call vehicle_getHitpoints;
	
	
	/** Let's remove the Object from the List outside the IF, to prevent "double" removing, when 2 IF's a true.. **/
	/** Also this must happen before we check, because otherwise it will be doubled, when calling server_updateObject **/
	diag_log format["Removed Object %1 from List", _object];
	needUpdate_objects = needUpdate_objects - [_object];
	
	/** Next we compare our results and check, if a Update is really required. **/
	/** Compare Position **/
	if (!(_lastPosition == _position)) then {
		diag_log format["Updating Position of %1", _object];
		[_object, "position"] call server_updateObject;
	};
	
	/** Compare Inventory **/
	if (!(_lastInventory == _inventory)) then {
		diag_log format["Updating Gear of %1", _object];
		[_object, "gear"] call server_updateObject;
	};
	
	/** Compare Hitpoints **/
	if (!(_lastHitpoints == _hitpoints)) then {
		diag_log format["Updating Hitpoints of %1", _object];
		[_object, "damage"] call server_updateObject;
	};
	
	//needUpdate_objects = needUpdate_objects - [_object];
	//[_object, "all"] call server_updateObject;
};

Link to comment
Share on other sites

will test this, and tell the results (the NOT SC Version!)

Nice work, Kollege :)

I just noticed a smal issue:

 

/** Compare Inventory **/
	if (!(_lastInventory == _hitpoints)) then {
		diag_log format["Updating Gear of %1", _object];
		[_object, "gear"] call server_updateObject;
	};
	
	/** Compare Hitpoints **/
	if (!(_lastHitpoints == _inventory)) then {
		diag_log format["Updating Hitpoints of %1", _object];
		[_object, "damage"] call server_updateObject;
	};

You might want to change that around :P

Link to comment
Share on other sites

  • 4 weeks later...
  • 1 month later...

Removing unnecessary functions causes RPT errors:

12:38:44 Error in expression <( (time - _lastUpdate) > 5) then {
call _object_damage;
} else {
if (!(_object i>
12:38:44   Error position: <_object_damage;
} else {
if (!(_object i>
12:38:44   Error Undefined variable in expression: _object_damage
12:38:44 File z\addons\dayz_server\compile\server_updateObject.sqf, line 259
12:38:53 "WAI: [Mission:[Bandit] Troop Supply]: Starting... [3824.03,14017.9,0]"
12:38:53 "WAI: Spawned a group of 3 AI (Hero) at [3829.03,14017.9,0]"
12:38:53 "WAI: Spawned a group of 3 AI (Hero) at [3829.03,14017.9,0]"
12:38:53 "WAI: Spawned a group of 3 AI (Hero) at [3829.03,14017.9,0]"
12:38:54 "WAI: Spawned a group of 1 AI (Hero) at [3829.03,14017.9,0]"
12:38:54 "WAI: Spawned in 2 M2StaticMG"
12:39:04 Error in expression <( (time - _lastUpdate) > 5) then {
call _object_damage;
} else {
if (!(_object i>
12:39:04   Error position: <_object_damage;
} else {
if (!(_object i>
12:39:04   Error Undefined variable in expression: _object_damage
12:39:04 File z\addons\dayz_server\compile\server_updateObject.sqf, line 259
12:39:11 Error in expression <( (time - _lastUpdate) > 5) then {
call _object_damage;
} else {
if (!(_object i>
12:39:11   Error position: <_object_damage;
} else {
if (!(_object i>
12:39:11   Error Undefined variable in expression: _object_damage
12:39:11 File z\addons\dayz_server\compile\server_updateObject.sqf, line 259
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
  • Discord

×
×
  • Create New...