From 0b34a13960f6866e35f12ae9c538c5214c69a549 Mon Sep 17 00:00:00 2001
From: johnb432 <58661205+johnb432@users.noreply.github.com>
Date: Sat, 15 Jul 2023 11:34:56 +0200
Subject: [PATCH 01/26] Update PBO checking
---
addons/common/functions/fnc_checkFiles.sqf | 75 +++---
addons/common/functions/fnc_checkPBOs.sqf | 72 +++--
addons/common/functions/fnc_errorMessage.sqf | 33 ++-
addons/common/scripts/checkVersionNumber.sqf | 268 +++++++++++--------
4 files changed, 261 insertions(+), 187 deletions(-)
diff --git a/addons/common/functions/fnc_checkFiles.sqf b/addons/common/functions/fnc_checkFiles.sqf
index 463ee20f0b8..601c4635306 100644
--- a/addons/common/functions/fnc_checkFiles.sqf
+++ b/addons/common/functions/fnc_checkFiles.sqf
@@ -16,12 +16,13 @@
*/
///////////////
-// check addons
+// Check addons
///////////////
-private _version = getText (configFile >> "CfgPatches" >> "ace_main" >> "versionStr");
+private _cfgPatches = configFile >> "CfgPatches";
+private _version = 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 ".";
@@ -29,34 +30,37 @@ private _cbaRequiredStr = _cbaRequiredAr joinString ".";
INFO_3("ACE is version %1 - CBA is version %2 (min required %3)",_version,_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 _errorMsg = "";
private _oldCompats = [];
+
{
- if (getText (configFile >> "CfgPatches" >> _x >> "versionStr") != _version) then {
- private _errorMsg = format ["File %1.pbo is outdated.", _x];
+ if (getText (_cfgPatches >> _x >> "versionStr") != _version) then {
+ _errorMsg = format ["File %1.pbo is outdated.", _x];
ERROR(_errorMsg);
if ((_x select [0, 10]) != "ace_compat") then {
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 {
_oldCompats pushBack _x; // Don't block game if it's just an old compat pbo
};
};
- false
-} count _addons;
+} forEach _addons;
+
if (_oldCompats isNotEqualTo []) then {
[{
// Lasts for ~10 seconds
@@ -65,24 +69,33 @@ if (_oldCompats isNotEqualTo []) then {
};
///////////////
-// 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];
};
@@ -90,11 +103,11 @@ if (!isServer && {_platform in ["linux", "osx"]}) then {
private _platformExt = [".dll", ".so"] select (_platform == "linux");
_extensionFile = format ["%1%2", _extensionFile, _platformExt];
- private _errorMsg = format ["Extension %1 not found.", _extensionFile];
+ _errorMsg = format ["Extension %1 not found.", _extensionFile];
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
@@ -103,25 +116,26 @@ 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) = _version;
GVAR(ServerAddons) = _addons;
publicVariable QGVAR(ServerVersion);
publicVariable QGVAR(ServerAddons);
} else {
- // clients have to wait for the variables
+ // Clients have to wait for the variables
[{
if (isNil QGVAR(ServerVersion) || isNil QGVAR(ServerAddons)) exitWith {};
@@ -133,22 +147,23 @@ if (isMultiplayer) 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);
};
};
_addons = _addons - 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];
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, [_version,_addons]] call CBA_fnc_addPerFrameHandler;
+ }, 0.5, [_version,_addons]] call CBA_fnc_addPerFrameHandler;
};
};
diff --git a/addons/common/functions/fnc_checkPBOs.sqf b/addons/common/functions/fnc_checkPBOs.sqf
index b45fae45d6e..d7a560d2115 100644
--- a/addons/common/functions/fnc_checkPBOs.sqf
+++ b/addons/common/functions/fnc_checkPBOs.sqf
@@ -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.
*
@@ -24,7 +24,7 @@
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);
@@ -32,75 +32,73 @@ 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:
";
+ private _errorMsg = "[ACE] Version mismatch:
";
private _error = format ["ACE version mismatch: %1: ", profileName];
if (_missingAddon) then {
- _text = _text + "Detected missing addon on client
";
+ _errorMsg = _errorMsg + "Detected missing addon on client
";
_error = _error + "Missing file(s); ";
};
+
if (_missingAddonServer) then {
- _text = _text + "Detected missing addon on server
";
+ _errorMsg = _errorMsg + "Detected missing addon on server
";
_error = _error + "Additional file(s); ";
};
+
if (_oldVersionClient) then {
- _text = _text + "Detected old client version
";
+ _errorMsg = _errorMsg + "Detected old client version
";
_error = _error + "Older version; ";
};
+
if (_oldVersionServer) then {
- _text = _text + "Detected old server version
";
+ _errorMsg = _errorMsg + "Detected old server version
";
_error = _error + "Newer version; ";
};
- //[QGVAR(systemChatGlobal), _error] call CBA_fnc_globalEvent;
-
ERROR(_error);
+ // Warn
if (_mode < 2) then {
- _text = composeText [lineBreak, parseText format ["%1", _text]];
+ _errorMsg = composeText [lineBreak, parseText format ["%1", _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 ["%1", _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 ["%1", _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
-};
+[_whitelist] spawn COMPILE_FILE(scripts\checkVersionNumber); // @todo
diff --git a/addons/common/functions/fnc_errorMessage.sqf b/addons/common/functions/fnc_errorMessage.sqf
index c062c8836cf..6582397993e 100644
--- a/addons/common/functions/fnc_errorMessage.sqf
+++ b/addons/common/functions/fnc_errorMessage.sqf
@@ -1,27 +1,36 @@
#include "script_component.hpp"
/*
- * 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.
*
* Arguments:
- * ?
+ * 0: Header
+ * 1: Text
+ * 2: Code that is executed when 'Ok' is pressed (default: {})
+ * 3: Code that is executed when 'Cancel' is pressed (default: {})
+ * 4: Display (default: call BIS_fnc_displayMission)
+ * 5: Show buttons
+ * 5.0: Show ok button if ok has code (default: true)
+ * 5.1: Show cancel button if cancel has code (default: true)
*
* Return Value:
* None
*
* Example:
- * call ace_common_fnc_errorMessage
+ * ["[ACE] ERROR", text "Test", {findDisplay 46 closeDisplay 0}] call ace_common_fnc_errorMessage
*
* Public: No
*/
disableSerialization;
+
+// Force stop any loading screens
endLoadingScreen;
-// no message without player possible
+// No message without player possible
if (!hasInterface) exitWith {};
-// wait for display
+// Wait for display
if (isNull (call BIS_fnc_displayMission)) exitWith {
[{
if (isNull (call BIS_fnc_displayMission)) exitWith {};
@@ -32,13 +41,14 @@ if (isNull (call BIS_fnc_displayMission)) exitWith {
}, 1, _this] call CBA_fnc_addPerFrameHandler;
};
-params ["_textHeader", "_textMessage", ["_onOK", {}], ["_onCancel", {}]];
+params ["_textHeader", "_textMessage", ["_onOK", {}, [{}]], ["_onCancel", {}, [{}]], ["_mainDisplay", call BIS_fnc_displayMission, [displayNull]], ["_showButtons", [true, true]]];
+_showButtons params [["_showOkButton", true, [false]], ["_showCancelButton", true, [false]]];
if (_textMessage isEqualType "") then {
_textMessage = parseText _textMessage;
};
-ARR_SELECT(_this,4,call BIS_fnc_displayMission) createDisplay "RscDisplayCommonMessagePause";
+_mainDisplay createDisplay "RscDisplayCommonMessagePause";
private _display = uiNamespace getVariable "RscDisplayCommonMessage_display";
private _ctrlRscMessageBox = _display displayCtrl 2351;
@@ -109,7 +119,7 @@ _ctrlRscMessageBox ctrlSetPosition [
_ctrlRscMessageBox ctrlEnable true;
_ctrlRscMessageBox ctrlCommit 0;
-if (_onOK isEqualTo {}) then {
+if (!_showOkButton || {_onOK isEqualTo {}}) then {
_ctrlButtonOK ctrlEnable false;
_ctrlButtonOK ctrlSetFade 0;
_ctrlButtonOK ctrlSetText "";
@@ -123,7 +133,7 @@ if (_onOK isEqualTo {}) then {
ctrlSetFocus _ctrlButtonOK;
};
-if (_onCancel isEqualTo {}) then {
+if (!_showCancelButton || {_onCancel isEqualTo {}}) then {
_ctrlButtonCancel ctrlEnable false;
_ctrlButtonCancel ctrlSetFade 0;
_ctrlButtonCancel ctrlSetText "";
@@ -140,8 +150,5 @@ if (_onCancel isEqualTo {}) then {
_ctrlButtonOK ctrlAddEventHandler ["buttonClick", {(ctrlParent (_this select 0)) closeDisplay 1; true}];
_ctrlButtonCancel ctrlAddEventHandler ["buttonClick", {(ctrlParent (_this select 0)) closeDisplay 2; true}];
-GVAR(errorOnOK) = _onOK;
-GVAR(errorOnCancel) = _onCancel;
-
-_display displayAddEventHandler ["unload", {call ([{}, GVAR(errorOnOK), GVAR(errorOnCancel)] select (_this select 1))}];
+[_display, "unload", {call (_thisArgs select (_this select 1))}, [{}, _onOK, _onCancel]] call CBA_fnc_addBISEventHandler;
_display displayAddEventHandler ["keyDown", {_this select 1 == 1}];
diff --git a/addons/common/scripts/checkVersionNumber.sqf b/addons/common/scripts/checkVersionNumber.sqf
index 15832ed2bd7..56fb21e8dd9 100644
--- a/addons/common/scripts/checkVersionNumber.sqf
+++ b/addons/common/scripts/checkVersionNumber.sqf
@@ -1,160 +1,214 @@
-// by commy2
#include "script_component.hpp"
+/*
+ * Author: commy2, johnb43
+ * Compares version numbers addons loaded.
+ *
+ * Arguments:
+ * 0: Whitelist (default: [])
+ *
+ * Return Value:
+ * None
+ *
+ * Public: No
+ */
+
+params [["_whitelist", []]];
-private _aceWhitelist = missionNamespace getVariable ["ACE_Version_Whitelist", []];
private _files = CBA_common_addons select {
- (_x select [0,3] != "a3_") &&
- {_x select [0,4] != "ace_"} &&
- {!((toLower _x) in _aceWhitelist)}
+ (_x select [0, 3] != "a3_") &&
+ {_x select [0, 4] != "ace_"} &&
+ {!((toLower _x) in _whitelist)}
};
+private _cfgPatches = configFile >> "CfgPatches";
+private _version = -1;
private _versions = [];
+
{
- getText (configFile >> "CfgPatches" >> _x >> "version") splitString "." params [["_major", "0"], ["_minor", "0"]];
- private _version = parseNumber _major + parseNumber _minor/100;
- _versions set [_forEachIndex, _version];
+ (getText (_cfgPatches >> _x >> "version") splitString ".") params [["_major", "0"], ["_minor", "0"]];
+ _version = parseNumber _major + parseNumber _minor / 100;
+ _versions pushBack _version;
} forEach _files;
-if (isServer) then {
+if (isServer) exitWith {
ACE_Version_ServerVersions = [_files, _versions];
publicVariable "ACE_Version_ServerVersions";
-} else {
- ACE_Version_ClientVersions = [_files, _versions];
+
+ // Raise event when done
+ ["ace_versioning_serverCheckDone", [+ACE_Version_ServerVersions]] call CBA_fnc_localEvent;
};
// Begin client version check
-if (!isServer) then {
- // Wait for server to send the servers files and version numbers
+ACE_Version_ClientVersions = [_files, _versions];
+
+// Wait for server to send the servers files and version numbers
+if (isNil "ACE_Version_ServerVersions") then {
waitUntil {
- sleep 1;
- !isNil "ACE_Version_ClientVersions" && {!isNil "ACE_Version_ServerVersions"}
+ sleep 0.5;
+ !isNil "ACE_Version_ServerVersions"
};
+};
- private _client = profileName;
+ACE_Version_ServerVersions params [["_serverFiles", []], ["_serverVersions", []]];
- _files = ACE_Version_ClientVersions select 0;
- _versions = ACE_Version_ClientVersions select 1;
+// Compare client and server files and versions
+private _client = profileName;
+private _missingAddons = [];
+private _oldVersionsClient = [];
+private _oldVersionsServer = [];
- private _serverFiles = ACE_Version_ServerVersions select 0;
- private _serverVersions = ACE_Version_ServerVersions select 1;
+private _clientVersion = -1;
+private _serverVersion = -1;
+private _index = -1;
- // Compare client and server files and versions
- private _missingAddons = [];
- private _oldVersionsClient = [];
- private _oldVersionsServer = [];
- {
- private _serverVersion = _serverVersions select _forEachIndex;
+{
+ _serverVersion = _serverVersions select _forEachIndex;
- private _index = _files find _x;
- if (_index == -1) then {
- if (_x != "ace_server") then {_missingAddons pushBack _x;};
- } else {
+ _index = _files find _x;
- private _clientVersion = _versions select _index;
+ if (_index == -1) then {
+ if (_x != "ace_server") then {
+ _missingAddons pushBack _x;
+ };
+ } else {
+ _clientVersion = _versions select _index;
- if (_clientVersion < _serverVersion) then {
- _oldVersionsClient pushBack [_x, _clientVersion, _serverVersion];
- };
+ if (_clientVersion < _serverVersion) then {
+ _oldVersionsClient pushBack [_x, _clientVersion, _serverVersion];
+ };
- if (_clientVersion > _serverVersion) then {
- _oldVersionsServer pushBack [_x, _clientVersion, _serverVersion];
- };
+ if (_clientVersion > _serverVersion) then {
+ _oldVersionsServer pushBack [_x, _clientVersion, _serverVersion];
};
- } forEach _serverFiles;
+ };
+} 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;
+// Find client files which the server doesn't have
+private _missingAddonsServer = [];
+
+{
+ if ((_serverFiles find _x) == -1) then {
+ _missingAddonsServer pushBack _x;
};
+} forEach _files;
- private _missingAddon = false;
- if (count _missingAddons > 0) then {
- _missingAddon = true;
+// Client missing addon
+private _missingAddon = _missingAddons isNotEqualTo [];
- private _error = format ["[ACE] %1: ERROR client missing addon(s): ", _client];
- {
- _error = _error + format ["%1, ", _x];
+if (_missingAddon) then {
+ private _error = [format ["[ACE] %1: ERROR client missing addon(s): ", _client]];
+ private _cutComma = true;
- if (_forEachIndex > 9) exitWith {};
- } forEach _missingAddons;
+ {
+ if (_forEachIndex >= 11) exitWith {
+ _error pushBack format ["and %1 more.", (count _missingAddons) - 11];
+ _cutComma = false;
+ };
- _error = _error call _fnc_cutComma;
+ _error pushBack format ["%1, ", _x];
+ } forEach _missingAddons;
- diag_log text _error;
- [QGVAR(systemChatGlobal), _error] call CBA_fnc_globalEvent;
- [QGVAR(serverLog), _error] call CBA_fnc_serverEvent;
+ _error = _error joinString "";
+
+ // Remove last comma and whitespace
+ if (_cutComma) then {
+ _error = _error select [0, count _error - 2];
};
- private _missingAddonServer = false;
- if (count _missingAddonsServer > 0) then {
- _missingAddonServer = true;
+ // Display and log error messages
+ diag_log text _error;
+ [QGVAR(systemChatGlobal), _error] call CBA_fnc_globalEvent;
+ [QGVAR(serverLog), _error] call CBA_fnc_serverEvent;
+};
- private _error = format ["[ACE] %1: ERROR server missing addon(s): ", _client];
- {
- _error = _error + format ["%1, ", _x];
+// Server missing addon
+private _missingAddonServer = _missingAddonsServer isNotEqualTo [];
- if (_forEachIndex > 9) exitWith {};
- } forEach _missingAddonsServer;
+if (_missingAddonServer) then {
+ private _error = [format ["[ACE] %1: ERROR server missing addon(s): ", _client]];
+ private _cutComma = true;
- _error = _error call _fnc_cutComma;
+ {
+ if (_forEachIndex >= 11) exitWith {
+ _error pushBack format ["and %1 more.", (count _missingAddonsServer) - 11];
+ _cutComma = false;
+ };
+
+ _error pushBack format ["%1, ", _x];
+ } forEach _missingAddonsServer;
+
+ _error = _error joinString "";
- diag_log text _error;
- [QGVAR(systemChatGlobal), _error] call CBA_fnc_globalEvent;
- [QGVAR(serverLog), _error] call CBA_fnc_serverEvent;
+ // Remove last comma and whitespace
+ if (_cutComma) then {
+ _error = _error select [0, count _error - 2];
};
- private _oldVersionClient = false;
- if (count _oldVersionsClient > 0) then {
- _oldVersionClient = true;
+ // Display and log error messages
+ diag_log text _error;
+ [QGVAR(systemChatGlobal), _error] call CBA_fnc_globalEvent;
+ [QGVAR(serverLog), _error] call CBA_fnc_serverEvent;
+};
+
+// Client outdated addon
+private _oldVersionClient = _oldVersionsClient isNotEqualTo [];
- 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 (_oldVersionClient) then {
+ private _error = [format ["[ACE] %1: ERROR outdated client addon(s): ", _client]];
+ private _cutComma = true;
+
+ {
+ if (_forEachIndex >= 11) exitWith {
+ _error pushBack format ["and %1 more.", (count _oldVersionsClient) - 11];
+ _cutComma = false;
+ };
- if (_forEachIndex > 9) exitWith {};
- } forEach _oldVersionsClient;
+ _error pushBack format ["%1 (client: %2, server: %3), ", _x select 0, _x select 1, _x select 2];
+ } forEach _oldVersionsClient;
- _error = _error call _fnc_cutComma;
+ _error = _error joinString "";
- diag_log text _error;
- [QGVAR(systemChatGlobal), _error] call CBA_fnc_globalEvent;
- [QGVAR(serverLog), _error] call CBA_fnc_serverEvent;
+ // Remove last comma and whitespace
+ if (_cutComma) then {
+ _error = _error select [0, count _error - 2];
};
- private _oldVersionServer = false;
- if (count _oldVersionsServer > 0) then {
- _oldVersionServer = true;
+ // Display and log error messages
+ diag_log text _error;
+ [QGVAR(systemChatGlobal), _error] call CBA_fnc_globalEvent;
+ [QGVAR(serverLog), _error] call CBA_fnc_serverEvent;
+};
+
+// Server outdated addon
+private _oldVersionServer = _oldVersionsServer isNotEqualTo [];
+
+if (_oldVersionServer) then {
+ private _error = [format ["[ACE] %1: ERROR outdated server addon(s): ", _client]];
+ private _cutComma = 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 >= 11) exitWith {
+ _error pushBack format ["and %1 more.", (count _oldVersionsServer) - 11];
+ _cutComma = false;
+ };
- if (_forEachIndex > 9) exitWith {};
- } forEach _oldVersionsServer;
+ _error pushBack format ["%1 (client: %2, server: %3), ", _x select 0, _x select 1, _x select 2];
+ } forEach _oldVersionsServer;
- _error = _error call _fnc_cutComma;
+ _error = _error joinString "";
- diag_log text _error;
- [QGVAR(systemChatGlobal), _error] call CBA_fnc_globalEvent;
- [QGVAR(serverLog), _error] call CBA_fnc_serverEvent;
+ // Remove last comma and whitespace
+ if (_cutComma) then {
+ _error = _error select [0, count _error - 2];
};
- ACE_Version_ClientErrors = [_missingAddon, _missingAddonServer, _oldVersionClient, _oldVersionServer];
+ // Display and log error messages
+ 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];
+
+// Raise event when done
+["ace_versioning_clientCheckDone", [+ACE_Version_ClientErrors]] call CBA_fnc_localEvent;
From 8386a3cf66207b58c21eb5a853793a2988e1ce1d Mon Sep 17 00:00:00 2001
From: johnb432 <58661205+johnb432@users.noreply.github.com>
Date: Tue, 1 Aug 2023 09:34:19 +0200
Subject: [PATCH 02/26] Added kicking of clients without ACE loaded
---
addons/common/XEH_PREP.hpp | 1 +
addons/common/XEH_postInit.sqf | 29 +++
addons/common/functions/fnc_checkFiles.sqf | 23 +-
addons/common/functions/fnc_checkPBOs.sqf | 3 +-
.../functions/fnc_checkVersionNumber.sqf | 216 ++++++++++++++++++
addons/common/functions/fnc_errorMessage.sqf | 10 +-
addons/common/scripts/checkVersionNumber.sqf | 214 -----------------
addons/common/scripts/script_component.hpp | 1 -
8 files changed, 270 insertions(+), 227 deletions(-)
create mode 100644 addons/common/functions/fnc_checkVersionNumber.sqf
delete mode 100644 addons/common/scripts/checkVersionNumber.sqf
delete mode 100644 addons/common/scripts/script_component.hpp
diff --git a/addons/common/XEH_PREP.hpp b/addons/common/XEH_PREP.hpp
index 323f2c1d0d4..962e94f1784 100644
--- a/addons/common/XEH_PREP.hpp
+++ b/addons/common/XEH_PREP.hpp
@@ -26,6 +26,7 @@ PREP(canInteractWith);
PREP(changeProjectileDirection);
PREP(checkFiles);
PREP(checkPBOs);
+PREP(checkVersionNumber);
PREP(claim);
PREP(claimSafeServer);
PREP(codeToString);
diff --git a/addons/common/XEH_postInit.sqf b/addons/common/XEH_postInit.sqf
index 00d1a4406b6..6e6b3e52727 100644
--- a/addons/common/XEH_postInit.sqf
+++ b/addons/common/XEH_postInit.sqf
@@ -244,6 +244,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 {
+ // Send function to client
+ _owner publicVariableClient QFUNC(errorMessage);
+
+ // 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];
+ }, _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
diff --git a/addons/common/functions/fnc_checkFiles.sqf b/addons/common/functions/fnc_checkFiles.sqf
index 601c4635306..27bbcaaf31a 100644
--- a/addons/common/functions/fnc_checkFiles.sqf
+++ b/addons/common/functions/fnc_checkFiles.sqf
@@ -135,14 +135,12 @@ if (isMultiplayer) then {
publicVariable QGVAR(ServerVersion);
publicVariable QGVAR(ServerAddons);
} else {
- // Clients have to wait for the variables
- [{
- if (isNil QGVAR(ServerVersion) || isNil QGVAR(ServerAddons)) exitWith {};
-
- (_this select 0) params ["_version", "_addons"];
+ GVAR(ClientVersion) = _version;
+ GVAR(ClientAddons) = _addons;
- if (_version != GVAR(ServerVersion)) then {
- private _errorMsg = format ["Client/Server Version Mismatch. Server: %1, Client: %2.", GVAR(ServerVersion), _version];
+ private _fnc_check = {
+ if (GVAR(ClientVersion) != GVAR(ServerVersion)) then {
+ private _errorMsg = format ["Client/Server Version Mismatch. Server: %1, Client: %2.", GVAR(ServerVersion), GVAR(ClientVersion)];
ERROR(_errorMsg);
@@ -151,7 +149,7 @@ if (isMultiplayer) then {
};
};
- _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];
@@ -162,8 +160,13 @@ if (isMultiplayer) then {
["[ACE] ERROR", _errorMsg, {findDisplay 46 closeDisplay 0}, {findDisplay 46 closeDisplay 0}, nil, [true, false]] call FUNC(errorMessage);
};
};
+ };
- [_this select 1] call CBA_fnc_removePerFrameHandler;
- }, 0.5, [_version,_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;
+ };
};
};
diff --git a/addons/common/functions/fnc_checkPBOs.sqf b/addons/common/functions/fnc_checkPBOs.sqf
index d7a560d2115..47d64b9a80f 100644
--- a/addons/common/functions/fnc_checkPBOs.sqf
+++ b/addons/common/functions/fnc_checkPBOs.sqf
@@ -101,4 +101,5 @@ if (!isServer) then {
}, [_mode]] call CBA_fnc_addEventHandlerArgs;
};
-[_whitelist] spawn COMPILE_FILE(scripts\checkVersionNumber); // @todo
+// Check file version numbers
+[_whitelist] call FUNC(checkVersionNumber);
diff --git a/addons/common/functions/fnc_checkVersionNumber.sqf b/addons/common/functions/fnc_checkVersionNumber.sqf
new file mode 100644
index 00000000000..496a0494c33
--- /dev/null
+++ b/addons/common/functions/fnc_checkVersionNumber.sqf
@@ -0,0 +1,216 @@
+#include "script_component.hpp"
+/*
+ * Author: commy2, johnb43
+ * Compares version numbers from loaded addons.
+ *
+ * Arguments:
+ * None
+ *
+ * Return Value:
+ * None
+ *
+ * Public: No
+ */
+
+private _whitelist = missionNamespace getVariable ["ACE_Version_Whitelist", []];
+
+private _files = CBA_common_addons select {
+ (_x select [0, 3] != "a3_") &&
+ {_x select [0, 4] != "ace_"} &&
+ {!((toLower _x) in _whitelist)}
+};
+
+private _cfgPatches = configFile >> "CfgPatches";
+private _version = -1;
+private _versions = [];
+
+{
+ (getText (_cfgPatches >> _x >> "version") splitString ".") params [["_major", "0"], ["_minor", "0"]];
+ _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 _missingAddons = [];
+ private _oldVersionsClient = [];
+ private _oldVersionsServer = [];
+
+ private _clientVersion = -1;
+ private _serverVersion = -1;
+ private _index = -1;
+
+ {
+ _serverVersion = _serverVersions select _forEachIndex;
+
+ _index = _files find _x;
+
+ if (_index == -1) then {
+ if (_x != "ace_server") then {
+ _missingAddons pushBack _x;
+ };
+ } else {
+ _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 = [];
+
+ {
+ if ((_serverFiles find _x) == -1) then {
+ _missingAddonsServer pushBack _x;
+ };
+ } forEach _files;
+
+ // Client missing addon
+ private _missingAddon = _missingAddons isNotEqualTo [];
+
+ if (_missingAddon) then {
+ private _error = [format ["[ACE] %1: ERROR client missing addon(s): ", _client]];
+ private _cutComma = true;
+
+ {
+ if (_forEachIndex >= 11) exitWith {
+ _error pushBack format ["and %1 more.", (count _missingAddons) - 11];
+ _cutComma = false;
+ };
+
+ _error pushBack format ["%1, ", _x];
+ } forEach _missingAddons;
+
+ _error = _error joinString "";
+
+ // Remove last comma and whitespace
+ if (_cutComma) then {
+ _error = _error select [0, count _error - 2];
+ };
+
+ // Display and log error messages
+ diag_log text _error;
+ [QGVAR(systemChatGlobal), _error] call CBA_fnc_globalEvent;
+ [QGVAR(serverLog), _error] call CBA_fnc_serverEvent;
+ };
+
+ // Server missing addon
+ private _missingAddonServer = _missingAddonsServer isNotEqualTo [];
+
+ if (_missingAddonServer) then {
+ private _error = [format ["[ACE] %1: ERROR server missing addon(s): ", _client]];
+ private _cutComma = true;
+
+ {
+ if (_forEachIndex >= 11) exitWith {
+ _error pushBack format ["and %1 more.", (count _missingAddonsServer) - 11];
+ _cutComma = false;
+ };
+
+ _error pushBack format ["%1, ", _x];
+ } forEach _missingAddonsServer;
+
+ _error = _error joinString "";
+
+ // Remove last comma and whitespace
+ if (_cutComma) then {
+ _error = _error select [0, count _error - 2];
+ };
+
+ // Display and log error messages
+ diag_log text _error;
+ [QGVAR(systemChatGlobal), _error] call CBA_fnc_globalEvent;
+ [QGVAR(serverLog), _error] call CBA_fnc_serverEvent;
+ };
+
+ // Client outdated addon
+ private _oldVersionClient = _oldVersionsClient isNotEqualTo [];
+
+ if (_oldVersionClient) then {
+ private _error = [format ["[ACE] %1: ERROR outdated client addon(s): ", _client]];
+ private _cutComma = true;
+
+ {
+ if (_forEachIndex >= 11) exitWith {
+ _error pushBack format ["and %1 more.", (count _oldVersionsClient) - 11];
+ _cutComma = false;
+ };
+
+ _error pushBack format ["%1 (client: %2, server: %3), ", _x select 0, _x select 1, _x select 2];
+ } forEach _oldVersionsClient;
+
+ _error = _error joinString "";
+
+ // Remove last comma and whitespace
+ if (_cutComma) then {
+ _error = _error select [0, count _error - 2];
+ };
+
+ // Display and log error messages
+ diag_log text _error;
+ [QGVAR(systemChatGlobal), _error] call CBA_fnc_globalEvent;
+ [QGVAR(serverLog), _error] call CBA_fnc_serverEvent;
+ };
+
+ // Server outdated addon
+ private _oldVersionServer = _oldVersionsServer isNotEqualTo [];
+
+ if (_oldVersionServer) then {
+ private _error = [format ["[ACE] %1: ERROR outdated server addon(s): ", _client]];
+ private _cutComma = true;
+
+ {
+ if (_forEachIndex >= 11) exitWith {
+ _error pushBack format ["and %1 more.", (count _oldVersionsServer) - 11];
+ _cutComma = false;
+ };
+
+ _error pushBack format ["%1 (client: %2, server: %3), ", _x select 0, _x select 1, _x select 2];
+ } forEach _oldVersionsServer;
+
+ _error = _error joinString "";
+
+ // Remove last comma and whitespace
+ if (_cutComma) then {
+ _error = _error select [0, count _error - 2];
+ };
+
+ // Display and log error messages
+ 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];
+
+ // 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;
+};
diff --git a/addons/common/functions/fnc_errorMessage.sqf b/addons/common/functions/fnc_errorMessage.sqf
index 6582397993e..5b5c5f187b7 100644
--- a/addons/common/functions/fnc_errorMessage.sqf
+++ b/addons/common/functions/fnc_errorMessage.sqf
@@ -150,5 +150,13 @@ if (!_showCancelButton || {_onCancel isEqualTo {}}) then {
_ctrlButtonOK ctrlAddEventHandler ["buttonClick", {(ctrlParent (_this select 0)) closeDisplay 1; true}];
_ctrlButtonCancel ctrlAddEventHandler ["buttonClick", {(ctrlParent (_this select 0)) closeDisplay 2; true}];
-[_display, "unload", {call (_thisArgs select (_this select 1))}, [{}, _onOK, _onCancel]] call CBA_fnc_addBISEventHandler;
+// CBA isn't guaranteed to be loaded
+private _ehID = _display displayAddEventHandler ["unload", {
+ params ["_display", "_exitCode"];
+
+ call ((_display getVariable [QGVAR(errorMessageCode_) + str _thisEventHandler, [{}, {}, {}]]) select _exitCode)
+}];
+
+_display setVariable [QGVAR(errorMessageCode_) + str _ehID, [{}, _onOK, _onCancel]];
+
_display displayAddEventHandler ["keyDown", {_this select 1 == 1}];
diff --git a/addons/common/scripts/checkVersionNumber.sqf b/addons/common/scripts/checkVersionNumber.sqf
deleted file mode 100644
index 56fb21e8dd9..00000000000
--- a/addons/common/scripts/checkVersionNumber.sqf
+++ /dev/null
@@ -1,214 +0,0 @@
-#include "script_component.hpp"
-/*
- * Author: commy2, johnb43
- * Compares version numbers addons loaded.
- *
- * Arguments:
- * 0: Whitelist (default: [])
- *
- * Return Value:
- * None
- *
- * Public: No
- */
-
-params [["_whitelist", []]];
-
-private _files = CBA_common_addons select {
- (_x select [0, 3] != "a3_") &&
- {_x select [0, 4] != "ace_"} &&
- {!((toLower _x) in _whitelist)}
-};
-
-private _cfgPatches = configFile >> "CfgPatches";
-private _version = -1;
-private _versions = [];
-
-{
- (getText (_cfgPatches >> _x >> "version") splitString ".") params [["_major", "0"], ["_minor", "0"]];
- _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];
-
-// Wait for server to send the servers files and version numbers
-if (isNil "ACE_Version_ServerVersions") then {
- waitUntil {
- sleep 0.5;
- !isNil "ACE_Version_ServerVersions"
- };
-};
-
-ACE_Version_ServerVersions params [["_serverFiles", []], ["_serverVersions", []]];
-
-// Compare client and server files and versions
-private _client = profileName;
-private _missingAddons = [];
-private _oldVersionsClient = [];
-private _oldVersionsServer = [];
-
-private _clientVersion = -1;
-private _serverVersion = -1;
-private _index = -1;
-
-{
- _serverVersion = _serverVersions select _forEachIndex;
-
- _index = _files find _x;
-
- if (_index == -1) then {
- if (_x != "ace_server") then {
- _missingAddons pushBack _x;
- };
- } else {
- _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 = [];
-
-{
- if ((_serverFiles find _x) == -1) then {
- _missingAddonsServer pushBack _x;
- };
-} forEach _files;
-
-// Client missing addon
-private _missingAddon = _missingAddons isNotEqualTo [];
-
-if (_missingAddon) then {
- private _error = [format ["[ACE] %1: ERROR client missing addon(s): ", _client]];
- private _cutComma = true;
-
- {
- if (_forEachIndex >= 11) exitWith {
- _error pushBack format ["and %1 more.", (count _missingAddons) - 11];
- _cutComma = false;
- };
-
- _error pushBack format ["%1, ", _x];
- } forEach _missingAddons;
-
- _error = _error joinString "";
-
- // Remove last comma and whitespace
- if (_cutComma) then {
- _error = _error select [0, count _error - 2];
- };
-
- // Display and log error messages
- diag_log text _error;
- [QGVAR(systemChatGlobal), _error] call CBA_fnc_globalEvent;
- [QGVAR(serverLog), _error] call CBA_fnc_serverEvent;
-};
-
-// Server missing addon
-private _missingAddonServer = _missingAddonsServer isNotEqualTo [];
-
-if (_missingAddonServer) then {
- private _error = [format ["[ACE] %1: ERROR server missing addon(s): ", _client]];
- private _cutComma = true;
-
- {
- if (_forEachIndex >= 11) exitWith {
- _error pushBack format ["and %1 more.", (count _missingAddonsServer) - 11];
- _cutComma = false;
- };
-
- _error pushBack format ["%1, ", _x];
- } forEach _missingAddonsServer;
-
- _error = _error joinString "";
-
- // Remove last comma and whitespace
- if (_cutComma) then {
- _error = _error select [0, count _error - 2];
- };
-
- // Display and log error messages
- diag_log text _error;
- [QGVAR(systemChatGlobal), _error] call CBA_fnc_globalEvent;
- [QGVAR(serverLog), _error] call CBA_fnc_serverEvent;
-};
-
-// Client outdated addon
-private _oldVersionClient = _oldVersionsClient isNotEqualTo [];
-
-if (_oldVersionClient) then {
- private _error = [format ["[ACE] %1: ERROR outdated client addon(s): ", _client]];
- private _cutComma = true;
-
- {
- if (_forEachIndex >= 11) exitWith {
- _error pushBack format ["and %1 more.", (count _oldVersionsClient) - 11];
- _cutComma = false;
- };
-
- _error pushBack format ["%1 (client: %2, server: %3), ", _x select 0, _x select 1, _x select 2];
- } forEach _oldVersionsClient;
-
- _error = _error joinString "";
-
- // Remove last comma and whitespace
- if (_cutComma) then {
- _error = _error select [0, count _error - 2];
- };
-
- // Display and log error messages
- diag_log text _error;
- [QGVAR(systemChatGlobal), _error] call CBA_fnc_globalEvent;
- [QGVAR(serverLog), _error] call CBA_fnc_serverEvent;
-};
-
-// Server outdated addon
-private _oldVersionServer = _oldVersionsServer isNotEqualTo [];
-
-if (_oldVersionServer) then {
- private _error = [format ["[ACE] %1: ERROR outdated server addon(s): ", _client]];
- private _cutComma = true;
-
- {
- if (_forEachIndex >= 11) exitWith {
- _error pushBack format ["and %1 more.", (count _oldVersionsServer) - 11];
- _cutComma = false;
- };
-
- _error pushBack format ["%1 (client: %2, server: %3), ", _x select 0, _x select 1, _x select 2];
- } forEach _oldVersionsServer;
-
- _error = _error joinString "";
-
- // Remove last comma and whitespace
- if (_cutComma) then {
- _error = _error select [0, count _error - 2];
- };
-
- // Display and log error messages
- 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];
-
-// Raise event when done
-["ace_versioning_clientCheckDone", [+ACE_Version_ClientErrors]] call CBA_fnc_localEvent;
diff --git a/addons/common/scripts/script_component.hpp b/addons/common/scripts/script_component.hpp
deleted file mode 100644
index 6a1bf9154d5..00000000000
--- a/addons/common/scripts/script_component.hpp
+++ /dev/null
@@ -1 +0,0 @@
-#include "\z\ace\addons\common\script_component.hpp"
From fcc8e1db1cdfa617c14ab20039feb6987bf90ebd Mon Sep 17 00:00:00 2001
From: johnb432 <58661205+johnb432@users.noreply.github.com>
Date: Thu, 14 Sep 2023 08:38:25 +0200
Subject: [PATCH 03/26] Update fnc_errorMessage.sqf
---
addons/common/functions/fnc_errorMessage.sqf | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/addons/common/functions/fnc_errorMessage.sqf b/addons/common/functions/fnc_errorMessage.sqf
index 5b5c5f187b7..e5eb224d09b 100644
--- a/addons/common/functions/fnc_errorMessage.sqf
+++ b/addons/common/functions/fnc_errorMessage.sqf
@@ -10,8 +10,8 @@
* 3: Code that is executed when 'Cancel' is pressed (default: {})
* 4: Display (default: call BIS_fnc_displayMission)
* 5: Show buttons
- * 5.0: Show ok button if ok has code (default: true)
- * 5.1: Show cancel button if cancel has code (default: true)
+ * - 0: Show ok button if ok has code (default: true)
+ * - 1: Show cancel button if cancel has code (default: true)
*
* Return Value:
* None
From f5c0fd4bd8a72f48c1e11e59c0950252402aa09f Mon Sep 17 00:00:00 2001
From: johnb432 <58661205+johnb432@users.noreply.github.com>
Date: Thu, 14 Sep 2023 08:46:09 +0200
Subject: [PATCH 04/26] Update fnc_checkVersionNumber.sqf
---
addons/common/functions/fnc_checkVersionNumber.sqf | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/addons/common/functions/fnc_checkVersionNumber.sqf b/addons/common/functions/fnc_checkVersionNumber.sqf
index 496a0494c33..d831c5c3d70 100644
--- a/addons/common/functions/fnc_checkVersionNumber.sqf
+++ b/addons/common/functions/fnc_checkVersionNumber.sqf
@@ -1,4 +1,4 @@
-#include "script_component.hpp"
+#include "..\script_component.hpp"
/*
* Author: commy2, johnb43
* Compares version numbers from loaded addons.
From 152995e3737d5a1d1f7d0c1a3c99ac1d9a666ae7 Mon Sep 17 00:00:00 2001
From: johnb432 <58661205+johnb432@users.noreply.github.com>
Date: Mon, 23 Oct 2023 23:34:08 +0200
Subject: [PATCH 05/26] More compatibility for #9568
---
addons/common/functions/fnc_checkFiles.sqf | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/addons/common/functions/fnc_checkFiles.sqf b/addons/common/functions/fnc_checkFiles.sqf
index 48905010d7c..d0ce92adf26 100644
--- a/addons/common/functions/fnc_checkFiles.sqf
+++ b/addons/common/functions/fnc_checkFiles.sqf
@@ -74,9 +74,9 @@ if (_oldAddons isNotEqualTo []) then {
_oldAddons = _oldAddons apply {"%1.pbo", _x};
private _errorMsg = if (count _oldAddons > 3) then {
- format ["The following files are outdated: %1, and %2 more.
ACE Main version is %3.
Loaded mods with outdated ACE files: %4", (_oldAddons select [0, 3]) joinString ", ", (count _oldAddons) - 3, _mainVersion, _oldSources joinString ", "];
+ format ["The following files are outdated: %1, and %2 more.
ACE Main version is %3 from %4.
Loaded mods with outdated ACE files: %5", (_oldAddons select [0, 3]) joinString ", ", (count _oldAddons) - 3, _mainVersion, _mainSource, _oldSources joinString ", "];
} else {
- format ["The following files are outdated: %1.
ACE Main version is %2.
Loaded mods with outdated ACE files: %3", _oldAddons joinString ", ", _mainVersion, _oldSources joinString ", "];
+ format ["The following files are outdated: %1.
ACE Main version is %2 from %3.
Loaded mods with outdated ACE files: %4", _oldAddons joinString ", ", _mainVersion, _mainSource, _oldSources joinString ", "];
};
if (hasInterface) then {
@@ -87,7 +87,7 @@ if (_oldAddons isNotEqualTo []) then {
};
if (_oldCompats isNotEqualTo []) then {
- _oldCompats = _oldCompats apply {format ["%1 (%2, source: %3)", _x select 0, _x select 1]};
+ _oldCompats = _oldCompats apply {format ["%1 (%2)", _x select 0, _x select 1]};
[{
// Lasts for ~10 seconds
From b5af26727b6f000fdc0f9201814ea5b5df8af121 Mon Sep 17 00:00:00 2001
From: johnb432 <58661205+johnb432@users.noreply.github.com>
Date: Wed, 25 Oct 2023 19:16:56 +0200
Subject: [PATCH 06/26] Cleanup
---
addons/common/functions/fnc_checkFiles.sqf | 29 ++--
addons/common/functions/fnc_checkPBOs.sqf | 8 +-
.../functions/fnc_checkVersionNumber.sqf | 145 +++++-------------
3 files changed, 64 insertions(+), 118 deletions(-)
diff --git a/addons/common/functions/fnc_checkFiles.sqf b/addons/common/functions/fnc_checkFiles.sqf
index 9ca77868084..ad52894a512 100644
--- a/addons/common/functions/fnc_checkFiles.sqf
+++ b/addons/common/functions/fnc_checkFiles.sqf
@@ -15,6 +15,11 @@
* Public: No
*/
+ // Don't execute in scheduled environment
+ if (canSuspend) exitWith {
+ [FUNC(checkFiles), nil] call CBA_fnc_directCall;
+ };
+
///////////////
// Check addons
///////////////
@@ -158,20 +163,21 @@ if (isMultiplayer) then {
if (isServer) then {
// Send server's version of ACE to all clients
- GVAR(ServerVersion) = _mainVersion;
- GVAR(ServerAddons) = _addons;
- publicVariable QGVAR(ServerVersion);
- publicVariable QGVAR(ServerAddons);
+ GVAR(serverVersion) = _mainVersion;
+ GVAR(serverAddons) = _addons;
+ publicVariable QGVAR(serverVersion);
+ publicVariable QGVAR(serverAddons);
} else {
- GVAR(ClientVersion) = _version;
- GVAR(ClientAddons) = _addons;
+ GVAR(clientVersion) = _version;
+ GVAR(clientAddons) = _addons;
private _fnc_check = {
- if (GVAR(ClientVersion) != GVAR(ServerVersion)) then {
- private _errorMsg = format ["Client/Server Version Mismatch. Server: %1, Client: %2.", GVAR(ServerVersion), GVAR(ClientVersion)];
+ 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 {
@@ -179,13 +185,14 @@ if (isMultiplayer) then {
};
};
- private _addons = GVAR(ClientAddons) - 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];
// Check ACE install
call FUNC(checkFiles_diagnoseACE);
+
ERROR(_errorMsg);
if (hasInterface) then {
@@ -195,8 +202,8 @@ if (isMultiplayer) then {
};
// Clients have to wait for the variables
- if (isNil QGVAR(ServerVersion) || isNil QGVAR(ServerAddons)) then {
- GVAR(ServerVersion) addPublicVariableEventHandler _fnc_check;
+ if (isNil QGVAR(serverVersion) || isNil QGVAR(serverAddons)) then {
+ GVAR(serverVersion) addPublicVariableEventHandler _fnc_check;
} else {
call _fnc_check;
};
diff --git a/addons/common/functions/fnc_checkPBOs.sqf b/addons/common/functions/fnc_checkPBOs.sqf
index 0bb8f63750f..37f8355b300 100644
--- a/addons/common/functions/fnc_checkPBOs.sqf
+++ b/addons/common/functions/fnc_checkPBOs.sqf
@@ -24,7 +24,7 @@
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);
@@ -41,15 +41,15 @@ if (!isServer) then {
[_thisType, _thisId] call CBA_fnc_removeEventHandler;
params ["_clientErrors"];
- _clientErrors params ["_missingAddon", "_missingAddonServer", "_oldVersionClient", "_oldVersionServer"];
+ _clientErrors params ["_missingAddonClient", "_missingAddonServer", "_oldVersionClient", "_oldVersionServer"];
_thisArgs params ["_mode"];
// Display error message(s)
- if (_missingAddon || {_missingAddonServer} || {_oldVersionClient} || {_oldVersionServer}) then {
+ if (_missingAddonClient || {_missingAddonServer} || {_oldVersionClient} || {_oldVersionServer}) then {
private _errorMsg = "[ACE] Version mismatch:
";
private _error = format ["ACE version mismatch: %1: ", profileName];
- if (_missingAddon) then {
+ if (_missingAddonClient) then {
_errorMsg = _errorMsg + "Detected missing addon on client
";
_error = _error + "Missing file(s); ";
};
diff --git a/addons/common/functions/fnc_checkVersionNumber.sqf b/addons/common/functions/fnc_checkVersionNumber.sqf
index d831c5c3d70..f76789a16d9 100644
--- a/addons/common/functions/fnc_checkVersionNumber.sqf
+++ b/addons/common/functions/fnc_checkVersionNumber.sqf
@@ -9,10 +9,18 @@
* Return Value:
* None
*
+ * Example:
+ * call ace_common_fnc_checkVersionNumber
+ *
* Public: No
*/
-private _whitelist = missionNamespace getVariable ["ACE_Version_Whitelist", []];
+// 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_") &&
@@ -86,123 +94,54 @@ private _fnc_check = {
};
} forEach _files;
- // Client missing addon
- private _missingAddon = _missingAddons isNotEqualTo [];
-
- if (_missingAddon) then {
- private _error = [format ["[ACE] %1: ERROR client missing addon(s): ", _client]];
- private _cutComma = true;
-
- {
- if (_forEachIndex >= 11) exitWith {
- _error pushBack format ["and %1 more.", (count _missingAddons) - 11];
- _cutComma = false;
- };
-
- _error pushBack format ["%1, ", _x];
- } forEach _missingAddons;
- _error = _error joinString "";
+ // Check for client missing addons, server missing addons, client outdated addons and server outdated addons
+ private _clientErrors = [];
+ private _errorLog = [];
+ private _errorMsg = "";
+ private _count = 0;
- // Remove last comma and whitespace
- if (_cutComma) then {
- _error = _error select [0, count _error - 2];
- };
-
- // Display and log error messages
- diag_log text _error;
- [QGVAR(systemChatGlobal), _error] call CBA_fnc_globalEvent;
- [QGVAR(serverLog), _error] call CBA_fnc_serverEvent;
- };
-
- // Server missing addon
- private _missingAddonServer = _missingAddonsServer isNotEqualTo [];
-
- if (_missingAddonServer) then {
- private _error = [format ["[ACE] %1: ERROR server missing addon(s): ", _client]];
- private _cutComma = true;
-
- {
- if (_forEachIndex >= 11) exitWith {
- _error pushBack format ["and %1 more.", (count _missingAddonsServer) - 11];
- _cutComma = false;
- };
+ #define DISPLAY_NUMBER_ADDONS (10 + 1) // +1 to account for header
- _error pushBack format ["%1, ", _x];
- } forEach _missingAddonsServer;
+ {
+ params ["_items", "_string"];
- _error = _error joinString "";
+ // Check if something is either missing or outdated
+ _missing = _items isNotEqualTo [];
- // Remove last comma and whitespace
- if (_cutComma) then {
- _error = _error select [0, count _error - 2];
- };
+ if (_missing) then {
+ // Generate error message
+ _errorLog = [format ["[ACE] %1: ERROR %2 addon(s): ", _client, _string]];
- // Display and log error messages
- diag_log text _error;
- [QGVAR(systemChatGlobal), _error] call CBA_fnc_globalEvent;
- [QGVAR(serverLog), _error] call CBA_fnc_serverEvent;
- };
+ _errorLog append _items;
- // Client outdated addon
- private _oldVersionClient = _oldVersionsClient isNotEqualTo [];
+ // Don't display all missing items, as they are logged
+ _errorMsg = (_errorLog select [0, DISPLAY_NUMBER_ADDONS]) joinString ", ";
+ _errorLog = _errorLog joinString ", ";
- if (_oldVersionClient) then {
- private _error = [format ["[ACE] %1: ERROR outdated client addon(s): ", _client]];
- private _cutComma = true;
+ _count = count _items;
- {
- if (_forEachIndex >= 11) exitWith {
- _error pushBack format ["and %1 more.", (count _oldVersionsClient) - 11];
- _cutComma = false;
+ if (_count > DISPLAY_NUMBER_ADDONS) then {
+ _errorMsg = _errorMsg + format ["and %1 more.", _count - DISPLAY_NUMBER_ADDONS];
};
- _error pushBack format ["%1 (client: %2, server: %3), ", _x select 0, _x select 1, _x select 2];
- } forEach _oldVersionsClient;
-
- _error = _error joinString "";
-
- // Remove last comma and whitespace
- if (_cutComma) then {
- _error = _error select [0, count _error - 2];
+ // Log and display error messages
+ diag_log text _errorLog;
+ [QGVAR(serverLog), _errorLog] call CBA_fnc_serverEvent;
+ [QGVAR(systemChatGlobal), _error] call CBA_fnc_globalEvent;
};
- // Display and log error messages
- diag_log text _error;
- [QGVAR(systemChatGlobal), _error] call CBA_fnc_globalEvent;
- [QGVAR(serverLog), _error] call CBA_fnc_serverEvent;
- };
-
- // Server outdated addon
- private _oldVersionServer = _oldVersionsServer isNotEqualTo [];
-
- if (_oldVersionServer) then {
- private _error = [format ["[ACE] %1: ERROR outdated server addon(s): ", _client]];
- private _cutComma = true;
-
- {
- if (_forEachIndex >= 11) exitWith {
- _error pushBack format ["and %1 more.", (count _oldVersionsServer) - 11];
- _cutComma = false;
- };
-
- _error pushBack format ["%1 (client: %2, server: %3), ", _x select 0, _x select 1, _x select 2];
- } forEach _oldVersionsServer;
-
- _error = _error joinString "";
-
- // Remove last comma and whitespace
- if (_cutComma) then {
- _error = _error select [0, count _error - 2];
- };
+ _clientErrors pushBack _missing;
+ } forEach [
+ [_missingAddonsClient, "client missing"],
+ [_missingAddonsServer, "server missing"],
+ [_oldVersionsClient, "outdated client"],
+ [_oldVersionsServer, "outdated server"]
+ ];
- // Display and log error messages
- diag_log text _error;
- [QGVAR(systemChatGlobal), _error] call CBA_fnc_globalEvent;
- [QGVAR(serverLog), _error] call CBA_fnc_serverEvent;
- };
+ TRACE_4("",_missingAddonsClient,_missingAddonsServer,_oldVersionsClient,_oldVersionsServer);
- ACE_Version_ClientErrors = [_missingAddon, _missingAddonServer, _oldVersionClient, _oldVersionServer];
+ ACE_Version_ClientErrors = _clientErrors;
// Raise event when done
["ace_versioning_clientCheckDone", [+ACE_Version_ClientErrors]] call CBA_fnc_localEvent;
From 4b560d29b0e73e9df5b1d0ddf7db4ed99bd99d5d Mon Sep 17 00:00:00 2001
From: johnb432 <58661205+johnb432@users.noreply.github.com>
Date: Sun, 29 Oct 2023 17:28:43 +0100
Subject: [PATCH 07/26] Minor cleanup + added server source
---
addons/common/functions/fnc_checkFiles.sqf | 10 ++--
.../functions/fnc_checkFiles_diagnoseACE.sqf | 46 +++++++++++++------
2 files changed, 38 insertions(+), 18 deletions(-)
diff --git a/addons/common/functions/fnc_checkFiles.sqf b/addons/common/functions/fnc_checkFiles.sqf
index ad52894a512..0005fcf4cb6 100644
--- a/addons/common/functions/fnc_checkFiles.sqf
+++ b/addons/common/functions/fnc_checkFiles.sqf
@@ -68,10 +68,11 @@ private _oldCompats = [];
// Check ACE install
call FUNC(checkFiles_diagnoseACE);
+ // Don't block game if it's just an old compat pbo
if ((_x select [0, 10]) != "ace_compat") then {
_oldAddons pushBack _x;
} else {
- _oldCompats pushBack [_x, _addonVersion]; // Don't block game if it's just an old compat pbo
+ _oldCompats pushBack [_x, _addonVersion];
};
};
} forEach _addons;
@@ -165,15 +166,18 @@ if (isMultiplayer) then {
// Send server's version of ACE to all clients
GVAR(serverVersion) = _mainVersion;
GVAR(serverAddons) = _addons;
+ GVAR(serverSource) = _mainSource;
+
publicVariable QGVAR(serverVersion);
publicVariable QGVAR(serverAddons);
+ publicVariable QGVAR(serverSource);
} else {
GVAR(clientVersion) = _version;
GVAR(clientAddons) = _addons;
private _fnc_check = {
if (GVAR(clientVersion) != GVAR(serverVersion)) then {
- private _errorMsg = format ["Client/Server Version Mismatch. Server: %1, Client: %2.", GVAR(serverVersion), GVAR(clientVersion)];
+ private _errorMsg = format ["Client/Server Version Mismatch. Server: %1, Client: %2. Server modDir: %3", GVAR(serverVersion), GVAR(clientVersion), GVAR(serverSource)];
// Check ACE install
call FUNC(checkFiles_diagnoseACE);
@@ -188,7 +192,7 @@ if (isMultiplayer) then {
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. Server modDir: %2", _addons, GVAR(serverSource)];
// Check ACE install
call FUNC(checkFiles_diagnoseACE);
diff --git a/addons/common/functions/fnc_checkFiles_diagnoseACE.sqf b/addons/common/functions/fnc_checkFiles_diagnoseACE.sqf
index 5b7f80198b5..9ec12154fd1 100644
--- a/addons/common/functions/fnc_checkFiles_diagnoseACE.sqf
+++ b/addons/common/functions/fnc_checkFiles_diagnoseACE.sqf
@@ -1,13 +1,13 @@
#include "..\script_component.hpp"
/*
* 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:
* None
*
* Return Value:
- * None
+ * ACE addons' WS IDs
*
* Example:
* [] call ace_common_fnc_checkFiles_diagnoseACE
@@ -16,40 +16,56 @@
*/
// Only run once
-if (missionNameSpace getVariable [QGVAR(checkFiles_diagnoseACE), false]) exitWith {};
+if (missionNameSpace getVariable [QGVAR(checkFiles_diagnoseACE), false]) exitWith {
+ createHashMap
+};
+
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 _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 _expectedModDir = getText (_cfg >> "ACE_expectedModDir");
- if (_expectedModDir == "") then { _expectedModDir = "@ace" };
+
+ if (_expectedModDir == "") then {
+ _expectedModDir = "@ace";
+ };
+
private _expectedSteamID = getText (_cfg >> "ACE_expectedSteamID");
- if (_expectedSteamID == "") then { _expectedSteamID = "463939057" };
+
+ if (_expectedSteamID == "") then {
+ _expectedSteamID = "463939057"
+ };
(_allMods getOrDefault [_actualModDir, [], true]) pushBackUnique _expectedSteamID;
+
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;
WARNING_1("%1",_errorMsg);
};
} forEach _addons;
-// Check all ACE ModDirs have expected steam WS ID
+// Check if all ACE ModDirs have expected steam WS ID
{
private _modDir = _x;
- if ((count _y) != 1) then { ERROR_2("Unexpected multiple steamIDs %1 - %2",_modDir,_y) };
- private _expectedSteamID = _y # 0;
- private _index = getLoadedModsInfo findIf {_x#1 == _modDir};
- (getLoadedModsInfo param [_index, []]) params [["_modName", "$Error$"], "", "", "", "", "", "", ["_actualID", ""]];
+
+ if (count _y != 1) then {
+ ERROR_2("Unexpected multiple steamIDs %1 - %2",_modDir,_y);
+ };
+
+ private _expectedSteamID = _y select 0;
+ private _index = _getLoadedModsInfo findIf {_x select 1 == _modDir};
+ (_getLoadedModsInfo param [_index, []]) params [["_modName", "$Error$"], "", "", "", "", "", "", ["_actualID", ""]];
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];
systemChat _errorMsg;
WARNING_1("%1",_errorMsg);
};
From 0de1b26c9d001769a116899f013aa3f7c0c20879 Mon Sep 17 00:00:00 2001
From: Grim <69561145+LinkIsGrim@users.noreply.github.com>
Date: Mon, 8 Jan 2024 04:24:31 -0300
Subject: [PATCH 08/26] update outdated/not present error message
---
addons/common/XEH_postInit.sqf | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/addons/common/XEH_postInit.sqf b/addons/common/XEH_postInit.sqf
index a3749403b21..95df21fe6e0 100644
--- a/addons/common/XEH_postInit.sqf
+++ b/addons/common/XEH_postInit.sqf
@@ -279,7 +279,7 @@ if (isServer) then {
// 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];
+ ["[ACE] ERROR", "ACE is not present or outdated past version 3.X.X", {findDisplay 46 closeDisplay 0}, {findDisplay 46 closeDisplay 0}, nil, [true, false]] remoteExecCall [QFUNC(errorMessage), _this];
}, _owner, 0.5] call CBA_fnc_waitAndExecute;
};
}, _this, 3] call CBA_fnc_waitAndExecute;
From cf50c786fd157b91d211b5d934013d45fd32ea5b Mon Sep 17 00:00:00 2001
From: LinkIsGrim
Date: Mon, 8 Jan 2024 06:09:41 -0300
Subject: [PATCH 09/26] check version number fixes
---
.../common/functions/fnc_checkVersionNumber.sqf | 17 ++++++++---------
1 file changed, 8 insertions(+), 9 deletions(-)
diff --git a/addons/common/functions/fnc_checkVersionNumber.sqf b/addons/common/functions/fnc_checkVersionNumber.sqf
index f76789a16d9..b86202bd495 100644
--- a/addons/common/functions/fnc_checkVersionNumber.sqf
+++ b/addons/common/functions/fnc_checkVersionNumber.sqf
@@ -55,7 +55,7 @@ private _fnc_check = {
// Compare client and server files and versions
private _client = profileName;
- private _missingAddons = [];
+ private _missingAddonsClient = [];
private _oldVersionsClient = [];
private _oldVersionsServer = [];
@@ -70,7 +70,7 @@ private _fnc_check = {
if (_index == -1) then {
if (_x != "ace_server") then {
- _missingAddons pushBack _x;
+ _missingAddonsClient pushBack _x;
};
} else {
_clientVersion = _versions select _index;
@@ -102,14 +102,13 @@ private _fnc_check = {
private _count = 0;
#define DISPLAY_NUMBER_ADDONS (10 + 1) // +1 to account for header
-
{
- params ["_items", "_string"];
+ _x params ["_items", "_string"];
// Check if something is either missing or outdated
- _missing = _items isNotEqualTo [];
+ private _isMissingItems = _items isNotEqualTo [];
- if (_missing) then {
+ if (_isMissingItems) then {
// Generate error message
_errorLog = [format ["[ACE] %1: ERROR %2 addon(s): ", _client, _string]];
@@ -122,16 +121,16 @@ private _fnc_check = {
_count = count _items;
if (_count > DISPLAY_NUMBER_ADDONS) then {
- _errorMsg = _errorMsg + format ["and %1 more.", _count - DISPLAY_NUMBER_ADDONS];
+ _errorMsg = _errorMsg + format [", and %1 more.", _count - DISPLAY_NUMBER_ADDONS];
};
// Log and display error messages
diag_log text _errorLog;
[QGVAR(serverLog), _errorLog] call CBA_fnc_serverEvent;
- [QGVAR(systemChatGlobal), _error] call CBA_fnc_globalEvent;
+ [QGVAR(systemChatGlobal), _errorMsg] call CBA_fnc_globalEvent;
};
- _clientErrors pushBack _missing;
+ _clientErrors pushBack _isMissingItems;
} forEach [
[_missingAddonsClient, "client missing"],
[_missingAddonsServer, "server missing"],
From 9168207f541b2e2f6c63344649993d9d1c4b8a0b Mon Sep 17 00:00:00 2001
From: johnb432 <58661205+johnb432@users.noreply.github.com>
Date: Mon, 8 Jan 2024 20:15:35 +0100
Subject: [PATCH 10/26] Update fnc_errorMessage.sqf
---
addons/common/functions/fnc_errorMessage.sqf | 20 +++++++++++---------
1 file changed, 11 insertions(+), 9 deletions(-)
diff --git a/addons/common/functions/fnc_errorMessage.sqf b/addons/common/functions/fnc_errorMessage.sqf
index cc47fde8b4d..50791d9aee2 100644
--- a/addons/common/functions/fnc_errorMessage.sqf
+++ b/addons/common/functions/fnc_errorMessage.sqf
@@ -1,7 +1,7 @@
#include "..\script_component.hpp"
/*
* 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.
*
* Arguments:
* 0: Header
@@ -17,7 +17,7 @@
* None
*
* Example:
- * ["[ACE] ERROR", text "Test", {findDisplay 46 closeDisplay 0}] call ace_common_fnc_errorMessage
+ * ["[ACE] ERROR", "Test", {findDisplay 46 closeDisplay 0}] call ace_common_fnc_errorMessage
*
* Public: No
*/
@@ -38,7 +38,7 @@ if (isNull (call BIS_fnc_displayMission)) exitWith {
(_this select 0) call FUNC(errorMessage);
[_this select 1] call CBA_fnc_removePerFrameHandler;
- }, 1, _this] call CBA_fnc_addPerFrameHandler;
+ }, 0.25, _this] call CBA_fnc_addPerFrameHandler;
};
params ["_textHeader", "_textMessage", ["_onOK", {}, [{}]], ["_onCancel", {}, [{}]], ["_mainDisplay", call BIS_fnc_displayMission, [displayNull]], ["_showButtons", [true, true]]];
@@ -147,16 +147,18 @@ if (!_showCancelButton || {_onCancel isEqualTo {}}) then {
ctrlSetFocus _ctrlButtonCancel;
};
-_ctrlButtonOK ctrlAddEventHandler ["buttonClick", {(ctrlParent (_this select 0)) closeDisplay 1; true}];
-_ctrlButtonCancel ctrlAddEventHandler ["buttonClick", {(ctrlParent (_this select 0)) closeDisplay 2; true}];
+_ctrlButtonOK ctrlAddEventHandler ["ButtonClick", {(ctrlParent (_this select 0)) closeDisplay 1; true}];
+_ctrlButtonCancel ctrlAddEventHandler ["ButtonClick", {(ctrlParent (_this select 0)) closeDisplay 2; true}];
// CBA isn't guaranteed to be loaded
-private _ehID = _display displayAddEventHandler ["unload", {
+private _ehID = _display displayAddEventHandler ["Unload", {
params ["_display", "_exitCode"];
- call ((_display getVariable [QGVAR(errorMessageCode_) + str _thisEventHandler, [{}, {}, {}]]) select _exitCode)
+ call ((_display getVariable [format [QGVAR(errorMessageCode_%1), _thisEventHandler], createHashMap]) getOrDefault [_exitCode, {}]);
}];
-_display setVariable [QGVAR(errorMessageCode_) + str _ehID, [{}, _onOK, _onCancel]];
+// Prevent data from being overwritten
+_display setVariable [format [QGVAR(errorMessageCode_%1), _ehID], compileFinal createHashMapFromArray [[1, compileFinal _onOK], [2, compileFinal _onCancel]]];
-_display displayAddEventHandler ["keyDown", {_this select 1 == 1}];
+// Intercept all keystrokes except the esacpe key
+_display displayAddEventHandler ["KeyDown", {_this select 1 == 1}];
From 1d08693b3642c1a73c87e3510dcdf9c80c7435f6 Mon Sep 17 00:00:00 2001
From: johnb432 <58661205+johnb432@users.noreply.github.com>
Date: Tue, 9 Jan 2024 11:14:51 +0100
Subject: [PATCH 11/26] Changed error names
Server is always right, client has either older or newer versions, or missing or additional addons
---
addons/common/functions/fnc_checkPBOs.sqf | 18 ++++++++---------
.../functions/fnc_checkVersionNumber.sqf | 20 +++++++++----------
2 files changed, 19 insertions(+), 19 deletions(-)
diff --git a/addons/common/functions/fnc_checkPBOs.sqf b/addons/common/functions/fnc_checkPBOs.sqf
index 37f8355b300..55229edbef9 100644
--- a/addons/common/functions/fnc_checkPBOs.sqf
+++ b/addons/common/functions/fnc_checkPBOs.sqf
@@ -41,31 +41,31 @@ if (!isServer) then {
[_thisType, _thisId] call CBA_fnc_removeEventHandler;
params ["_clientErrors"];
- _clientErrors params ["_missingAddonClient", "_missingAddonServer", "_oldVersionClient", "_oldVersionServer"];
+ _clientErrors params ["_missingAddonClient", "_additionalAddonClient", "_olderVersionClient", "_newerVersionClient"];
_thisArgs params ["_mode"];
// Display error message(s)
- if (_missingAddonClient || {_missingAddonServer} || {_oldVersionClient} || {_oldVersionServer}) then {
+ if (_missingAddonClient || {_additionalAddonClient} || {_olderVersionClient} || {_newerVersionClient}) then {
private _errorMsg = "[ACE] Version mismatch:
";
- private _error = format ["ACE version mismatch: %1: ", profileName];
+ private _error = format ["[ACE] Version mismatch: %1: ", profileName];
if (_missingAddonClient) then {
_errorMsg = _errorMsg + "Detected missing addon on client
";
_error = _error + "Missing file(s); ";
};
- if (_missingAddonServer) then {
- _errorMsg = _errorMsg + "Detected missing addon on server
";
+ if (_additionalAddonClient) then {
+ _errorMsg = _errorMsg + "Detected additional addon on client
";
_error = _error + "Additional file(s); ";
};
- if (_oldVersionClient) then {
- _errorMsg = _errorMsg + "Detected old client version
";
+ if (_olderVersionClient) then {
+ _errorMsg = _errorMsg + "Detected older client version
";
_error = _error + "Older version; ";
};
- if (_oldVersionServer) then {
- _errorMsg = _errorMsg + "Detected old server version
";
+ if (_newerVersionClient) then {
+ _errorMsg = _errorMsg + "Detected newer client version
";
_error = _error + "Newer version; ";
};
diff --git a/addons/common/functions/fnc_checkVersionNumber.sqf b/addons/common/functions/fnc_checkVersionNumber.sqf
index b86202bd495..5939f12dc12 100644
--- a/addons/common/functions/fnc_checkVersionNumber.sqf
+++ b/addons/common/functions/fnc_checkVersionNumber.sqf
@@ -56,8 +56,8 @@ private _fnc_check = {
// Compare client and server files and versions
private _client = profileName;
private _missingAddonsClient = [];
- private _oldVersionsClient = [];
- private _oldVersionsServer = [];
+ private _olderVersionsClient = [];
+ private _newerVersionsClient = [];
private _clientVersion = -1;
private _serverVersion = -1;
@@ -76,21 +76,21 @@ private _fnc_check = {
_clientVersion = _versions select _index;
if (_clientVersion < _serverVersion) then {
- _oldVersionsClient pushBack [_x, _clientVersion, _serverVersion];
+ _olderVersionsClient pushBack [_x, _clientVersion, _serverVersion];
};
if (_clientVersion > _serverVersion) then {
- _oldVersionsServer pushBack [_x, _clientVersion, _serverVersion];
+ _newerVersionsClient pushBack [_x, _clientVersion, _serverVersion];
};
};
} forEach _serverFiles;
// Find client files which the server doesn't have
- private _missingAddonsServer = [];
+ private _additionalAddonsClient = [];
{
if ((_serverFiles find _x) == -1) then {
- _missingAddonsServer pushBack _x;
+ _additionalAddonsClient pushBack _x;
};
} forEach _files;
@@ -133,12 +133,12 @@ private _fnc_check = {
_clientErrors pushBack _isMissingItems;
} forEach [
[_missingAddonsClient, "client missing"],
- [_missingAddonsServer, "server missing"],
- [_oldVersionsClient, "outdated client"],
- [_oldVersionsServer, "outdated server"]
+ [_additionalAddonsClient, "client additional"],
+ [_olderVersionsClient, "older client"],
+ [_newerVersionsClient, "newer client"]
];
- TRACE_4("",_missingAddonsClient,_missingAddonsServer,_oldVersionsClient,_oldVersionsServer);
+ TRACE_4("",_missingAddonsClient,_additionalAddonsClient,_olderVersionsClient,_newerVersionsClient);
ACE_Version_ClientErrors = _clientErrors;
From c84a7fbc6e5082cb79bd21bbb8d66a60c26018cf Mon Sep 17 00:00:00 2001
From: johnb432 <58661205+johnb432@users.noreply.github.com>
Date: Wed, 10 Jan 2024 09:21:59 +0100
Subject: [PATCH 12/26] Improved ACE detection method
---
addons/common/XEH_PREP.hpp | 2 +
addons/common/XEH_postInit.sqf | 45 +++--
addons/common/config.cpp | 2 +-
.../common/functions/fnc_checkAcePresence.sqf | 36 ++++
.../functions/fnc_checkErrorMessage.sqf | 173 ++++++++++++++++++
addons/common/functions/fnc_checkFiles.sqf | 20 +-
addons/common/functions/fnc_checkPBOs.sqf | 2 +-
addons/common/functions/fnc_errorMessage.sqf | 17 +-
8 files changed, 257 insertions(+), 40 deletions(-)
create mode 100644 addons/common/functions/fnc_checkAcePresence.sqf
create mode 100644 addons/common/functions/fnc_checkErrorMessage.sqf
diff --git a/addons/common/XEH_PREP.hpp b/addons/common/XEH_PREP.hpp
index de5b4d5e3f8..9ccbb505740 100644
--- a/addons/common/XEH_PREP.hpp
+++ b/addons/common/XEH_PREP.hpp
@@ -26,6 +26,8 @@ PREP(canDig);
PREP(canGetInPosition);
PREP(canInteractWith);
PREP(changeProjectileDirection);
+PREP(checkAcePresence);
+PREP(checkErrorMessage);
PREP(checkFiles);
PREP(checkFiles_diagnoseACE);
PREP(checkPBOs);
diff --git a/addons/common/XEH_postInit.sqf b/addons/common/XEH_postInit.sqf
index 95df21fe6e0..79ff75159f6 100644
--- a/addons/common/XEH_postInit.sqf
+++ b/addons/common/XEH_postInit.sqf
@@ -263,33 +263,38 @@ 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"];
+ params ["", "", "", "", "_owner"];
- // If ACE is not loaded, kick unit
- if !(missionNamespace getVariable [QGVAR(aceLoaded_) + _uid, false]) then {
- // Send function to client
- _owner publicVariableClient QFUNC(errorMessage);
+ private _random = [];
- // Wait for function to broadcast, then kick client
- [{
- ["[ACE] ERROR", "ACE is not present or outdated past version 3.X.X", {findDisplay 46 closeDisplay 0}, {findDisplay 46 closeDisplay 0}, nil, [true, false]] remoteExecCall [QFUNC(errorMessage), _this];
- }, _owner, 0.5] call CBA_fnc_waitAndExecute;
- };
- }, _this, 3] call CBA_fnc_waitAndExecute;
- }];
+ // Make a random string of length 64
+ for "_i" from 0 to 31 do {
+ _random pushBack selectRandom GVAR(hexArray); // used GVAR(hexArray) because it was easy to use
+ };
+
+ _random = _random joinString "";
+
+ // Add the random suffix, so that it's much harder for the client to predict the function name and put preventive mesures in place
+ private _fncNameCheckAcePresence = format [QFUNC(checkAcePresence_%1), _random];
+ private _fncNameCheckErrorMessage = format [QFUNC(checkErrorMessage_%1), _random];
+
+ // Send functions to the connecting client
+ missionNamespace setVariable [_fncNameCheckAcePresence, /*compile toString */FUNC(checkAcePresence), _owner]; // compile toString removes isFinal status
+ missionNamespace setVariable [_fncNameCheckErrorMessage, /*compile toString */FUNC(checkErrorMessage), _owner];
+
+ // Wait for function to broadcast, then run function on client
+ [{
+ params ["_owner", "_fncNameCheckAcePresence", "_fncNameCheckErrorMessage"];
- addMissionEventHandler ["PlayerDisconnected", {
- params ["", "_uid"];
+ _fncNameCheckErrorMessage remoteExecCall [_fncNameCheckAcePresence, _owner];
- // Reset variable
- missionNamespace setVariable [QGVAR(aceLoaded_) + _uid, nil];
+ // Delete the functions on the server
+ //missionNamespace setVariable [_fncNameCheckAcePresence, nil];
+ //missionNamespace setVariable [_fncNameCheckErrorMessage, nil];
+ }, [_owner, _fncNameCheckAcePresence, _fncNameCheckErrorMessage], 1] call CBA_fnc_waitAndExecute;
}];
};
diff --git a/addons/common/config.cpp b/addons/common/config.cpp
index 144e7d96c61..88e5a5ca9c3 100644
--- a/addons/common/config.cpp
+++ b/addons/common/config.cpp
@@ -6,7 +6,7 @@ class CfgPatches {
units[] = {"ACE_Box_Misc", "ACE_bananaItem", "ACE_Flag_Black", "ACE_Flag_White"};
weapons[] = {"ACE_ItemCore", "ACE_FakePrimaryWeapon", "ACE_Banana"};
requiredVersion = REQUIRED_VERSION;
- requiredAddons[] = {"ace_main","ace_modules"};
+ requiredAddons[] = {"ace_main", "ace_modules"};
author = CSTRING(ACETeam);
authors[] = {"KoffeinFlummi"};
url = ECSTRING(main,URL);
diff --git a/addons/common/functions/fnc_checkAcePresence.sqf b/addons/common/functions/fnc_checkAcePresence.sqf
new file mode 100644
index 00000000000..e394c1ed5ff
--- /dev/null
+++ b/addons/common/functions/fnc_checkAcePresence.sqf
@@ -0,0 +1,36 @@
+#include "..\script_component.hpp"
+/*
+ * Author: johnb43
+ * Used to check if ACE is loaded. If ACE is not present, an error message is shown.
+ * This function is sent by the server to the client, client runs the function.
+ *
+ * Arguments:
+ * 0: Unique name of the error message function sent by the server
+ *
+ * Return Value:
+ * None
+ *
+ * Example:
+ * "ace_common_fnc_checkErrorMessage" call ace_common_fnc_checkAcePresence
+ *
+ * Public: No
+ */
+
+params ["_fncNameCheckErrorMessage"];
+
+INFO("Checking for ACE presence");
+
+private _cfgPatches = configFile >> "CfgPatches";
+
+if (
+ getText (_cfgPatches >> "ace_main" >> "versionStr") == "" ||
+ {getText (_cfgPatches >> QUOTE(ADDON) >> "versionStr") == ""} ||
+ {getArray (_cfgPatches >> "cba_main" >> "versionAr") isEqualTo []} ||
+ {getArray (configFile >> "CfgSettings" >> "CBA" >> "Versioning" >> "ACE" >> "dependencies" >> "CBA") isEqualTo []}
+) exitWith {
+ INFO("ACE was not detected");
+
+ ["[ACE] ERROR", "ACE is not present or outdated past version 3.X.X", _fncNameCheckErrorMessage] call (missionNamespace getVariable [_fncNameCheckErrorMessage, ""]);
+};
+
+INFO("ACE was detected");
diff --git a/addons/common/functions/fnc_checkErrorMessage.sqf b/addons/common/functions/fnc_checkErrorMessage.sqf
new file mode 100644
index 00000000000..4a4a17e5a13
--- /dev/null
+++ b/addons/common/functions/fnc_checkErrorMessage.sqf
@@ -0,0 +1,173 @@
+#include "..\script_component.hpp"
+#include "\a3\ui_f\hpp\defineResincl.inc"
+/*
+ * Author: commy2, johnb43, based on BIS_fnc_errorMsg and BIS_fnc_guiMessage by Karel Moricky (BI)
+ * Opens a textbox with an error message, used for PBO checking.
+ * CBA isn't guaranteed to be loaded, so use vanilla functionality only!
+ *
+ * Arguments:
+ * 0: Header
+ * 1: Text
+ * 2: Unique name of the error message function sent by the server
+ *
+ * Return Value:
+ * None
+ *
+ * Example:
+ * ["[ACE] ERROR", "Test"] call ace_common_fnc_checkErrorMessage
+ *
+ * Public: No
+ */
+
+disableSerialization;
+
+// Force stop any loading screens
+endLoadingScreen;
+
+// No message without player possible
+if (!hasInterface) exitWith {};
+
+private _mainDisplay = call BIS_fnc_displayMission;
+
+// Wait for display
+if (isNull _mainDisplay) exitWith {
+ _this spawn {
+ params ["", "", "_fncNameCheckErrorMessage"];
+
+ waitUntil {
+ uiSleep 0.25;
+
+ !isNull (call BIS_fnc_displayMission)
+ };
+
+ _this call (missionNamespace getVariable [_fncNameCheckErrorMessage, ""]);
+ };
+};
+
+params ["_textHeader", "_textMessage"];
+
+// Use curator display if present
+private _curatorDisplay = findDisplay 312;
+
+if (!isNull _curatorDisplay) then {
+ _mainDisplay = _curatorDisplay;
+};
+
+if (_textMessage isEqualType "") then {
+ _textMessage = parseText _textMessage;
+};
+
+private _display = _mainDisplay createDisplay "RscDisplayCommonMessagePause";
+
+if (isNull _display) exitWith {};
+
+private _ctrlRscMessageBox = _display displayCtrl 2351;
+private _ctrlBcgCommonTop = _display displayCtrl 235100;
+private _ctrlBcgCommon = _display displayCtrl 235101;
+private _ctrlText = _display displayCtrl 235102;
+private _ctrlBackgroundButtonOK = _display displayCtrl 235103;
+private _ctrlBackgroundButtonMiddle = _display displayCtrl 235104;
+private _ctrlBackgroundButtonCancel = _display displayCtrl 235105;
+private _ctrlButtonOK = _display displayCtrl 235106;
+private _ctrlButtonCancel = _display displayCtrl 235107;
+
+_ctrlBcgCommonTop ctrlSetText _textHeader;
+
+private _ctrlButtonOKPos = ctrlPosition _ctrlButtonOK;
+private _ctrlBcgCommonPos = ctrlPosition _ctrlBcgCommon;
+private _bottomSpaceY = (_ctrlButtonOKPos select 1) - ((_ctrlBcgCommonPos select 1) + (_ctrlBcgCommonPos select 3));
+
+private _ctrlTextPos = ctrlPosition _ctrlText;
+private _marginX = (_ctrlTextPos select 0) - (_ctrlBcgCommonPos select 0);
+private _marginY = (_ctrlTextPos select 1) - (_ctrlBcgCommonPos select 1);
+
+_ctrlText ctrlSetStructuredText _textMessage;
+private _ctrlTextPosH = ctrlTextHeight _ctrlText;
+
+_ctrlBcgCommon ctrlSetPosition [
+ _ctrlBcgCommonPos select 0,
+ _ctrlBcgCommonPos select 1,
+ _ctrlBcgCommonPos select 2,
+ _ctrlTextPosH + _marginY * 2
+];
+_ctrlBcgCommon ctrlCommit 0;
+
+_ctrlText ctrlSetPosition [
+ (_ctrlBcgCommonPos select 0) + _marginX,
+ (_ctrlBcgCommonPos select 1) + _marginY,
+ (_ctrlBcgCommonPos select 2) - _marginX * 2,
+ _ctrlTextPosH
+];
+_ctrlText ctrlCommit 0;
+
+private _bottomPosY = (_ctrlBcgCommonPos select 1) + _ctrlTextPosH + (_marginY * 2) + _bottomSpaceY;
+
+{
+ private _xPos = ctrlPosition _x;
+
+ _xPos set [1, _bottomPosY];
+ _x ctrlSetPosition _xPos;
+ _x ctrlCommit 0;
+} forEach [
+ _ctrlBackgroundButtonOK,
+ _ctrlBackgroundButtonMiddle,
+ _ctrlBackgroundButtonCancel,
+ _ctrlButtonOK,
+ _ctrlButtonCancel
+];
+
+private _ctrlRscMessageBoxPos = ctrlPosition _ctrlRscMessageBox;
+private _ctrlRscMessageBoxPosH = _bottomPosY + (_ctrlButtonOKPos select 3);
+
+_ctrlRscMessageBox ctrlSetPosition [
+ 0.5 - (_ctrlBcgCommonPos select 2) / 2,
+ 0.5 - _ctrlRscMessageBoxPosH / 2,
+ (_ctrlBcgCommonPos select 2) + 0.5,
+ _ctrlRscMessageBoxPosH
+];
+
+_ctrlRscMessageBox ctrlEnable true;
+_ctrlRscMessageBox ctrlCommit 0;
+
+// Enable ok button
+_ctrlButtonOK ctrlEnable true;
+_ctrlButtonOK ctrlSetFade 0;
+_ctrlButtonOK ctrlSetText localize "STR_DISP_OK";
+_ctrlButtonOK ctrlCommit 0;
+
+ctrlSetFocus _ctrlButtonOK;
+
+// Disable cancel button
+_ctrlButtonCancel ctrlEnable false;
+_ctrlButtonCancel ctrlSetFade 0;
+_ctrlButtonCancel ctrlSetText "";
+_ctrlButtonCancel ctrlCommit 0;
+
+_ctrlButtonOK ctrlAddEventHandler ["ButtonClick", {(ctrlParent (_this select 0)) closeDisplay IDC_OK; true}];
+_ctrlButtonCancel ctrlAddEventHandler ["ButtonClick", {(ctrlParent (_this select 0)) closeDisplay IDC_CANCEL; true}];
+
+// Intercept all keystrokes except the esacpe key
+_display displayAddEventHandler ["KeyDown", {_this select 1 == 1}];
+
+// If BIS_fnc_guiMessage is called while the display is opened, the "Unload" display EH will be lost and won't fire
+[_display] spawn {
+ disableSerialization;
+
+ params ["_display"];
+
+ // Wait until the display has been closed
+ waitUntil {
+ uiSleep 0.25;
+
+ !isNull _display;
+ };
+
+ // Just to be safe
+ endLoadingScreen;
+
+ // Close curator and mission displays
+ findDisplay 312 closeDisplay 0;
+ findDisplay 46 closeDisplay 0;
+};
+
+nil
diff --git a/addons/common/functions/fnc_checkFiles.sqf b/addons/common/functions/fnc_checkFiles.sqf
index cce022722e6..12c8ddaaac5 100644
--- a/addons/common/functions/fnc_checkFiles.sqf
+++ b/addons/common/functions/fnc_checkFiles.sqf
@@ -15,10 +15,10 @@
* Public: No
*/
- // Don't execute in scheduled environment
- if (canSuspend) exitWith {
- [FUNC(checkFiles), nil] call CBA_fnc_directCall;
- };
+// Don't execute in scheduled environment
+if (canSuspend) exitWith {
+ [FUNC(checkFiles), nil] call CBA_fnc_directCall;
+};
///////////////
// Check addons
@@ -41,7 +41,7 @@ if ([_cbaRequiredAr, _cbaVersionAr] call CBA_versioning_fnc_version_compare) the
ERROR(_errorMsg);
if (hasInterface) then {
- ["[ACE] ERROR", _errorMsg, {findDisplay 46 closeDisplay 0}, {findDisplay 46 closeDisplay 0}, nil, [true, false]] call FUNC(errorMessage);
+ ["[ACE] ERROR", _errorMsg] call FUNC(checkErrorMessage);
};
};
@@ -87,7 +87,7 @@ if (_oldAddons isNotEqualTo []) then {
};
if (hasInterface) then {
- ["[ACE] ERROR", _errorMsg, {findDisplay 46 closeDisplay 0}, {findDisplay 46 closeDisplay 0}, nil, [true, false]] call FUNC(errorMessage);
+ ["[ACE] ERROR", _errorMsg] call FUNC(checkErrorMessage);
};
ERROR(_errorMsg);
@@ -141,7 +141,7 @@ if (!isServer && {_platform in ["linux", "osx"]}) then {
ERROR(_errorMsg);
if (hasInterface) then {
- ["[ACE] ERROR", _errorMsg, {findDisplay 46 closeDisplay 0}, {findDisplay 46 closeDisplay 0}, nil, [true, false]] call FUNC(errorMessage);
+ ["[ACE] ERROR", _errorMsg] call FUNC(checkErrorMessage);
};
} else {
// Print the current extension version
@@ -185,14 +185,14 @@ if (isMultiplayer) then {
ERROR(_errorMsg);
if (hasInterface) then {
- ["[ACE] ERROR", _errorMsg, {findDisplay 46 closeDisplay 0}, {findDisplay 46 closeDisplay 0}, nil, [true, false]] call FUNC(errorMessage);
+ ["[ACE] ERROR", _errorMsg] call FUNC(checkErrorMessage);
};
};
private _addons = GVAR(clientAddons) - GVAR(serverAddons);
if (_addons isNotEqualTo []) then {
- private _errorMsg = format ["Client/Server Addon Mismatch. Client has extra addons: %1. Server modDir: %2", _addons, GVAR(serverSource)];
+ 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);
@@ -200,7 +200,7 @@ if (isMultiplayer) then {
ERROR(_errorMsg);
if (hasInterface) then {
- ["[ACE] ERROR", _errorMsg, {findDisplay 46 closeDisplay 0}, {findDisplay 46 closeDisplay 0}, nil, [true, false]] call FUNC(errorMessage);
+ ["[ACE] ERROR", _errorMsg] call FUNC(checkErrorMessage);
};
};
};
diff --git a/addons/common/functions/fnc_checkPBOs.sqf b/addons/common/functions/fnc_checkPBOs.sqf
index 55229edbef9..63b6fabc36d 100644
--- a/addons/common/functions/fnc_checkPBOs.sqf
+++ b/addons/common/functions/fnc_checkPBOs.sqf
@@ -94,7 +94,7 @@ if (!isServer) then {
[{alive player}, {
TRACE_2("Player is alive, showing msg and exiting",time,_this);
private _errorMsg = composeText [parseText format ["%1", _this]];
- ["[ACE] ERROR", _errorMsg, {findDisplay 46 closeDisplay 0}, {findDisplay 46 closeDisplay 0}, nil, [true, false]] call FUNC(errorMessage);
+ ["[ACE] ERROR", _errorMsg] call FUNC(checkErrorMessage);
}, _errorMsg] call CBA_fnc_waitUntilAndExecute;
};
};
diff --git a/addons/common/functions/fnc_errorMessage.sqf b/addons/common/functions/fnc_errorMessage.sqf
index 50791d9aee2..104a9cfb388 100644
--- a/addons/common/functions/fnc_errorMessage.sqf
+++ b/addons/common/functions/fnc_errorMessage.sqf
@@ -1,4 +1,5 @@
#include "..\script_component.hpp"
+#include "\a3\ui_f\hpp\defineResincl.inc"
/*
* Author: commy2, johnb43, based on BIS_fnc_errorMsg and BIS_fnc_guiMessage by Karel Moricky (BI)
* Opens a textbox with an error message.
@@ -48,9 +49,10 @@ if (_textMessage isEqualType "") then {
_textMessage = parseText _textMessage;
};
-_mainDisplay createDisplay "RscDisplayCommonMessagePause";
+private _display = _mainDisplay createDisplay "RscDisplayCommonMessagePause";
+
+if (isNull _display) exitWith {};
-private _display = uiNamespace getVariable "RscDisplayCommonMessage_display";
private _ctrlRscMessageBox = _display displayCtrl 2351;
private _ctrlBcgCommonTop = _display displayCtrl 235100;
private _ctrlBcgCommon = _display displayCtrl 235101;
@@ -147,10 +149,12 @@ if (!_showCancelButton || {_onCancel isEqualTo {}}) then {
ctrlSetFocus _ctrlButtonCancel;
};
-_ctrlButtonOK ctrlAddEventHandler ["ButtonClick", {(ctrlParent (_this select 0)) closeDisplay 1; true}];
-_ctrlButtonCancel ctrlAddEventHandler ["ButtonClick", {(ctrlParent (_this select 0)) closeDisplay 2; true}];
+_ctrlButtonOK ctrlAddEventHandler ["ButtonClick", {(ctrlParent (_this select 0)) closeDisplay IDC_OK; true}];
+_ctrlButtonCancel ctrlAddEventHandler ["ButtonClick", {(ctrlParent (_this select 0)) closeDisplay IDC_CANCEL; true}];
+
+// Intercept all keystrokes except the esacpe key
+_display displayAddEventHandler ["KeyDown", {_this select 1 == 1}];
-// CBA isn't guaranteed to be loaded
private _ehID = _display displayAddEventHandler ["Unload", {
params ["_display", "_exitCode"];
@@ -159,6 +163,3 @@ private _ehID = _display displayAddEventHandler ["Unload", {
// Prevent data from being overwritten
_display setVariable [format [QGVAR(errorMessageCode_%1), _ehID], compileFinal createHashMapFromArray [[1, compileFinal _onOK], [2, compileFinal _onCancel]]];
-
-// Intercept all keystrokes except the esacpe key
-_display displayAddEventHandler ["KeyDown", {_this select 1 == 1}];
From dd84f2fa359deca936385cfb0cb50a39aebf9184 Mon Sep 17 00:00:00 2001
From: johnb432 <58661205+johnb432@users.noreply.github.com>
Date: Wed, 10 Jan 2024 10:50:06 +0100
Subject: [PATCH 13/26] Tweaks and fixes
---
addons/common/XEH_postInit.sqf | 3 ++
.../functions/fnc_checkErrorMessage.sqf | 32 +++++++++++--------
addons/common/functions/fnc_errorMessage.sqf | 5 +--
3 files changed, 25 insertions(+), 15 deletions(-)
diff --git a/addons/common/XEH_postInit.sqf b/addons/common/XEH_postInit.sqf
index 79ff75159f6..bd3795eb3c7 100644
--- a/addons/common/XEH_postInit.sqf
+++ b/addons/common/XEH_postInit.sqf
@@ -268,6 +268,9 @@ if (isServer) then {
addMissionEventHandler ["PlayerConnected", {
params ["", "", "", "", "_owner"];
+ // Don't run on server
+ if (_owner == 2) exitWith {};
+
private _random = [];
// Make a random string of length 64
diff --git a/addons/common/functions/fnc_checkErrorMessage.sqf b/addons/common/functions/fnc_checkErrorMessage.sqf
index 4a4a17e5a13..9825a6b4909 100644
--- a/addons/common/functions/fnc_checkErrorMessage.sqf
+++ b/addons/common/functions/fnc_checkErrorMessage.sqf
@@ -1,5 +1,6 @@
#include "..\script_component.hpp"
#include "\a3\ui_f\hpp\defineResincl.inc"
+#include "\a3\ui_f\hpp\defineDIKCodes.inc"
/*
* Author: commy2, johnb43, based on BIS_fnc_errorMsg and BIS_fnc_guiMessage by Karel Moricky (BI)
* Opens a textbox with an error message, used for PBO checking.
@@ -144,30 +145,35 @@ _ctrlButtonCancel ctrlSetText "";
_ctrlButtonCancel ctrlCommit 0;
_ctrlButtonOK ctrlAddEventHandler ["ButtonClick", {(ctrlParent (_this select 0)) closeDisplay IDC_OK; true}];
-_ctrlButtonCancel ctrlAddEventHandler ["ButtonClick", {(ctrlParent (_this select 0)) closeDisplay IDC_CANCEL; true}];
-// Intercept all keystrokes except the esacpe key
-_display displayAddEventHandler ["KeyDown", {_this select 1 == 1}];
+// Intercept all keystrokes except the enter keys
+_display displayAddEventHandler ["KeyDown", {!((_this select 1) in [DIK_RETURN, DIK_NUMPADENTER])}];
+
+// Close curator and mission displays (because of the message display, it doesn't quit the mission yet)
+findDisplay 312 closeDisplay 0;
+findDisplay 46 closeDisplay 0;
-// If BIS_fnc_guiMessage is called while the display is opened, the "Unload" display EH will be lost and won't fire
[_display] spawn {
+ // Limitation: This can't close error message boxes (e.g. "No entry")
disableSerialization;
params ["_display"];
- // Wait until the display has been closed
- waitUntil {
- uiSleep 0.25;
+ // This sleep will work when game is paused
+ uiSleep 17.5;
- !isNull _display;
+ // Close display automatically
+ if (!isNull _display) then {
+ _display closeDisplay IDC_OK;
};
- // Just to be safe
- endLoadingScreen;
+ uiSleep 2.5;
- // Close curator and mission displays
- findDisplay 312 closeDisplay 0;
- findDisplay 46 closeDisplay 0;
+ // Close any other BIS_fnc_guiMessage messages that could be open
+ if (!isNull findDisplay 46) then {
+ uiNamespace setVariable ["BIS_fnc_guiMessage_status", true];
+ findDisplay 46 closeDisplay 0;
+ };
};
nil
diff --git a/addons/common/functions/fnc_errorMessage.sqf b/addons/common/functions/fnc_errorMessage.sqf
index 104a9cfb388..326c2da6697 100644
--- a/addons/common/functions/fnc_errorMessage.sqf
+++ b/addons/common/functions/fnc_errorMessage.sqf
@@ -1,5 +1,6 @@
#include "..\script_component.hpp"
#include "\a3\ui_f\hpp\defineResincl.inc"
+#include "\a3\ui_f\hpp\defineDIKCodes.inc"
/*
* Author: commy2, johnb43, based on BIS_fnc_errorMsg and BIS_fnc_guiMessage by Karel Moricky (BI)
* Opens a textbox with an error message.
@@ -152,8 +153,8 @@ if (!_showCancelButton || {_onCancel isEqualTo {}}) then {
_ctrlButtonOK ctrlAddEventHandler ["ButtonClick", {(ctrlParent (_this select 0)) closeDisplay IDC_OK; true}];
_ctrlButtonCancel ctrlAddEventHandler ["ButtonClick", {(ctrlParent (_this select 0)) closeDisplay IDC_CANCEL; true}];
-// Intercept all keystrokes except the esacpe key
-_display displayAddEventHandler ["KeyDown", {_this select 1 == 1}];
+// Intercept the escape key
+_display displayAddEventHandler ["KeyDown", {_this select 1 == DIK_ESCAPE}];
private _ehID = _display displayAddEventHandler ["Unload", {
params ["_display", "_exitCode"];
From 551437329fcdce3bfb62aaa74785f757079ff9c7 Mon Sep 17 00:00:00 2001
From: johnb432 <58661205+johnb432@users.noreply.github.com>
Date: Thu, 11 Jan 2024 00:24:02 +0100
Subject: [PATCH 14/26] Try another approach
---
addons/common/XEH_PREP.hpp | 2 -
addons/common/XEH_postInit.sqf | 56 ++++--
addons/common/XEH_preInit.sqf | 5 +
.../common/functions/fnc_checkAcePresence.sqf | 36 ----
.../functions/fnc_checkErrorMessage.sqf | 179 ------------------
addons/common/functions/fnc_checkFiles.sqf | 10 +-
addons/common/functions/fnc_checkPBOs.sqf | 2 +-
addons/common/functions/fnc_errorMessage.sqf | 94 ++++-----
8 files changed, 85 insertions(+), 299 deletions(-)
delete mode 100644 addons/common/functions/fnc_checkAcePresence.sqf
delete mode 100644 addons/common/functions/fnc_checkErrorMessage.sqf
diff --git a/addons/common/XEH_PREP.hpp b/addons/common/XEH_PREP.hpp
index 9ccbb505740..de5b4d5e3f8 100644
--- a/addons/common/XEH_PREP.hpp
+++ b/addons/common/XEH_PREP.hpp
@@ -26,8 +26,6 @@ PREP(canDig);
PREP(canGetInPosition);
PREP(canInteractWith);
PREP(changeProjectileDirection);
-PREP(checkAcePresence);
-PREP(checkErrorMessage);
PREP(checkFiles);
PREP(checkFiles_diagnoseACE);
PREP(checkPBOs);
diff --git a/addons/common/XEH_postInit.sqf b/addons/common/XEH_postInit.sqf
index bd3795eb3c7..1d7ff321c53 100644
--- a/addons/common/XEH_postInit.sqf
+++ b/addons/common/XEH_postInit.sqf
@@ -266,38 +266,52 @@ call FUNC(checkFiles);
// This handles clients joining that do not have ACE loaded
if (isServer) then {
addMissionEventHandler ["PlayerConnected", {
- params ["", "", "", "", "_owner"];
+ params ["", "_uid", "_name", "", "_owner"];
// Don't run on server
if (_owner == 2) exitWith {};
- private _random = [];
+ INFO_3("Client %1 connected. UID is %2, Client ID is %3",_name,_uid,_owner);
- // Make a random string of length 64
- for "_i" from 0 to 31 do {
- _random pushBack selectRandom GVAR(hexArray); // used GVAR(hexArray) because it was easy to use
- };
+ [{
+ params ["", "_uid", "_name", "", "_owner"];
- _random = _random joinString "";
+ // If the player has left, ignore the rest
+ if (allUsers findIf {_userInfo = getUserInfo _x; (_userInfo select 1) == _owner && {(_userInfo select 2) == _uid}} == -1) exitWith {};
- // Add the random suffix, so that it's much harder for the client to predict the function name and put preventive mesures in place
- private _fncNameCheckAcePresence = format [QFUNC(checkAcePresence_%1), _random];
- private _fncNameCheckErrorMessage = format [QFUNC(checkErrorMessage_%1), _random];
+ // If ACE is not loaded, kick unit
+ if !(missionNamespace getVariable [format [QGVAR(aceLoaded_%1), _owner], false]) then {
+ WARNING_3("Client %1 connected without ACE. UID is %2, Client ID is %3",_name,_uid,_owner);
- // Send functions to the connecting client
- missionNamespace setVariable [_fncNameCheckAcePresence, /*compile toString */FUNC(checkAcePresence), _owner]; // compile toString removes isFinal status
- missionNamespace setVariable [_fncNameCheckErrorMessage, /*compile toString */FUNC(checkErrorMessage), _owner];
+ private _random = [];
- // Wait for function to broadcast, then run function on client
- [{
- params ["_owner", "_fncNameCheckAcePresence", "_fncNameCheckErrorMessage"];
+ // Make a random string of length 32
+ for "_i" from 0 to 15 do {
+ _random pushBack selectRandom GVAR(hexArray); // used GVAR(hexArray) because it was easy to use
+ };
+
+ // Add the random string as a suffix, so that it's much harder for the client to predict the function name and put preventive measures in place
+ private _fncName = format [QFUNC(errorMessage_%1), _random joinString ""];
- _fncNameCheckErrorMessage remoteExecCall [_fncNameCheckAcePresence, _owner];
+ // This avoids 'Attempt to delete final function' error spammed in RPT, which happens if a final function is sent directly to the client
+ missionNamespace setVariable [_fncName, FUNC(errorMessage)];
+
+ // Send function to the connecting client
+ _owner publicVariableClient _fncName;
+
+ // Wait for function to broadcast, then run function on client
+ [{
+ ["[ACE] ERROR", "ACE is not present or outdated past version 3.X.X"] remoteExec _this;
+ }, [_fncName, _owner], 0.5] call CBA_fnc_waitAndExecute;
+ };
+ }, _this, 15] call CBA_fnc_waitAndExecute;
+ }];
+
+ addMissionEventHandler ["PlayerDisconnected", {
+ params ["", "", "", "", "_owner"];
- // Delete the functions on the server
- //missionNamespace setVariable [_fncNameCheckAcePresence, nil];
- //missionNamespace setVariable [_fncNameCheckErrorMessage, nil];
- }, [_owner, _fncNameCheckAcePresence, _fncNameCheckErrorMessage], 1] call CBA_fnc_waitAndExecute;
+ // Reset variable
+ missionNamespace setVariable [format [QGVAR(aceLoaded_%1), _owner], nil];
}];
};
diff --git a/addons/common/XEH_preInit.sqf b/addons/common/XEH_preInit.sqf
index 78c08d5e428..a910f255c99 100644
--- a/addons/common/XEH_preInit.sqf
+++ b/addons/common/XEH_preInit.sqf
@@ -7,6 +7,11 @@ PREP_RECOMPILE_START;
#include "XEH_PREP.hpp"
PREP_RECOMPILE_END;
+// Let the server know that we have ACE loaded
+if (!isServer) then {
+ missionNamespace setVariable [format [QGVAR(aceLoaded_%1), clientOwner], true, 2];
+};
+
GVAR(syncedEvents) = createHashMap;
GVAR(showHudHash) = createHashMap;
GVAR(vehicleIconCache) = createHashMap; // for getVehicleIcon
diff --git a/addons/common/functions/fnc_checkAcePresence.sqf b/addons/common/functions/fnc_checkAcePresence.sqf
deleted file mode 100644
index e394c1ed5ff..00000000000
--- a/addons/common/functions/fnc_checkAcePresence.sqf
+++ /dev/null
@@ -1,36 +0,0 @@
-#include "..\script_component.hpp"
-/*
- * Author: johnb43
- * Used to check if ACE is loaded. If ACE is not present, an error message is shown.
- * This function is sent by the server to the client, client runs the function.
- *
- * Arguments:
- * 0: Unique name of the error message function sent by the server
- *
- * Return Value:
- * None
- *
- * Example:
- * "ace_common_fnc_checkErrorMessage" call ace_common_fnc_checkAcePresence
- *
- * Public: No
- */
-
-params ["_fncNameCheckErrorMessage"];
-
-INFO("Checking for ACE presence");
-
-private _cfgPatches = configFile >> "CfgPatches";
-
-if (
- getText (_cfgPatches >> "ace_main" >> "versionStr") == "" ||
- {getText (_cfgPatches >> QUOTE(ADDON) >> "versionStr") == ""} ||
- {getArray (_cfgPatches >> "cba_main" >> "versionAr") isEqualTo []} ||
- {getArray (configFile >> "CfgSettings" >> "CBA" >> "Versioning" >> "ACE" >> "dependencies" >> "CBA") isEqualTo []}
-) exitWith {
- INFO("ACE was not detected");
-
- ["[ACE] ERROR", "ACE is not present or outdated past version 3.X.X", _fncNameCheckErrorMessage] call (missionNamespace getVariable [_fncNameCheckErrorMessage, ""]);
-};
-
-INFO("ACE was detected");
diff --git a/addons/common/functions/fnc_checkErrorMessage.sqf b/addons/common/functions/fnc_checkErrorMessage.sqf
deleted file mode 100644
index 9825a6b4909..00000000000
--- a/addons/common/functions/fnc_checkErrorMessage.sqf
+++ /dev/null
@@ -1,179 +0,0 @@
-#include "..\script_component.hpp"
-#include "\a3\ui_f\hpp\defineResincl.inc"
-#include "\a3\ui_f\hpp\defineDIKCodes.inc"
-/*
- * Author: commy2, johnb43, based on BIS_fnc_errorMsg and BIS_fnc_guiMessage by Karel Moricky (BI)
- * Opens a textbox with an error message, used for PBO checking.
- * CBA isn't guaranteed to be loaded, so use vanilla functionality only!
- *
- * Arguments:
- * 0: Header
- * 1: Text
- * 2: Unique name of the error message function sent by the server
- *
- * Return Value:
- * None
- *
- * Example:
- * ["[ACE] ERROR", "Test"] call ace_common_fnc_checkErrorMessage
- *
- * Public: No
- */
-
-disableSerialization;
-
-// Force stop any loading screens
-endLoadingScreen;
-
-// No message without player possible
-if (!hasInterface) exitWith {};
-
-private _mainDisplay = call BIS_fnc_displayMission;
-
-// Wait for display
-if (isNull _mainDisplay) exitWith {
- _this spawn {
- params ["", "", "_fncNameCheckErrorMessage"];
-
- waitUntil {
- uiSleep 0.25;
-
- !isNull (call BIS_fnc_displayMission)
- };
-
- _this call (missionNamespace getVariable [_fncNameCheckErrorMessage, ""]);
- };
-};
-
-params ["_textHeader", "_textMessage"];
-
-// Use curator display if present
-private _curatorDisplay = findDisplay 312;
-
-if (!isNull _curatorDisplay) then {
- _mainDisplay = _curatorDisplay;
-};
-
-if (_textMessage isEqualType "") then {
- _textMessage = parseText _textMessage;
-};
-
-private _display = _mainDisplay createDisplay "RscDisplayCommonMessagePause";
-
-if (isNull _display) exitWith {};
-
-private _ctrlRscMessageBox = _display displayCtrl 2351;
-private _ctrlBcgCommonTop = _display displayCtrl 235100;
-private _ctrlBcgCommon = _display displayCtrl 235101;
-private _ctrlText = _display displayCtrl 235102;
-private _ctrlBackgroundButtonOK = _display displayCtrl 235103;
-private _ctrlBackgroundButtonMiddle = _display displayCtrl 235104;
-private _ctrlBackgroundButtonCancel = _display displayCtrl 235105;
-private _ctrlButtonOK = _display displayCtrl 235106;
-private _ctrlButtonCancel = _display displayCtrl 235107;
-
-_ctrlBcgCommonTop ctrlSetText _textHeader;
-
-private _ctrlButtonOKPos = ctrlPosition _ctrlButtonOK;
-private _ctrlBcgCommonPos = ctrlPosition _ctrlBcgCommon;
-private _bottomSpaceY = (_ctrlButtonOKPos select 1) - ((_ctrlBcgCommonPos select 1) + (_ctrlBcgCommonPos select 3));
-
-private _ctrlTextPos = ctrlPosition _ctrlText;
-private _marginX = (_ctrlTextPos select 0) - (_ctrlBcgCommonPos select 0);
-private _marginY = (_ctrlTextPos select 1) - (_ctrlBcgCommonPos select 1);
-
-_ctrlText ctrlSetStructuredText _textMessage;
-private _ctrlTextPosH = ctrlTextHeight _ctrlText;
-
-_ctrlBcgCommon ctrlSetPosition [
- _ctrlBcgCommonPos select 0,
- _ctrlBcgCommonPos select 1,
- _ctrlBcgCommonPos select 2,
- _ctrlTextPosH + _marginY * 2
-];
-_ctrlBcgCommon ctrlCommit 0;
-
-_ctrlText ctrlSetPosition [
- (_ctrlBcgCommonPos select 0) + _marginX,
- (_ctrlBcgCommonPos select 1) + _marginY,
- (_ctrlBcgCommonPos select 2) - _marginX * 2,
- _ctrlTextPosH
-];
-_ctrlText ctrlCommit 0;
-
-private _bottomPosY = (_ctrlBcgCommonPos select 1) + _ctrlTextPosH + (_marginY * 2) + _bottomSpaceY;
-
-{
- private _xPos = ctrlPosition _x;
-
- _xPos set [1, _bottomPosY];
- _x ctrlSetPosition _xPos;
- _x ctrlCommit 0;
-} forEach [
- _ctrlBackgroundButtonOK,
- _ctrlBackgroundButtonMiddle,
- _ctrlBackgroundButtonCancel,
- _ctrlButtonOK,
- _ctrlButtonCancel
-];
-
-private _ctrlRscMessageBoxPos = ctrlPosition _ctrlRscMessageBox;
-private _ctrlRscMessageBoxPosH = _bottomPosY + (_ctrlButtonOKPos select 3);
-
-_ctrlRscMessageBox ctrlSetPosition [
- 0.5 - (_ctrlBcgCommonPos select 2) / 2,
- 0.5 - _ctrlRscMessageBoxPosH / 2,
- (_ctrlBcgCommonPos select 2) + 0.5,
- _ctrlRscMessageBoxPosH
-];
-
-_ctrlRscMessageBox ctrlEnable true;
-_ctrlRscMessageBox ctrlCommit 0;
-
-// Enable ok button
-_ctrlButtonOK ctrlEnable true;
-_ctrlButtonOK ctrlSetFade 0;
-_ctrlButtonOK ctrlSetText localize "STR_DISP_OK";
-_ctrlButtonOK ctrlCommit 0;
-
-ctrlSetFocus _ctrlButtonOK;
-
-// Disable cancel button
-_ctrlButtonCancel ctrlEnable false;
-_ctrlButtonCancel ctrlSetFade 0;
-_ctrlButtonCancel ctrlSetText "";
-_ctrlButtonCancel ctrlCommit 0;
-
-_ctrlButtonOK ctrlAddEventHandler ["ButtonClick", {(ctrlParent (_this select 0)) closeDisplay IDC_OK; true}];
-
-// Intercept all keystrokes except the enter keys
-_display displayAddEventHandler ["KeyDown", {!((_this select 1) in [DIK_RETURN, DIK_NUMPADENTER])}];
-
-// Close curator and mission displays (because of the message display, it doesn't quit the mission yet)
-findDisplay 312 closeDisplay 0;
-findDisplay 46 closeDisplay 0;
-
-[_display] spawn {
- // Limitation: This can't close error message boxes (e.g. "No entry")
- disableSerialization;
-
- params ["_display"];
-
- // This sleep will work when game is paused
- uiSleep 17.5;
-
- // Close display automatically
- if (!isNull _display) then {
- _display closeDisplay IDC_OK;
- };
-
- uiSleep 2.5;
-
- // Close any other BIS_fnc_guiMessage messages that could be open
- if (!isNull findDisplay 46) then {
- uiNamespace setVariable ["BIS_fnc_guiMessage_status", true];
- findDisplay 46 closeDisplay 0;
- };
-};
-
-nil
diff --git a/addons/common/functions/fnc_checkFiles.sqf b/addons/common/functions/fnc_checkFiles.sqf
index 12c8ddaaac5..bc7145518d5 100644
--- a/addons/common/functions/fnc_checkFiles.sqf
+++ b/addons/common/functions/fnc_checkFiles.sqf
@@ -41,7 +41,7 @@ if ([_cbaRequiredAr, _cbaVersionAr] call CBA_versioning_fnc_version_compare) the
ERROR(_errorMsg);
if (hasInterface) then {
- ["[ACE] ERROR", _errorMsg] call FUNC(checkErrorMessage);
+ ["[ACE] ERROR", _errorMsg] spawn FUNC(errorMessage);
};
};
@@ -87,7 +87,7 @@ if (_oldAddons isNotEqualTo []) then {
};
if (hasInterface) then {
- ["[ACE] ERROR", _errorMsg] call FUNC(checkErrorMessage);
+ ["[ACE] ERROR", _errorMsg] spawn FUNC(errorMessage);
};
ERROR(_errorMsg);
@@ -141,7 +141,7 @@ if (!isServer && {_platform in ["linux", "osx"]}) then {
ERROR(_errorMsg);
if (hasInterface) then {
- ["[ACE] ERROR", _errorMsg] call FUNC(checkErrorMessage);
+ ["[ACE] ERROR", _errorMsg] spawn FUNC(errorMessage);
};
} else {
// Print the current extension version
@@ -185,7 +185,7 @@ if (isMultiplayer) then {
ERROR(_errorMsg);
if (hasInterface) then {
- ["[ACE] ERROR", _errorMsg] call FUNC(checkErrorMessage);
+ ["[ACE] ERROR", _errorMsg] spawn FUNC(errorMessage);
};
};
@@ -200,7 +200,7 @@ if (isMultiplayer) then {
ERROR(_errorMsg);
if (hasInterface) then {
- ["[ACE] ERROR", _errorMsg] call FUNC(checkErrorMessage);
+ ["[ACE] ERROR", _errorMsg] spawn FUNC(errorMessage);
};
};
};
diff --git a/addons/common/functions/fnc_checkPBOs.sqf b/addons/common/functions/fnc_checkPBOs.sqf
index 63b6fabc36d..e3a8e6aae87 100644
--- a/addons/common/functions/fnc_checkPBOs.sqf
+++ b/addons/common/functions/fnc_checkPBOs.sqf
@@ -94,7 +94,7 @@ if (!isServer) then {
[{alive player}, {
TRACE_2("Player is alive, showing msg and exiting",time,_this);
private _errorMsg = composeText [parseText format ["%1", _this]];
- ["[ACE] ERROR", _errorMsg] call FUNC(checkErrorMessage);
+ ["[ACE] ERROR", _errorMsg] spawn FUNC(errorMessage);
}, _errorMsg] call CBA_fnc_waitUntilAndExecute;
};
};
diff --git a/addons/common/functions/fnc_errorMessage.sqf b/addons/common/functions/fnc_errorMessage.sqf
index 326c2da6697..7746d3e0756 100644
--- a/addons/common/functions/fnc_errorMessage.sqf
+++ b/addons/common/functions/fnc_errorMessage.sqf
@@ -3,48 +3,52 @@
#include "\a3\ui_f\hpp\defineDIKCodes.inc"
/*
* Author: commy2, johnb43, based on BIS_fnc_errorMsg and BIS_fnc_guiMessage by Karel Moricky (BI)
- * Opens a textbox with an error message.
+ * Opens a textbox with an error message, used for PBO checking.
+ * This function is sent by the server to the client, client runs the function.
+ * CBA isn't guaranteed to be loaded, so use vanilla functionality only!
*
* Arguments:
* 0: Header
* 1: Text
- * 2: Code that is executed when 'Ok' is pressed (default: {})
- * 3: Code that is executed when 'Cancel' is pressed (default: {})
- * 4: Display (default: call BIS_fnc_displayMission)
- * 5: Show buttons
- * - 0: Show ok button if ok has code (default: true)
- * - 1: Show cancel button if cancel has code (default: true)
*
* Return Value:
* None
*
* Example:
- * ["[ACE] ERROR", "Test", {findDisplay 46 closeDisplay 0}] call ace_common_fnc_errorMessage
+ * ["[ACE] ERROR", "Test"] spawn ace_common_fnc_errorMessage
*
* Public: No
*/
-disableSerialization;
-
// Force stop any loading screens
endLoadingScreen;
// No message without player possible
if (!hasInterface) exitWith {};
+params ["_textHeader", "_textMessage"];
+
+disableSerialization;
+
+private _mainDisplay = call BIS_fnc_displayMission;
+
// Wait for display
-if (isNull (call BIS_fnc_displayMission)) exitWith {
- [{
- if (isNull (call BIS_fnc_displayMission)) exitWith {};
+if (isNull _mainDisplay) then {
+ waitUntil {
+ uiSleep 0.25;
- (_this select 0) call FUNC(errorMessage);
- [_this select 1] call CBA_fnc_removePerFrameHandler;
+ _mainDisplay = call BIS_fnc_displayMission;
- }, 0.25, _this] call CBA_fnc_addPerFrameHandler;
+ !isNull _mainDisplay
+ };
};
-params ["_textHeader", "_textMessage", ["_onOK", {}, [{}]], ["_onCancel", {}, [{}]], ["_mainDisplay", call BIS_fnc_displayMission, [displayNull]], ["_showButtons", [true, true]]];
-_showButtons params [["_showOkButton", true, [false]], ["_showCancelButton", true, [false]]];
+// Use curator display if present
+private _curatorDisplay = findDisplay 312;
+
+if (!isNull _curatorDisplay) then {
+ _mainDisplay = _curatorDisplay;
+};
if (_textMessage isEqualType "") then {
_textMessage = parseText _textMessage;
@@ -122,45 +126,25 @@ _ctrlRscMessageBox ctrlSetPosition [
_ctrlRscMessageBox ctrlEnable true;
_ctrlRscMessageBox ctrlCommit 0;
-if (!_showOkButton || {_onOK isEqualTo {}}) then {
- _ctrlButtonOK ctrlEnable false;
- _ctrlButtonOK ctrlSetFade 0;
- _ctrlButtonOK ctrlSetText "";
- _ctrlButtonOK ctrlCommit 0;
-} else {
- _ctrlButtonOK ctrlEnable true;
- _ctrlButtonOK ctrlSetFade 0;
- _ctrlButtonOK ctrlSetText localize "STR_DISP_OK";
- _ctrlButtonOK ctrlCommit 0;
-
- ctrlSetFocus _ctrlButtonOK;
-};
-
-if (!_showCancelButton || {_onCancel isEqualTo {}}) then {
- _ctrlButtonCancel ctrlEnable false;
- _ctrlButtonCancel ctrlSetFade 0;
- _ctrlButtonCancel ctrlSetText "";
- _ctrlButtonCancel ctrlCommit 0;
-} else {
- _ctrlButtonCancel ctrlEnable true;
- _ctrlButtonCancel ctrlSetFade 0;
- _ctrlButtonCancel ctrlSetText localize "STR_DISP_CANCEL";
- _ctrlButtonCancel ctrlCommit 0;
-
- ctrlSetFocus _ctrlButtonCancel;
-};
+// Enable ok button
+_ctrlButtonOK ctrlEnable true;
+_ctrlButtonOK ctrlSetFade 0;
+_ctrlButtonOK ctrlSetText localize "STR_DISP_OK";
+_ctrlButtonOK ctrlCommit 0;
-_ctrlButtonOK ctrlAddEventHandler ["ButtonClick", {(ctrlParent (_this select 0)) closeDisplay IDC_OK; true}];
-_ctrlButtonCancel ctrlAddEventHandler ["ButtonClick", {(ctrlParent (_this select 0)) closeDisplay IDC_CANCEL; true}];
+ctrlSetFocus _ctrlButtonOK;
-// Intercept the escape key
-_display displayAddEventHandler ["KeyDown", {_this select 1 == DIK_ESCAPE}];
+// Disable cancel button
+_ctrlButtonCancel ctrlEnable false;
+_ctrlButtonCancel ctrlSetFade 0;
+_ctrlButtonCancel ctrlSetText "";
+_ctrlButtonCancel ctrlCommit 0;
-private _ehID = _display displayAddEventHandler ["Unload", {
- params ["_display", "_exitCode"];
+_ctrlButtonOK ctrlAddEventHandler ["ButtonClick", {(ctrlParent (_this select 0)) closeDisplay IDC_OK; true}];
- call ((_display getVariable [format [QGVAR(errorMessageCode_%1), _thisEventHandler], createHashMap]) getOrDefault [_exitCode, {}]);
-}];
+// Intercept all keystrokes except the enter keys
+_display displayAddEventHandler ["KeyDown", {!((_this select 1) in [DIK_RETURN, DIK_NUMPADENTER])}];
-// Prevent data from being overwritten
-_display setVariable [format [QGVAR(errorMessageCode_%1), _ehID], compileFinal createHashMapFromArray [[1, compileFinal _onOK], [2, compileFinal _onCancel]]];
+// Close curator and mission displays (because of the message display, it doesn't quit the mission yet)
+findDisplay 312 closeDisplay 0;
+findDisplay 46 closeDisplay 0;
From a9fa625f17bd6627e25b4f3242f89af78b0e5691 Mon Sep 17 00:00:00 2001
From: johnb432 <58661205+johnb432@users.noreply.github.com>
Date: Thu, 11 Jan 2024 00:41:50 +0100
Subject: [PATCH 15/26] Update events-framework.md
---
docs/wiki/framework/events-framework.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/docs/wiki/framework/events-framework.md b/docs/wiki/framework/events-framework.md
index c29f271719c..12a2ba7ea34 100644
--- a/docs/wiki/framework/events-framework.md
+++ b/docs/wiki/framework/events-framework.md
@@ -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_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_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`)
From c45344a342739804e2ecf98c0eeb6fc78643ab43 Mon Sep 17 00:00:00 2001
From: johnb432 <58661205+johnb432@users.noreply.github.com>
Date: Sun, 28 Jan 2024 09:55:39 +0100
Subject: [PATCH 16/26] Update XEH_postInit.sqf
---
addons/common/XEH_postInit.sqf | 11 ++---------
1 file changed, 2 insertions(+), 9 deletions(-)
diff --git a/addons/common/XEH_postInit.sqf b/addons/common/XEH_postInit.sqf
index f7c30b6be26..a5af12a405d 100644
--- a/addons/common/XEH_postInit.sqf
+++ b/addons/common/XEH_postInit.sqf
@@ -283,15 +283,8 @@ if (isServer) then {
if !(missionNamespace getVariable [format [QGVAR(aceLoaded_%1), _owner], false]) then {
WARNING_3("Client %1 connected without ACE. UID is %2, Client ID is %3",_name,_uid,_owner);
- private _random = [];
-
- // Make a random string of length 32
- for "_i" from 0 to 15 do {
- _random pushBack selectRandom GVAR(hexArray); // used GVAR(hexArray) because it was easy to use
- };
-
- // Add the random string as a suffix, so that it's much harder for the client to predict the function name and put preventive measures in place
- private _fncName = format [QFUNC(errorMessage_%1), _random joinString ""];
+ // Add a UUID as a suffix, so that it's much harder for the client to predict the function name and put preventive measures in place
+ private _fncName = format [QFUNC(errorMessage_%1), call CBA_fnc_createUUID];
// This avoids 'Attempt to delete final function' error spammed in RPT, which happens if a final function is sent directly to the client
missionNamespace setVariable [_fncName, FUNC(errorMessage)];
From 6b2e036ce54c6dece39e9ff10708f68532492d3a Mon Sep 17 00:00:00 2001
From: johnb432 <58661205+johnb432@users.noreply.github.com>
Date: Sun, 24 Mar 2024 11:47:25 +0100
Subject: [PATCH 17/26] Update fnc_checkVersionNumber.sqf
---
addons/common/functions/fnc_checkVersionNumber.sqf | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/addons/common/functions/fnc_checkVersionNumber.sqf b/addons/common/functions/fnc_checkVersionNumber.sqf
index 5939f12dc12..7eb9572f4b9 100644
--- a/addons/common/functions/fnc_checkVersionNumber.sqf
+++ b/addons/common/functions/fnc_checkVersionNumber.sqf
@@ -25,7 +25,7 @@ params [["_whitelist", missionNamespace getVariable ["ACE_Version_Whitelist", []
private _files = CBA_common_addons select {
(_x select [0, 3] != "a3_") &&
{_x select [0, 4] != "ace_"} &&
- {!((toLower _x) in _whitelist)}
+ {!((toLowerANSI _x) in _whitelist)}
};
private _cfgPatches = configFile >> "CfgPatches";
From c21c5cae939f296a426d2a6725cf6433cf1ccb98 Mon Sep 17 00:00:00 2001
From: johnb432 <58661205+johnb432@users.noreply.github.com>
Date: Sun, 24 Mar 2024 23:02:55 +0100
Subject: [PATCH 18/26] Removed check for non-ACE clients
---
addons/common/XEH_postInit.sqf | 45 ----------------------------------
addons/common/XEH_preInit.sqf | 5 ----
2 files changed, 50 deletions(-)
diff --git a/addons/common/XEH_postInit.sqf b/addons/common/XEH_postInit.sqf
index c3cb0116a05..56f6f5b3ac0 100644
--- a/addons/common/XEH_postInit.sqf
+++ b/addons/common/XEH_postInit.sqf
@@ -263,51 +263,6 @@ if (_currentVersion != _previousVersion) then {
call FUNC(checkFiles);
-// This handles clients joining that do not have ACE loaded
-if (isServer) then {
- addMissionEventHandler ["PlayerConnected", {
- params ["", "_uid", "_name", "", "_owner"];
-
- // Don't run on server
- if (_owner == 2) exitWith {};
-
- INFO_3("Client %1 connected. UID is %2, Client ID is %3",_name,_uid,_owner);
-
- [{
- params ["", "_uid", "_name", "", "_owner"];
-
- // If the player has left, ignore the rest
- if (allUsers findIf {_userInfo = getUserInfo _x; (_userInfo select 1) == _owner && {(_userInfo select 2) == _uid}} == -1) exitWith {};
-
- // If ACE is not loaded, kick unit
- if !(missionNamespace getVariable [format [QGVAR(aceLoaded_%1), _owner], false]) then {
- WARNING_3("Client %1 connected without ACE. UID is %2, Client ID is %3",_name,_uid,_owner);
-
- // Add a UUID as a suffix, so that it's much harder for the client to predict the function name and put preventive measures in place
- private _fncName = format [QFUNC(errorMessage_%1), call CBA_fnc_createUUID];
-
- // This avoids 'Attempt to delete final function' error spammed in RPT, which happens if a final function is sent directly to the client
- missionNamespace setVariable [_fncName, FUNC(errorMessage)];
-
- // Send function to the connecting client
- _owner publicVariableClient _fncName;
-
- // Wait for function to broadcast, then run function on client
- [{
- ["[ACE] ERROR", "ACE is not present or outdated past version 3.X.X"] remoteExec _this;
- }, [_fncName, _owner], 0.5] call CBA_fnc_waitAndExecute;
- };
- }, _this, 15] call CBA_fnc_waitAndExecute;
- }];
-
- addMissionEventHandler ["PlayerDisconnected", {
- params ["", "", "", "", "_owner"];
-
- // Reset variable
- missionNamespace setVariable [format [QGVAR(aceLoaded_%1), _owner], nil];
- }];
-};
-
//////////////////////////////////////////////////
// Set up ace_settingsInitialized eventhandler
//////////////////////////////////////////////////
diff --git a/addons/common/XEH_preInit.sqf b/addons/common/XEH_preInit.sqf
index e4ab6421d62..9b5d27d12ca 100644
--- a/addons/common/XEH_preInit.sqf
+++ b/addons/common/XEH_preInit.sqf
@@ -7,11 +7,6 @@ PREP_RECOMPILE_START;
#include "XEH_PREP.hpp"
PREP_RECOMPILE_END;
-// Let the server know that we have ACE loaded
-if (!isServer) then {
- missionNamespace setVariable [format [QGVAR(aceLoaded_%1), clientOwner], true, 2];
-};
-
GVAR(syncedEvents) = createHashMap;
GVAR(showHudHash) = createHashMap;
GVAR(vehicleIconCache) = createHashMap; // for getVehicleIcon
From a45c37a9fada127f5e45ff858f44e9dd2ecd0513 Mon Sep 17 00:00:00 2001
From: johnb432 <58661205+johnb432@users.noreply.github.com>
Date: Sun, 24 Mar 2024 23:04:23 +0100
Subject: [PATCH 19/26] Update XEH_postInit.sqf
---
addons/common/XEH_postInit.sqf | 1 +
1 file changed, 1 insertion(+)
diff --git a/addons/common/XEH_postInit.sqf b/addons/common/XEH_postInit.sqf
index 56f6f5b3ac0..cf1f4b6fe0e 100644
--- a/addons/common/XEH_postInit.sqf
+++ b/addons/common/XEH_postInit.sqf
@@ -263,6 +263,7 @@ if (_currentVersion != _previousVersion) then {
call FUNC(checkFiles);
+
//////////////////////////////////////////////////
// Set up ace_settingsInitialized eventhandler
//////////////////////////////////////////////////
From 59f189b27b324d6db179144dab3fba0aab5bd2b8 Mon Sep 17 00:00:00 2001
From: johnb432 <58661205+johnb432@users.noreply.github.com>
Date: Mon, 1 Apr 2024 20:18:33 +0200
Subject: [PATCH 20/26] Cleanup
---
addons/common/functions/fnc_checkFiles.sqf | 10 +-
.../functions/fnc_checkFiles_diagnoseACE.sqf | 4 +-
addons/common/functions/fnc_checkPBOs.sqf | 7 +-
.../functions/fnc_checkVersionNumber.sqf | 10 +-
addons/common/functions/fnc_errorMessage.sqf | 231 +++++++++---------
5 files changed, 122 insertions(+), 140 deletions(-)
diff --git a/addons/common/functions/fnc_checkFiles.sqf b/addons/common/functions/fnc_checkFiles.sqf
index a112efe7818..31fc2e7e460 100644
--- a/addons/common/functions/fnc_checkFiles.sqf
+++ b/addons/common/functions/fnc_checkFiles.sqf
@@ -41,7 +41,7 @@ if ([_cbaRequiredAr, _cbaVersionAr] call CBA_versioning_fnc_version_compare) the
ERROR(_errorMsg);
if (hasInterface) then {
- ["[ACE] ERROR", _errorMsg] spawn FUNC(errorMessage);
+ ["[ACE] ERROR", _errorMsg] call FUNC(errorMessage);
};
};
@@ -87,7 +87,7 @@ if (_oldAddons isNotEqualTo []) then {
};
if (hasInterface) then {
- ["[ACE] ERROR", _errorMsg] spawn FUNC(errorMessage);
+ ["[ACE] ERROR", _errorMsg] call FUNC(errorMessage);
};
ERROR(_errorMsg);
@@ -141,7 +141,7 @@ if (!isServer && {_platform in ["linux", "osx"]}) then {
ERROR(_errorMsg);
if (hasInterface) then {
- ["[ACE] ERROR", _errorMsg] spawn FUNC(errorMessage);
+ ["[ACE] ERROR", _errorMsg] call FUNC(errorMessage);
};
} else {
// Print the current extension version
@@ -185,7 +185,7 @@ if (isMultiplayer) then {
ERROR(_errorMsg);
if (hasInterface) then {
- ["[ACE] ERROR", _errorMsg] spawn FUNC(errorMessage);
+ ["[ACE] ERROR", _errorMsg] call FUNC(errorMessage);
};
};
@@ -200,7 +200,7 @@ if (isMultiplayer) then {
ERROR(_errorMsg);
if (hasInterface) then {
- ["[ACE] ERROR", _errorMsg] spawn FUNC(errorMessage);
+ ["[ACE] ERROR", _errorMsg] call FUNC(errorMessage);
};
};
};
diff --git a/addons/common/functions/fnc_checkFiles_diagnoseACE.sqf b/addons/common/functions/fnc_checkFiles_diagnoseACE.sqf
index 9ec12154fd1..f9271ca2137 100644
--- a/addons/common/functions/fnc_checkFiles_diagnoseACE.sqf
+++ b/addons/common/functions/fnc_checkFiles_diagnoseACE.sqf
@@ -17,7 +17,7 @@
// Only run once
if (missionNameSpace getVariable [QGVAR(checkFiles_diagnoseACE), false]) exitWith {
- createHashMap
+ createHashMap // return
};
GVAR(checkFiles_diagnoseACE) = true;
@@ -71,4 +71,4 @@ private _getLoadedModsInfo = getLoadedModsInfo;
};
} forEach _allMods;
-_allMods
+_allMods // return
diff --git a/addons/common/functions/fnc_checkPBOs.sqf b/addons/common/functions/fnc_checkPBOs.sqf
index 3fb4ee9da4f..8af3fda001d 100644
--- a/addons/common/functions/fnc_checkPBOs.sqf
+++ b/addons/common/functions/fnc_checkPBOs.sqf
@@ -78,10 +78,7 @@ if (!isServer) then {
private _rscLayer = "ACE_RscErrorHint" call BIS_fnc_rscLayer;
_rscLayer cutRsc ["ACE_RscErrorHint", "PLAIN", 0, true];
- disableSerialization;
-
- private _ctrlHint = uiNamespace getVariable "ACE_ctrlErrorHint";
- _ctrlHint ctrlSetStructuredText _errorMsg;
+ (uiNamespace getVariable "ACE_ctrlErrorHint") ctrlSetStructuredText _errorMsg;
if (_mode == 0) then {
[{
@@ -94,7 +91,7 @@ if (!isServer) then {
[{alive player}, {
TRACE_2("Player is alive, showing msg and exiting",time,_this);
private _errorMsg = composeText [parseText format ["%1", _this]];
- ["[ACE] ERROR", _errorMsg] spawn FUNC(errorMessage);
+ ["[ACE] ERROR", _errorMsg] call FUNC(errorMessage);
}, _errorMsg] call CBA_fnc_waitUntilAndExecute;
};
};
diff --git a/addons/common/functions/fnc_checkVersionNumber.sqf b/addons/common/functions/fnc_checkVersionNumber.sqf
index 7eb9572f4b9..3612fcbcda2 100644
--- a/addons/common/functions/fnc_checkVersionNumber.sqf
+++ b/addons/common/functions/fnc_checkVersionNumber.sqf
@@ -86,14 +86,7 @@ private _fnc_check = {
} forEach _serverFiles;
// Find client files which the server doesn't have
- private _additionalAddonsClient = [];
-
- {
- if ((_serverFiles find _x) == -1) then {
- _additionalAddonsClient pushBack _x;
- };
- } forEach _files;
-
+ private _additionalAddonsClient = _files select {!(_x in _serverFiles)};
// Check for client missing addons, server missing addons, client outdated addons and server outdated addons
private _clientErrors = [];
@@ -102,6 +95,7 @@ private _fnc_check = {
private _count = 0;
#define DISPLAY_NUMBER_ADDONS (10 + 1) // +1 to account for header
+
{
_x params ["_items", "_string"];
diff --git a/addons/common/functions/fnc_errorMessage.sqf b/addons/common/functions/fnc_errorMessage.sqf
index 7746d3e0756..8085f3dbd74 100644
--- a/addons/common/functions/fnc_errorMessage.sqf
+++ b/addons/common/functions/fnc_errorMessage.sqf
@@ -4,8 +4,6 @@
/*
* Author: commy2, johnb43, based on BIS_fnc_errorMsg and BIS_fnc_guiMessage by Karel Moricky (BI)
* Opens a textbox with an error message, used for PBO checking.
- * This function is sent by the server to the client, client runs the function.
- * CBA isn't guaranteed to be loaded, so use vanilla functionality only!
*
* Arguments:
* 0: Header
@@ -23,128 +21,121 @@
// Force stop any loading screens
endLoadingScreen;
-// No message without player possible
+// No message without interface possible
if (!hasInterface) exitWith {};
-params ["_textHeader", "_textMessage"];
+[{
+ !isNull (call BIS_fnc_displayMission)
+}, {
+ params ["_textHeader", "_textMessage"];
-disableSerialization;
+ disableSerialization;
-private _mainDisplay = call BIS_fnc_displayMission;
+ // Use curator display if present
+ private _curatorDisplay = findDisplay 312;
-// Wait for display
-if (isNull _mainDisplay) then {
- waitUntil {
- uiSleep 0.25;
-
- _mainDisplay = call BIS_fnc_displayMission;
+ private _mainDisplay = if (!isNull _curatorDisplay) then {
+ _curatorDisplay
+ } else {
+ call BIS_fnc_displayMission
+ };
- !isNull _mainDisplay
+ if (_textMessage isEqualType "") then {
+ _textMessage = parseText _textMessage;
};
-};
-
-// Use curator display if present
-private _curatorDisplay = findDisplay 312;
-
-if (!isNull _curatorDisplay) then {
- _mainDisplay = _curatorDisplay;
-};
-
-if (_textMessage isEqualType "") then {
- _textMessage = parseText _textMessage;
-};
-
-private _display = _mainDisplay createDisplay "RscDisplayCommonMessagePause";
-
-if (isNull _display) exitWith {};
-
-private _ctrlRscMessageBox = _display displayCtrl 2351;
-private _ctrlBcgCommonTop = _display displayCtrl 235100;
-private _ctrlBcgCommon = _display displayCtrl 235101;
-private _ctrlText = _display displayCtrl 235102;
-private _ctrlBackgroundButtonOK = _display displayCtrl 235103;
-private _ctrlBackgroundButtonMiddle = _display displayCtrl 235104;
-private _ctrlBackgroundButtonCancel = _display displayCtrl 235105;
-private _ctrlButtonOK = _display displayCtrl 235106;
-private _ctrlButtonCancel = _display displayCtrl 235107;
-
-_ctrlBcgCommonTop ctrlSetText _textHeader;
-
-private _ctrlButtonOKPos = ctrlPosition _ctrlButtonOK;
-private _ctrlBcgCommonPos = ctrlPosition _ctrlBcgCommon;
-private _bottomSpaceY = (_ctrlButtonOKPos select 1) - ((_ctrlBcgCommonPos select 1) + (_ctrlBcgCommonPos select 3));
-
-private _ctrlTextPos = ctrlPosition _ctrlText;
-private _marginX = (_ctrlTextPos select 0) - (_ctrlBcgCommonPos select 0);
-private _marginY = (_ctrlTextPos select 1) - (_ctrlBcgCommonPos select 1);
-
-_ctrlText ctrlSetStructuredText _textMessage;
-private _ctrlTextPosH = ctrlTextHeight _ctrlText;
-
-_ctrlBcgCommon ctrlSetPosition [
- _ctrlBcgCommonPos select 0,
- _ctrlBcgCommonPos select 1,
- _ctrlBcgCommonPos select 2,
- _ctrlTextPosH + _marginY * 2
-];
-_ctrlBcgCommon ctrlCommit 0;
-
-_ctrlText ctrlSetPosition [
- (_ctrlBcgCommonPos select 0) + _marginX,
- (_ctrlBcgCommonPos select 1) + _marginY,
- (_ctrlBcgCommonPos select 2) - _marginX * 2,
- _ctrlTextPosH
-];
-_ctrlText ctrlCommit 0;
-
-private _bottomPosY = (_ctrlBcgCommonPos select 1) + _ctrlTextPosH + (_marginY * 2) + _bottomSpaceY;
-
-{
- private _xPos = ctrlPosition _x;
-
- _xPos set [1, _bottomPosY];
- _x ctrlSetPosition _xPos;
- _x ctrlCommit 0;
-} forEach [
- _ctrlBackgroundButtonOK,
- _ctrlBackgroundButtonMiddle,
- _ctrlBackgroundButtonCancel,
- _ctrlButtonOK,
- _ctrlButtonCancel
-];
-
-private _ctrlRscMessageBoxPos = ctrlPosition _ctrlRscMessageBox;
-private _ctrlRscMessageBoxPosH = _bottomPosY + (_ctrlButtonOKPos select 3);
-
-_ctrlRscMessageBox ctrlSetPosition [
- 0.5 - (_ctrlBcgCommonPos select 2) / 2,
- 0.5 - _ctrlRscMessageBoxPosH / 2,
- (_ctrlBcgCommonPos select 2) + 0.5,
- _ctrlRscMessageBoxPosH
-];
-
-_ctrlRscMessageBox ctrlEnable true;
-_ctrlRscMessageBox ctrlCommit 0;
-
-// Enable ok button
-_ctrlButtonOK ctrlEnable true;
-_ctrlButtonOK ctrlSetFade 0;
-_ctrlButtonOK ctrlSetText localize "STR_DISP_OK";
-_ctrlButtonOK ctrlCommit 0;
-
-ctrlSetFocus _ctrlButtonOK;
-
-// Disable cancel button
-_ctrlButtonCancel ctrlEnable false;
-_ctrlButtonCancel ctrlSetFade 0;
-_ctrlButtonCancel ctrlSetText "";
-_ctrlButtonCancel ctrlCommit 0;
-
-_ctrlButtonOK ctrlAddEventHandler ["ButtonClick", {(ctrlParent (_this select 0)) closeDisplay IDC_OK; true}];
-
-// Intercept all keystrokes except the enter keys
-_display displayAddEventHandler ["KeyDown", {!((_this select 1) in [DIK_RETURN, DIK_NUMPADENTER])}];
-
-// Close curator and mission displays (because of the message display, it doesn't quit the mission yet)
-findDisplay 312 closeDisplay 0;
-findDisplay 46 closeDisplay 0;
+
+ private _display = _mainDisplay createDisplay "RscDisplayCommonMessagePause";
+
+ if (isNull _display) exitWith {};
+
+ private _ctrlRscMessageBox = _display displayCtrl 2351;
+ private _ctrlBcgCommonTop = _display displayCtrl 235100;
+ private _ctrlBcgCommon = _display displayCtrl 235101;
+ private _ctrlText = _display displayCtrl 235102;
+ private _ctrlBackgroundButtonOK = _display displayCtrl 235103;
+ private _ctrlBackgroundButtonMiddle = _display displayCtrl 235104;
+ private _ctrlBackgroundButtonCancel = _display displayCtrl 235105;
+ private _ctrlButtonOK = _display displayCtrl 235106;
+ private _ctrlButtonCancel = _display displayCtrl 235107;
+
+ _ctrlBcgCommonTop ctrlSetText _textHeader;
+
+ private _ctrlButtonOKPos = ctrlPosition _ctrlButtonOK;
+ private _ctrlBcgCommonPos = ctrlPosition _ctrlBcgCommon;
+ private _bottomSpaceY = (_ctrlButtonOKPos select 1) - ((_ctrlBcgCommonPos select 1) + (_ctrlBcgCommonPos select 3));
+
+ private _ctrlTextPos = ctrlPosition _ctrlText;
+ private _marginX = (_ctrlTextPos select 0) - (_ctrlBcgCommonPos select 0);
+ private _marginY = (_ctrlTextPos select 1) - (_ctrlBcgCommonPos select 1);
+
+ _ctrlText ctrlSetStructuredText _textMessage;
+ private _ctrlTextPosH = ctrlTextHeight _ctrlText;
+
+ _ctrlBcgCommon ctrlSetPosition [
+ _ctrlBcgCommonPos select 0,
+ _ctrlBcgCommonPos select 1,
+ _ctrlBcgCommonPos select 2,
+ _ctrlTextPosH + _marginY * 2
+ ];
+ _ctrlBcgCommon ctrlCommit 0;
+
+ _ctrlText ctrlSetPosition [
+ (_ctrlBcgCommonPos select 0) + _marginX,
+ (_ctrlBcgCommonPos select 1) + _marginY,
+ (_ctrlBcgCommonPos select 2) - _marginX * 2,
+ _ctrlTextPosH
+ ];
+ _ctrlText ctrlCommit 0;
+
+ private _bottomPosY = (_ctrlBcgCommonPos select 1) + _ctrlTextPosH + (_marginY * 2) + _bottomSpaceY;
+
+ {
+ private _xPos = ctrlPosition _x;
+
+ _xPos set [1, _bottomPosY];
+ _x ctrlSetPosition _xPos;
+ _x ctrlCommit 0;
+ } forEach [
+ _ctrlBackgroundButtonOK,
+ _ctrlBackgroundButtonMiddle,
+ _ctrlBackgroundButtonCancel,
+ _ctrlButtonOK,
+ _ctrlButtonCancel
+ ];
+
+ private _ctrlRscMessageBoxPos = ctrlPosition _ctrlRscMessageBox;
+ private _ctrlRscMessageBoxPosH = _bottomPosY + (_ctrlButtonOKPos select 3);
+
+ _ctrlRscMessageBox ctrlSetPosition [
+ 0.5 - (_ctrlBcgCommonPos select 2) / 2,
+ 0.5 - _ctrlRscMessageBoxPosH / 2,
+ (_ctrlBcgCommonPos select 2) + 0.5,
+ _ctrlRscMessageBoxPosH
+ ];
+
+ _ctrlRscMessageBox ctrlEnable true;
+ _ctrlRscMessageBox ctrlCommit 0;
+
+ // Enable ok button
+ _ctrlButtonOK ctrlEnable true;
+ _ctrlButtonOK ctrlSetFade 0;
+ _ctrlButtonOK ctrlSetText localize "STR_DISP_OK";
+ _ctrlButtonOK ctrlCommit 0;
+
+ ctrlSetFocus _ctrlButtonOK;
+
+ // Disable cancel button
+ _ctrlButtonCancel ctrlEnable false;
+ _ctrlButtonCancel ctrlSetFade 0;
+ _ctrlButtonCancel ctrlSetText "";
+ _ctrlButtonCancel ctrlCommit 0;
+
+ _ctrlButtonOK ctrlAddEventHandler ["ButtonClick", {(ctrlParent (_this select 0)) closeDisplay IDC_OK; true}];
+
+ // Intercept all keystrokes except the enter keys
+ _display displayAddEventHandler ["KeyDown", {!((_this select 1) in [DIK_RETURN, DIK_NUMPADENTER])}];
+
+ // Close curator and mission displays (because of the message display, it doesn't quit the mission yet)
+ findDisplay 312 closeDisplay 0;
+ findDisplay 46 closeDisplay 0;
+}, _this] call CBA_fnc_waitUntilAndExecute;
From 87eac7739558e390cc251403f76a93145148df3b Mon Sep 17 00:00:00 2001
From: johnb432 <58661205+johnb432@users.noreply.github.com>
Date: Thu, 4 Apr 2024 16:52:00 +0200
Subject: [PATCH 21/26] Remove rogue change
---
addons/common/config.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/addons/common/config.cpp b/addons/common/config.cpp
index 88e5a5ca9c3..144e7d96c61 100644
--- a/addons/common/config.cpp
+++ b/addons/common/config.cpp
@@ -6,7 +6,7 @@ class CfgPatches {
units[] = {"ACE_Box_Misc", "ACE_bananaItem", "ACE_Flag_Black", "ACE_Flag_White"};
weapons[] = {"ACE_ItemCore", "ACE_FakePrimaryWeapon", "ACE_Banana"};
requiredVersion = REQUIRED_VERSION;
- requiredAddons[] = {"ace_main", "ace_modules"};
+ requiredAddons[] = {"ace_main","ace_modules"};
author = CSTRING(ACETeam);
authors[] = {"KoffeinFlummi"};
url = ECSTRING(main,URL);
From effcfd1aaadf4151796b0301c06c81349f3e6a23 Mon Sep 17 00:00:00 2001
From: johnb432 <58661205+johnb432@users.noreply.github.com>
Date: Thu, 4 Apr 2024 18:53:05 +0200
Subject: [PATCH 22/26] Improved message display in systemChat
---
addons/common/functions/fnc_checkPBOs.sqf | 12 ++---
.../functions/fnc_checkVersionNumber.sqf | 45 ++++++++++++++-----
2 files changed, 38 insertions(+), 19 deletions(-)
diff --git a/addons/common/functions/fnc_checkPBOs.sqf b/addons/common/functions/fnc_checkPBOs.sqf
index 8af3fda001d..ea72b7eceb2 100644
--- a/addons/common/functions/fnc_checkPBOs.sqf
+++ b/addons/common/functions/fnc_checkPBOs.sqf
@@ -71,14 +71,14 @@ if (!isServer) then {
ERROR(_error);
+ _errorMsg = parseText format ["%1", _errorMsg];
+
// Warn
if (_mode < 2) then {
- _errorMsg = composeText [lineBreak, parseText format ["%1", _errorMsg]];
-
private _rscLayer = "ACE_RscErrorHint" call BIS_fnc_rscLayer;
_rscLayer cutRsc ["ACE_RscErrorHint", "PLAIN", 0, true];
- (uiNamespace getVariable "ACE_ctrlErrorHint") ctrlSetStructuredText _errorMsg;
+ (uiNamespace getVariable "ACE_ctrlErrorHint") ctrlSetStructuredText composeText [lineBreak, _errorMsg];
if (_mode == 0) then {
[{
@@ -88,11 +88,7 @@ if (!isServer) then {
};
} else {
// Kick
- [{alive player}, {
- TRACE_2("Player is alive, showing msg and exiting",time,_this);
- private _errorMsg = composeText [parseText format ["%1", _this]];
- ["[ACE] ERROR", _errorMsg] call FUNC(errorMessage);
- }, _errorMsg] call CBA_fnc_waitUntilAndExecute;
+ ["[ACE] ERROR", composeText [_errorMsg]] call FUNC(errorMessage);
};
};
}, [_mode]] call CBA_fnc_addEventHandlerArgs;
diff --git a/addons/common/functions/fnc_checkVersionNumber.sqf b/addons/common/functions/fnc_checkVersionNumber.sqf
index 3612fcbcda2..d3bb3a70f6d 100644
--- a/addons/common/functions/fnc_checkVersionNumber.sqf
+++ b/addons/common/functions/fnc_checkVersionNumber.sqf
@@ -90,9 +90,11 @@ private _fnc_check = {
// Check for client missing addons, server missing addons, client outdated addons and server outdated addons
private _clientErrors = [];
+ private _isMissingItems = false;
private _errorLog = [];
+ private _header = "";
private _errorMsg = "";
- private _count = 0;
+ private _count = -1;
#define DISPLAY_NUMBER_ADDONS (10 + 1) // +1 to account for header
@@ -100,17 +102,16 @@ private _fnc_check = {
_x params ["_items", "_string"];
// Check if something is either missing or outdated
- private _isMissingItems = _items isNotEqualTo [];
+ _isMissingItems = _items isNotEqualTo [];
if (_isMissingItems) then {
// Generate error message
- _errorLog = [format ["[ACE] %1: ERROR %2 addon(s): ", _client, _string]];
-
- _errorLog append _items;
+ _errorLog = +_items;
+ _header = format ["[ACE] %1: ERROR %2 addon(s): ", _client, _string];
// Don't display all missing items, as they are logged
- _errorMsg = (_errorLog select [0, DISPLAY_NUMBER_ADDONS]) joinString ", ";
- _errorLog = _errorLog joinString ", ";
+ _errorMsg = _header + ((_errorLog select [0, DISPLAY_NUMBER_ADDONS]) joinString ", ");
+ _errorLog = _header + (_errorLog joinString ", ");
_count = count _items;
@@ -118,10 +119,32 @@ private _fnc_check = {
_errorMsg = _errorMsg + format [", and %1 more.", _count - DISPLAY_NUMBER_ADDONS];
};
- // 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 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;
From 7d84ea96069e3e4286d91f8eb11977ddc5c4bcda Mon Sep 17 00:00:00 2001
From: johnb432 <58661205+johnb432@users.noreply.github.com>
Date: Wed, 10 Apr 2024 09:53:46 +0200
Subject: [PATCH 23/26] Update fnc_checkPBOs.sqf
---
addons/common/functions/fnc_checkPBOs.sqf | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/addons/common/functions/fnc_checkPBOs.sqf b/addons/common/functions/fnc_checkPBOs.sqf
index ea72b7eceb2..f8391dd2a24 100644
--- a/addons/common/functions/fnc_checkPBOs.sqf
+++ b/addons/common/functions/fnc_checkPBOs.sqf
@@ -47,29 +47,29 @@ if (!isServer) then {
// Display error message(s)
if (_missingAddonClient || {_additionalAddonClient} || {_olderVersionClient} || {_newerVersionClient}) then {
private _errorMsg = "[ACE] Version mismatch:
";
- private _error = format ["[ACE] Version mismatch: %1: ", profileName];
+ private _error = [];
if (_missingAddonClient) then {
_errorMsg = _errorMsg + "Detected missing addon on client
";
- _error = _error + "Missing file(s); ";
+ _error pushBack "Missing file(s)";
};
if (_additionalAddonClient) then {
_errorMsg = _errorMsg + "Detected additional addon on client
";
- _error = _error + "Additional file(s); ";
+ _error pushBack "Additional file(s)";
};
if (_olderVersionClient) then {
_errorMsg = _errorMsg + "Detected older client version
";
- _error = _error + "Older version; ";
+ _error pushBack "Older version";
};
if (_newerVersionClient) then {
_errorMsg = _errorMsg + "Detected newer client version
";
- _error = _error + "Newer version; ";
+ _error pushBack "Newer version";
};
- ERROR(_error);
+ ERROR_2("[ACE] Version mismatch: %1: %2",profileName,_error joinString ", ");
_errorMsg = parseText format ["%1", _errorMsg];
From 6ddcfb183bfa937edc8988155d7a5f68fca1f96a Mon Sep 17 00:00:00 2001
From: johnb432 <58661205+johnb432@users.noreply.github.com>
Date: Thu, 6 Jun 2024 09:46:35 +0200
Subject: [PATCH 24/26] Removed loop variable initialisers
---
addons/common/functions/fnc_checkFiles.sqf | 26 ++++++-----------
.../functions/fnc_checkVersionNumber.sqf | 28 ++++++-------------
2 files changed, 17 insertions(+), 37 deletions(-)
diff --git a/addons/common/functions/fnc_checkFiles.sqf b/addons/common/functions/fnc_checkFiles.sqf
index 31fc2e7e460..7b90a1b0a85 100644
--- a/addons/common/functions/fnc_checkFiles.sqf
+++ b/addons/common/functions/fnc_checkFiles.sqf
@@ -48,20 +48,16 @@ if ([_cbaRequiredAr, _cbaVersionAr] call CBA_versioning_fnc_version_compare) the
//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 _addonCfg = configNull;
-private _addonVersion = "";
-private _addonSource = "";
-
private _oldAddons = [];
private _oldSources = [];
private _oldCompats = [];
{
- _addonCfg = configFile >> "CfgPatches" >> _x;
- _addonVersion = getText (_addonCfg >> "versionStr");
+ private _addonCfg = configFile >> "CfgPatches" >> _x;
+ private _addonVersion = getText (_addonCfg >> "versionStr");
if (_addonVersion != _mainVersion) then {
- _addonSource = configSourceMod _addonCfg;
+ private _addonSource = configSourceMod _addonCfg;
_oldSources pushBackUnique _addonSource;
@@ -111,18 +107,12 @@ 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;
-
{
- _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};
+ 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};
if ((_isWindows || _isLinux) && {_isClient || _isServer}) then {
private _versionEx = _extension callExtension "version";
diff --git a/addons/common/functions/fnc_checkVersionNumber.sqf b/addons/common/functions/fnc_checkVersionNumber.sqf
index d3bb3a70f6d..0343e745aae 100644
--- a/addons/common/functions/fnc_checkVersionNumber.sqf
+++ b/addons/common/functions/fnc_checkVersionNumber.sqf
@@ -29,12 +29,11 @@ private _files = CBA_common_addons select {
};
private _cfgPatches = configFile >> "CfgPatches";
-private _version = -1;
private _versions = [];
{
(getText (_cfgPatches >> _x >> "version") splitString ".") params [["_major", "0"], ["_minor", "0"]];
- _version = parseNumber _major + parseNumber _minor / 100;
+ private _version = parseNumber _major + parseNumber _minor / 100;
_versions pushBack _version;
} forEach _files;
@@ -59,21 +58,17 @@ private _fnc_check = {
private _olderVersionsClient = [];
private _newerVersionsClient = [];
- private _clientVersion = -1;
- private _serverVersion = -1;
- private _index = -1;
-
{
- _serverVersion = _serverVersions select _forEachIndex;
+ private _serverVersion = _serverVersions select _forEachIndex;
- _index = _files find _x;
+ private _index = _files find _x;
if (_index == -1) then {
if (_x != "ace_server") then {
_missingAddonsClient pushBack _x;
};
} else {
- _clientVersion = _versions select _index;
+ private _clientVersion = _versions select _index;
if (_clientVersion < _serverVersion) then {
_olderVersionsClient pushBack [_x, _clientVersion, _serverVersion];
@@ -90,11 +85,6 @@ private _fnc_check = {
// Check for client missing addons, server missing addons, client outdated addons and server outdated addons
private _clientErrors = [];
- private _isMissingItems = false;
- private _errorLog = [];
- private _header = "";
- private _errorMsg = "";
- private _count = -1;
#define DISPLAY_NUMBER_ADDONS (10 + 1) // +1 to account for header
@@ -102,18 +92,18 @@ private _fnc_check = {
_x params ["_items", "_string"];
// Check if something is either missing or outdated
- _isMissingItems = _items isNotEqualTo [];
+ private _isMissingItems = _items isNotEqualTo [];
if (_isMissingItems) then {
// Generate error message
- _errorLog = +_items;
- _header = format ["[ACE] %1: ERROR %2 addon(s): ", _client, _string];
+ private _errorLog = +_items;
+ private _header = format ["[ACE] %1: ERROR %2 addon(s): ", _client, _string];
// Don't display all missing items, as they are logged
- _errorMsg = _header + ((_errorLog select [0, DISPLAY_NUMBER_ADDONS]) joinString ", ");
+ private _errorMsg = _header + ((_errorLog select [0, DISPLAY_NUMBER_ADDONS]) joinString ", ");
_errorLog = _header + (_errorLog joinString ", ");
- _count = count _items;
+ private _count = count _items;
if (_count > DISPLAY_NUMBER_ADDONS) then {
_errorMsg = _errorMsg + format [", and %1 more.", _count - DISPLAY_NUMBER_ADDONS];
From fbea26cfa389b649d52deb0896ddcbd1ba5cbf3a Mon Sep 17 00:00:00 2001
From: johnb432 <58661205+johnb432@users.noreply.github.com>
Date: Fri, 14 Jun 2024 20:43:12 +0200
Subject: [PATCH 25/26] Fixed header
---
addons/common/functions/fnc_errorMessage.sqf | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/addons/common/functions/fnc_errorMessage.sqf b/addons/common/functions/fnc_errorMessage.sqf
index 8085f3dbd74..e98a5baf8f9 100644
--- a/addons/common/functions/fnc_errorMessage.sqf
+++ b/addons/common/functions/fnc_errorMessage.sqf
@@ -7,13 +7,13 @@
*
* Arguments:
* 0: Header
- * 1: Text
+ * 1: Text
*
* Return Value:
* None
*
* Example:
- * ["[ACE] ERROR", "Test"] spawn ace_common_fnc_errorMessage
+ * ["[ACE] ERROR", "Test"] call ace_common_fnc_errorMessage
*
* Public: No
*/
From 27b3fbab52ace47bff176669f3abc5c801c76c36 Mon Sep 17 00:00:00 2001
From: johnb432 <58661205+johnb432@users.noreply.github.com>
Date: Sat, 22 Jun 2024 15:48:12 +0200
Subject: [PATCH 26/26] Updated headers
---
addons/common/functions/fnc_checkPBOs.sqf | 4 ++--
addons/common/functions/fnc_checkVersionNumber.sqf | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/addons/common/functions/fnc_checkPBOs.sqf b/addons/common/functions/fnc_checkPBOs.sqf
index f8391dd2a24..4f2e3f4fa6b 100644
--- a/addons/common/functions/fnc_checkPBOs.sqf
+++ b/addons/common/functions/fnc_checkPBOs.sqf
@@ -9,8 +9,8 @@
* 0 = Warn once
* 1 = Warn permanently
* 2 = Kick
- * 1: Check all PBOs? (default: false)
- * 2: Whitelist (default: "")
+ * 1: Check all PBOs? (default: false)
+ * 2: Whitelist (default: "")
*
* Return Value:
* None
diff --git a/addons/common/functions/fnc_checkVersionNumber.sqf b/addons/common/functions/fnc_checkVersionNumber.sqf
index 0343e745aae..a2861299174 100644
--- a/addons/common/functions/fnc_checkVersionNumber.sqf
+++ b/addons/common/functions/fnc_checkVersionNumber.sqf
@@ -4,7 +4,7 @@
* Compares version numbers from loaded addons.
*
* Arguments:
- * None
+ * 0: Lowercase addon whitelist (default: missionNamespace getVariable ["ACE_Version_Whitelist", []])
*
* Return Value:
* None