API CreateTimer en - LIHACHTETAN/ClassicUO-BadNewbie-BasicIDE GitHub Wiki

CreateTimer / script timers

ClassicUO • Basic

CreateTimer creates a stopped callback timer for this script. Start schedules a Sub on the same execution thread. This project extension is separate from Basic Timer(), which reads elapsed seconds.

Exact syntax

CreateTimer(milliseconds, handler) -> Object (ScriptTimer)
CreateTimer(milliseconds, handler, repeating) -> Object (ScriptTimer)
timer.Start() -> Unit
timer.Stop() -> Unit
timer.Dispose() -> Unit
timer.Enabled() -> Integer (0/1)
timer.Interval() -> Integer (ms)
timer.SetInterval(milliseconds) -> Unit
Using timer ... End Using

Parameters

  • milliseconds — Integer milliseconds, 1..2147483647. Strings, fractions, zero and negative intervals are errors. SetInterval uses the same rule. Interval() returns the configured milliseconds, not remaining time.
  • handler — AddressOf a uniquely declared Sub with exactly zero parameters, or a callback variable/factory from this loaded script. Function, Optional/ParamArray parameters, a name string and a foreign reference are rejected. Shared handler state belongs in Module fields; no closure is captured.
  • repeating — Optional third argument: True/1 repeats; False/0 fires once. Default True. The named argument is repeating:=. Other numbers and strings are errors. A one-shot timer becomes disabled before invoking its handler.
  • timer / Start / Stop / Dispose / SetInterval — The returned object owns Start(), Stop(), Dispose(), Enabled(), Interval(), SetInterval(milliseconds). Start on an enabled timer does nothing. Stop permits a later Start. SetInterval restarts an enabled timer’s interval from now; a stopped timer stays stopped. Dispose is idempotent and permanent; Start/SetInterval afterwards fail. Using disposes the captured object on exit.

Returns

CreateTimer returns Object (ScriptTimer), never an item ID or a running-script index. Start/Stop/Dispose/SetInterval return Unit. Enabled returns Integer 1=True or 0=False; either comparison form works. Interval returns milliseconds, not a Boolean. Example results are String "3:0", "ready:0", "tick failed:0".

Behavior

  • The scheduler checks monotonic elapsed time between script statements and inside Basic Wait/Sleep and Wait Until. With enabled timers, Wait is divided into slices of at most 25 ms. A game API call or another blocking native call must return before a timer can run. Timers have no guaranteed real-time precision and do not create threads.
  • Due timers run by deadline, then creation order for ties, at most 64 handlers per checkpoint. The next checkpoint handles remaining due work. Dispatch does not re-enter while a handler is executing, even if it waits. A repeating timer schedules its next interval after completion; missed intervals are skipped instead of accumulating. Pause suspends dispatch; after resume an overdue timer runs once and resumes normal scheduling.
  • A handler error disables that timer and reaches the caller’s Catch/Finally. Stop or interval changes inside a handler take effect. Emergency cancellation is not caught as a normal error. Stop/exit/error of the top-level script disposes its timers; another run/reload must create new ones. Closing only the IDE keeps a running script’s timers alive. Maximum 1024 undisposed timers per interpreter; Dispose releases a slot.
  • RunThreePulses and GetHandler below are fully shown script helpers, not built-in commands. Internally CreateTimer validates arguments/ownership, stores a stopped handle, Start records the next deadline, Pump calls the Sub, Fire schedules the next deadline after completion, and Release disposes handles when the root call ends. No OS timer or background service continues after the script ends.

Examples

1. Three periodic calls with cleanup

# Main calls the complete RunThreePulses function. 20 is the interval in milliseconds; the missing third parameter means repeating=True. CountPulse increments shared State.count and stops at three. Wait Until pumps handlers while checking the count, with a 3000 ms timeout. Enabled() is 0 after Stop; the result is "3:0". Using disposes the timer even when the function returns.
Option Explicit On
Module State
    Public Dim count As Integer = 0
    Public Dim pulse
End Module

Sub CountPulse()
    State.count += 1
    If State.count >= 3 Then
        State.pulse.Stop()
    End If
End Sub

