Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Common - Improve PBO checking #9266

Merged
merged 39 commits into from
Jun 22, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
0b34a13
Update PBO checking
johnb432 Jul 15, 2023
8386a3c
Added kicking of clients without ACE loaded
johnb432 Aug 1, 2023
fcc8e1d
Update fnc_errorMessage.sqf
johnb432 Sep 14, 2023
42fa32b
Merge remote-tracking branch 'upstream/master' into pbo-check-update
johnb432 Sep 14, 2023
f5c0fd4
Update fnc_checkVersionNumber.sqf
johnb432 Sep 14, 2023
c41f623
Merge remote-tracking branch 'upstream/master' into pbo-check-update
johnb432 Oct 23, 2023
942a72d
Compatibility with #9568
johnb432 Oct 23, 2023
0d7669f
Merge branch 'master' into pbo-check-update
johnb432 Oct 23, 2023
152995e
More compatibility for #9568
johnb432 Oct 23, 2023
29d1f69
Merge branch 'pbo-check-update' of https://github.com/johnb432/ACE3 i…
johnb432 Oct 23, 2023
b5af267
Cleanup
johnb432 Oct 25, 2023
4b560d2
Minor cleanup + added server source
johnb432 Oct 29, 2023
329c9bb
Merge master
johnb432 Dec 20, 2023
968d643
Merge branch 'master' into pr/9266
johnb432 Jan 7, 2024
0de1b26
update outdated/not present error message
LinkIsGrim Jan 8, 2024
cf50c78
check version number fixes
LinkIsGrim Jan 8, 2024
9168207
Update fnc_errorMessage.sqf
johnb432 Jan 8, 2024
1d08693
Changed error names
johnb432 Jan 9, 2024
c84a7fb
Improved ACE detection method
johnb432 Jan 10, 2024
dd84f2f
Tweaks and fixes
johnb432 Jan 10, 2024
5514373
Try another approach
johnb432 Jan 10, 2024
a9fa625
Update events-framework.md
johnb432 Jan 10, 2024
c0f1c61
Merge branch 'master' into pr/9266
johnb432 Jan 28, 2024
c45344a
Update XEH_postInit.sqf
johnb432 Jan 28, 2024
cf711dc
Merge branch 'master' into pr/9266
johnb432 Mar 24, 2024
6b2e036
Update fnc_checkVersionNumber.sqf
johnb432 Mar 24, 2024
c21c5ca
Removed check for non-ACE clients
johnb432 Mar 24, 2024
a45c37a
Update XEH_postInit.sqf
johnb432 Mar 24, 2024
59f189b
Cleanup
johnb432 Apr 1, 2024
c66aa37
Merge branch 'master' into pr/9266
johnb432 Apr 3, 2024
87eac77
Remove rogue change
johnb432 Apr 4, 2024
effcfd1
Improved message display in systemChat
johnb432 Apr 4, 2024
7d84ea9
Update fnc_checkPBOs.sqf
johnb432 Apr 10, 2024
03d26ed
Merge branch 'master' into pr/9266
johnb432 Apr 19, 2024
6ddcfb1
Removed loop variable initialisers
johnb432 Jun 6, 2024
0d32f55
Merge branch 'master' into pr/9266
johnb432 Jun 6, 2024
5c47e88
Merge branch 'master' into pr/9266
johnb432 Jun 14, 2024
fbea26c
Fixed header
johnb432 Jun 14, 2024
27b3fba
Updated headers
johnb432 Jun 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions addons/common/XEH_PREP.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ PREP(changeProjectileDirection);
PREP(checkFiles);
PREP(checkFiles_diagnoseACE);
PREP(checkPBOs);
PREP(checkVersionNumber);
PREP(claim);
PREP(claimSafeServer);
PREP(codeToString);
Expand Down
29 changes: 29 additions & 0 deletions addons/common/XEH_postInit.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,35 @@ if (_currentVersion != _previousVersion) then {

call FUNC(checkFiles);

// Let the server know that we have ACE loaded
missionNamespace setVariable [QGVAR(aceLoaded_) + getPlayerUID player, true, 2];

// This handles clients joining that do not have ACE loaded
if (isServer) then {
addMissionEventHandler ["PlayerConnected", {
[{
params ["", "_uid", "", "", "_owner"];

// If ACE is not loaded, kick unit
if !(missionNamespace getVariable [QGVAR(aceLoaded_) + _uid, false]) then {
johnb432 marked this conversation as resolved.
Show resolved Hide resolved
// Send function to client
_owner publicVariableClient QFUNC(errorMessage);
johnb432 marked this conversation as resolved.
Show resolved Hide resolved

// Wait for function to broadcast, then kick client
[{
["[ACE] ERROR", "ACE is not present", {findDisplay 46 closeDisplay 0}, {findDisplay 46 closeDisplay 0}, nil, [true, false]] remoteExecCall [QFUNC(errorMessage), _this];
LinkIsGrim marked this conversation as resolved.
Show resolved Hide resolved
}, _owner, 0.5] call CBA_fnc_waitAndExecute;
};
}, _this, 3] call CBA_fnc_waitAndExecute;
}];

addMissionEventHandler ["PlayerDisconnected", {
params ["", "_uid"];

// Reset variable
missionNamespace setVariable [QGVAR(aceLoaded_) + _uid, nil];
}];
};

//////////////////////////////////////////////////
// Set up ace_settingsInitialized eventhandler
Expand Down
115 changes: 72 additions & 43 deletions addons/common/functions/fnc_checkFiles.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -16,44 +16,54 @@
*/

///////////////
// check addons
// Check addons
///////////////
private _mainVersion = getText (configFile >> "CfgPatches" >> "ace_main" >> "versionStr");
private _cfgPatches = configFile >> "CfgPatches";
private _mainVersion = getText (_cfgPatches >> "ace_main" >> "versionStr");

//CBA Versioning check - close main display if using incompatible version
private _cbaVersionAr = getArray (configFile >> "CfgPatches" >> "cba_main" >> "versionAr");
// CBA Versioning check - close main display if using incompatible version
private _cbaVersionAr = getArray (_cfgPatches >> "cba_main" >> "versionAr");
private _cbaRequiredAr = getArray (configFile >> "CfgSettings" >> "CBA" >> "Versioning" >> "ACE" >> "dependencies" >> "CBA") select 1;

private _cbaVersionStr = _cbaVersionAr joinString ".";
private _cbaRequiredStr = _cbaRequiredAr joinString ".";

INFO_3("ACE is version %1 - CBA is version %2 (min required %3)",_mainVersion,_cbaVersionStr,_cbaRequiredStr);

if ([_cbaRequiredAr, _cbaVersionAr] call cba_versioning_fnc_version_compare) then {
if ([_cbaRequiredAr, _cbaVersionAr] call CBA_versioning_fnc_version_compare) then {
private _errorMsg = format ["CBA version %1 is outdated (required %2)", _cbaVersionStr, _cbaRequiredStr];
ERROR(_errorMsg);

if (hasInterface) then {
["[ACE] ERROR", _errorMsg, {findDisplay 46 closeDisplay 0}] call FUNC(errorMessage);
["[ACE] ERROR", _errorMsg, {findDisplay 46 closeDisplay 0}, {findDisplay 46 closeDisplay 0}, nil, [true, false]] call FUNC(errorMessage);
};
};

//private _addons = activatedAddons; // broken with High-Command module, see #2134
private _addons = (cba_common_addons select {(_x select [0,4]) == "ace_"}) apply {toLower _x};
//private _addons = activatedAddons; // Broken with High-Command module, see #2134
private _addons = (CBA_common_addons select {(_x select [0, 4]) == "ace_"}) apply {toLower _x};

private _addonCfg = configNull;
private _addonVersion = "";
private _addonSource = "";

private _oldAddons = [];
private _oldSources = [];
private _oldCompats = [];

{
private _addonCfg = configFile >> "CfgPatches" >> _x;
private _addonVersion = getText (_addonCfg >> "versionStr");
_addonCfg = configFile >> "CfgPatches" >> _x;
_addonVersion = getText (_addonCfg >> "versionStr");

if (_addonVersion != _mainVersion) then {
private _addonSource = configSourceMod _addonCfg;
_addonSource = configSourceMod _addonCfg;

_oldSources pushBackUnique _addonSource;

// Check ACE install
call FUNC(checkFiles_diagnoseACE);

if ((_x select [0, 10]) != "ace_compat") then {
if (hasInterface) then {
_oldAddons pushBack _x;
};
_oldAddons pushBack _x;
} else {
_oldCompats pushBack [_x, _addonVersion]; // Don't block game if it's just an old compat pbo
};
Expand All @@ -62,45 +72,57 @@ private _oldCompats = [];

if (_oldAddons isNotEqualTo []) then {
_oldAddons = _oldAddons apply {"%1.pbo", _x};
private _errorMsg = "";
if (count _oldAddons > 3) then {
_errorMsg = format ["The following files are outdated: %1, and %2 more.<br/>ACE Main version is %3.<br/>Loaded mods with outdated ACE files: %4", (_oldAddons select [0, 3]) joinString ", ", (count _oldAddons) -3, _mainVersion, (_oldSources joinString ", ")];

private _errorMsg = if (count _oldAddons > 3) then {
format ["The following files are outdated: %1, and %2 more.<br/>ACE Main version is %3.<br/>Loaded mods with outdated ACE files: %4", (_oldAddons select [0, 3]) joinString ", ", (count _oldAddons) - 3, _mainVersion, _oldSources joinString ", "];
} else {
_errorMsg = format ["The following files are outdated: %1.<br/>ACE Main version is %2.<br/>Loaded mods with outdated ACE files: %3", (_oldAddons) joinString ", ", _mainVersion, (_oldSources) joinString ", "];
format ["The following files are outdated: %1.<br/>ACE Main version is %2.<br/>Loaded mods with outdated ACE files: %3", _oldAddons joinString ", ", _mainVersion, _oldSources joinString ", "];
};

if (hasInterface) then {
["[ACE] ERROR", _errorMsg, {findDisplay 46 closeDisplay 0}] call FUNC(errorMessage);
["[ACE] ERROR", _errorMsg, {findDisplay 46 closeDisplay 0}, {findDisplay 46 closeDisplay 0}, nil, [true, false]] call FUNC(errorMessage);
};

ERROR(_errorMsg);
};

if (_oldCompats isNotEqualTo []) then {
_oldCompats = _oldCompats apply {format ["%1 (%2, source: %3)", _x select 0, _x select 1]};

[{
// Lasts for ~10 seconds
ERROR_WITH_TITLE_2("The following ACE compatiblity PBOs are outdated", "%1. ACE Main version is %2",_this select 0,_this select 1);
}, [_oldCompats, _mainVersion], 1] call CBA_fnc_waitAndExecute;
};

///////////////
// check extensions
// Check extensions
///////////////
private _platform = toLower (productVersion select 6);

if (!isServer && {_platform in ["linux", "osx"]}) then {
// Linux and OSX client ports do not support extensions at all
INFO("Operating system does not support extensions");
} else {
private _extension = "";
private _isWindows = false;
private _isLinux = false;
private _isClient = false;
private _isServer = false;

{
private _extension = configName _x;
private _isWindows = _platform == "windows" && {getNumber (_x >> "windows") == 1};
private _isLinux = _platform == "linux" && {getNumber (_x >> "linux") == 1};
private _isClient = hasInterface && {getNumber (_x >> "client") == 1};
private _isServer = !hasInterface && {getNumber (_x >> "server") == 1};
_extension = configName _x;
_isWindows = _platform == "windows" && {getNumber (_x >> "windows") == 1};
_isLinux = _platform == "linux" && {getNumber (_x >> "linux") == 1};
_isClient = hasInterface && {getNumber (_x >> "client") == 1};
_isServer = !hasInterface && {getNumber (_x >> "server") == 1};

if ((_isWindows || _isLinux) && {_isClient || _isServer}) then {
private _versionEx = _extension callExtension "version";

if (_versionEx == "") then {
private _extensionFile = _extension;

if (productVersion select 7 == "x64") then {
_extensionFile = format ["%1_x64", _extensionFile];
};
Expand All @@ -112,7 +134,7 @@ if (!isServer && {_platform in ["linux", "osx"]}) then {
ERROR(_errorMsg);

if (hasInterface) then {
["[ACE] ERROR", _errorMsg, {findDisplay 46 closeDisplay 0}] call FUNC(errorMessage);
["[ACE] ERROR", _errorMsg, {findDisplay 46 closeDisplay 0}, {findDisplay 46 closeDisplay 0}, nil, [true, false]] call FUNC(errorMessage);
};
} else {
// Print the current extension version
Expand All @@ -121,54 +143,61 @@ if (!isServer && {_platform in ["linux", "osx"]}) then {
};
} forEach ("true" configClasses (configFile >> "ACE_Extensions"));
};

if (isArray (configFile >> "ACE_Extensions" >> "extensions")) then {
WARNING("extensions[] array no longer supported");
};

///////////////
// check server version/addons
// Check server version/addons
///////////////
if (isMultiplayer) then {
// don't check optional addons
_addons = _addons select {getNumber (configFile >> "CfgPatches" >> _x >> "ACE_isOptional") != 1};
// Don't check optional addons
_addons = _addons select {getNumber (_cfgPatches >> _x >> "ACE_isOptional") != 1};

if (isServer) then {
// send servers version of ACE to all clients
// Send server's version of ACE to all clients
GVAR(ServerVersion) = _mainVersion;
GVAR(ServerAddons) = _addons;
publicVariable QGVAR(ServerVersion);
publicVariable QGVAR(ServerAddons);
} else {
// clients have to wait for the variables
[{
if (isNil QGVAR(ServerVersion) || isNil QGVAR(ServerAddons)) exitWith {};
GVAR(ClientVersion) = _version;
GVAR(ClientAddons) = _addons;

(_this select 0) params ["_mainVersion", "_addons"];

if (_mainVersion != GVAR(ServerVersion)) then {
private _errorMsg = format ["Client/Server Version Mismatch. Server: %1, Client: %2.", GVAR(ServerVersion), _mainVersion];
private _fnc_check = {
if (GVAR(ClientVersion) != GVAR(ServerVersion)) then {
private _errorMsg = format ["Client/Server Version Mismatch. Server: %1, Client: %2.", GVAR(ServerVersion), GVAR(ClientVersion)];

// Check ACE install
call FUNC(checkFiles_diagnoseACE);
ERROR(_errorMsg);

if (hasInterface) then {
["[ACE] ERROR", _errorMsg, {findDisplay 46 closeDisplay 0}] call FUNC(errorMessage);
["[ACE] ERROR", _errorMsg, {findDisplay 46 closeDisplay 0}, {findDisplay 46 closeDisplay 0}, nil, [true, false]] call FUNC(errorMessage);
};
};

_addons = _addons - GVAR(ServerAddons);
private _addons = GVAR(ClientAddons) - GVAR(ServerAddons);

if (_addons isNotEqualTo []) then {
private _errorMsg = format ["Client/Server Addon Mismatch. Client has extra addons: %1.",_addons];
private _errorMsg = format ["Client/Server Addon Mismatch. Client has extra addons: %1.", _addons];

// Check ACE install
call FUNC(checkFiles_diagnoseACE);
ERROR(_errorMsg);

if (hasInterface) then {
["[ACE] ERROR", _errorMsg, {findDisplay 46 closeDisplay 0}] call FUNC(errorMessage);
["[ACE] ERROR", _errorMsg, {findDisplay 46 closeDisplay 0}, {findDisplay 46 closeDisplay 0}, nil, [true, false]] call FUNC(errorMessage);
};
};
};

[_this select 1] call CBA_fnc_removePerFrameHandler;
}, 1, [_mainVersion,_addons]] call CBA_fnc_addPerFrameHandler;
// Clients have to wait for the variables
if (isNil QGVAR(ServerVersion) || isNil QGVAR(ServerAddons)) then {
GVAR(ServerVersion) addPublicVariableEventHandler _fnc_check;
} else {
call _fnc_check;
};
};
};
73 changes: 36 additions & 37 deletions addons/common/functions/fnc_checkPBOs.sqf
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "..\script_component.hpp"
/*
* Author: commy2
* Author: commy2, johnb43
* Used to execute the checkPBOs module without placing the module. Don't use this together with the module.
* Checks PBO versions and compares to the one running on server.
*
Expand All @@ -24,83 +24,82 @@
params ["_mode", ["_checkAll", false], ["_whitelist", "", [""]]];
TRACE_3("params",_mode,_checkAll,_whitelist);

//lowercase and convert whiteList String into array of strings:
// Lowercase and convert whiteList string into array of strings:
_whitelist = toLower _whitelist;
_whitelist = _whitelist splitString "[,""']";
TRACE_1("Array",_whitelist);

ACE_Version_CheckAll = _checkAll;
ACE_Version_Whitelist = _whitelist;

if (!_checkAll) exitWith {}; //ACE is checked by FUNC(checkFiles)
// ACE is checked by FUNC(checkFiles)
if (!_checkAll) exitWith {};

if (!isServer) then {
[{
if (isNil "ACE_Version_ClientErrors") exitWith {};
["ace_versioning_clientCheckDone", {
// Don't let this event get triggered again
[_thisType, _thisId] call CBA_fnc_removeEventHandler;

ACE_Version_ClientErrors params ["_missingAddon", "_missingAddonServer", "_oldVersionClient", "_oldVersionServer"];
params ["_clientErrors"];
_clientErrors params ["_missingAddon", "_missingAddonServer", "_oldVersionClient", "_oldVersionServer"];
_thisArgs params ["_mode"];

(_this select 0) params ["_mode", "_checkAll", "_whitelist"];

// Display error message.
// Display error message(s)
if (_missingAddon || {_missingAddonServer} || {_oldVersionClient} || {_oldVersionServer}) then {
private _text = "[ACE] Version mismatch:<br/><br/>";
private _errorMsg = "[ACE] Version mismatch:<br/><br/>";
private _error = format ["ACE version mismatch: %1: ", profileName];

if (_missingAddon) then {
_text = _text + "Detected missing addon on client<br/>";
_errorMsg = _errorMsg + "Detected missing addon on client<br/>";
_error = _error + "Missing file(s); ";
};

if (_missingAddonServer) then {
_text = _text + "Detected missing addon on server<br/>";
_errorMsg = _errorMsg + "Detected missing addon on server<br/>";
_error = _error + "Additional file(s); ";
};

if (_oldVersionClient) then {
_text = _text + "Detected old client version<br/>";
_errorMsg = _errorMsg + "Detected old client version<br/>";
_error = _error + "Older version; ";
};

if (_oldVersionServer) then {
_text = _text + "Detected old server version<br/>";
_errorMsg = _errorMsg + "Detected old server version<br/>";
_error = _error + "Newer version; ";
};

//[QGVAR(systemChatGlobal), _error] call CBA_fnc_globalEvent;

ERROR(_error);

// Warn
if (_mode < 2) then {
_text = composeText [lineBreak, parseText format ["<t align='center'>%1</t>", _text]];
_errorMsg = composeText [lineBreak, parseText format ["<t align='center'>%1</t>", _errorMsg]];

private _rscLayer = "ACE_RscErrorHint" call BIS_fnc_rscLayer;
_rscLayer cutRsc ["ACE_RscErrorHint", "PLAIN", 0, true];

disableSerialization;

private _ctrlHint = uiNamespace getVariable "ACE_ctrlErrorHint";
_ctrlHint ctrlSetStructuredText _text;
_ctrlHint ctrlSetStructuredText _errorMsg;

if (_mode == 0) then {
[{
params ["_rscLayer"];
TRACE_2("Hiding Error message after 10 seconds",time,_rscLayer);
_rscLayer cutFadeOut 0.2;
}, [_rscLayer], 10] call CBA_fnc_waitAndExecute;
TRACE_2("Hiding Error message after 10 seconds",time,_this);
_this cutFadeOut 0.2;
}, _rscLayer, 10] call CBA_fnc_waitAndExecute;
};
};

if (_mode == 2) then {
[{alive player}, { // To be able to show list if using checkAll
params ["_text"];
TRACE_2("Player is alive, showing msg and exiting",time,_text);
_text = composeText [parseText format ["<t align='center'>%1</t>", _text]];
["[ACE] ERROR", _text, {findDisplay 46 closeDisplay 0}] call FUNC(errorMessage);
}, [_text]] call CBA_fnc_waitUntilAndExecute;
} else {
// Kick
[{alive player}, {
TRACE_2("Player is alive, showing msg and exiting",time,_this);
private _errorMsg = composeText [parseText format ["<t align='center'>%1</t>", _this]];
["[ACE] ERROR", _errorMsg, {findDisplay 46 closeDisplay 0}, {findDisplay 46 closeDisplay 0}, nil, [true, false]] call FUNC(errorMessage);
}, _errorMsg] call CBA_fnc_waitUntilAndExecute;
};
};

[_this select 1] call CBA_fnc_removePerFrameHandler;
}, 1, [_mode, _checkAll, _whitelist]] call CBA_fnc_addPerFrameHandler;
}, [_mode]] call CBA_fnc_addEventHandlerArgs;
};

if (_checkAll) then {
0 spawn COMPILE_FILE(scripts\checkVersionNumber); // @todo
};
// Check file version numbers
[_whitelist] call FUNC(checkVersionNumber);
Loading