I've been lately working on destructable and item indexer and everyone knows, that events do not fire before map init. I went looking at wc3c/the helper for answers and possible solutions - outcome: each library has it's own preload stuff (if it does cover mentioned issue). UnitIndexer isn't exception.
I guess we should talk about preloading events so we can get best possible way to fix the issue. Personaly, I have had custom public struct preloader to do the job for me. Problem was, each time I wanted to implement Register<...>/TriggerRegister<...> functions, it forced me to write up additional things. Thus, such struct can't be a resource since user still has to manualy change some stuff.
So.. I started thinking about kinda extension for Event to cover that part. The key in my approach was to get into the core of event firing.. the fire method.
JASS:
library PreLoader
//! textmacro PRELOADER
private static boolean hasPreloaded=false
static thistype preloader=0
static integer array eval
private boolexpr bexpr
static method executePreload takes nothing returns nothing
local trigger t=CreateTrigger()
local thistype this=1
set hasPreloaded=true
loop
exitwhen integer(this)>w
set preloader=this
if eval[this]>0 and this.bexpr!=null then
call TriggerClearConditions(t)
call TriggerAddCondition(t,this.bexpr)
call TriggerEvaluate(t)
endif
set this=this+1
endloop
call DestroyTimer(GetExpiredTimer())
call DestroyTrigger(t)
set t=null
endmethod
static method addPreloader takes code c, thistype ev returns nothing
set ev.bexpr=Condition(c)
endmethod
private static method onInit takes nothing returns nothing
call TimerStart(CreateTimer(),0,false,function thistype.executePreload)
endmethod
//! endtextmacro PRELOADER
module PreLoadData
static method preloadEvent takes nothing returns boolean
local integer this=1
local Event ev=Event.preloader
endmodule
module PreLoadSet
loop
exitwhen this > Event.eval[ev]
endmodule
module PreLoadNull
call ev.fire()
set this=this+1
endloop
endmodule
module PreLoadEnd
return false
endmethod
endmodule
endlibrary
and the fire method changes:
JASS:
method fire takes nothing returns nothing
set q=0
set q=this
call TriggerEvaluate(e[this])
static if LIBRARY_PreLoader then
if not thistype.hasPreloaded then
set eval[this] = eval[this]+1
endif
endif
endmethod
Now, lets bring the fact that indexers start indexing from 1. Above lib with consideration of such fact allows typical indexer to avoid implementation of custom preload member and instead offers:
JASS:
implement PreLoadData
local integer prev = eventIndex
implement PreLoadSet
set eventIndex = this
implement PreLoadNull
set eventIndex = prev
implement PreLoadEnd
With addition of (example):
JASS:
call Event.addPreloader(function thistype.preloadEvent, ItemIndex.INDEX)
at onInit method for given library.
Such method ignores the division on trigger/condition part since it calls .fire() method.
Next, there is basicaly no gain, if you use this for just UnitIndexer for example. However, if you'd go for additional one, like ItemIndexer then it happily cuts the code and makes things look cleaner.
Once again, it's just a suggestion and since conversations can bring nothing but profit I'd like to know ur opinions about that issue.
There are few options available:
a) each lib implements it's own stuff to deal with this
b) create a lib which covers this on it's own (but how could you acces the event data then)?
c) interference with Event itself
Edit: Additional variant of API from previous lib:
JASS:
//! textmacro PRELOADER takes DATA
static method preloadEvent takes nothing returns boolean
local integer this=next[0]
local Event ev=Event.preloader
local integer save = $DATA$
loop
exitwhen 0==this
set $DATA$ = this
call ev.fire()
set this=next[this]
endloop
set $DATA$ = save
return false
endmethod
//! endtextmacro
Uses the linked list from library directly. Now, you can just type:
//! runtextmacro PRELOADER("o")
in $DATA$ place type global event index name.
That variant requires no changes in fire method.