Function RunThreePulses() As String
    State.pulse = CreateTimer(20, AddressOf CountPulse)
    Using State.pulse
        State.pulse.Start()
        Wait Until State.count >= 3 Timeout 3000
        Return CStr(State.count) & ":" & CStr(State.pulse.Enabled())
    End Using
End Function

Sub Main()
    Return RunThreePulses()
End Sub

Parameter and execution notes:

Main calls the complete RunThreePulses function. 20 is the interval in milliseconds; the missing third parameter means repeating=True. CountPulse increments shared State.count and stops at three. Wait Until pumps handlers while checking the count, with a 3000 ms timeout. Enabled() is 0 after Stop; the result is "3:0". Using disposes the timer even when the function returns.

2. One-shot callback and named parameters

# GetHandler returns AddressOf SetReady. CreateTimer receives 5 ms, that callback and repeating=False in named order. SetInterval changes 5 to 10 before Start. SetReady stores "ready" in Module state; the one-shot timer is already disabled. Main waits at most 3000 ms and returns "ready:0". Every helper is included.
Option Explicit On
Module State
    Public Dim message As String = ""
End Module

Sub SetReady()
    State.message = "ready"
End Sub

Function GetHandler()
    Return AddressOf SetReady
End Function

Sub Main()
    Dim callback = GetHandler()
    Dim notice = CreateTimer(repeating:=False, handler:=callback, milliseconds:=5)
    Using notice
        notice.SetInterval(10)
        notice.Start()
        Wait Until State.message = "ready" Timeout 3000
        Return State.message & ":" & CStr(notice.Enabled())
    End Using
End Sub

Parameter and execution notes:

GetHandler returns AddressOf SetReady. CreateTimer receives 5 ms, that callback and repeating=False in named order. SetInterval changes 5 to 10 before Start. SetReady stores "ready" in Module state; the one-shot timer is already disabled. Main waits at most 3000 ms and returns "ready:0". Every helper is included.

3. Catch a timer failure during Wait

# FailingPulse throws "tick failed". The 5 ms timer runs during Wait(2000), is disabled on error, and interrupts that wait. Catch stores the text and reads Enabled()=0; Finally disposes it. The return "tick failed:0" includes both the error and the logical state. Emergency stop is handled by the runtime, not this Catch.
Option Explicit On
Sub FailingPulse()
    Throw "tick failed"
End Sub

Sub Main()
    Dim pulse = CreateTimer(5, AddressOf FailingPulse)
    Dim problemText As String = ""
    Dim enabledAfterError As Boolean = True
    Try
        pulse.Start()
        Wait(2000)
    Catch problem
        problemText = problem
        enabledAfterError = pulse.Enabled()
    Finally
        pulse.Dispose()
    End Try
    Return problemText & ":" & CStr(enabledAfterError)
End Sub

Parameter and execution notes:

FailingPulse throws "tick failed". The 5 ms timer runs during Wait(2000), is disabled on error, and interrupts that wait. Catch stores the text and reads Enabled()=0; Finally disposes it. The return "tick failed:0" includes both the error and the logical state. Emergency stop is handled by the runtime, not this Catch.

Internal functions: from call to result

RunThreePulses and GetHandler below are fully shown script helpers, not built-in commands. Internally CreateTimer validates arguments/ownership, stores a stopped handle, Start records the next deadline, Pump calls the Sub, Fire schedules the next deadline after completion, and Release disposes handles when the root call ends. No OS timer or background service continues after the script ends.

1. CreateTimer

Integer milliseconds, 1..2147483647. Strings, fractions, zero and negative intervals are errors. SetInterval uses the same rule. Interval() returns the configured milliseconds, not remaining time.

AddressOf a uniquely declared Sub with exactly zero parameters, or a callback variable/factory from this loaded script. Function, Optional/ParamArray parameters, a name string and a foreign reference are rejected. Shared handler state belongs in Module fields; no closure is captured.

Optional third argument: True/1 repeats; False/0 fires once. Default True. The named argument is repeating:=. Other numbers and strings are errors. A one-shot timer becomes disabled before invoking its handler.

