From 1986228670bdf3e3af1bc15889512fa0857d457c Mon Sep 17 00:00:00 2001 From: PeaAshMeter Date: Sun, 1 Feb 2026 03:56:18 +0300 Subject: [PATCH] Refactor spell casts to use task utilities and simplify callbacks Add task.chain utility for chaining asynchronous tasks --- lib/character/behaviors/sprite.lua | 2 +- lib/spellbook.lua | 42 +++++++++++------------------- lib/utils/task.lua | 17 ++++++++++++ test/task.lua | 16 +++++++++++- 4 files changed, 48 insertions(+), 29 deletions(-) diff --git a/lib/character/behaviors/sprite.lua b/lib/character/behaviors/sprite.lua index 96eac8f..0f6710c 100644 --- a/lib/character/behaviors/sprite.lua +++ b/lib/character/behaviors/sprite.lua @@ -70,7 +70,7 @@ function sprite:draw() end --- @return Task -function sprite:animate(state, node) +function sprite:animate(state) return function(callback) if not self.animationGrid[state] then print("[SpriteBehavior]: no animation for '" .. state .. "'") diff --git a/lib/spellbook.lua b/lib/spellbook.lua index 8be53ac..0843174 100644 --- a/lib/spellbook.lua +++ b/lib/spellbook.lua @@ -7,7 +7,7 @@ --- --TODO: каждый каст должен возвращать объект, который позволит отследить момент завершения анимации спелла --- Да, это Future/Promise/await/async -local Counter = require 'lib.utils.counter' +local task = require 'lib.utils.task' --- @class Spell Здесь будет много бойлерплейта, поэтому тоже понадобится спеллмейкерский фреймворк, который просто вернет готовый Spell --- @field tag string @@ -55,11 +55,7 @@ function walk:cast(caster, target) return end - return function(callback) - return caster:has(Tree.behaviors.tiled):followPath(path)( - callback - ) -- <- callback вызовется после followPath - end + return caster:has(Tree.behaviors.tiled):followPath(path) end function walk:update(caster, dt) @@ -103,14 +99,10 @@ function regenerateMana:cast(caster, target) Tree.behaviors.positioned.new(caster:has(Tree.behaviors.positioned).position + Vec3 { 0.5, 0.5 }), } - return function(callback) - light:has(Tree.behaviors.light):animateColor(Vec3 {})( - function() - light:die() - end - ) - sprite:animate("hurt")(callback) - end + return task.wait { + light:has(Tree.behaviors.light):animateColor(Vec3 {}), + sprite:animate("hurt") + } end local attack = setmetatable({}, spell) @@ -143,20 +135,16 @@ function attack:cast(caster, target) caster:try(Tree.behaviors.positioned, function(b) b:lookAt(target) end) - return function(callback) - local c = Counter(callback) - - c.push() - sprite:animate("attack")(c.pop) - - c.push() - targetCharacter:has(Tree.behaviors.residentsleeper):sleep(200)( - function() - targetSprite:animate("hurt")(c.pop) + return + task.wait { + sprite:animate("attack"), + task.wait { + task.chain(targetCharacter:has(Tree.behaviors.residentsleeper):sleep(200), + function() return targetSprite:animate("hurt") end + ), Tree.audio:play(Tree.assets.files.audio.sounds.hurt) - end - ) - end + } + } end ---------------------------------------- diff --git a/lib/utils/task.lua b/lib/utils/task.lua index 009f0e7..04ef2ae 100644 --- a/lib/utils/task.lua +++ b/lib/utils/task.lua @@ -61,6 +61,23 @@ local function wait(tasks) end end + +--- Последовательно объединяет два `Task` в один. +--- @generic T +--- @generic R +--- @param task Task `Task`, который выполнится первым +--- @param onCompleted fun(value: T): Task Конструктор второго `Task`. Принимает результат выполнения первого `Task` +--- @return Task +local function chain(task, onCompleted) + return function(callback) + task(function(value) + local task2 = onCompleted(value) + task2(callback) + end) + end +end + return { wait = wait, + chain = chain } diff --git a/test/task.lua b/test/task.lua index 93908bf..1c25616 100644 --- a/test/task.lua +++ b/test/task.lua @@ -41,7 +41,21 @@ function test:run(complete) print("task.wait completed in " .. dt .. " sec", "t1 = " .. t1 - t0, "t2 = " .. t2 - t0) - complete() + + t0 = love.timer.getTime() + task.chain(task1(), function(value) + t1 = value + assert(t1 - t0 >= 1) + return task2() + end)( + function(value) + t2 = value + assert(t2 - t0 >= 2) + print("task.chain completed in " .. t2 - t0 .. " sec") + + complete() + end + ) end) end