Merge pull request #581 from MihailRis/schedule

Schedule class, built-in schedules, await function
This commit is contained in:
MihailRis 2025-08-01 22:16:04 +03:00 committed by GitHub
commit df8dbc14f7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 107 additions and 5 deletions

View File

@ -259,8 +259,15 @@ function sleep(timesec: number)
Вызывает остановку корутины до тех пор, пока не пройдёт количество секунд, указанное в **timesec**. Функция может быть использована только внутри корутины.
```lua
function await(co: coroutine) -> result, error
```
Ожидает завершение переданной корутины, возвращая поток управления. Функция может быть использована только внутри корутины.
Возвращает значения аналогичные возвращаемым значениям *pcall*.
```lua
os.pid -> number
```
Константа, в которой хранится PID текущего инстанса движка
Константа, в которой хранится PID текущего инстанса движка

46
res/modules/schedule.lua Normal file
View File

@ -0,0 +1,46 @@
local Schedule = {
__index = {
set_interval = function(self, ms, callback, repetions)
local id = self._next_interval
self._intervals[id] = {
last_called = 0.0,
delay = ms / 1000.0,
callback = callback,
repetions = repetions,
}
self._next_interval = id + 1
return id
end,
tick = function(self, dt)
local timer = self._timer + dt
for id, interval in pairs(self._intervals) do
if timer - interval.last_called >= interval.delay then
xpcall(interval.callback, function(s)
debug.error(s..'\n'..debug.traceback())
end)
interval.last_called = timer
local repetions = interval.repetions
if repetions then
if repetions <= 1 then
self:remove_interval(id)
else
interval.repetions = repetions - 1
end
end
end
end
self._timer = timer
end,
remove_interval = function (self, id)
self._intervals[id] = nil
end
}
}
return function ()
return setmetatable({
_next_interval = 1,
_timer = 0.0,
_intervals = {},
}, Schedule)
end

View File

@ -470,8 +470,37 @@ function __vc_on_hud_open()
hud.open_permanent("core:ingame_chat")
end
local ScheduleGroup_mt = {
__index = {
publish = function(self, schedule)
local id = self._next_schedule
self._schedules[id] = schedule
self._next_schedule = id + 1
end,
tick = function(self, dt)
for id, schedule in pairs(self._schedules) do
schedule:tick(dt)
end
end,
remove = function(self, id)
self._schedules[id] = nil
end
}
}
local function ScheduleGroup()
return setmetatable({
_next_schedule = 1,
_schedules = {},
}, ScheduleGroup_mt)
end
time.schedules = {}
local RULES_FILE = "world:rules.toml"
function __vc_on_world_open()
time.schedules.world = ScheduleGroup()
if not file.exists(RULES_FILE) then
return
end
@ -481,6 +510,10 @@ function __vc_on_world_open()
end
end
function __vc_on_world_tick(tps)
time.schedules.world:tick(1.0 / tps)
end
function __vc_on_world_save()
local rule_values = {}
for name, rule in pairs(rules.rules) do
@ -650,4 +683,4 @@ function dofile(path)
end
end
return _dofile(path)
end
end

View File

@ -20,6 +20,18 @@ if not ipairs_mt_supported then
end
end
function await(co)
local res, err
while coroutine.status(co) ~= 'dead' do
coroutine.yield()
res, err = coroutine.resume(co)
if err then
return res, err
end
end
return res, err
end
local _ffi = ffi
function __vc_Canvas_set_data(self, data)
if type(data) == "cdata" then

View File

@ -127,7 +127,7 @@ void BlocksController::update(float delta, uint padding) {
onBlocksTick(blocksTickClock.getPart(), blocksTickClock.getParts());
}
if (worldTickClock.update(delta)) {
scripting::on_world_tick();
scripting::on_world_tick(worldTickClock.getTickRate());
}
}

View File

@ -297,8 +297,12 @@ void scripting::on_world_load(LevelController* controller) {
}
}
void scripting::on_world_tick() {
void scripting::on_world_tick(int tps) {
auto L = lua::get_main_state();
if (lua::getglobal(L, "__vc_on_world_tick")) {
lua::pushinteger(L, tps);
lua::call_nothrow(L, 1, 0);
}
for (auto& pack : content_control->getAllContentPacks()) {
lua::emit_event(L, pack.id + ":.worldtick");
}

View File

@ -70,7 +70,7 @@ namespace scripting {
);
void on_world_load(LevelController* controller);
void on_world_tick();
void on_world_tick(int tps);
void on_world_save();
void on_world_quit();
void cleanup();