rekterakathom / DynamicCamoSystem

A lightweight ARMA 3 mod that calculates camouflage levels based on worn gear
https://steamcommunity.com/sharedfiles/filedetails/?id=2800081814
GNU General Public License v3.0
1 stars 4 forks source link

Client-side coefficient calculation #9

Open rekterakathom opened 1 year ago

rekterakathom commented 1 year ago

Calculate coefficients on clients because dedicated servers are unreliable

rekterakathom commented 1 year ago

Technically it still works even without the client having the mod, it's just that every client without the mod won't be contributing any texture information.

For remote execution, the function would need to exist on the client or we would need to send the entire function over the network, which really isn't ideal.

I'll think about this for a while, it would be a drastic change for all server admins who currently expect this mod to work serverside to suddenly add a clientside requirement, but that would be the easiest solution by far...

rekterakathom commented 1 year ago

Now it's back to being totally serverside. I'll investigate any possible solutions to reducing the network load before release though

thegamecracks commented 1 year ago

fwiw I know Advanced Urban Rappelling broadcasts its 28 functions over JIP, but I haven't noticed any issues running it:

AUR_Advanced_Urban_Rappelling_Install = {
    if(!isNil "AUR_RAPPELLING_INIT") exitWith {};
    ... // global function definitions
};
publicVariable "AUR_Advanced_Urban_Rappelling_Install";
[] call AUR_Advanced_Urban_Rappelling_Install;
remoteExecCall ["AUR_Advanced_Urban_Rappelling_Install", -2,true];

There's also the extra bandwidth cost of sending texture data to every client despite the computations being server-side; perhaps that can be implemented as a callback for when texture data isn't available?

/* fn_updateCamo.sqf */
// Client may remote execute this function to give us texture data
// BREAKING CHANGE: DYNCAS_fnc_updateCamo required in CfgRemoteExec
params ["_unit", ["_playerTexAvg", []], ["_groundTexAvg", []]];

_playerTex = (getObjectTextures _unit) param [0, ""];
_groundTex = surfaceTexture getPosASL _unit;

// Use cached texture if available;
// if not available then add client textures to cache, if defined
_playerTexAvg = GVAR(texInfoCache) getOrDefault [_playerTex, _playerTexAvg, _playerTexAvg isNotEqualTo []];
_groundTexAvg = GVAR(texInfoCache) getOrDefault [_groundTex, _groundTexAvg, _groundTexAvg isNotEqualTo []];

// No texture from client/cache? Ask client for textures
// Possibly timestamp player/ground textures to rate-limit calls?
if (_playerTexAvg isEqualTo [] || {_groundTexAvg isEqualTo []}) exitWith {
    [[_playerTex, _groundTex], FUNC(clientSendTextures)] remoteExec ["call", _unit];
};

// Otherwise we're good to calculate camouflageCoef...
/* fn_clientSendTextures.sqf */
params ["_playerTex", "_groundTex"];

_playerTexAvg = (getTextureInfo _playerTex) # 2;
_playerTexAvg deleteAt 3;
_groundTexAvg = (getTextureInfo _groundTex) # 2;
_groundTexAvg deleteAt 3;

[player, _playerTexAvg, _groundTexAvg] remoteExec [QFUNC(updateCamo), 2];
rekterakathom commented 1 year ago

Currently the texture information is shared to all to avoid clients sending duplicate data to server. Maybe a callback system would indeed be smarter, that way the only JIP bloat would be the function itself.