CreateTimer returns Object (ScriptTimer), never an item ID or a running-script index. Start/Stop/Dispose/SetInterval return Unit. Enabled returns Integer 1=True or 0=False; either comparison form works. Interval returns milliseconds, not a Boolean. Example results are String "3:0", "ready:0", "tick failed:0".

Project source: external/InjectionScript/src/InjectionScript/Runtime/Interpreter.Timers.cs; function CreateTimer.

2. Start

The returned object owns Start(), Stop(), Dispose(), Enabled(), Interval(), SetInterval(milliseconds). Start on an enabled timer does nothing. Stop permits a later Start. SetInterval restarts an enabled timer’s interval from now; a stopped timer stays stopped. Dispose is idempotent and permanent; Start/SetInterval afterwards fail. Using disposes the captured object on exit.

Due = now + interval; enabled = true;

Project source: external/InjectionScript/src/InjectionScript/Runtime/ObjectTypes/ScriptTimerObject.cs; function Start.

3. WaitWithTimers

The scheduler checks monotonic elapsed time between script statements and inside Basic Wait/Sleep and Wait Until. With enabled timers, Wait is divided into slices of at most 25 ms. A game API call or another blocking native call must return before a timer can run. Timers have no guaranteed real-time precision and do not create threads.

checkpoint -> Pump -> min(remaining, nextDue, 25 ms) -> Wait

Project source: external/InjectionScript/src/InjectionScript/Runtime/Interpreter.Timers.cs; function WaitWithTimers.

4. Pump

Due timers run by deadline, then creation order for ties, at most 64 handlers per checkpoint. The next checkpoint handles remaining due work. Dispatch does not re-enter while a handler is executing, even if it waits. A repeating timer schedules its next interval after completion; missed intervals are skipped instead of accumulating. Pause suspends dispatch; after resume an overdue timer runs once and resumes normal scheduling.

snapshot -> deadline / sequence -> checkpoint -> Fire; limit = 64

Project source: external/InjectionScript/src/InjectionScript/Runtime/ScriptTimerScheduler.cs; function Pump.

5. Fire

A handler error disables that timer and reaches the caller’s Catch/Finally. Stop or interval changes inside a handler take effect. Emergency cancellation is not caught as a normal error. Stop/exit/error of the top-level script disposes its timers; another run/reload must create new ones. Closing only the IDE keeps a running script’s timers alive. Maximum 1024 undisposed timers per interpreter; Dispose releases a slot.

callback -> completion -> next Due; error -> disabled -> throw

Project source: external/InjectionScript/src/InjectionScript/Runtime/ObjectTypes/ScriptTimerObject.cs; function Fire.

6. Dispose

The returned object owns Start(), Stop(), Dispose(), Enabled(), Interval(), SetInterval(milliseconds). Start on an enabled timer does nothing. Stop permits a later Start. SetInterval restarts an enabled timer’s interval from now; a stopped timer stays stopped. Dispose is idempotent and permanent; Start/SetInterval afterwards fail. Using disposes the captured object on exit.

Release -> scheduler.Remove -> Changed

Project source: external/InjectionScript/src/InjectionScript/Runtime/ObjectTypes/ScriptTimerObject.cs; function Dispose.

7. Release

A handler error disables that timer and reaches the caller’s Catch/Finally. Stop or interval changes inside a handler take effect. Emergency cancellation is not caught as a normal error. Stop/exit/error of the top-level script disposes its timers; another run/reload must create new ones. Closing only the IDE keeps a running script’s timers alive. Maximum 1024 undisposed timers per interpreter; Dispose releases a slot.

timer.Release for each handle -> timers.Clear -> no pending deadline

Project source: external/InjectionScript/src/InjectionScript/Runtime/ScriptTimerScheduler.cs; function Release.

Main calls the complete RunThreePulses function. 20 is the interval in milliseconds; the missing third parameter means repeating=True. CountPulse increments shared State.count and stops at three. Wait Until pumps handlers while checking the count, with a 3000 ms timeout. Enabled() is 0 after Stop; the result is "3:0". Using disposes the timer even when the function returns.


en · ru · uk · fr · de · it · es · zh-tw · ja · ko

Basic