Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local class = require(script.Parent:WaitForChild('Class'))
- local Minisched = class('Minisched') do
- function Minisched:__Construct(bind)
- self.schedule = {}
- if bind ~= false then
- self:BindTo(game:GetService('RunService').Stepped)
- end
- end
- function Minisched:SortSchedule()
- table.sort(self.schedule, function(a, b)
- return a.at <= b.at
- end)
- end
- function Minisched:Schedule(coro, at, ...)
- local task = {coro = coro, at = at, args = table.pack(...)}
- table.insert(self.schedule, task)
- self:SortSchedule()
- return task
- end
- function Minisched:Unschedule(task)
- local i = table.find(self.schedule, task)
- if i then table.remove(self.schedule, i) end
- return i ~= nil
- end
- function Minisched:Resume(task, remove)
- if remove then self:Unschedule(task) end
- local status = coroutine.status(task.coro)
- if status ~= 'suspended' then
- warn('Encountered a scheduled coroutine with status ' .. status)
- return
- end
- local parent = Minisched.Current
- Minisched.Current = self
- local results = table.pack(coroutine.resume(task.coro, table.unpack(task.args, 1, task.args.n)))
- Minisched.Current = parent
- if not results[1] then
- warn(results[2])
- warn(debug.traceback(task.coro))
- end
- return table.unpack(results, 1, results.n)
- end
- function Minisched:GetOverdueTasks(t, remove)
- local t = t or tick()
- local overdue = {}
- for _, task in ipairs(self.schedule) do
- if task.at > t then break end
- table.insert(overdue, task)
- end
- if remove then
- for i = 1, #overdue do
- table.remove(self.schedule, 1)
- end
- end
- return overdue
- end
- function Minisched:Dispatch()
- local overdue = self:GetOverdueTasks(tick(), true)
- for _, task in ipairs(overdue) do
- self:Resume(task)
- end
- end
- function Minisched:BindTo(event)
- return event:Connect(function()
- self:Dispatch()
- end)
- end
- function Minisched:New(...)
- return Minisched(...)
- end
- --------------------------------------------------------------------------------
- -- Yields
- --------------------------------------------------------------------------------
- local function ensureYieldable()
- if not coroutine.isyieldable() then error('Cannot yield') end
- end
- function Minisched:Wait(t, ...)
- ensureYieldable()
- return coroutine.yield(self:Schedule(coroutine.running(), tick() + (t or 0), ...))
- end
- local function eventSchedule(self, event)
- local task = {coro = coroutine.running()}
- local conn
- conn = event:Connect(function(...)
- conn:Disconnect()
- task.args = table.pack(...)
- self:Resume(task)
- end)
- return conn
- end
- function Minisched:EventWait(event)
- ensureYieldable()
- eventSchedule(self, event)
- return coroutine.yield()
- end
- function Minisched:EventTimeout(event, t)
- ensureYieldable()
- local running = coroutine.running()
- local symbol = newproxy()
- local eventTask = eventSchedule(self, event)
- local waitTask = self:Schedule(running, tick() + (t or 0), symbol)
- local results = table.pack(coroutine.yield())
- if results[1] == symbol then
- eventTask:Disconnect()
- return false
- end
- self:Unschedule(waitTask)
- return true, table.unpack(results, 1, results.n)
- end
- function Minisched:Encapsulate(func, ...)
- ensureYieldable()
- local task = {coro = coroutine.running()}
- local err
- Minisched.Corospawn(function(...)
- local results = table.pack(pcall(func, ...))
- err = not results[1]
- task.args = not err and results or table.pack(results[2])
- self:Resume(task)
- end, ...)
- local results = table.pack(coroutine.yield())
- if err then
- error(results[1], 2)
- end
- return results
- end
- --------------------------------------------------------------------------------
- -- Spawns
- --------------------------------------------------------------------------------
- function Minisched.Corospawn(func, ...)
- local coro = coroutine.create(func)
- return coro, coroutine.resume(coro, ...)
- end
- function Minisched.Quickspawn(func, ...)
- if not Minisched.QuickspawnEvent then
- Minisched.QuickspawnEvent = Instance.new('BindableEvent')
- Minisched.QuickspawnEvent.Event:Connect(function(func, ...)
- func(...)
- end)
- end
- Minisched.QuickspawnEvent:Fire(func, ...)
- end
- function Minisched:Queue(func, ...)
- local coro = coroutine.create(func)
- return coro, self:Schedule(coro, 0, ...)
- end
- function Minisched:Delegate(func, ...)
- local coro, queued = self:Queue(func, ...)
- return coro, self:Resume(queued, true)
- end
- function Minisched:Delay(func, t, ...)
- local coro = coroutine.create(func)
- return coro, self:Schedule(coro, tick() + (t or 0), ...)
- end
- --------------------------------------------------------------------------------
- -- Auto-targeting
- --------------------------------------------------------------------------------
- Minisched.Current = nil
- local function getCurrentMinisched()
- return Minisched.Current or error('Not running in Minisched')
- end
- function Minisched.TWait(...) getCurrentMinisched():Wait(...) end
- function Minisched.TEventWait(...) getCurrentMinisched():EventWait(...) end
- function Minisched.TEventTimeout(...) getCurrentMinisched():EventTimeout(...) end
- function Minisched.TEncapsulate(...) getCurrentMinisched():Encapsulate(...) end
- function Minisched.TQueue(...) getCurrentMinisched():Queue(...) end
- function Minisched.TDelegate(...) getCurrentMinisched():Delegate(...) end
- function Minisched.TDelay(...) getCurrentMinisched():Delay(...) end
- end
- return Minisched()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement