User Details
- User Since
- Dec 30 2013, 6:22 AM (573 w, 3 d)
May 10 2016
I get your point that spawn pushes the execution to the scheduled environment i.e. postInit. What I still don't get is why you or BI feel there is no use case for client-server communications in unscheduled environment. Anyway, I am more accepting of the fact, after reading through KK's tutorial again, linked below:
http://killzonekid.com/arma-scripting-tutorials-code-performance/
SilentSpike your sarcasm is funny but on these forums, these are srz ppl running a srz bznz. Xeno, Skaronator, KK and yourself even are expert scripters/developers.
preInit allows you to run scripts in an unscheduled environment, meaning it allows you to get all your initialization done, in the mission splash/startup screen before the game session starts.
Of course, you can also run scripts in an unscheduled environment using a mission event handler like Draw3D. However with Draw3D, the user's session has already started and if the script within Draw3D is computationally heavy, the user experience is temporarily suspended. Generally, doing this to the player is not good practice.
Hopefully BI will do something now. publicVariableServer and publicVariableClient are amazing client-server messaging tools. All it needs is a more direct way to identify clients and connections that works not just in preInit but everywhere else. Searching by name through playableUnits (if the server is initiating the messaging) or waiting for the client to send an object, typically {player}, so that the server can apply {owner} to it to extract the clientid, sounds "hacky".
The _id in onPlayerConnect corresponds to DirectPlay id, and cannot be used for publicVariableClient messaging. I am not even sure if onPlayerConnect has already fired whilst the new client session is still in preInit. Will test later.
Can you please clarify further on how "public variables do not work in preInit"?
The reproduction code shows that publicVariables DO work in preInit. The only aspect that does not seem to work is publicVariableClient, because there does not appear to be any means (at least ones that I know of) of identifying the clientId of a client in preInit. Most methods discussed rely on use of objects, playableUnits and the owner command. Yet, the same client in preInit is already able to send and receive messages using commands publicVariable and publicVariableServer.
Use-case for releasing files after reads or loads
- Accelerates script development, especially if the scripts are read from files.
- Allows hotfixes and run-time changes of configurations/settings.
- Increases interoperability and file-based interfacing.
Client-side, to release files held by a multiplayer session, it is necessary to back out to the multiplayer server selection screen.
Server-side, it is necessary to restart the server.
Please, prioritise this. Not releasing files after reads and loads is not very professional.
Verified cache. Still happening. But have confirmed that this is localised. Friend's sessions are not experiencing this. I'll provide more info when I find out local circumstances leading to this.
Yes the reproduction is on a clean new mission in editor. Stacking event handlers is not the answer.
Hmmm local problem to my machine? I tried the following. The number scrolls then stops.
- spawn { oneachframe {hintsilent str diag_frameno}; };
onEachFrame is now broken. Draws only 1 frame and doesnt seem to loop anymore.
The cause of this was one version of CBA. Therefore not related. Happy for this to close.
BI scripts are located in some of the PBOs in the client Addons folder. If you unpack the PBO's, it is possible to use some text-search-all-files-in-folder (e.g. Notepad++) to find "trigger". The results of this approach will be less empirical and more exhaustive.
Another interesting observation is that in a mission with not a single trigger, both server-side and client local, "EmptyDetector" exists and grows in number over time.
The specific problem here is that this is essentially an unmanageable, irrecoverable but identifiable use of resource, otherwise, known as a "memory leak".
This means that the server will have to be restarted over time.
#destructioneffects are not the same as craters. Craters are removable objects.
Deleting EmptyDetector, #smokesource and #destructioneffects objects only makes them unplottable on the map or resets to position [0,0,0], but they remain in the object space. Please check the histogram system text that the code produces. The numbers remain unchanged even after you relog, which means its not local.
There is no evidence of the server garbage collecting #destructioneffects and #smokesource. It simply builds up to astronomical numbers in a heavily populated MP server over time.
I'd appreciate proper investigation and less guesswork or flippant comments please.
Yes true.
Its ok to close this.
vehicles, entities, nearEntities do not pick up GroundWeaponHolder.
nearObjects and nearestObjects do pick up GroundWeaponHolder.
It seems that entities and nearEntities pick up everything in "ReammoBox_F" but not "ReammoBox". Legacy issue? GroundWeaponHolder falls under ReammoBox whereas most of Arma 3 crates are in ReammoBox_F.
Two interim workarounds to this issue:
- nearObjects is not so costly afterall e.g.
systemChat str count (position player nearObjects ["GroundWeaponHolder",10000000]) doesnt seem to cost any more if the range value is lower. Perhaps, the function has to loop through the entire object space anyway to work out distance to the reference position. Still, its a cost to have to work out the distance.
- get the client to tell the server that a GroundWeaponHolder is created and have the server clean up the GroundWeaponHolder after a certain delay.
player addEventHandler ["Put",{
private ["_container"];
_container = _this select 1;
if (_container isKindOf "GroundWeaponHolder") then {
serverRegisterGWH = _container; publicVariableServer "serverDespawnGWH";
};
}];
"serverDespawnGWH" addPublicVariableEventHandler {
[_this select 1] spawn {
private ["_obj"]; _obj = _this select 0; sleep 120; if (!isNull _obj) then { deleteVehicle _obj; };
};
};
allMissionObjects is more elegant :)
At large distances, the "desync" behaviour observed is most likely caused by basic.cfg settings for MinErrorToSend and MinErrorToSendNear, documented here: https://community.bistudio.com/wiki/basic.cfg
Also observing vehicles with no players drivers/pilots/passengers, sinking into the ground, flying off at some vector, momentarily before resetting its position.
This is not conclusive but it appears to be happening more since 1.12 (http://dev.arma3.com/spotrep-00020).
Here are some observations to help with isolating the problem:
- It happens on a recently restarted server also.
- It is happening also to vehicles with no pilots and passengers. Vehicles are sinking into the ground and sliding. Having multiple players in the vehicle is not automatically causative factor.
- It does not feel like individual player lag because we checked their Ping, Bandwidth and Desync stats when they are showing "vehicle desync" behaviour.
- Occassionally, we get server wide desync with the majority of players showing 100000 in the Desync field.
Its ok to close this. This issue has been resolved.
Testing on 1.12 finds the following:
- damage from heat sources start on the head at around 10-11m (this damage is approximately the same at 10-11m regardless of current uniform or vest)
- at 10m, damage to body, hands and legs begin only when vest is removed i.e. removing uniform does not appear to do anything. Also the distance to fire source for hand body and legs damage to start is slightly less (< 1m) or closer than the distance required for head
- with vest on, damage to body, hands and legs start at about 5m
Good work.
The following is my most recent script-side workaround for this issue. Obviously this is no match compared to a native solution, hence its just an interim workaround until BI finds the solution. Basically, the boarder attempts to sync with the client holding locality over the vehicle, until the latter can confirm that the boarder is in the vehicle.
confirmGetIn = {
if (player == (driver (vehicle player))) exitWith {};
vehicleSyncNotConfirmed = true;
while { vehicleSyncNotConfirmed && (player != (vehicle player)) } do {
systemChat "confirming vehicle boarding ..."; pvConfirmGetIn = [player,assignedVehicle player,assignedVehicleRole player]; publicVariable "pvConfirmGetIn"; sleep 1;
};
};
checkGetIn = {
_unit = _this select 0;
_veh = _this select 1;
if (!local _veh) exitWith {};
_seat = _this select 2;
if ((count _seat) == 0) exitWith {};
if (_unit == (vehicle _unit)) then {
systemChat format ["%1 boarding vehicle",name _unit]; switch (_seat select 0) do { case "Driver" : { _unit moveInDriver _veh; }; case "Cargo" : { _unit moveInCargo _veh; }; case "Turret" : { _unit moveInTurret [_veh,_seat select 1]; }; }; _unit moveInAny _veh; // backup moveIn if above fails
}
else {
systemChat format ["%1 boarded vehicle",name _unit]; pvGetInConfirmed = _unit; publicVariable "pvGetInConfirmed";
};
};
"pvConfirmGetIn" addPublicVariableEventHandler {
(_this select 1) spawn checkGetIn;
};
"pvGetInConfirmed" addPublicVariableEventHandler {
if (player == (_this select 1)) exitWith { vehicleSyncNotConfirmed = false; };
};
{
_x removeAllEventHandlers "GetIn"; // change this if its affecting other GetIn event handlers
_x addEventHandler ["GetIn",{
- spawn confirmGetIn;
false;
}];
} forEach vehicles;
can be optimised by restricting GetIn eventhandler to only playable vehicles
dont forget to apply to newly spawned playable vehicles
After some struggle with finding a workaround to this issue, can confirm that this is an MP desync issue because, the player that is glitching sees himself as perfectly seated within the chopper in his session, whereas everyone sees the player outside of the chopper but following the chopper on the map. The glitching players name is not on the passenger list of the vehicle.
We tried a number of strategies including turning off collision detection. Turning off collision detection doesnt work because the GetIn eventhandler (or alternative vehicle player != player methods) will only fire on the session of the player that is glitching. It will not fire for everyone else because on everyone else's session, the glitching player hasnt actually boarded the chopper yet. If you still want to turn off collision detection, you can still do so for any players coming close to the vehicle but that means you take away the ability of the vehicle to run people over.
In the end, we went back to something simpler. We disabled the co-pilot seat of transport choppers. This is not a perfect fix but it takes away some of the pain.
The problem affects gunner seats also. AH-99 Blackhawks are still vulnerable to this glitch but at least, it affects less people than a transport chopper full of people.
The link below contains our temporary workaround code and observation notes on this issue.
http://www.thelanbox.com.au/forum/topic/90/temporary-pilotcheck-sqf-fix-for-co-pilot-bug/
The cause of the MP desync can be many, and not necessary limited to latency or packetloss. For example, the glitching player may have a different version of truth on which seat is occupied compared to all other players and perfectly unaware that he is occupying a seat that is already occupied by someone else.
If I have the source, I'd look into how vehicle boarding and seat allocation/negotiation is handled in multiplayer mode. Cheers.
If you are using the hideObject workaround, bear in mind the locality of this command is "Effect Local", meaning you may have to execute it within BIS_fnc_MP for global effect (or publicVariableServer and hideObjectGlobal, the latter command only works when called on the server). Not pretty.