TimerIndexer v1.2

Scripts

9 years
edited 8 years
Useful system especially in making an MUI spell which uses timers. Instead of saving the spell data in a hashtable with the handleid of the timer as the parent key, you can just use normal arrays with the timerid as the index. This also allows you to pass custom data (integer) to timers.

System Features:
  • Indexed timers (Array safe, 1-8190 but can also be customized to be 8190+) NEW
  • Timer custom data (integer) attachment [NEW]
  • Timer double free protection
  • Automatic timer replacement (Useful safety feature which automatically replaces timers belonging to this system with a timer of the same timerid and handleid when destroyed)


    Timer Indexer v1.2
    Code (jass) Select
    1
    library TimerIndexer //v1.2
    2
    3
    4
    //! novjass
    5
         ________________
    6
        |                |
    7
        | Written by AGD |
    8
        |________________|
    9
    10
    11
        |=====|
    12
        | API |
    13
        |=====|
    14
    15
            function GetTimer takes nothing returns timer/*
    16
            - Allocates a new usable timer from the stock
    17
    18
          */function GetTimerEx takes integer i returns timer/*
    19
            - Retrieves a new usable timer from the stock and initializes
    20
              its custom integer data to <i>
    21
    22
          */function GetTimerById takes integer i returns timer/*
    23
            - Retrieves a timer of ID <i> from the stock but returns
    24
              null if that timer is not free
    25
    26
          */function FreeTimer takes timer t returns nothing/*
    27
            - Releases the timer back to the stock
    28
    29
          */function GetTimerId takes timer t returns integer/*
    30
            - Returns the index of the timer
    31
    32
          */function GetTimerData takes timer t returns integer/*
    33
            - Returns the custom integer data attached to the timer
    34
    35
          */function SetTimerData takes timer t, integer i returns nothing/*
    36
            - Attaches a custom integer data to the timer
    37
    38
          */function IsTimerStocked takes timer t returns boolean/*
    39
            - Checks if the timer is free
    40
    41
          */function GetTimerFlag takes timer t returns boolean/*
    42
            - Checks if the timer is included in this system's timer stock
    43
    44
    *///! endnovjass
    45
    46
        globals
    47
    /*
    48
            Determines the total number of timers on the stock          */
    49
            private constant integer TIMER_STOCK_SIZE = 8190
    50
    51
    /*      Determines the delay of timer replacement in case a
    52
            timer belonging to the stock is accidentally destroyed
    53
            Note that this value should be greater than the time
    54
            delay of the handleId recycling which is approximately
    55
            0.0050000 ( It's not advised to change this anyway )        */
    56
            private constant real REPLACE_DELAY = 0.0050001
    57
    58
        endglobals
    59
    60
        //================================================================
    61
    62
        globals
    63
            private timer array T[TIMER_STOCK_SIZE]
    64
            private timer tempTimer
    65
            private integer START_HANDLE
    66
            private integer destroyed
    67
            private integer current
    68
            private integer pitStop
    69
            private integer this
    70
            private integer array recycler[TIMER_STOCK_SIZE]
    71
            private integer array data[TIMER_STOCK_SIZE]
    72
            private boolean dont = false
    73
            private boolean array isTimerStocked[TIMER_STOCK_SIZE]
    74
        endglobals
    75
    76
        static if DEBUG_MODE then
    77
            private function Debug takes string msg returns nothing
    78
                call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "|CFFFFCC00[Timer Indexer]|R : " + msg)
    79
            endfunction
    80
        endif
    81
    82
        function GetTimerId takes timer t returns integer
    83
            return GetHandleId(t) - START_HANDLE
    84
        endfunction
    85
    86
        function GetTimerData takes timer t returns integer
    87
            return data[GetTimerId(t)]
    88
        endfunction
    89
    90
        function SetTimerData takes timer t, integer i returns nothing
    91
            set data[GetTimerId(t)] = i
    92
        endfunction
    93
    94
        function IsTimerStocked takes timer t returns boolean
    95
            return isTimerStocked[GetTimerId(t)]
    96
        endfunction
    97
    98
        function GetTimerFlag takes timer t returns boolean
    99
            return GetTimerId(t) > 0 and GetTimerId(t) <= TIMER_STOCK_SIZE
    100
        endfunction
    101
    102
        function GetTimer takes nothing returns timer
    103
            set this = recycler[0]
    104
            set recycler[0] = recycler[this]
    105
            if isTimerStocked[this] then
    106
                set isTimerStocked[this] = false
    107
                debug call Debug("Retrieving Timer [" + I2S(this) + "] from stock")
    108
                return T[this]
    109
            endif
    110
            debug call Debug("ERROR: No free timers available, creating a temporary timer.")
    111
            return CreateTimer()
    112
        endfunction
    113
    114
        function GetTimerById takes integer i returns timer
    115
            if isTimerStocked[i] then
    116
                debug call Debug("Retrieving Timer [" + I2S(i) + "] from stock")
    117
                return T[i]
    118
            endif
    119
            debug if i < 1 or i > TIMER_STOCK_SIZE then
    120
                debug call Debug("ERROR: Specified timer ID is out of bounds")
    121
            debug else
    122
                debug call Debug("ERROR: Timer [" + I2S(i) + "] is not free")
    123
            debug endif
    124
            return null
    125
        endfunction
    126
    127
        function GetTimerEx takes integer i returns timer
    128
            set tempTimer = GetTimer()
    129
            set data[GetTimerId(tempTimer)] = i
    130
            return tempTimer
    131
        endfunction
    132
    133
        function FreeTimer takes timer t returns nothing
    134
            local integer i = GetTimerId(t)
    135
            if not isTimerStocked[i] and GetTimerFlag(t) then
    136
                call TimerStart(t, 0, false, null)
    137
                set isTimerStocked[i] = true
    138
                set data[i] = 0
    139
                set recycler[i] = recycler[0]
    140
                set recycler[0] = i
    141
                debug call Debug("Releasing Timer [" + I2S(i) + "] back to the stock")
    142
            elseif not GetTimerFlag(t) then
    143
                call DestroyTimer(t)
    144
                debug call Debug("ERROR: Freed timer does not belong to the stack, destroying timer")
    145
            debug else
    146
                debug call Debug("ERROR: Attempt to double-free Timer [" + I2S(i) + "]")
    147
            endif
    148
        endfunction
    149
    150
        private function Replace takes nothing returns nothing
    151
            local integer i = destroyed
    152
            set T[i] = CreateTimer()
    153
            if GetTimerId(T[i]) == i then
    154
                set isTimerStocked[i] = true
    155
                debug call Debug("Timer [" + I2S(GetTimerId(T[i])) + "] was replaced")
    156
            else
    157
                debug call Debug("ERROR: Unable to replace Timer [" + I2S(i) + "]")
    158
                set dont = true
    159
                call DestroyTimer(T[i])
    160
                set dont = false
    161
                set T[i] = null
    162
            endif
    163
            call FreeTimer(GetExpiredTimer())
    164
        endfunction
    165
    166
        private function OnDestroy takes timer t returns nothing
    167
            local integer i = GetTimerId(t)
    168
            local trigger trig
    169
            if not dont and GetTimerFlag(t) then
    170
                set T[i] = null
    171
                set isTimerStocked[i] = false
    172
                set destroyed = i
    173
                call DestroyTimer(null)
    174
                call TimerStart(GetTimer(), REPLACE_DELAY, false, function Replace)
    175
                debug call Debug("WARNING: Timer [" + I2S(i) + "] got destroyed!")
    176
                set trig = null
    177
            endif
    178
        endfunction
    179
    180
        hook DestroyTimer OnDestroy
    181
    182
        private function Delegate takes nothing returns nothing
    183
            local integer i = current
    184
            loop
    185
                set i = i + 1
    186
                set T[i] = CreateTimer()
    187
                set isTimerStocked[i] = true
    188
                set recycler[i] = i + 1
    189
                if i == TIMER_STOCK_SIZE then
    190
                    debug call Debug("Total number of timers created: " + I2S(i))
    191
                    debug call Debug("Timer stock count is complete")
    192
                    return
    193
                endif
    194
                exitwhen i == current + pitStop
    195
            endloop
    196
            set current = i
    197
            call Delegate.evaluate()
    198
        endfunction
    199
    200
        private module M
    201
            private static method onInit takes nothing returns nothing
    202
                local integer i = 1
    203
                if TIMER_STOCK_SIZE <= 8190 then
    204
                    set pitStop = TIMER_STOCK_SIZE
    205
                else
    206
                    set pitStop = 1000
    207
                endif
    208
                set recycler[TIMER_STOCK_SIZE] = 0
    209
                set recycler[0] = 1
    210
                set recycler[1] = 2
    211
                set T[i] = CreateTimer()
    212
                set START_HANDLE = GetHandleId(T[i]) - 1
    213
                set isTimerStocked[i] = true
    214
                loop
    215
                    set i = i + 1
    216
                    set T[i] = CreateTimer()
    217
                    set isTimerStocked[i] = true
    218
                    set recycler[i] = i + 1
    219
                    exitwhen i == pitStop
    220
                endloop
    221
                set current = i
    222
                if TIMER_STOCK_SIZE > current then
    223
                    call Delegate.evaluate()
    224
                debug else
    225
                    debug call Debug("Total number of timers created: " + I2S(i))
    226
                    debug call Debug("Timer stock count is complete")
    227
                endif
    228
            endmethod
    229
        endmodule
    230
    231
        private struct S extends array
    232
            implement M
    233
        endstruct
    234
    235
    endlibrary



    Changelogs
    Spoiler

    v1.2
    - Added more functionalities such as attaching custom timer data, now the system comprises all but is not limited to the main functionalities of Vexorian's TimerUtils
    - Optimized the code especially in the part in updating the timer stack
    - Fixed some bugs

    v1.1
    - Added the possibility for users to configure the timer stock size above 8190
    - Some fixes

    v1.0
    - First Release