Skip to content

Commit

Permalink
Compile and cache configFile eventhandlers at preStart (#1052)
Browse files Browse the repository at this point in the history
* Compile configFile eventhandlers at preStart

* Hacking protection

* Fix server/client only EH caching

* Fix

* xeh - cache server/client events seperatly

* Finish applying to initEH, skip on filepatching

* Disable debug

* Add missing preStart changes

* handle extra local variables, cleanup

* formatting, parentheses

* PATHTO_FNC() macro
  • Loading branch information
dedmen authored and commy2 committed Feb 17, 2019
1 parent a9b2d08 commit 76a09cb
Show file tree
Hide file tree
Showing 8 changed files with 179 additions and 168 deletions.
56 changes: 11 additions & 45 deletions addons/xeh/CfgFunctions.hpp
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down
143 changes: 81 additions & 62 deletions addons/xeh/fnc_compileEventHandlers.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -27,72 +27,80 @@ 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 {
// events on clients and server
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"];
Expand All @@ -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?
Expand All @@ -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";

Expand All @@ -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 + ";";
};
};

Expand All @@ -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 [{},{},{}])}
2 changes: 1 addition & 1 deletion addons/xeh/fnc_initDisplay.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -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];
};
49 changes: 48 additions & 1 deletion addons/xeh/fnc_postInit.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -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
Loading

0 comments on commit 76a09cb

Please sign in to comment.