- Joined
- Jun 23, 2007
- Messages
- 4,066
System Code
Examples
Compatibility With Other Indexers
UnitIndexer
GUI Unit Indexer
AIDS
AutoIndex
Changelog
v1.2.2
- UnitDexRemove was moved below the struct to prevent JassHelper from generating an unnecessary function
- Pre-placed units are now enumerated on initialization.
v1.2.1
- UnitDexRemove now returns true on success
- Remove method added to struct
- UnitDexRemove now just calls .Remove
- Fixed a bug where UnitDex.Count wouldn't decrease when a unit left
- OnUnitIndex/OnUnitDeindex functions added
- LastIndex now readonly
- Hashtable option removed (due to static if's not working properly with modules outside of the struct)
- Minor optimizations
v1.2.0
- IsUnitIndexed now works correctly when using the hashtable version
- UnitRecycleId -> UnitDexRemove
- UnitDexRemove now set the units id to zero
- When using hashtable version the stored integer now gets reset to zero
v1.1.9
- Bug fixes
v1.1.8
- Fixed a bug where events would fire an extra time on initialization.
- readonly boolean "Initialized" added to the UnitDex struct.
v1.1.7
- A public unitgroup (UnitDex.Group) has been implemented to allow easy enumeration of all indexed units.
- TimerUtils removed due to module initializing.
- Documentation improved.
v1.1.6
- Events registered at initialization are now properly executed via a timer.
- Because of the timer required for runInitTriggers, TimerUtils has become optional for preloading and recycling.
v1.1.5
- Units are now stored in a publicly accessible, readonly array (UnitDex.Unit).
- Initialization is now done through a module to ensure all units are indexed.
- A few globals have been moved to the UnitDex struct, to allow public use.
- The private function, SetUnitId was removed.
- PlayerUtils optional requirement removed, due to module initializing.
v1.1.4
- Flush removed.
- UnitDexConfig no longer optional.
- Filtering units is now done by defining onFilter inside the configuration. If the method doesn't exist than static if's will remove unused code.
- Removed the need for a trigger queue by using TriggerRegisterVariableEvent, meaning much better efficiency and cleaner code.
v1.1.3
- UnitDex struct implemented.
- Removed unused variables
- You can now reset the indexer via .Flush() or UnitDexReset.
- Bounds safety removed because it had little performance benefit.
- You can now filter which units get indexed through the UnitDexOptions module.
- IsIndexingEnabled added.
- UnitRecycleIndex renamed to UnitRecycleId.
v1.1.2
- Fixed a small leak on initialization where I nulled the region instead of the rect.
- Evaluating the trigger queue is now ignored when there's no registered events.
- RemoveUnitIndexEvent implemented to allow you to unregister events.
- RegisterUnitIndexEvent now returns triggercondition so you can catch the handle.
v1.1.1
- Fixed a few bugs concerning the hashtable only version.
- UnitRecycleIndex implemented to allow manual deindexing.
- Can now toggle the indexer with UnitDexEnable.
- onLeave now nulls the unit index.
- Optimized GetIndexedUnit.
- IsUnitIndexed added.
- Units properly removed from the table if hashtable was used for indexing.
v1.1.0
- Event API simplified without sacrificing inlining.
- Merged trigger queue counters.
v1.0.5
- Bounds Safety now sets user data as well.
- GetUnitId now inlines with bounds safety on.
- Bounds Safety no longer uses hashtable for storing the index (performance boost).
- Event API modified to allow inlining as well as allow you to register indexing and deindexing events in a single call.
v1.0.4
- Defaulted LastIndexedUnit to 0 to prevent thread crashing.
- Fixed an issue where onLeave would fire for units who cast the generic Defend ability.
- Fixed an issue where onLeave would only fire the first trigger registered.
- Now the script doesn't deindex dead units, only removed ones.
- Merged trigger queues into one variable and made a wrapper for looping through them.
- Fixed a bug where a hashtable would be created regardless.
v1.0.3
- Documentation improved.
- Fixed an issue where some optional libraries wouldn't be detected.
- Fixed a leak that only occured in debug mode.
v1.0.2
- Debugging options added.
- Fixed an issue where a units id would be -1 on deindexing events.
- Added a bounds safety option that will switch to a hashtable once the array limit has been reached.
v1.0.1
-- Improved variable names
-- Fixed a possible leak.
JASS:
library UnitDex uses optional WorldBounds, optional GroupUtils
/***************************************************************
*
* v1.2.2, by TriggerHappy
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
* UnitDex assigns every unit an unique integer. It attempts to make that number within the
* maximum array limit so you can associate it with one.
* _________________________________________________________________________
* 1. Installation
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
* Copy the script to your map, save it, then restart the editor and comment out the line below.
*/
//! external ObjectMerger w3a Adef uDex anam "Detect Leave" ansf "(UnitDex)" aart "" acat "" arac 0
/* ________________________________________________________________________
* 2. Configuration
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
*/
private module UnitDexConfig
// The raw code of the leave detection ability.
static constant integer DETECT_LEAVE_ABILITY = 'uDex'
// Allow debug messages (debug mode must also be on)
static constant boolean ALLOW_DEBUGGING = true
// Uncomment the lines below to define a global filter for units being indexed
/*static method onFilter takes unit u returns boolean
return true
endmethod*/
endmodule
/* _________________________________________________________________________
* 3. Function API
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
* Every function inlines.
*
* function GetUnitId takes unit whichUnit returns integer
* function GetUnitById takes integer index returns unit
*
* function UnitDexEnable takes boolean flag returns nothing
* function UnitDexRemove takes unit u, boolean runEvents returns boolean
*
* function IsUnitIndexed takes unit u returns boolean
* function IsIndexingEnabled takes nothing returns boolean
*
* function GetIndexedUnit takes nothing returns unit
* function GetIndexedUnitId takes nothing returns integer
*
* function RegisterUnitIndexEvent takes boolexpr func, integer eventtype returns indexevent
* function RemoveUnitIndexEvent takes triggercondition c, integer eventtype returns nothing
* function TriggerRegisterUnitIndexEvent takes trigger t, integer eventtype returns nothing
*
* function OnUnitIndex takes code func returns triggercondition
* function OnUnitDeidex takes code func returns triggercondition
* _________________________________________________________________________
* 4. Struct API
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
* UnitDex.Enabled = false // toggle the indexer
* UnitDex.Initialized // returns true if the preload timer has finished
* UnitDex.Count // returns the amount of units indexed
* UnitDex.Unit[0] // access the UnitDex array directly
* UnitDex.Group // a unit group containing every indexed unit (for enumeration)
* UnitDex.LastIndex // returns the last indexed unit's id
* _________________________________________________________________________
* 5. Public Variables
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
* These are to be used with the "eventtype" argument of the event API:
*
* constant integer EVENT_UNIT_INDEX = 0
* constant integer EVENT_UNIT_DEINDEX = 1
* _________________________________________________________________________
* 6. Examples
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
* 1. Associate a unit with a variable
*
* set UnitFlag[GetUnitId(yourUnit)] = true
*
* 2. Allocate a struct instance using a units assigned ID
*
* local somestruct data = GetUnitId(yourUnit)
*
* 3. Detect when a unit leaves the map
*
* function Exit takes nothing returns nothing
* call BJDebugMsg("The unit " + GetUnitName(GetIndexedUnit()) + " has left the map.")
* endfunction
*
* call OnUnitDeindex(function Exit)
* // or
* call RegisterUnitIndexEvent(Filter(function Exit), EVENT_UNIT_DEINDEX)
*
*
* _________________________________________________________________________
* 7. How it works
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
* 1. Enumerate all preplaced units
* 2. TriggerRegisterEnterRegion native to detect when a unit enters the map
* 3. Assign each unit that enters the map a unique integer
* 4. Give every unit an ability based off of defend. There is no native to accurately
* detect when a unit leaves the map but when a unit dies or is removed from the game
* they are issued the "undefend" order
* 5. Catch the "undefend" order and remove unit from the queue
* _________________________________________________________________________
* 8. Notes
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
* - This system is compatable with GUI because it utilizes UnitUserData (custom values for units).
* - The object merger line should be commented out after saving and restarting.
*
* -http://www.hiveworkshop.com/forums/submissions-414/unitdex-lightweight-unit-indexer-248209/
*
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
*/
globals
// Event types
constant integer EVENT_UNIT_INDEX = 0
constant integer EVENT_UNIT_DEINDEX = 1
// System variables
private trigger array IndexTrig
private integer Index = 0
private real E=-1
private boolexpr FilterEnter
endglobals
function GetUnitId takes unit whichUnit returns integer
return GetUnitUserData(whichUnit)
endfunction
function GetUnitById takes integer index returns unit
return UnitDex.Unit[index]
endfunction
function GetIndexedUnit takes nothing returns unit
return UnitDex.Unit[UnitDex.LastIndex]
endfunction
function GetIndexedUnitId takes nothing returns integer
return UnitDex.LastIndex
endfunction
function IsUnitIndexed takes unit u returns boolean
return (GetUnitById(GetUnitId(u)) != null)
endfunction
function UnitDexEnable takes boolean flag returns nothing
set UnitDex.Enabled = flag
endfunction
function IsIndexingEnabled takes nothing returns boolean
return UnitDex.Enabled
endfunction
function RegisterUnitIndexEvent takes boolexpr func, integer eventtype returns triggercondition
return TriggerAddCondition(IndexTrig[eventtype], func)
endfunction
function RemoveUnitIndexEvent takes triggercondition c, integer eventtype returns nothing
call TriggerRemoveCondition(IndexTrig[eventtype], c)
endfunction
function TriggerRegisterUnitIndexEvent takes trigger t, integer eventtype returns nothing
call TriggerRegisterVariableEvent(t, SCOPE_PRIVATE + "E", EQUAL, eventtype)
endfunction
function OnUnitIndex takes code func returns triggercondition
return TriggerAddCondition(IndexTrig[EVENT_UNIT_INDEX], Filter(func))
endfunction
function OnUnitDeindex takes code func returns triggercondition
return TriggerAddCondition(IndexTrig[EVENT_UNIT_DEINDEX], Filter(func))
endfunction
/****************************************************************/
private keyword UnitDexCore
struct UnitDex extends array
static boolean Enabled = true
readonly static integer LastIndex
readonly static boolean Initialized=false
readonly static group Group=CreateGroup()
readonly static unit array Unit
readonly static integer Count = 0
readonly static integer array List
implement UnitDexConfig
private static integer Counter = 0
implement UnitDexCore
endstruct
function UnitDexRemove takes unit u, boolean runEvents returns boolean
return UnitDex.Remove(u, runEvents)
endfunction
/****************************************************************/
private module UnitDexCore
static method Remove takes unit u, boolean runEvents returns boolean
local integer i
if (IsUnitIndexed(u)) then
set i = GetUnitId(u)
set UnitDex.List[i] = Index
set Index = i
call GroupRemoveUnit(UnitDex.Group, u)
call SetUnitUserData(u, 0)
if (runEvents) then
set UnitDex.LastIndex = i
set E = EVENT_UNIT_DEINDEX
call TriggerEvaluate(IndexTrig[EVENT_UNIT_DEINDEX])
set E = -1
endif
set UnitDex.Unit[i] = null
set UnitDex.Count = UnitDex.Count - 1
return true
endif
return false
endmethod
private static method onGameStart takes nothing returns nothing
local integer i = 1
loop
exitwhen i > Counter
set LastIndex = i
call TriggerEvaluate(IndexTrig[EVENT_UNIT_INDEX])
set E = EVENT_UNIT_INDEX
set E = -1
set i = i + 1
endloop
set LastIndex = Counter
set Initialized = true
set FilterEnter = null
call DestroyTimer(GetExpiredTimer())
endmethod
private static method onEnter takes nothing returns boolean
local unit u = GetFilterUnit()
local integer i = GetUnitId(u)
local integer t = Index
if (i == 0 and thistype.Enabled) then
// If a filter was defined pass the unit through it.
static if (thistype.onFilter.exists) then
if (not thistype.onFilter(u)) then
set u = null
return false // check failed
endif
endif
// Handle debugging
static if (thistype.DEBUG_MODE and thistype.ALLOW_DEBUGGING) then
if (t == 0 and Counter+1 >= JASS_MAX_ARRAY_SIZE) then
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "UnitDex: Maximum number of units reached!")
set u = null
return false
endif
endif
// Add to group of indexed units
call GroupAddUnit(thistype.Group, u)
// Give unit the leave detection ability
call UnitAddAbility(u, thistype.DETECT_LEAVE_ABILITY)
call UnitMakeAbilityPermanent(u, true, thistype.DETECT_LEAVE_ABILITY)
// Allocate index
if (Index != 0) then
set Index = List[t]
else
set Counter = Counter + 1
set t = Counter
endif
set List[t] = -1
set LastIndex = t
set thistype.Unit[t] = u
set Count = Count + 1
// Store the index
call SetUnitUserData(u, t)
if (thistype.Initialized) then
// Execute custom events registered with RegisterUnitIndexEvent
call TriggerEvaluate(IndexTrig[EVENT_UNIT_INDEX])
// Handle TriggerRegisterUnitIndexEvent
set E = EVENT_UNIT_INDEX
// Reset so the event can occur again
set E = -1
endif
endif
set u = null
return false
endmethod
private static method onLeave takes nothing returns boolean
local unit u
local integer i
// Check if order is undefend.
if (thistype.Enabled and GetIssuedOrderId() == 852056) then
set u = GetTriggerUnit()
// If unit was killed (not removed) then don't continue
if (GetUnitAbilityLevel(u, thistype.DETECT_LEAVE_ABILITY) != 0) then
set u = null
return false
endif
set i = GetUnitId(u)
// If unit has been indexed then deindex it
if (i > 0 and i <= Counter and u == GetUnitById(i)) then
// Recycle the index
set List[i] = Index
set Index = i
set LastIndex = i
// Remove to group of indexed units
call GroupRemoveUnit(thistype.Group, u)
// Execute custom events without any associated triggers
call TriggerEvaluate(IndexTrig[EVENT_UNIT_DEINDEX])
// Handle TriggerRegisterUnitIndexEvent
set E = EVENT_UNIT_DEINDEX
// Remove entry
call SetUnitUserData(u, 0)
set thistype.Unit[i] = null
// Decrement unit count
set Count = Count - 1
// Reset so the event can occur again
set E = -1
endif
set u = null
endif
return false
endmethod
private static method onInit takes nothing returns nothing
local trigger t = CreateTrigger()
local integer i = 0
local player p
local unit u
static if (not LIBRARY_WorldBounds) then // Check if WorldBounts exists, if not then define the necessary vars
local region reg = CreateRegion() // If WorldBounds wasn't found, create the region manually
local rect world = GetWorldBounds()
endif
static if (not LIBRARY_GroupUtils) then // Check if GroupUtils exists so we can use it's enumeration group.
local group ENUM_GROUP = CreateGroup() // If not, create the group.
endif
set FilterEnter = Filter(function thistype.onEnter)
// Begin to index units when they enter the map
static if (LIBRARY_WorldBounds) then
call TriggerRegisterEnterRegion(CreateTrigger(), WorldBounds.worldRegion, FilterEnter)
else
call RegionAddRect(reg, world)
call TriggerRegisterEnterRegion(CreateTrigger(), reg, FilterEnter)
call RemoveRect(world)
set world = null
endif
call TriggerAddCondition(t, Filter(function thistype.onLeave))
set IndexTrig[EVENT_UNIT_INDEX] = CreateTrigger()
set IndexTrig[EVENT_UNIT_DEINDEX] = CreateTrigger()
loop
set p = Player(i)
// Detect "undefend"
call TriggerRegisterPlayerUnitEvent(t, p, EVENT_PLAYER_UNIT_ISSUED_ORDER, null)
// Hide the detect ability from players
call SetPlayerAbilityAvailable(p, thistype.DETECT_LEAVE_ABILITY, false)
set i = i + 1
exitwhen i == bj_MAX_PLAYER_SLOTS
endloop
// Index preplaced units
set i = 0
loop
call GroupEnumUnitsOfPlayer(ENUM_GROUP, Player(i), FilterEnter)
set i = i + 1
exitwhen i == bj_MAX_PLAYER_SLOTS
endloop
static if (not LIBRARY_GroupUtils) then
call DestroyGroup(ENUM_GROUP)
set ENUM_GROUP = null
endif
set LastIndex = Counter
// run init triggers
call TimerStart(CreateTimer(), 0.00, false, function thistype.onGameStart)
endmethod
endmodule
endlibrary
Examples
JASS:
set GlobalInteger[GetUnitId(unit)] = 50
JASS:
function onIndex takes nothing returns boolean
call BJDebugMsg(GetUnitName(GetIndexedUnit()) + "[" + I2S(GetIndexedUnitId()) + "] enters the map.")
return false
endfunction
function onDeindex takes nothing returns boolean
call BJDebugMsg(GetUnitName(GetIndexedUnit()) + "[" + I2S(GetIndexedUnitId()) + "] leaves the map.")
return false
endfunction
//===========================================================================
function InitTrig_UnitDex_Example takes nothing returns nothing
call RegisterUnitIndexEvent(Filter(function onIndex) , EVENT_UNIT_INDEX)
call RegisterUnitIndexEvent(Filter(function onDeindex), EVENT_UNIT_DEINDEX)
endfunction
JASS:
struct UnitData
static method operator[] takes unit u returns integer
return GetUnitId(u)
endmethod
endstruct
local UnitData data = UnitData[GetTriggerUnit()]
Compatibility With Other Indexers
UnitIndexer
JASS:
library UnitIndexer requires UnitDex
struct UnitIndexer
readonly static integer INDEX = EVENT_UNIT_INDEX
readonly static integer DEINDEX = EVENT_UNIT_DEINDEX
static method operator enabled= takes boolean b returns nothing
set UnitDex.Enabled=b
endmethod
static method operator enabled takes nothing returns boolean
return UnitDex.Enabled
endmethod
endstruct
module UnitIndexStructMethods
static method operator [] takes unit u returns thistype
return GetUnitUserData(u)
endmethod
method operator unit takes nothing returns unit
return UnitDex.Unit[this]
endmethod
endmodule
module UnitIndexStruct
implement UnitIndexStructMethods
method operator allocated takes nothing returns boolean
return this==GetUnitUserData(UnitDex.Unit[this])
endmethod
endmodule
function IsUnitDeindexing takes unit u returns boolean
return IsUnitIndexed(u) and 0==GetUnitAbilityLevel(u, UnitDex.DETECT_LEAVE_ABILITY)
endfunction
struct UnitIndex extends array
method lock takes nothing returns nothing
endmethod
method unlock takes nothing returns nothing
endmethod
method operator unit takes nothing returns unit
return UnitDex.Unit[this]
endmethod
static method operator [] takes unit whichUnit returns thistype
return GetUnitUserData(whichUnit)
endmethod
endstruct
endlibrary
GUI Unit Indexer
JASS:
library UnitIndexerGUI initializer Init requires UnitDex
private function OnIndex takes nothing returns nothing
set udg_UDex = GetIndexedUnitId()
set udg_UDexUnits[udg_UDex] = GetIndexedUnit()
set udg_UnitIndexEvent = 1.
set udg_UnitIndexEvent = 0.
endfunction
private function OnDeindex takes nothing returns nothing
set udg_UDex = GetIndexedUnitId()
set udg_UDexUnits[udg_UDex] = GetUnitById(udg_UDex)
set udg_UnitIndexEvent = 2.
set udg_UnitIndexEvent = 0.
endfunction
private function Init takes nothing returns nothing
call OnUnitIndex(function OnIndex)
call OnUnitIndex(function OnDeindex)
endfunction
endlibrary
AIDS
(Thanks to Bannar)
JASS:
library AIDS requires UnitDex
public function RegisterOnEnter takes boolexpr b returns triggercondition
return RegisterUnitIndexEvent(b, EVENT_UNIT_INDEX)
endfunction
public function RegisterOnEnterAllocated takes boolexpr b returns triggercondition
return RegisterUnitIndexEvent(b, EVENT_UNIT_INDEX)
endfunction
public function RegisterOnDeallocate takes boolexpr b returns triggercondition
return RegisterUnitIndexEvent(b, EVENT_UNIT_DEINDEX)
endfunction
function GetIndexUnit takes integer index returns unit
return GetUnitById(index)
endfunction
function GetUnitIndex takes unit u returns integer
return GetUnitId(u)
endfunction
public struct DEFAULT extends array
method AIDS_onCreate takes nothing returns nothing
endmethod
method AIDS_onDestroy takes nothing returns nothing
endmethod
static method AIDS_filter takes unit u returns boolean
return true
endmethod
static method AIDS_onInit takes nothing returns nothing
endmethod
endstruct
//! textmacro AIDS
private static delegate AIDS_DEFAULT deleg = 0
method AIDS_addLock takes nothing returns nothing
endmethod
method AIDS_removeLock takes nothing returns nothing
endmethod
static method operator[] takes unit whichUnit returns thistype
return GetUnitId(whichUnit)
endmethod
method operator unit takes nothing returns unit
return GetUnitById(this)
endmethod
private static method AIDS_onEnter takes nothing returns boolean
call thistype(GetIndexedUnitId()).AIDS_onCreate()
return false
endmethod
private static method AIDS_onDeallocate takes nothing returns boolean
if IsUnitIndexed(GetIndexedUnit()) then
call thistype(GetIndexedUnitId()).AIDS_onDestroy()
endif
return false
endmethod
private static method onInit takes nothing returns nothing
call RegisterUnitIndexEvent(Filter(function thistype.AIDS_onEnter), EVENT_UNIT_INDEX)
call RegisterUnitIndexEvent(Filter(function thistype.AIDS_onDeallocate), EVENT_UNIT_DEINDEX)
call thistype.AIDS_onInit()
endmethod
//! endtextmacro
endlibrary
AutoIndex
JASS:
library AutoIndex requires UnitDex
function interface IndexFunc takes unit u returns nothing
struct AutoIndex
private static IndexFunc array indexfuncs
private static integer indexfuncs_n = -1
private static IndexFunc array deindexfuncs
private static integer deindexfuncs_n = -1
private static IndexFunc indexfunc
static method getIndex takes unit u returns integer
return GetUnitId(u)
endmethod
static method isUnitIndexed takes unit u returns boolean
return u != null and UnitDex.Unit[GetUnitId(u)] == u
endmethod
static method getIndexDebug takes unit u returns integer
if u == null then
return 0
elseif GetUnitTypeId(u) == 0 then
call BJDebugMsg("AutoIndex error: Removed or decayed unit passed to GetUnitId.")
elseif UnitDex.Unit[GetUnitId(u)] != u and GetIssuedOrderId() != 852056 then
call BJDebugMsg("AutoIndex error: "+GetUnitName(u)+" is a filtered unit.")
endif
return getIndex(u)
endmethod
private static method onUnitIndexed_sub takes nothing returns nothing
call indexfunc.evaluate(GetEnumUnit())
endmethod
static method onUnitIndexed takes IndexFunc func returns nothing
set indexfuncs_n = indexfuncs_n + 1
set indexfuncs[indexfuncs_n] = func
if UnitDex.Initialized then //During initialization, evaluate the indexfunc for every preplaced unit.
set indexfunc = func
call ForGroup(UnitDex.Group, function AutoIndex.onUnitIndexed_sub)
endif
endmethod
static method onUnitDeindexed takes IndexFunc func returns nothing
set deindexfuncs_n = deindexfuncs_n + 1
set deindexfuncs[deindexfuncs_n] = func
endmethod
endstruct
function OnUnitIndexed takes IndexFunc func returns nothing
call AutoIndex.onUnitIndexed(func)
endfunction
function OnUnitDeindexed takes IndexFunc func returns nothing
call AutoIndex.onUnitDeindexed(func)
endfunction
endlibrary
Changelog
v1.2.2
- UnitDexRemove was moved below the struct to prevent JassHelper from generating an unnecessary function
- Pre-placed units are now enumerated on initialization.
v1.2.1
- UnitDexRemove now returns true on success
- Remove method added to struct
- UnitDexRemove now just calls .Remove
- Fixed a bug where UnitDex.Count wouldn't decrease when a unit left
- OnUnitIndex/OnUnitDeindex functions added
- LastIndex now readonly
- Hashtable option removed (due to static if's not working properly with modules outside of the struct)
- Minor optimizations
v1.2.0
- IsUnitIndexed now works correctly when using the hashtable version
- UnitRecycleId -> UnitDexRemove
- UnitDexRemove now set the units id to zero
- When using hashtable version the stored integer now gets reset to zero
v1.1.9
- Bug fixes
v1.1.8
- Fixed a bug where events would fire an extra time on initialization.
- readonly boolean "Initialized" added to the UnitDex struct.
v1.1.7
- A public unitgroup (UnitDex.Group) has been implemented to allow easy enumeration of all indexed units.
- TimerUtils removed due to module initializing.
- Documentation improved.
v1.1.6
- Events registered at initialization are now properly executed via a timer.
- Because of the timer required for runInitTriggers, TimerUtils has become optional for preloading and recycling.
v1.1.5
- Units are now stored in a publicly accessible, readonly array (UnitDex.Unit).
- Initialization is now done through a module to ensure all units are indexed.
- A few globals have been moved to the UnitDex struct, to allow public use.
- The private function, SetUnitId was removed.
- PlayerUtils optional requirement removed, due to module initializing.
v1.1.4
- Flush removed.
- UnitDexConfig no longer optional.
- Filtering units is now done by defining onFilter inside the configuration. If the method doesn't exist than static if's will remove unused code.
- Removed the need for a trigger queue by using TriggerRegisterVariableEvent, meaning much better efficiency and cleaner code.
v1.1.3
- UnitDex struct implemented.
- Removed unused variables
- You can now reset the indexer via .Flush() or UnitDexReset.
- Bounds safety removed because it had little performance benefit.
- You can now filter which units get indexed through the UnitDexOptions module.
- IsIndexingEnabled added.
- UnitRecycleIndex renamed to UnitRecycleId.
v1.1.2
- Fixed a small leak on initialization where I nulled the region instead of the rect.
- Evaluating the trigger queue is now ignored when there's no registered events.
- RemoveUnitIndexEvent implemented to allow you to unregister events.
- RegisterUnitIndexEvent now returns triggercondition so you can catch the handle.
v1.1.1
- Fixed a few bugs concerning the hashtable only version.
- UnitRecycleIndex implemented to allow manual deindexing.
- Can now toggle the indexer with UnitDexEnable.
- onLeave now nulls the unit index.
- Optimized GetIndexedUnit.
- IsUnitIndexed added.
- Units properly removed from the table if hashtable was used for indexing.
v1.1.0
- Event API simplified without sacrificing inlining.
- Merged trigger queue counters.
v1.0.5
- Bounds Safety now sets user data as well.
- GetUnitId now inlines with bounds safety on.
- Bounds Safety no longer uses hashtable for storing the index (performance boost).
- Event API modified to allow inlining as well as allow you to register indexing and deindexing events in a single call.
v1.0.4
- Defaulted LastIndexedUnit to 0 to prevent thread crashing.
- Fixed an issue where onLeave would fire for units who cast the generic Defend ability.
- Fixed an issue where onLeave would only fire the first trigger registered.
- Now the script doesn't deindex dead units, only removed ones.
- Merged trigger queues into one variable and made a wrapper for looping through them.
- Fixed a bug where a hashtable would be created regardless.
v1.0.3
- Documentation improved.
- Fixed an issue where some optional libraries wouldn't be detected.
- Fixed a leak that only occured in debug mode.
v1.0.2
- Debugging options added.
- Fixed an issue where a units id would be -1 on deindexing events.
- Added a bounds safety option that will switch to a hashtable once the array limit has been reached.
v1.0.1
-- Improved variable names
-- Fixed a possible leak.
Last edited: