mirror of
https://github.com/acemod/ACE3.git
synced 2024-08-30 18:23:18 +00:00
Common - Improve PBO checking (#9266)
* Update PBO checking * Added kicking of clients without ACE loaded * Update fnc_errorMessage.sqf * Update fnc_checkVersionNumber.sqf * More compatibility for #9568 * Cleanup * Minor cleanup + added server source * update outdated/not present error message * check version number fixes * Update fnc_errorMessage.sqf * Changed error names Server is always right, client has either older or newer versions, or missing or additional addons * Improved ACE detection method * Tweaks and fixes * Try another approach * Update events-framework.md * Update XEH_postInit.sqf * Update fnc_checkVersionNumber.sqf * Removed check for non-ACE clients * Update XEH_postInit.sqf * Cleanup * Remove rogue change * Improved message display in systemChat * Update fnc_checkPBOs.sqf * Removed loop variable initialisers * Fixed header * Updated headers --------- Co-authored-by: Grim <69561145+LinkIsGrim@users.noreply.github.com> Co-authored-by: LinkIsGrim <salluci.lovi@gmail.com>
This commit is contained in:
parent
db6c4a72a6
commit
7ea2aab2c9
@ -30,6 +30,7 @@ PREP(changeProjectileDirection);
|
|||||||
PREP(checkFiles);
|
PREP(checkFiles);
|
||||||
PREP(checkFiles_diagnoseACE);
|
PREP(checkFiles_diagnoseACE);
|
||||||
PREP(checkPBOs);
|
PREP(checkPBOs);
|
||||||
|
PREP(checkVersionNumber);
|
||||||
PREP(claim);
|
PREP(claim);
|
||||||
PREP(claimSafeServer);
|
PREP(claimSafeServer);
|
||||||
PREP(codeToString);
|
PREP(codeToString);
|
||||||
|
@ -15,15 +15,20 @@
|
|||||||
* Public: No
|
* Public: No
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Don't execute in scheduled environment
|
||||||
|
if (canSuspend) exitWith {
|
||||||
|
[FUNC(checkFiles), nil] call CBA_fnc_directCall;
|
||||||
|
};
|
||||||
|
|
||||||
///////////////
|
///////////////
|
||||||
// check addons
|
// Check addons
|
||||||
///////////////
|
///////////////
|
||||||
private _mainCfg = configFile >> "CfgPatches" >> "ace_main";
|
private _cfgPatches = configFile >> "CfgPatches";
|
||||||
private _mainVersion = getText (_mainCfg >> "versionStr");
|
private _mainVersion = getText (_cfgPatches >> "ace_main" >> "versionStr");
|
||||||
private _mainSource = configSourceMod _mainCfg;
|
private _mainSource = configSourceMod (_cfgPatches >> "ace_main");
|
||||||
|
|
||||||
// CBA Versioning check - close main display if using incompatible version
|
// CBA Versioning check - close main display if using incompatible version
|
||||||
private _cbaVersionAr = getArray (configFile >> "CfgPatches" >> "cba_main" >> "versionAr");
|
private _cbaVersionAr = getArray (_cfgPatches >> "cba_main" >> "versionAr");
|
||||||
private _cbaRequiredAr = getArray (configFile >> "CfgSettings" >> "CBA" >> "Versioning" >> "ACE" >> "dependencies" >> "CBA") select 1;
|
private _cbaRequiredAr = getArray (configFile >> "CfgSettings" >> "CBA" >> "Versioning" >> "ACE" >> "dependencies" >> "CBA") select 1;
|
||||||
|
|
||||||
private _cbaVersionStr = _cbaVersionAr joinString ".";
|
private _cbaVersionStr = _cbaVersionAr joinString ".";
|
||||||
@ -31,53 +36,62 @@ private _cbaRequiredStr = _cbaRequiredAr joinString ".";
|
|||||||
|
|
||||||
INFO_3("ACE is version %1 - CBA is version %2 (min required %3)",_mainVersion,_cbaVersionStr,_cbaRequiredStr);
|
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];
|
private _errorMsg = format ["CBA version %1 is outdated (required %2)", _cbaVersionStr, _cbaRequiredStr];
|
||||||
ERROR(_errorMsg);
|
ERROR(_errorMsg);
|
||||||
|
|
||||||
if (hasInterface) then {
|
if (hasInterface) then {
|
||||||
["[ACE] ERROR", _errorMsg, {findDisplay 46 closeDisplay 0}] call FUNC(errorMessage);
|
["[ACE] ERROR", _errorMsg] call FUNC(errorMessage);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
//private _addons = activatedAddons; // broken with High-Command module, see #2134
|
//private _addons = activatedAddons; // Broken with High-Command module, see #2134
|
||||||
private _addons = (cba_common_addons select {(_x select [0,4]) == "ace_"}) apply {toLowerANSI _x};
|
private _addons = (CBA_common_addons select {(_x select [0, 4]) == "ace_"}) apply {toLowerANSI _x};
|
||||||
|
|
||||||
private _oldAddons = [];
|
private _oldAddons = [];
|
||||||
private _oldSources = [];
|
private _oldSources = [];
|
||||||
private _oldCompats = [];
|
private _oldCompats = [];
|
||||||
|
|
||||||
{
|
{
|
||||||
private _addonCfg = configFile >> "CfgPatches" >> _x;
|
private _addonCfg = configFile >> "CfgPatches" >> _x;
|
||||||
private _addonVersion = getText (_addonCfg >> "versionStr");
|
private _addonVersion = getText (_addonCfg >> "versionStr");
|
||||||
|
|
||||||
if (_addonVersion != _mainVersion) then {
|
if (_addonVersion != _mainVersion) then {
|
||||||
private _addonSource = configSourceMod _addonCfg;
|
private _addonSource = configSourceMod _addonCfg;
|
||||||
|
|
||||||
_oldSources pushBackUnique _addonSource;
|
_oldSources pushBackUnique _addonSource;
|
||||||
|
|
||||||
|
// Check ACE install
|
||||||
call FUNC(checkFiles_diagnoseACE);
|
call FUNC(checkFiles_diagnoseACE);
|
||||||
|
|
||||||
|
// Don't block game if it's just an old compat pbo
|
||||||
if ((_x select [0, 10]) != "ace_compat") then {
|
if ((_x select [0, 10]) != "ace_compat") then {
|
||||||
if (hasInterface) then {
|
|
||||||
_oldAddons pushBack _x;
|
_oldAddons pushBack _x;
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
_oldCompats pushBack [_x, _addonVersion]; // Don't block game if it's just an old compat pbo
|
_oldCompats pushBack [_x, _addonVersion];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
} forEach _addons;
|
} forEach _addons;
|
||||||
|
|
||||||
if (_oldAddons isNotEqualTo []) then {
|
if (_oldAddons isNotEqualTo []) then {
|
||||||
_oldAddons = _oldAddons apply {format ["%1.pbo", _x]};
|
_oldAddons = _oldAddons apply {format ["%1.pbo", _x]};
|
||||||
private _errorMsg = "";
|
|
||||||
if (count _oldAddons > 3) then {
|
private _errorMsg = if (count _oldAddons > 3) then {
|
||||||
_errorMsg = format ["The following files are outdated: %1, and %2 more.<br/>ACE Main version is %3 from %4.<br/>Loaded mods with outdated ACE files: %5", (_oldAddons select [0, 3]) joinString ", ", (count _oldAddons) -3, _mainVersion, _mainSource, (_oldSources joinString ", ")];
|
format ["The following files are outdated: %1, and %2 more.<br/>ACE Main version is %3 from %4.<br/>Loaded mods with outdated ACE files: %5", (_oldAddons select [0, 3]) joinString ", ", (count _oldAddons) - 3, _mainVersion, _mainSource, _oldSources joinString ", "];
|
||||||
} else {
|
} else {
|
||||||
_errorMsg = format ["The following files are outdated: %1.<br/>ACE Main version is %2 from %3.<br/>Loaded mods with outdated ACE files: %4", (_oldAddons) joinString ", ", _mainVersion, _mainSource, (_oldSources) joinString ", "];
|
format ["The following files are outdated: %1.<br/>ACE Main version is %2 from %3.<br/>Loaded mods with outdated ACE files: %4", _oldAddons joinString ", ", _mainVersion, _mainSource, _oldSources joinString ", "];
|
||||||
};
|
};
|
||||||
|
|
||||||
if (hasInterface) then {
|
if (hasInterface) then {
|
||||||
["[ACE] ERROR", _errorMsg, {findDisplay 46 closeDisplay 0}] call FUNC(errorMessage);
|
["[ACE] ERROR", _errorMsg] call FUNC(errorMessage);
|
||||||
};
|
};
|
||||||
|
|
||||||
ERROR(_errorMsg);
|
ERROR(_errorMsg);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (_oldCompats isNotEqualTo []) then {
|
if (_oldCompats isNotEqualTo []) then {
|
||||||
_oldCompats = _oldCompats apply {format ["%1 (%2)", _x select 0, _x select 1]};
|
_oldCompats = _oldCompats apply {format ["%1 (%2)", _x select 0, _x select 1]};
|
||||||
|
|
||||||
[{
|
[{
|
||||||
// Lasts for ~10 seconds
|
// Lasts for ~10 seconds
|
||||||
ERROR_WITH_TITLE_3("The following ACE compatiblity PBOs are outdated","%1. ACE Main version is %2 from %3.",_this select 0,_this select 1,_this select 2);
|
ERROR_WITH_TITLE_3("The following ACE compatiblity PBOs are outdated","%1. ACE Main version is %2 from %3.",_this select 0,_this select 1,_this select 2);
|
||||||
@ -85,9 +99,10 @@ if (_oldCompats isNotEqualTo []) then {
|
|||||||
};
|
};
|
||||||
|
|
||||||
///////////////
|
///////////////
|
||||||
// check extensions
|
// Check extensions
|
||||||
///////////////
|
///////////////
|
||||||
private _platform = toLowerANSI (productVersion select 6);
|
private _platform = toLowerANSI (productVersion select 6);
|
||||||
|
|
||||||
if (!isServer && {_platform in ["linux", "osx"]}) then {
|
if (!isServer && {_platform in ["linux", "osx"]}) then {
|
||||||
// Linux and OSX client ports do not support extensions at all
|
// Linux and OSX client ports do not support extensions at all
|
||||||
INFO("Operating system does not support extensions");
|
INFO("Operating system does not support extensions");
|
||||||
@ -101,8 +116,10 @@ if (!isServer && {_platform in ["linux", "osx"]}) then {
|
|||||||
|
|
||||||
if ((_isWindows || _isLinux) && {_isClient || _isServer}) then {
|
if ((_isWindows || _isLinux) && {_isClient || _isServer}) then {
|
||||||
private _versionEx = _extension callExtension "version";
|
private _versionEx = _extension callExtension "version";
|
||||||
|
|
||||||
if (_versionEx == "") then {
|
if (_versionEx == "") then {
|
||||||
private _extensionFile = _extension;
|
private _extensionFile = _extension;
|
||||||
|
|
||||||
if (productVersion select 7 == "x64") then {
|
if (productVersion select 7 == "x64") then {
|
||||||
_extensionFile = format ["%1_x64", _extensionFile];
|
_extensionFile = format ["%1_x64", _extensionFile];
|
||||||
};
|
};
|
||||||
@ -114,7 +131,7 @@ if (!isServer && {_platform in ["linux", "osx"]}) then {
|
|||||||
ERROR(_errorMsg);
|
ERROR(_errorMsg);
|
||||||
|
|
||||||
if (hasInterface) then {
|
if (hasInterface) then {
|
||||||
["[ACE] ERROR", _errorMsg, {findDisplay 46 closeDisplay 0}] call FUNC(errorMessage);
|
["[ACE] ERROR", _errorMsg] call FUNC(errorMessage);
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
// Print the current extension version
|
// Print the current extension version
|
||||||
@ -123,54 +140,66 @@ if (!isServer && {_platform in ["linux", "osx"]}) then {
|
|||||||
};
|
};
|
||||||
} forEach ("true" configClasses (configFile >> "ACE_Extensions"));
|
} forEach ("true" configClasses (configFile >> "ACE_Extensions"));
|
||||||
};
|
};
|
||||||
|
|
||||||
if (isArray (configFile >> "ACE_Extensions" >> "extensions")) then {
|
if (isArray (configFile >> "ACE_Extensions" >> "extensions")) then {
|
||||||
WARNING("extensions[] array no longer supported");
|
WARNING("extensions[] array no longer supported");
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////
|
///////////////
|
||||||
// check server version/addons
|
// Check server version/addons
|
||||||
///////////////
|
///////////////
|
||||||
if (isMultiplayer) then {
|
if (isMultiplayer) then {
|
||||||
// don't check optional addons
|
// Don't check optional addons
|
||||||
_addons = _addons select {getNumber (configFile >> "CfgPatches" >> _x >> "ACE_isOptional") != 1};
|
_addons = _addons select {getNumber (_cfgPatches >> _x >> "ACE_isOptional") != 1};
|
||||||
|
|
||||||
if (isServer) then {
|
if (isServer) then {
|
||||||
// send servers version of ACE to all clients
|
// Send server's version of ACE to all clients
|
||||||
GVAR(ServerVersion) = _mainVersion;
|
GVAR(serverVersion) = _mainVersion;
|
||||||
GVAR(ServerAddons) = _addons;
|
GVAR(serverAddons) = _addons;
|
||||||
publicVariable QGVAR(ServerVersion);
|
GVAR(serverSource) = _mainSource;
|
||||||
publicVariable QGVAR(ServerAddons);
|
|
||||||
|
publicVariable QGVAR(serverVersion);
|
||||||
|
publicVariable QGVAR(serverAddons);
|
||||||
|
publicVariable QGVAR(serverSource);
|
||||||
} else {
|
} else {
|
||||||
// clients have to wait for the variables
|
GVAR(clientVersion) = _version;
|
||||||
[{
|
GVAR(clientAddons) = _addons;
|
||||||
if (isNil QGVAR(ServerVersion) || isNil QGVAR(ServerAddons)) exitWith {};
|
|
||||||
|
|
||||||
(_this select 0) params ["_mainVersion", "_addons"];
|
private _fnc_check = {
|
||||||
|
if (GVAR(clientVersion) != GVAR(serverVersion)) then {
|
||||||
if (_mainVersion != GVAR(ServerVersion)) then {
|
private _errorMsg = format ["Client/Server Version Mismatch. Server: %1, Client: %2. Server modDir: %3", GVAR(serverVersion), GVAR(clientVersion), GVAR(serverSource)];
|
||||||
private _errorMsg = format ["Client/Server Version Mismatch. Server: %1, Client: %2.", GVAR(ServerVersion), _mainVersion];
|
|
||||||
|
|
||||||
|
// Check ACE install
|
||||||
call FUNC(checkFiles_diagnoseACE);
|
call FUNC(checkFiles_diagnoseACE);
|
||||||
|
|
||||||
ERROR(_errorMsg);
|
ERROR(_errorMsg);
|
||||||
|
|
||||||
if (hasInterface) then {
|
if (hasInterface) then {
|
||||||
["[ACE] ERROR", _errorMsg, {findDisplay 46 closeDisplay 0}] call FUNC(errorMessage);
|
["[ACE] ERROR", _errorMsg] call FUNC(errorMessage);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
_addons = _addons - GVAR(ServerAddons);
|
private _addons = GVAR(clientAddons) - GVAR(serverAddons);
|
||||||
|
|
||||||
if (_addons isNotEqualTo []) then {
|
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 additional addons: %1. Server modDir: %2", _addons, GVAR(serverSource)];
|
||||||
|
|
||||||
|
// Check ACE install
|
||||||
call FUNC(checkFiles_diagnoseACE);
|
call FUNC(checkFiles_diagnoseACE);
|
||||||
|
|
||||||
ERROR(_errorMsg);
|
ERROR(_errorMsg);
|
||||||
|
|
||||||
if (hasInterface) then {
|
if (hasInterface) then {
|
||||||
["[ACE] ERROR", _errorMsg, {findDisplay 46 closeDisplay 0}] call FUNC(errorMessage);
|
["[ACE] ERROR", _errorMsg] call FUNC(errorMessage);
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
[_this select 1] call CBA_fnc_removePerFrameHandler;
|
// Clients have to wait for the variables
|
||||||
}, 1, [_mainVersion,_addons]] call CBA_fnc_addPerFrameHandler;
|
if (isNil QGVAR(serverVersion) || isNil QGVAR(serverAddons)) then {
|
||||||
|
GVAR(serverVersion) addPublicVariableEventHandler _fnc_check;
|
||||||
|
} else {
|
||||||
|
call _fnc_check;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
#include "..\script_component.hpp"
|
#include "..\script_component.hpp"
|
||||||
/*
|
/*
|
||||||
* Author: PabstMirror
|
* Author: PabstMirror
|
||||||
* Diagnose ACE install problems, this will only be called if there is a known problem
|
* Diagnoses ACE install problems, this will only be called if there is a known problem.
|
||||||
*
|
*
|
||||||
* Arguments:
|
* Arguments:
|
||||||
* None
|
* None
|
||||||
*
|
*
|
||||||
* Return Value:
|
* Return Value:
|
||||||
* None
|
* ACE addons' WS IDs <HASHMAP>
|
||||||
*
|
*
|
||||||
* Example:
|
* Example:
|
||||||
* [] call ace_common_fnc_checkFiles_diagnoseACE
|
* [] call ace_common_fnc_checkFiles_diagnoseACE
|
||||||
@ -16,23 +16,35 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Only run once
|
// Only run once
|
||||||
if (missionNameSpace getVariable [QGVAR(checkFiles_diagnoseACE), false]) exitWith {};
|
if (missionNameSpace getVariable [QGVAR(checkFiles_diagnoseACE), false]) exitWith {
|
||||||
|
createHashMap // return
|
||||||
|
};
|
||||||
|
|
||||||
GVAR(checkFiles_diagnoseACE) = true;
|
GVAR(checkFiles_diagnoseACE) = true;
|
||||||
|
|
||||||
private _addons = cba_common_addons select {(_x select [0,4]) == "ace_"};
|
private _addons = CBA_common_addons select {(_x select [0, 4]) == "ace_"};
|
||||||
private _cfgPatches = configFile >> "CfgPatches";
|
private _cfgPatches = configFile >> "CfgPatches";
|
||||||
private _allMods = createHashMap;
|
private _allMods = createHashMap;
|
||||||
|
private _getLoadedModsInfo = getLoadedModsInfo;
|
||||||
|
|
||||||
// Check ACE_ADDONs are in expected mod DIR
|
// Check if ACE_ADDONs are in expected mod DIR
|
||||||
{
|
{
|
||||||
private _cfg = (_cfgPatches >> _x);
|
private _cfg = _cfgPatches >> _x;
|
||||||
private _actualModDir = configSourceMod _cfg;
|
private _actualModDir = configSourceMod _cfg;
|
||||||
private _expectedModDir = getText (_cfg >> "ACE_expectedModDir");
|
private _expectedModDir = getText (_cfg >> "ACE_expectedModDir");
|
||||||
if (_expectedModDir == "") then { _expectedModDir = "@ace" };
|
|
||||||
|
if (_expectedModDir == "") then {
|
||||||
|
_expectedModDir = "@ace";
|
||||||
|
};
|
||||||
|
|
||||||
private _expectedSteamID = getText (_cfg >> "ACE_expectedSteamID");
|
private _expectedSteamID = getText (_cfg >> "ACE_expectedSteamID");
|
||||||
if (_expectedSteamID == "") then { _expectedSteamID = "463939057" };
|
|
||||||
|
if (_expectedSteamID == "") then {
|
||||||
|
_expectedSteamID = "463939057"
|
||||||
|
};
|
||||||
|
|
||||||
(_allMods getOrDefault [_actualModDir, [], true]) pushBackUnique _expectedSteamID;
|
(_allMods getOrDefault [_actualModDir, [], true]) pushBackUnique _expectedSteamID;
|
||||||
|
|
||||||
if (_actualModDir != _expectedModDir) then {
|
if (_actualModDir != _expectedModDir) then {
|
||||||
private _errorMsg = format ["%1 loading from unexpected modDir [%2]", _x, _actualModDir];
|
private _errorMsg = format ["%1 loading from unexpected modDir [%2]", _x, _actualModDir];
|
||||||
systemChat _errorMsg;
|
systemChat _errorMsg;
|
||||||
@ -40,13 +52,17 @@ private _allMods = createHashMap;
|
|||||||
};
|
};
|
||||||
} forEach _addons;
|
} forEach _addons;
|
||||||
|
|
||||||
// Check all ACE ModDirs have expected steam WS ID
|
// Check if all ACE ModDirs have expected steam WS ID
|
||||||
{
|
{
|
||||||
private _modDir = _x;
|
private _modDir = _x;
|
||||||
if ((count _y) != 1) then { ERROR_2("Unexpected multiple steamIDs %1 - %2",_modDir,_y) };
|
|
||||||
private _expectedSteamID = _y # 0;
|
if (count _y != 1) then {
|
||||||
private _index = getLoadedModsInfo findIf {_x#1 == _modDir};
|
ERROR_2("Unexpected multiple steamIDs %1 - %2",_modDir,_y);
|
||||||
(getLoadedModsInfo param [_index, []]) params [["_modName", "$Error$"], "", "", "", "", "", "", ["_actualID", ""]];
|
};
|
||||||
|
|
||||||
|
private _expectedSteamID = _y select 0;
|
||||||
|
private _index = _getLoadedModsInfo findIf {_x select 1 == _modDir};
|
||||||
|
(_getLoadedModsInfo param [_index, []]) params [["_modName", "$Error$"], "", "", "", "", "", "", ["_actualID", ""]];
|
||||||
|
|
||||||
if (_actualID != _expectedSteamID) then {
|
if (_actualID != _expectedSteamID) then {
|
||||||
private _errorMsg = format ["%1 [%2] unexpected workshopID [%3]", _modDir, _modName, _actualID];
|
private _errorMsg = format ["%1 [%2] unexpected workshopID [%3]", _modDir, _modName, _actualID];
|
||||||
@ -55,4 +71,4 @@ private _allMods = createHashMap;
|
|||||||
};
|
};
|
||||||
} forEach _allMods;
|
} forEach _allMods;
|
||||||
|
|
||||||
_allMods
|
_allMods // return
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "..\script_component.hpp"
|
#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.
|
* 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.
|
* Checks PBO versions and compares to the one running on server.
|
||||||
*
|
*
|
||||||
@ -9,8 +9,8 @@
|
|||||||
* 0 = Warn once
|
* 0 = Warn once
|
||||||
* 1 = Warn permanently
|
* 1 = Warn permanently
|
||||||
* 2 = Kick
|
* 2 = Kick
|
||||||
* 1: Check all PBOs? (default: false) <BOOL>
|
* 1: Check all PBOs? <BOOL> (default: false)
|
||||||
* 2: Whitelist (default: "") <STRING>
|
* 2: Whitelist <STRING> (default: "")
|
||||||
*
|
*
|
||||||
* Return Value:
|
* Return Value:
|
||||||
* None
|
* None
|
||||||
@ -24,7 +24,7 @@
|
|||||||
params ["_mode", ["_checkAll", false], ["_whitelist", "", [""]]];
|
params ["_mode", ["_checkAll", false], ["_whitelist", "", [""]]];
|
||||||
TRACE_3("params",_mode,_checkAll,_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 = toLowerANSI _whitelist;
|
_whitelist = toLowerANSI _whitelist;
|
||||||
_whitelist = _whitelist splitString "[,""']";
|
_whitelist = _whitelist splitString "[,""']";
|
||||||
TRACE_1("Array",_whitelist);
|
TRACE_1("Array",_whitelist);
|
||||||
@ -32,75 +32,67 @@ TRACE_1("Array",_whitelist);
|
|||||||
ACE_Version_CheckAll = _checkAll;
|
ACE_Version_CheckAll = _checkAll;
|
||||||
ACE_Version_Whitelist = _whitelist;
|
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 (!isServer) then {
|
||||||
[{
|
["ace_versioning_clientCheckDone", {
|
||||||
if (isNil "ACE_Version_ClientErrors") exitWith {};
|
// 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 ["_missingAddonClient", "_additionalAddonClient", "_olderVersionClient", "_newerVersionClient"];
|
||||||
|
_thisArgs params ["_mode"];
|
||||||
|
|
||||||
(_this select 0) params ["_mode", "_checkAll", "_whitelist"];
|
// Display error message(s)
|
||||||
|
if (_missingAddonClient || {_additionalAddonClient} || {_olderVersionClient} || {_newerVersionClient}) then {
|
||||||
|
private _errorMsg = "[ACE] Version mismatch:<br/><br/>";
|
||||||
|
private _error = [];
|
||||||
|
|
||||||
// Display error message.
|
if (_missingAddonClient) then {
|
||||||
if (_missingAddon || {_missingAddonServer} || {_oldVersionClient} || {_oldVersionServer}) then {
|
_errorMsg = _errorMsg + "Detected missing addon on client<br/>";
|
||||||
private _text = "[ACE] Version mismatch:<br/><br/>";
|
_error pushBack "Missing file(s)";
|
||||||
private _error = format ["ACE version mismatch: %1: ", profileName];
|
|
||||||
|
|
||||||
if (_missingAddon) then {
|
|
||||||
_text = _text + "Detected missing addon on client<br/>";
|
|
||||||
_error = _error + "Missing file(s); ";
|
|
||||||
};
|
|
||||||
if (_missingAddonServer) then {
|
|
||||||
_text = _text + "Detected missing addon on server<br/>";
|
|
||||||
_error = _error + "Additional file(s); ";
|
|
||||||
};
|
|
||||||
if (_oldVersionClient) then {
|
|
||||||
_text = _text + "Detected old client version<br/>";
|
|
||||||
_error = _error + "Older version; ";
|
|
||||||
};
|
|
||||||
if (_oldVersionServer) then {
|
|
||||||
_text = _text + "Detected old server version<br/>";
|
|
||||||
_error = _error + "Newer version; ";
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//[QGVAR(systemChatGlobal), _error] call CBA_fnc_globalEvent;
|
if (_additionalAddonClient) then {
|
||||||
|
_errorMsg = _errorMsg + "Detected additional addon on client<br/>";
|
||||||
|
_error pushBack "Additional file(s)";
|
||||||
|
};
|
||||||
|
|
||||||
ERROR(_error);
|
if (_olderVersionClient) then {
|
||||||
|
_errorMsg = _errorMsg + "Detected older client version<br/>";
|
||||||
|
_error pushBack "Older version";
|
||||||
|
};
|
||||||
|
|
||||||
|
if (_newerVersionClient) then {
|
||||||
|
_errorMsg = _errorMsg + "Detected newer client version<br/>";
|
||||||
|
_error pushBack "Newer version";
|
||||||
|
};
|
||||||
|
|
||||||
|
ERROR_2("[ACE] Version mismatch: %1: %2",profileName,_error joinString ", ");
|
||||||
|
|
||||||
|
_errorMsg = parseText format ["<t align='center'>%1</t>", _errorMsg];
|
||||||
|
|
||||||
|
// Warn
|
||||||
if (_mode < 2) then {
|
if (_mode < 2) then {
|
||||||
_text = composeText [lineBreak, parseText format ["<t align='center'>%1</t>", _text]];
|
|
||||||
|
|
||||||
private _rscLayer = "ACE_RscErrorHint" call BIS_fnc_rscLayer;
|
private _rscLayer = "ACE_RscErrorHint" call BIS_fnc_rscLayer;
|
||||||
_rscLayer cutRsc ["ACE_RscErrorHint", "PLAIN", 0, true];
|
_rscLayer cutRsc ["ACE_RscErrorHint", "PLAIN", 0, true];
|
||||||
|
|
||||||
disableSerialization;
|
(uiNamespace getVariable "ACE_ctrlErrorHint") ctrlSetStructuredText composeText [lineBreak, _errorMsg];
|
||||||
private _ctrlHint = uiNamespace getVariable "ACE_ctrlErrorHint";
|
|
||||||
_ctrlHint ctrlSetStructuredText _text;
|
|
||||||
|
|
||||||
if (_mode == 0) then {
|
if (_mode == 0) then {
|
||||||
[{
|
[{
|
||||||
params ["_rscLayer"];
|
TRACE_2("Hiding Error message after 10 seconds",time,_this);
|
||||||
TRACE_2("Hiding Error message after 10 seconds",time,_rscLayer);
|
_this cutFadeOut 0.2;
|
||||||
_rscLayer cutFadeOut 0.2;
|
}, _rscLayer, 10] call CBA_fnc_waitAndExecute;
|
||||||
}, [_rscLayer], 10] call CBA_fnc_waitAndExecute;
|
|
||||||
};
|
};
|
||||||
|
} else {
|
||||||
|
// Kick
|
||||||
|
["[ACE] ERROR", composeText [_errorMsg]] call FUNC(errorMessage);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}, [_mode]] call CBA_fnc_addEventHandlerArgs;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (_mode == 2) then {
|
// Check file version numbers
|
||||||
[{alive player}, { // To be able to show list if using checkAll
|
[_whitelist] call FUNC(checkVersionNumber);
|
||||||
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;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
[_this select 1] call CBA_fnc_removePerFrameHandler;
|
|
||||||
}, 1, [_mode, _checkAll, _whitelist]] call CBA_fnc_addPerFrameHandler;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (_checkAll) then {
|
|
||||||
0 spawn COMPILE_FILE(scripts\checkVersionNumber); // @todo
|
|
||||||
};
|
|
||||||
|
161
addons/common/functions/fnc_checkVersionNumber.sqf
Normal file
161
addons/common/functions/fnc_checkVersionNumber.sqf
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
#include "..\script_component.hpp"
|
||||||
|
/*
|
||||||
|
* Author: commy2, johnb43
|
||||||
|
* Compares version numbers from loaded addons.
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* 0: Lowercase addon whitelist <ARRAY> (default: missionNamespace getVariable ["ACE_Version_Whitelist", []])
|
||||||
|
*
|
||||||
|
* Return Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* call ace_common_fnc_checkVersionNumber
|
||||||
|
*
|
||||||
|
* Public: No
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Don't execute in scheduled environment
|
||||||
|
if (canSuspend) exitWith {
|
||||||
|
[FUNC(checkVersionNumber), _this] call CBA_fnc_directCall;
|
||||||
|
};
|
||||||
|
|
||||||
|
params [["_whitelist", missionNamespace getVariable ["ACE_Version_Whitelist", []]]];
|
||||||
|
|
||||||
|
private _files = CBA_common_addons select {
|
||||||
|
(_x select [0, 3] != "a3_") &&
|
||||||
|
{_x select [0, 4] != "ace_"} &&
|
||||||
|
{!((toLowerANSI _x) in _whitelist)}
|
||||||
|
};
|
||||||
|
|
||||||
|
private _cfgPatches = configFile >> "CfgPatches";
|
||||||
|
private _versions = [];
|
||||||
|
|
||||||
|
{
|
||||||
|
(getText (_cfgPatches >> _x >> "version") splitString ".") params [["_major", "0"], ["_minor", "0"]];
|
||||||
|
private _version = parseNumber _major + parseNumber _minor / 100;
|
||||||
|
_versions pushBack _version;
|
||||||
|
} forEach _files;
|
||||||
|
|
||||||
|
if (isServer) exitWith {
|
||||||
|
ACE_Version_ServerVersions = [_files, _versions];
|
||||||
|
publicVariable "ACE_Version_ServerVersions";
|
||||||
|
|
||||||
|
// Raise event when done
|
||||||
|
["ace_versioning_serverCheckDone", [+ACE_Version_ServerVersions]] call CBA_fnc_localEvent;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Begin client version check
|
||||||
|
ACE_Version_ClientVersions = [_files, _versions];
|
||||||
|
|
||||||
|
private _fnc_check = {
|
||||||
|
ACE_Version_ClientVersions params [["_files", []], ["_versions", []]];
|
||||||
|
ACE_Version_ServerVersions params [["_serverFiles", []], ["_serverVersions", []]];
|
||||||
|
|
||||||
|
// Compare client and server files and versions
|
||||||
|
private _client = profileName;
|
||||||
|
private _missingAddonsClient = [];
|
||||||
|
private _olderVersionsClient = [];
|
||||||
|
private _newerVersionsClient = [];
|
||||||
|
|
||||||
|
{
|
||||||
|
private _serverVersion = _serverVersions select _forEachIndex;
|
||||||
|
|
||||||
|
private _index = _files find _x;
|
||||||
|
|
||||||
|
if (_index == -1) then {
|
||||||
|
if (_x != "ace_server") then {
|
||||||
|
_missingAddonsClient pushBack _x;
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
private _clientVersion = _versions select _index;
|
||||||
|
|
||||||
|
if (_clientVersion < _serverVersion) then {
|
||||||
|
_olderVersionsClient pushBack [_x, _clientVersion, _serverVersion];
|
||||||
|
};
|
||||||
|
|
||||||
|
if (_clientVersion > _serverVersion) then {
|
||||||
|
_newerVersionsClient pushBack [_x, _clientVersion, _serverVersion];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} forEach _serverFiles;
|
||||||
|
|
||||||
|
// Find client files which the server doesn't have
|
||||||
|
private _additionalAddonsClient = _files select {!(_x in _serverFiles)};
|
||||||
|
|
||||||
|
// Check for client missing addons, server missing addons, client outdated addons and server outdated addons
|
||||||
|
private _clientErrors = [];
|
||||||
|
|
||||||
|
#define DISPLAY_NUMBER_ADDONS (10 + 1) // +1 to account for header
|
||||||
|
|
||||||
|
{
|
||||||
|
_x params ["_items", "_string"];
|
||||||
|
|
||||||
|
// Check if something is either missing or outdated
|
||||||
|
private _isMissingItems = _items isNotEqualTo [];
|
||||||
|
|
||||||
|
if (_isMissingItems) then {
|
||||||
|
// Generate error message
|
||||||
|
private _errorLog = +_items;
|
||||||
|
private _header = format ["[ACE] %1: ERROR %2 addon(s): ", _client, _string];
|
||||||
|
|
||||||
|
// Don't display all missing items, as they are logged
|
||||||
|
private _errorMsg = _header + ((_errorLog select [0, DISPLAY_NUMBER_ADDONS]) joinString ", ");
|
||||||
|
_errorLog = _header + (_errorLog joinString ", ");
|
||||||
|
|
||||||
|
private _count = count _items;
|
||||||
|
|
||||||
|
if (_count > DISPLAY_NUMBER_ADDONS) then {
|
||||||
|
_errorMsg = _errorMsg + format [", and %1 more.", _count - DISPLAY_NUMBER_ADDONS];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Wait until in briefing screen
|
||||||
|
[{
|
||||||
|
getClientStateNumber >= 9 // "BRIEFING SHOWN"
|
||||||
|
}, {
|
||||||
|
params ["_errorLog", "_errorMsg"];
|
||||||
|
|
||||||
|
// Log and display error messages
|
||||||
|
diag_log text _errorLog;
|
||||||
|
[QGVAR(serverLog), _errorLog] call CBA_fnc_serverEvent;
|
||||||
|
[QGVAR(systemChatGlobal), _errorMsg] call CBA_fnc_globalEvent;
|
||||||
|
|
||||||
|
// Wait until after map screen
|
||||||
|
[{
|
||||||
|
!isNull (call BIS_fnc_displayMission)
|
||||||
|
}, {
|
||||||
|
params ["_errorMsg", "_timeOut"];
|
||||||
|
|
||||||
|
// If the briefing screen was shown for less than 5 seconds, display the error message again, but locally
|
||||||
|
if (_timeOut < CBA_missionTime) exitWith {};
|
||||||
|
|
||||||
|
// Make sure systemChat is ready by waiting a bit
|
||||||
|
[{
|
||||||
|
systemChat _this;
|
||||||
|
}, _errorMsg, 1] call CBA_fnc_waitAndExecute;
|
||||||
|
}, [_errorMsg, CBA_missionTime + 5]] call CBA_fnc_waitUntilAndExecute;
|
||||||
|
}, [_errorLog, _errorMsg]] call CBA_fnc_waitUntilAndExecute;
|
||||||
|
};
|
||||||
|
|
||||||
|
_clientErrors pushBack _isMissingItems;
|
||||||
|
} forEach [
|
||||||
|
[_missingAddonsClient, "client missing"],
|
||||||
|
[_additionalAddonsClient, "client additional"],
|
||||||
|
[_olderVersionsClient, "older client"],
|
||||||
|
[_newerVersionsClient, "newer client"]
|
||||||
|
];
|
||||||
|
|
||||||
|
TRACE_4("",_missingAddonsClient,_additionalAddonsClient,_olderVersionsClient,_newerVersionsClient);
|
||||||
|
|
||||||
|
ACE_Version_ClientErrors = _clientErrors;
|
||||||
|
|
||||||
|
// Raise event when done
|
||||||
|
["ace_versioning_clientCheckDone", [+ACE_Version_ClientErrors]] call CBA_fnc_localEvent;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Wait for server to send the servers files and version numbers
|
||||||
|
if (isNil "ACE_Version_ServerVersions") then {
|
||||||
|
ACE_Version_ServerVersions addPublicVariableEventHandler _fnc_check;
|
||||||
|
} else {
|
||||||
|
call _fnc_check;
|
||||||
|
};
|
@ -1,46 +1,53 @@
|
|||||||
#include "..\script_component.hpp"
|
#include "..\script_component.hpp"
|
||||||
|
#include "\a3\ui_f\hpp\defineResincl.inc"
|
||||||
|
#include "\a3\ui_f\hpp\defineDIKCodes.inc"
|
||||||
/*
|
/*
|
||||||
* Author: commy2, based on BIS_fnc_errorMsg and BIS_fnc_guiMessage by Karel Moricky (BI)
|
* Author: commy2, johnb43, based on BIS_fnc_errorMsg and BIS_fnc_guiMessage by Karel Moricky (BI)
|
||||||
* Stops simulation and opens a textbox with error message.
|
* Opens a textbox with an error message, used for PBO checking.
|
||||||
*
|
*
|
||||||
* Arguments:
|
* Arguments:
|
||||||
* ?
|
* 0: Header <STRING>
|
||||||
|
* 1: Text <STRING|TEXT>
|
||||||
*
|
*
|
||||||
* Return Value:
|
* Return Value:
|
||||||
* None
|
* None
|
||||||
*
|
*
|
||||||
* Example:
|
* Example:
|
||||||
* call ace_common_fnc_errorMessage
|
* ["[ACE] ERROR", "Test"] call ace_common_fnc_errorMessage
|
||||||
*
|
*
|
||||||
* Public: No
|
* Public: No
|
||||||
*/
|
*/
|
||||||
|
|
||||||
disableSerialization;
|
// Force stop any loading screens
|
||||||
endLoadingScreen;
|
endLoadingScreen;
|
||||||
|
|
||||||
// no message without player possible
|
// No message without interface possible
|
||||||
if (!hasInterface) exitWith {};
|
if (!hasInterface) exitWith {};
|
||||||
|
|
||||||
// wait for display
|
|
||||||
if (isNull (call BIS_fnc_displayMission)) exitWith {
|
|
||||||
[{
|
[{
|
||||||
if (isNull (call BIS_fnc_displayMission)) exitWith {};
|
!isNull (call BIS_fnc_displayMission)
|
||||||
|
}, {
|
||||||
|
params ["_textHeader", "_textMessage"];
|
||||||
|
|
||||||
(_this select 0) call FUNC(errorMessage);
|
disableSerialization;
|
||||||
[_this select 1] call CBA_fnc_removePerFrameHandler;
|
|
||||||
|
|
||||||
}, 1, _this] call CBA_fnc_addPerFrameHandler;
|
// Use curator display if present
|
||||||
|
private _curatorDisplay = findDisplay 312;
|
||||||
|
|
||||||
|
private _mainDisplay = if (!isNull _curatorDisplay) then {
|
||||||
|
_curatorDisplay
|
||||||
|
} else {
|
||||||
|
call BIS_fnc_displayMission
|
||||||
};
|
};
|
||||||
|
|
||||||
params ["_textHeader", "_textMessage", ["_onOK", {}], ["_onCancel", {}]];
|
|
||||||
|
|
||||||
if (_textMessage isEqualType "") then {
|
if (_textMessage isEqualType "") then {
|
||||||
_textMessage = parseText _textMessage;
|
_textMessage = parseText _textMessage;
|
||||||
};
|
};
|
||||||
|
|
||||||
ARR_SELECT(_this,4,call BIS_fnc_displayMission) createDisplay "RscDisplayCommonMessagePause";
|
private _display = _mainDisplay createDisplay "RscDisplayCommonMessagePause";
|
||||||
|
|
||||||
|
if (isNull _display) exitWith {};
|
||||||
|
|
||||||
private _display = uiNamespace getVariable "RscDisplayCommonMessage_display";
|
|
||||||
private _ctrlRscMessageBox = _display displayCtrl 2351;
|
private _ctrlRscMessageBox = _display displayCtrl 2351;
|
||||||
private _ctrlBcgCommonTop = _display displayCtrl 235100;
|
private _ctrlBcgCommonTop = _display displayCtrl 235100;
|
||||||
private _ctrlBcgCommon = _display displayCtrl 235101;
|
private _ctrlBcgCommon = _display displayCtrl 235101;
|
||||||
@ -109,39 +116,26 @@ _ctrlRscMessageBox ctrlSetPosition [
|
|||||||
_ctrlRscMessageBox ctrlEnable true;
|
_ctrlRscMessageBox ctrlEnable true;
|
||||||
_ctrlRscMessageBox ctrlCommit 0;
|
_ctrlRscMessageBox ctrlCommit 0;
|
||||||
|
|
||||||
if (_onOK isEqualTo {}) then {
|
// Enable ok button
|
||||||
_ctrlButtonOK ctrlEnable false;
|
|
||||||
_ctrlButtonOK ctrlSetFade 0;
|
|
||||||
_ctrlButtonOK ctrlSetText "";
|
|
||||||
_ctrlButtonOK ctrlCommit 0;
|
|
||||||
} else {
|
|
||||||
_ctrlButtonOK ctrlEnable true;
|
_ctrlButtonOK ctrlEnable true;
|
||||||
_ctrlButtonOK ctrlSetFade 0;
|
_ctrlButtonOK ctrlSetFade 0;
|
||||||
_ctrlButtonOK ctrlSetText localize "STR_DISP_OK";
|
_ctrlButtonOK ctrlSetText localize "STR_DISP_OK";
|
||||||
_ctrlButtonOK ctrlCommit 0;
|
_ctrlButtonOK ctrlCommit 0;
|
||||||
|
|
||||||
ctrlSetFocus _ctrlButtonOK;
|
ctrlSetFocus _ctrlButtonOK;
|
||||||
};
|
|
||||||
|
|
||||||
if (_onCancel isEqualTo {}) then {
|
// Disable cancel button
|
||||||
_ctrlButtonCancel ctrlEnable false;
|
_ctrlButtonCancel ctrlEnable false;
|
||||||
_ctrlButtonCancel ctrlSetFade 0;
|
_ctrlButtonCancel ctrlSetFade 0;
|
||||||
_ctrlButtonCancel ctrlSetText "";
|
_ctrlButtonCancel ctrlSetText "";
|
||||||
_ctrlButtonCancel ctrlCommit 0;
|
_ctrlButtonCancel ctrlCommit 0;
|
||||||
} else {
|
|
||||||
_ctrlButtonCancel ctrlEnable true;
|
|
||||||
_ctrlButtonCancel ctrlSetFade 0;
|
|
||||||
_ctrlButtonCancel ctrlSetText localize "STR_DISP_CANCEL";
|
|
||||||
_ctrlButtonCancel ctrlCommit 0;
|
|
||||||
|
|
||||||
ctrlSetFocus _ctrlButtonCancel;
|
_ctrlButtonOK ctrlAddEventHandler ["ButtonClick", {(ctrlParent (_this select 0)) closeDisplay IDC_OK; true}];
|
||||||
};
|
|
||||||
|
|
||||||
_ctrlButtonOK ctrlAddEventHandler ["ButtonClick", {(ctrlParent (_this select 0)) closeDisplay 1; true}];
|
// Intercept all keystrokes except the enter keys
|
||||||
_ctrlButtonCancel ctrlAddEventHandler ["ButtonClick", {(ctrlParent (_this select 0)) closeDisplay 2; true}];
|
_display displayAddEventHandler ["KeyDown", {!((_this select 1) in [DIK_RETURN, DIK_NUMPADENTER])}];
|
||||||
|
|
||||||
GVAR(errorOnOK) = _onOK;
|
// Close curator and mission displays (because of the message display, it doesn't quit the mission yet)
|
||||||
GVAR(errorOnCancel) = _onCancel;
|
findDisplay 312 closeDisplay 0;
|
||||||
|
findDisplay 46 closeDisplay 0;
|
||||||
_display displayAddEventHandler ["Unload", {call ([{}, GVAR(errorOnOK), GVAR(errorOnCancel)] select (_this select 1))}];
|
}, _this] call CBA_fnc_waitUntilAndExecute;
|
||||||
_display displayAddEventHandler ["KeyDown", {_this select 1 == 1}];
|
|
||||||
|
@ -1,160 +0,0 @@
|
|||||||
// by commy2
|
|
||||||
#include "..\script_component.hpp"
|
|
||||||
|
|
||||||
private _aceWhitelist = missionNamespace getVariable ["ACE_Version_Whitelist", []];
|
|
||||||
private _files = CBA_common_addons select {
|
|
||||||
(_x select [0,3] != "a3_") &&
|
|
||||||
{_x select [0,4] != "ace_"} &&
|
|
||||||
{!((toLowerANSI _x) in _aceWhitelist)}
|
|
||||||
};
|
|
||||||
|
|
||||||
private _versions = [];
|
|
||||||
{
|
|
||||||
getText (configFile >> "CfgPatches" >> _x >> "version") splitString "." params [["_major", "0"], ["_minor", "0"]];
|
|
||||||
private _version = parseNumber _major + parseNumber _minor/100;
|
|
||||||
_versions set [_forEachIndex, _version];
|
|
||||||
} forEach _files;
|
|
||||||
|
|
||||||
if (isServer) then {
|
|
||||||
ACE_Version_ServerVersions = [_files, _versions];
|
|
||||||
publicVariable "ACE_Version_ServerVersions";
|
|
||||||
} else {
|
|
||||||
ACE_Version_ClientVersions = [_files, _versions];
|
|
||||||
};
|
|
||||||
|
|
||||||
// Begin client version check
|
|
||||||
if (!isServer) then {
|
|
||||||
// Wait for server to send the servers files and version numbers
|
|
||||||
waitUntil {
|
|
||||||
sleep 1;
|
|
||||||
!isNil "ACE_Version_ClientVersions" && {!isNil "ACE_Version_ServerVersions"}
|
|
||||||
};
|
|
||||||
|
|
||||||
private _client = profileName;
|
|
||||||
|
|
||||||
_files = ACE_Version_ClientVersions select 0;
|
|
||||||
_versions = ACE_Version_ClientVersions select 1;
|
|
||||||
|
|
||||||
private _serverFiles = ACE_Version_ServerVersions select 0;
|
|
||||||
private _serverVersions = ACE_Version_ServerVersions select 1;
|
|
||||||
|
|
||||||
// Compare client and server files and versions
|
|
||||||
private _missingAddons = [];
|
|
||||||
private _oldVersionsClient = [];
|
|
||||||
private _oldVersionsServer = [];
|
|
||||||
{
|
|
||||||
private _serverVersion = _serverVersions select _forEachIndex;
|
|
||||||
|
|
||||||
private _index = _files find _x;
|
|
||||||
if (_index == -1) then {
|
|
||||||
if (_x != "ace_server") then {_missingAddons pushBack _x;};
|
|
||||||
} else {
|
|
||||||
|
|
||||||
private _clientVersion = _versions select _index;
|
|
||||||
|
|
||||||
if (_clientVersion < _serverVersion) then {
|
|
||||||
_oldVersionsClient pushBack [_x, _clientVersion, _serverVersion];
|
|
||||||
};
|
|
||||||
|
|
||||||
if (_clientVersion > _serverVersion) then {
|
|
||||||
_oldVersionsServer pushBack [_x, _clientVersion, _serverVersion];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
} forEach _serverFiles;
|
|
||||||
|
|
||||||
// find client files which the server doesn't have
|
|
||||||
private _missingAddonsServer = [];
|
|
||||||
{
|
|
||||||
private _index = _serverFiles find _x;
|
|
||||||
if (_index == -1) then {
|
|
||||||
_missingAddonsServer pushBack _x;
|
|
||||||
}
|
|
||||||
} forEach _files;
|
|
||||||
|
|
||||||
// display and log error messages
|
|
||||||
private _fnc_cutComma = {
|
|
||||||
private _string = _this;
|
|
||||||
_string = toArray _string;
|
|
||||||
|
|
||||||
private _count = count _string;
|
|
||||||
_string set [_count - 2, toArray "." select 0];
|
|
||||||
_string set [_count - 1, -1];
|
|
||||||
_string = _string - [-1];
|
|
||||||
|
|
||||||
toString _string;
|
|
||||||
};
|
|
||||||
|
|
||||||
private _missingAddon = false;
|
|
||||||
if (count _missingAddons > 0) then {
|
|
||||||
_missingAddon = true;
|
|
||||||
|
|
||||||
private _error = format ["[ACE] %1: ERROR client missing addon(s): ", _client];
|
|
||||||
{
|
|
||||||
_error = _error + format ["%1, ", _x];
|
|
||||||
|
|
||||||
if (_forEachIndex > 9) exitWith {};
|
|
||||||
} forEach _missingAddons;
|
|
||||||
|
|
||||||
_error = _error call _fnc_cutComma;
|
|
||||||
|
|
||||||
diag_log text _error;
|
|
||||||
[QGVAR(systemChatGlobal), _error] call CBA_fnc_globalEvent;
|
|
||||||
[QGVAR(serverLog), _error] call CBA_fnc_serverEvent;
|
|
||||||
};
|
|
||||||
|
|
||||||
private _missingAddonServer = false;
|
|
||||||
if (count _missingAddonsServer > 0) then {
|
|
||||||
_missingAddonServer = true;
|
|
||||||
|
|
||||||
private _error = format ["[ACE] %1: ERROR server missing addon(s): ", _client];
|
|
||||||
{
|
|
||||||
_error = _error + format ["%1, ", _x];
|
|
||||||
|
|
||||||
if (_forEachIndex > 9) exitWith {};
|
|
||||||
} forEach _missingAddonsServer;
|
|
||||||
|
|
||||||
_error = _error call _fnc_cutComma;
|
|
||||||
|
|
||||||
diag_log text _error;
|
|
||||||
[QGVAR(systemChatGlobal), _error] call CBA_fnc_globalEvent;
|
|
||||||
[QGVAR(serverLog), _error] call CBA_fnc_serverEvent;
|
|
||||||
};
|
|
||||||
|
|
||||||
private _oldVersionClient = false;
|
|
||||||
if (count _oldVersionsClient > 0) then {
|
|
||||||
_oldVersionClient = true;
|
|
||||||
|
|
||||||
private _error = format ["[ACE] %1: ERROR outdated client addon(s): ", _client];
|
|
||||||
{
|
|
||||||
_error = _error + format ["%1 (client: %2, server: %3), ", _x select 0, _x select 1, _x select 2];
|
|
||||||
|
|
||||||
if (_forEachIndex > 9) exitWith {};
|
|
||||||
} forEach _oldVersionsClient;
|
|
||||||
|
|
||||||
_error = _error call _fnc_cutComma;
|
|
||||||
|
|
||||||
diag_log text _error;
|
|
||||||
[QGVAR(systemChatGlobal), _error] call CBA_fnc_globalEvent;
|
|
||||||
[QGVAR(serverLog), _error] call CBA_fnc_serverEvent;
|
|
||||||
};
|
|
||||||
|
|
||||||
private _oldVersionServer = false;
|
|
||||||
if (count _oldVersionsServer > 0) then {
|
|
||||||
_oldVersionServer = true;
|
|
||||||
|
|
||||||
private _error = format ["[ACE] %1: ERROR outdated server addon(s): ", _client];
|
|
||||||
{
|
|
||||||
_error = _error + format ["%1 (client: %2, server: %3), ", _x select 0, _x select 1, _x select 2];
|
|
||||||
|
|
||||||
if (_forEachIndex > 9) exitWith {};
|
|
||||||
} forEach _oldVersionsServer;
|
|
||||||
|
|
||||||
_error = _error call _fnc_cutComma;
|
|
||||||
|
|
||||||
diag_log text _error;
|
|
||||||
[QGVAR(systemChatGlobal), _error] call CBA_fnc_globalEvent;
|
|
||||||
[QGVAR(serverLog), _error] call CBA_fnc_serverEvent;
|
|
||||||
};
|
|
||||||
|
|
||||||
ACE_Version_ClientErrors = [_missingAddon, _missingAddonServer, _oldVersionClient, _oldVersionServer];
|
|
||||||
};
|
|
@ -30,6 +30,8 @@ The vehicle events will also have the following local variables available `_gunn
|
|||||||
|`ace_firedPlayerVehicle` | [_vehicle, _weapon, _muzzle, _mode, _ammo, _magazine, _projectile] | Local | Listen | ACE_player turret fires |
|
|`ace_firedPlayerVehicle` | [_vehicle, _weapon, _muzzle, _mode, _ammo, _magazine, _projectile] | Local | Listen | ACE_player turret fires |
|
||||||
|`ace_firedPlayerVehicleNonLocal` | [_vehicle, _weapon, _muzzle, _mode, _ammo, _magazine, _projectile] | Local | Listen | Any other player turret fires |
|
|`ace_firedPlayerVehicleNonLocal` | [_vehicle, _weapon, _muzzle, _mode, _ammo, _magazine, _projectile] | Local | Listen | Any other player turret fires |
|
||||||
|`ace_firedNonPlayerVehicle` | [_vehicle, _weapon, _muzzle, _mode, _ammo, _magazine, _projectile] | Local | Listen | AI turret fires |
|
|`ace_firedNonPlayerVehicle` | [_vehicle, _weapon, _muzzle, _mode, _ammo, _magazine, _projectile] | Local | Listen | AI turret fires |
|
||||||
|
|`ace_versioning_clientCheckDone` | [[_missingAddonsClient, _additionalAddonsClient, _olderVersionsClient, _newerVersionsClient]] | Local | Listen | When PBO checking has finished on a client |
|
||||||
|
|`ace_versioning_serverCheckDone` | [[_serverFiles, _serverVersions]] | Local | Listen | When PBO checking has finished on the server |
|
||||||
|
|
||||||
### 2.2 Medical (`ace_medical`)
|
### 2.2 Medical (`ace_medical`)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user