diff --git a/addons/xeh/CfgFunctions.hpp b/addons/xeh/CfgFunctions.hpp index f1b730641..041f27a54 100644 --- a/addons/xeh/CfgFunctions.hpp +++ b/addons/xeh/CfgFunctions.hpp @@ -1,65 +1,31 @@ class CfgFunctions { class CBA { class XEH { - class isScheduled { - description = "Check if the current scope is running in scheduled or unscheduled environment."; - file = PATHTOF(fnc_isScheduled.sqf); - }; - class isRecompileEnabled { - description = "Check if recompiling is enabled."; - file = PATHTOF(fnc_isRecompileEnabled.sqf); - }; - class addClassEventHandler { - description = "Add an eventhandler to a class and all children."; - file = PATHTOF(fnc_addClassEventHandler.sqf); - }; - class init { - headerType = -1; - description = "Runs Init and InitPost event handlers on this object."; - file = PATHTOF(fnc_init.sqf); - }; - class initEvents { - headerType = -1; - description = "Adds all event handlers to this object."; - file = PATHTOF(fnc_initEvents.sqf); - }; - class supportMonitor { - description = "Iterate through all vehicle classes and find those who don't support extended event handlers."; - file = PATHTOF(fnc_supportMonitor.sqf); - }; - class compileEventHandlers { - description = "Compiles all Extended EventHandlers in given config."; - file = PATHTOF(fnc_compileEventHandlers.sqf); - }; - class compileFunction { - description = "Compiles a function into mission namespace and into ui namespace for caching purposes."; - file = PATHTOF(fnc_compileFunction.sqf); - }; + PATHTO_FNC(isScheduled); + PATHTO_FNC(isRecompileEnabled); + PATHTO_FNC(addClassEventHandler); + PATHTO_FNC(init); + PATHTO_FNC(initEvents); + PATHTO_FNC(supportMonitor); + PATHTO_FNC(compileEventHandlers); + PATHTO_FNC(compileFunction); + PATHTO_FNC(startFallbackLoop); + class preStart { preStart = 1; - description = "Occurs once during game start."; file = PATHTOF(fnc_preStart.sqf); }; class preInit { preInit = 1; - description = "Occurs once per mission before objects are initialized."; file = PATHTOF(fnc_preInit.sqf); }; class postInit { postInit = 1; - description = "Occurs once per mission after objects and functions are initialized."; file = PATHTOF(fnc_postInit.sqf); }; - class postInit_unscheduled { - description = "Occurs once per mission after objects and functions are initialized."; - file = PATHTOF(fnc_postInit_unscheduled.sqf); - }; - class startFallbackLoop { - description = "Starts a loop to iterate through all objects to initialize event handlers on XEH incompatible objects."; - file = PATHTOF(fnc_startFallbackLoop.sqf); - }; }; }; + class A3 { class GUI { class initDisplay { diff --git a/addons/xeh/fnc_compileEventHandlers.sqf b/addons/xeh/fnc_compileEventHandlers.sqf index b8fce6643..0a5a4f471 100644 --- a/addons/xeh/fnc_compileEventHandlers.sqf +++ b/addons/xeh/fnc_compileEventHandlers.sqf @@ -27,13 +27,24 @@ params [["_baseConfig", configNull, [configNull]]]; private _result = []; private _resultNames = []; +private _allowRecompile = _baseConfig isEqualTo configFile; + +if (_allowRecompile) then { + if ("compile" call CBA_fnc_isRecompileEnabled || {isFilePatchingEnabled}) then { + XEH_LOG("XEH: init function preProcessing disabled [recompile or filepatching enabled]"); + _allowRecompile = false; + }; +}; + // note: format is never used for config parsing here, because of it's 8192 character limitation. { private _eventName = _x; { - private _eventFunc = ""; + private _funcAll = ""; + private _funcClient = ""; + private _funcServer = ""; private _customName = configName _x; if (isClass _x) then { @@ -41,58 +52,55 @@ private _resultNames = []; private _entry = _x >> "init"; if (isText _entry) then { - _eventFunc = _eventFunc + getText _entry + ";"; + _funcAll = getText _entry; }; // client only events - if (!isDedicated) then { - _entry = _x >> "clientInit"; - - if (isText _entry) then { - _eventFunc = _eventFunc + getText _entry + ";"; - }; + _entry = _x >> "clientInit"; + if (isText _entry) then { + _funcClient = getText _entry; }; // server only events - if (isServer) then { - _entry = _x >> "serverInit"; - - if (isText _entry) then { - _eventFunc = _eventFunc + getText _entry + ";"; - }; + _entry = _x >> "serverInit"; + if (isText _entry) then { + _funcServer = getText _entry; }; } else { // global events if (isText _x) then { - _eventFunc = getText _x + ";"; + _funcAll = getText _x; }; }; - if !(_eventFunc isEqualTo "") then { - - //Optimize "QUOTE(call COMPILE_FILE(XEH_preInit));" down to just the content of the EH script - if (!(["compile"] call CBA_fnc_isRecompileEnabled) && { //Users might expect their preInit script to be reloaded everytime when debugging - (toLower (_eventFunc select [0,40])) isEqualTo "call compile preprocessfilelinenumbers '" && { - (_eventFunc select [count _eventFunc -2]) isEqualTo "';" - }}) then { - private _funcPath = _eventFunc select [40, count _eventFunc - 42]; - //If there is a quote mark in the path, then something went wrong and we got multiple paths, just skip optimization - //Example cause: "call COMPILE_FILE(XEH_preInit);call COMPILE_FILE(XEH_preClientInit)" - if (_funcPath find "'" == -1) then { - _eventFunc = preprocessFileLineNumbers _funcPath; - - TRACE_2("eventfunction redirected",_customName,_funcPath); + private _eventFuncs = [_funcAll, _funcClient, _funcServer] apply { + if (_x == "") then { + TRACE_2("does NOT do something",_customName,_eventName); + {} // apply return + } else { + TRACE_2("does something",_customName,_eventName); + private _eventFunc = _x; + + //Optimize "QUOTE(call COMPILE_FILE(XEH_preInit));" down to just the content of the EH script + if (_allowRecompile) then { + if (toLower (_eventFunc select [0,40]) isEqualTo "call compile preprocessfilelinenumbers '" && {(_eventFunc select [count _eventFunc - 1]) isEqualTo "'"}) then { + private _funcPath = _eventFunc select [40, count _eventFunc - 41]; + + //If there is a quote mark in the path, then something went wrong and we got multiple paths, just skip optimization + //Example cause: "call COMPILE_FILE(XEH_preInit);call COMPILE_FILE(XEH_preClientInit)" + if (_funcPath find "'" == -1) then { + _eventFunc = preprocessFileLineNumbers _funcPath; + TRACE_2("eventfunction redirected",_customName,_funcPath); + }; + }; + // if (_eventFunc isEqualTo _x) then { diag_log text format ["XEH: Could not recompile [%1-%2]: %3", _eventName, _customName, _eventFunc]; }; }; - }; - _eventFunc = compile _eventFunc; - TRACE_2("does something",_customName,_eventName); - } else { - _eventFunc = {}; - TRACE_2("does NOT do something",_customName,_eventName); + compile _eventFunc // apply return + }; }; - _result pushBack ["", _eventName, _eventFunc]; + _result pushBack ["", _eventName, _eventFuncs]; _resultNames pushBack _customName; } forEach configProperties [_baseConfig >> XEH_FORMAT_CONFIG_NAME(_eventName)]; } forEach ["preInit", "postInit"]; @@ -119,10 +127,12 @@ private _resultNames = []; }; { - private _eventFunc = _eventFuncBase; private _customName = configName _x; private _allowInheritance = true; private _excludedClasses = []; + private _funcAll = ""; + private _funcClient = ""; + private _funcServer = ""; if (isClass _x) then { // allow inheritance of this event? @@ -132,6 +142,9 @@ private _resultNames = []; _allowInheritance = getNumber _scope != 0; }; + // init event handlers that should run on respawn again, onRespawn = 1 + private _onRespawn = toLower _eventName in ["init", "initpost"] && {getNumber (_x >> "onRespawn") == 1}; + // classes excluded from this event private _exclude = _x >> "exclude"; @@ -147,35 +160,38 @@ private _resultNames = []; private _entry = _x >> _entryName; if (isText _entry) then { - _eventFunc = _eventFunc + getText _entry + ";"; + _funcAll = _eventFuncBase + getText _entry + ";"; + + if (_onRespawn) then { + _funcAll = _funcAll + "(_this select 0) addEventHandler ['Respawn', " + str _funcAll + "];"; + }; }; // client only events - if (!isDedicated) then { - _entry = _x >> format ["client%1", _entryName]; + _entry = _x >> format ["client%1", _entryName]; + + if (isText _entry) then { + _funcClient = _eventFuncBase + getText _entry + ";"; - if (isText _entry) then { - _eventFunc = _eventFunc + getText _entry + ";"; + if (_onRespawn) then { + _funcClient = _funcClient + "(_this select 0) addEventHandler ['Respawn', " + str _funcClient + "];"; }; }; // server only events - if (isServer) then { - _entry = _x >> format ["server%1", _entryName]; + _entry = _x >> format ["server%1", _entryName]; - if (isText _entry) then { - _eventFunc = _eventFunc + getText _entry + ";"; - }; - }; + if (isText _entry) then { + _funcServer = _eventFuncBase + getText _entry + ";"; - // init event handlers that should run on respawn again, onRespawn = 1 - if (toLower _eventName in ["init", "initpost"] && {getNumber (_x >> "onRespawn") == 1}) then { - _eventFunc = _eventFunc + "(_this select 0) addEventHandler ['Respawn', " + str _eventFunc + "];"; + if (_onRespawn) then { + _funcServer = _funcServer + "(_this select 0) addEventHandler ['Respawn', " + str _funcServer + "];"; + }; }; } else { // global events if (isText _x) then { - _eventFunc = _eventFunc + getText _x + ";"; + _funcAll = _eventFuncBase + getText _x + ";"; }; }; @@ -197,19 +213,22 @@ private _resultNames = []; }; } forEach _resultNames; - // only add event on machines where it exists - if !(_eventFunc isEqualTo _eventFuncBase) then { - _eventFunc = compile _eventFunc; - TRACE_3("does something",_customName,_className,_eventName); - } else { - _eventFunc = {}; - TRACE_3("does NOT do something",_customName,_className,_eventName); + private _eventFuncs = [_funcAll, _funcClient, _funcServer] apply { + // only add event on machines where it exists + if (_x == "") then { + TRACE_3("does NOT do something",_customName,_className,_eventName); + {} + } else { + TRACE_3("does something",_customName,_className,_eventName); + compile _x + }; }; - - _result pushBack [_className, _eventName, _eventFunc, _allowInheritance, _excludedClasses]; + _result pushBack [_className, _eventName, _eventFuncs, _allowInheritance, _excludedClasses]; _resultNames pushBack _customName; } forEach configProperties [_x]; } forEach configProperties [_baseConfig >> XEH_FORMAT_CONFIG_NAME(_eventName), "isClass _x"]; } forEach [XEH_EVENTS]; -_result select {!((_x select 2) isEqualTo {})} +TRACE_2("compiled",_baseConfig,count _result); + +_result select {!((_x select 2) isEqualTo [{},{},{}])} diff --git a/addons/xeh/fnc_initDisplay.sqf b/addons/xeh/fnc_initDisplay.sqf index 7612dcee9..f11c1d2da 100644 --- a/addons/xeh/fnc_initDisplay.sqf +++ b/addons/xeh/fnc_initDisplay.sqf @@ -15,5 +15,5 @@ if !(_event isEqualTo "") then { private ["_event", "_className"]; // prevent these variables from being overwritten _args call compile getText _x; } forEach configProperties [_x >> XEH_FORMAT_CONFIG_NAME(_event) >> _className, "isText _x"]; - } forEach XEH_MAIN_CONFIGS; + } forEach [configFile, campaignConfigFile, missionConfigFile]; }; diff --git a/addons/xeh/fnc_postInit.sqf b/addons/xeh/fnc_postInit.sqf index 37a4d4f5c..3b38f1e89 100644 --- a/addons/xeh/fnc_postInit.sqf +++ b/addons/xeh/fnc_postInit.sqf @@ -16,4 +16,51 @@ Author: commy2 ---------------------------------------------------------------------------- */ -CBA_fnc_postInit_unscheduled call CBA_fnc_directCall; +isNil { + XEH_LOG("XEH: PostInit started. " + PFORMAT_9("MISSIONINIT",missionName,missionVersion,worldName,isMultiplayer,isServer,isDedicated,CBA_isHeadlessClient,hasInterface,didJIP)); + + // fix CBA_missionTime being -1 on (non-JIP) clients at mission start. + if (CBA_missionTime == -1) then { + CBA_missionTime = 0; + }; + + // call PostInit events + { + if (_x select 1 == "postInit") then { + (_x select 2) call { + private "_x"; + + [] call (_this select 0); + + if (!isDedicated) then { + [] call (_this select 1); + }; + + if (isServer) then { + [] call (_this select 2); + }; + }; + }; + } forEach GVAR(allEventHandlers); + + // do InitPost + { + _x params ["_this"]; + + { + [_this] call _x; + } forEach (_this getVariable QGVAR(initPost)); + } forEach GVAR(initPostStack); + + GVAR(initPostStack) = nil; + + #ifdef DEBUG_MODE_FULL + diag_log text format ["isScheduled = %1", call CBA_fnc_isScheduled]; + #endif + + SLX_XEH_MACHINE set [8, true]; // PostInit passed + + XEH_LOG("XEH: PostInit finished."); +}; + +nil diff --git a/addons/xeh/fnc_postInit_unscheduled.sqf b/addons/xeh/fnc_postInit_unscheduled.sqf deleted file mode 100644 index 3cf1046f4..000000000 --- a/addons/xeh/fnc_postInit_unscheduled.sqf +++ /dev/null @@ -1,50 +0,0 @@ -#include "script_component.hpp" -/* ---------------------------------------------------------------------------- -Function: CBA_fnc_postInit_unscheduled - -Description: - Occurs once per mission after objects and functions are initialized. - Internal use only. - -Parameters: - None - -Returns: - None - -Author: - commy2 ----------------------------------------------------------------------------- */ - -XEH_LOG("XEH: PostInit started. " + PFORMAT_9("MISSIONINIT",missionName,missionVersion,worldName,isMultiplayer,isServer,isDedicated,CBA_isHeadlessClient,hasInterface,didJIP)); - -// fix CBA_missionTime being -1 on (non-JIP) clients at mission start. -if (CBA_missionTime == -1) then { - CBA_missionTime = 0; -}; - -// call PostInit events -{ - if (_x select 1 == "postInit") then { - [] call (_x select 2); - }; -} forEach GVAR(allEventHandlers); - -// do InitPost -{ - _x params ["_this"]; - - { - [_this] call _x; - } forEach (_this getVariable QGVAR(initPost)); -} forEach GVAR(initPostStack); - -GVAR(initPostStack) = nil; - -#ifdef DEBUG_MODE_FULL - diag_log text format ["isScheduled = %1", call CBA_fnc_isScheduled]; -#endif - -SLX_XEH_MACHINE set [8, true]; // PostInit passed - -XEH_LOG("XEH: PostInit finished."); diff --git a/addons/xeh/fnc_preInit.sqf b/addons/xeh/fnc_preInit.sqf index 194621537..e42b45c9b 100644 --- a/addons/xeh/fnc_preInit.sqf +++ b/addons/xeh/fnc_preInit.sqf @@ -73,9 +73,9 @@ GVAR(EventsLowercase) = []; // generate list of incompatible classes GVAR(incompatible) = [] call CBA_fnc_createNamespace; -private _cfgVehicles = configFile >> "CfgVehicles"; + { - private _class = _cfgVehicles >> _x; + private _class = configFile >> "CfgVehicles" >> _x; while {isClass _class && {!ISINCOMP(configName _class)}} do { SETINCOMP(configName _class); @@ -89,11 +89,12 @@ private _cfgVehicles = configFile >> "CfgVehicles"; XEH_LOG("XEH: Compiling XEH START"); #endif -GVAR(allEventHandlers) = []; +//Get configFile eventhandlers from cache that was generated at preStart +GVAR(allEventHandlers) = call (uiNamespace getVariable [QGVAR(configFileEventHandlers), {[]}]); { GVAR(allEventHandlers) append (_x call CBA_fnc_compileEventHandlers); -} forEach XEH_MAIN_CONFIGS; +} forEach [campaignConfigFile, missionConfigFile]; #ifdef DEBUG_MODE_FULL XEH_LOG("XEH: Compiling XEH END"); @@ -106,7 +107,19 @@ GVAR(fallbackRunning) = false; { if (_x select 0 == "") then { if (_x select 1 == "preInit") then { - [] call (_x select 2); + (_x select 2) call { + private "_x"; + + [] call (_this select 0); + + if (!isDedicated) then { + [] call (_this select 1); + }; + + if (isServer) then { + [] call (_this select 2); + }; + }; }; } else { _x params ["_className", "_eventName", "_eventFunc", "_allowInheritance", "_excludedClasses"]; @@ -116,8 +129,22 @@ GVAR(fallbackRunning) = false; _eventName = "fired"; }; - private _success = [_className, _eventName, _eventFunc, _allowInheritance, _excludedClasses] call CBA_fnc_addClassEventHandler; - TRACE_3("addClassEventHandler",_className,_eventName,_success); + _eventFunc params ["_funcAll", "_funcClient", "_funcServer"]; + + if !(_funcAll isEqualTo {}) then { + private _success = [_className, _eventName, _funcAll, _allowInheritance, _excludedClasses] call CBA_fnc_addClassEventHandler; + TRACE_3("addClassEventHandler",_className,_eventName,_success); + }; + + if (!isDedicated && {!(_funcClient isEqualTo {})}) then { + private _success = [_className, _eventName, _funcClient, _allowInheritance, _excludedClasses] call CBA_fnc_addClassEventHandler; + TRACE_3("addClassEventHandler",_className,_eventName,_success); + }; + + if (isServer && {!(_funcServer isEqualTo {})}) then { + private _success = [_className, _eventName, _funcServer, _allowInheritance, _excludedClasses] call CBA_fnc_addClassEventHandler; + TRACE_3("addClassEventHandler",_className,_eventName,_success); + }; }; } forEach GVAR(allEventHandlers); diff --git a/addons/xeh/fnc_preStart.sqf b/addons/xeh/fnc_preStart.sqf index 7f5b89056..22c4b0d07 100644 --- a/addons/xeh/fnc_preStart.sqf +++ b/addons/xeh/fnc_preStart.sqf @@ -68,5 +68,9 @@ with uiNamespace do { // cache incompatible classes that are needed in preInit GVAR(incompatibleClasses) = compileFinal str ([false, true] call CBA_fnc_supportMonitor); + + // compile and cache configFile eventhandlers as they won't change from here on + GVAR(configFileEventHandlers) = compileFinal str (configFile call CBA_fnc_compileEventHandlers); + nil // needs return value [a3\functions_f\initfunctions.sqf Line 499] }; diff --git a/addons/xeh/script_component.hpp b/addons/xeh/script_component.hpp index cb3fd1032..41be0b1fc 100644 --- a/addons/xeh/script_component.hpp +++ b/addons/xeh/script_component.hpp @@ -38,8 +38,6 @@ #include "script_xeh.hpp" -#define XEH_MAIN_CONFIGS [configFile, campaignConfigFile, missionConfigFile] - #undef XEH_ENABLED #define XEH_ENABLED class EventHandlers {class XEH_CLASS: XEH_CLASS_BASE {};}; SLX_XEH_DISABLED = 0