From b28aa718459f8b5b960870063d6e10946cc5ca06 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Fri, 1 Aug 2025 21:08:23 +0300 Subject: [PATCH 1/5] add Schedule class & add time.schedule.world schedule group --- res/modules/schedule.lua | 37 +++++++++++++++++++++++++++++++ res/scripts/stdlib.lua | 33 +++++++++++++++++++++++++++ src/logic/scripting/scripting.cpp | 3 +++ 3 files changed, 73 insertions(+) create mode 100644 res/modules/schedule.lua diff --git a/res/modules/schedule.lua b/res/modules/schedule.lua new file mode 100644 index 00000000..91e47813 --- /dev/null +++ b/res/modules/schedule.lua @@ -0,0 +1,37 @@ +local Schedule = { + __index = { + set_interval = function(self, ms, callback) + local id = self._next_interval + self._intervals[id] = { + last_called = 0.0, + delay = ms / 1000.0, + callback = callback, + } + 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 + 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 diff --git a/res/scripts/stdlib.lua b/res/scripts/stdlib.lua index 765d2c08..060d40f0 100644 --- a/res/scripts/stdlib.lua +++ b/res/scripts/stdlib.lua @@ -450,8 +450,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 @@ -461,6 +490,10 @@ function __vc_on_world_open() end end +function __vc_on_world_tick() + time.schedules.world:tick(1.0 / 20.0) +end + function __vc_on_world_save() local rule_values = {} for name, rule in pairs(rules.rules) do diff --git a/src/logic/scripting/scripting.cpp b/src/logic/scripting/scripting.cpp index f766f29d..5da5b3ba 100644 --- a/src/logic/scripting/scripting.cpp +++ b/src/logic/scripting/scripting.cpp @@ -299,6 +299,9 @@ void scripting::on_world_load(LevelController* controller) { void scripting::on_world_tick() { auto L = lua::get_main_state(); + if (lua::getglobal(L, "__vc_on_world_tick")) { + lua::call_nothrow(L, 0, 0); + } for (auto& pack : content_control->getAllContentPacks()) { lua::emit_event(L, pack.id + ":.worldtick"); } From ddb04418ba3cd270bb78b072bda56b50ba1d0534 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Fri, 1 Aug 2025 21:09:03 +0300 Subject: [PATCH 2/5] add 'await' function --- res/scripts/stdmin.lua | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/res/scripts/stdmin.lua b/res/scripts/stdmin.lua index 9f8c48c2..38fdbfdc 100644 --- a/res/scripts/stdmin.lua +++ b/res/scripts/stdmin.lua @@ -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 From f37bbc64f4a6f2f563f8914a7401a14fa1be2c1e Mon Sep 17 00:00:00 2001 From: MihailRis Date: Fri, 1 Aug 2025 21:15:04 +0300 Subject: [PATCH 3/5] add set_interval 'repetions' argument --- res/modules/schedule.lua | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/res/modules/schedule.lua b/res/modules/schedule.lua index 91e47813..24d216f0 100644 --- a/res/modules/schedule.lua +++ b/res/modules/schedule.lua @@ -1,11 +1,12 @@ local Schedule = { __index = { - set_interval = function(self, ms, callback) + 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 @@ -18,6 +19,14 @@ local Schedule = { 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 From 8e7a5a0b8c067060fee7a25f4b4d89587b8497d8 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Fri, 1 Aug 2025 21:34:00 +0300 Subject: [PATCH 4/5] update extensions.md --- doc/ru/scripting/extensions.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/doc/ru/scripting/extensions.md b/doc/ru/scripting/extensions.md index 32798e43..08c8fa33 100644 --- a/doc/ru/scripting/extensions.md +++ b/doc/ru/scripting/extensions.md @@ -258,3 +258,10 @@ function sleep(timesec: number) ``` Вызывает остановку корутины до тех пор, пока не пройдёт количество секунд, указанное в **timesec**. Функция может быть использована только внутри корутины. + +```lua +function await(co: coroutine) -> result, error +``` + +Ожидает завершение переданной корутины, возвращая поток управления. Функция может быть использована только внутри корутины. +Возвращает значения аналогичные возвращаемым значениям *pcall*. From 9e8acac783f41cb57ab0149c6bf86d2bf4def34c Mon Sep 17 00:00:00 2001 From: MihailRis Date: Fri, 1 Aug 2025 22:00:29 +0300 Subject: [PATCH 5/5] minor refactor --- res/scripts/stdlib.lua | 6 +++--- src/logic/BlocksController.cpp | 2 +- src/logic/scripting/scripting.cpp | 5 +++-- src/logic/scripting/scripting.hpp | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/res/scripts/stdlib.lua b/res/scripts/stdlib.lua index 6202a445..b0fb86ea 100644 --- a/res/scripts/stdlib.lua +++ b/res/scripts/stdlib.lua @@ -510,8 +510,8 @@ function __vc_on_world_open() end end -function __vc_on_world_tick() - time.schedules.world:tick(1.0 / 20.0) +function __vc_on_world_tick(tps) + time.schedules.world:tick(1.0 / tps) end function __vc_on_world_save() @@ -683,4 +683,4 @@ function dofile(path) end end return _dofile(path) -end \ No newline at end of file +end diff --git a/src/logic/BlocksController.cpp b/src/logic/BlocksController.cpp index cdc25b48..ee74bb95 100644 --- a/src/logic/BlocksController.cpp +++ b/src/logic/BlocksController.cpp @@ -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()); } } diff --git a/src/logic/scripting/scripting.cpp b/src/logic/scripting/scripting.cpp index 5da5b3ba..39168843 100644 --- a/src/logic/scripting/scripting.cpp +++ b/src/logic/scripting/scripting.cpp @@ -297,10 +297,11 @@ 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::call_nothrow(L, 0, 0); + lua::pushinteger(L, tps); + lua::call_nothrow(L, 1, 0); } for (auto& pack : content_control->getAllContentPacks()) { lua::emit_event(L, pack.id + ":.worldtick"); diff --git a/src/logic/scripting/scripting.hpp b/src/logic/scripting/scripting.hpp index 0f375746..bae5aac6 100644 --- a/src/logic/scripting/scripting.hpp +++ b/src/logic/scripting/scripting.hpp @@ -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();