scheduler.py 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. # apilot/stubs/scheduler.py
  2. """计时轮: Python 侧驱动, Lua 侧全局函数注入。对齐游戏 50ms tick 节奏。"""
  3. from __future__ import annotations
  4. import itertools
  5. from typing import Callable
  6. class Scheduler:
  7. def __init__(self) -> None:
  8. self._ids = itertools.count(1)
  9. self._timers: dict[int, tuple[Callable[[], None], float, float, bool]] = {}
  10. # id -> (fn, interval, elapsed, repeat)
  11. def schedule(self, fn: Callable[[], None], interval_s: float) -> int:
  12. eid = next(self._ids)
  13. self._timers[eid] = (fn, interval_s, 0.0, True)
  14. return eid
  15. def delay(self, fn: Callable[[], None], delay_s: float) -> int:
  16. eid = next(self._ids)
  17. self._timers[eid] = (fn, delay_s, 0.0, False)
  18. return eid
  19. def unschedule(self, eid: int) -> None:
  20. self._timers.pop(eid, None)
  21. def tick(self, dt: float) -> None:
  22. for eid in list(self._timers):
  23. entry = self._timers.get(eid)
  24. if entry is None: # 回调内已 unschedule 本 tick 未遍历的条目
  25. continue
  26. fn, interval, elapsed, repeat = entry
  27. elapsed += dt
  28. if elapsed >= interval:
  29. if repeat:
  30. self._timers[eid] = (fn, interval, elapsed - interval, True)
  31. else:
  32. self._timers.pop(eid)
  33. fn()
  34. else:
  35. self._timers[eid] = (fn, interval, elapsed, repeat)
  36. def install_scheduler(lua, sched: Scheduler) -> None:
  37. py_sched = sched # Lupa: Python 对象直接可见
  38. def lua_schedule(fn, interval: float, loops=None) -> int:
  39. # 游戏里 Schedule(fn, interval, loops) 第三参 nil/缺省=循环, >0=一次性
  40. if loops is None or loops == 0:
  41. return py_sched.schedule(fn, float(interval))
  42. return py_sched.delay(fn, float(interval))
  43. def lua_perform_delay(fn, delay_s: float) -> int:
  44. return py_sched.delay(fn, float(delay_s))
  45. def lua_unschedule(eid: int) -> None:
  46. py_sched.unschedule(int(eid))
  47. lua.globals()["PerformWithDelayGlobal"] = lua_perform_delay
  48. lua.globals()["Schedule"] = lua_schedule
  49. lua.globals()["UnSchedule"] = lua_unschedule
  50. lua.globals()["SL_getScheduler"] = lambda: py_sched