Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[
- usage:
- local w = require("wait") -- assumes this script is saved in wait.lua
- local function errf(player, creature, gameobject) print(player, creature, gameobject) end -- in case of error, run this function, args are set to nil if missing, so you can detect which ones are there and which are not
- local function func(...) print(...) w.wait(3000) print(...) end -- wait 3 seconds in middle
- w.call(errf, func, player, creature, gameobject) -- errf can be nil to ignore errors, func is called with arguments that follow it. The first argument (player) is used as the object used for waiting (RegisterEvent) and as the object that fetches other objects when waiting ends.
- --]]
- --[[
- This script is a proof of concept and not the most performant and polished solution or API.
- How it works internally?
- Lua coroutines are used to wrap the called function and then yield and resume in addition to timed events (RegisterEvent)
- are used to achieve waiting x amount of time in middle of functions.
- RegisterEvent is used on the first argument to the called function.
- What if a player logs out while function is waiting?
- All parameters are checked for if they are userdata (player,creature,gameobject). If they are, then they are encapsulated by proxy tables.
- These proxies are then offered instead of the actual userdata. The proxies allow changing/updating the underlying userdata.
- The proxies store information such as guid to update the userdata.
- If updating a proxy fails, the errf function is called.
- Updating is needed since when a player relogs the pointer/userdata can be different to that player object.
- Does it have problems?
- - any new objects inside a function are not proxied, so they are dangerous to use. As an example victim = creature:GetVictim(); w.wait(1); print(victim:GetName()); is dangerous
- - if a creature dies, the new creature spawned is not going to be recognized as the same npc that died and errf is called
- --]]
- local function data(obj)
- return {mapid = obj:GetMapId(), instid = obj:GetInstanceId(), guid = obj:GetGUID()}
- end
- local function fetch(waiter, data)
- if waiter:GetMapId() == data.mapid and waiter:GetInstanceId() == data.instid then
- return waiter:GetMap():GetWorldObject(data.guid)
- end
- end
- local refreshers = {
- Player = {
- data = data,
- fetch = fetch,
- },
- Creature = {
- data = data,
- fetch = fetch,
- },
- GameObject = {
- data = data,
- fetch = fetch,
- },
- }
- local function canproxy(t)
- local ty = type(t)
- return ty == "userdata" and t.GetObjectType and refreshers[t:GetObjectType()]
- end
- local function isproxy(t)
- return type(t) == "table" and t.isproxy
- end
- local function proxy(t, o)
- local mt = {}
- local p = setmetatable(t, mt)
- mt.__index = function(t,k) return function(_, ...) return o[k](o, ...) end end
- local dataf = refreshers[o:GetObjectType()].data
- local fetch = refreshers[o:GetObjectType()].fetch
- local data = dataf(o)
- p.fetch = function(waiter)
- local o = fetch(waiter, data)
- if o then
- data = dataf(o)
- end
- return o
- end
- p.isproxy = true
- return p
- end
- function wrap(errf, f, waiter, ...)
- local co = coroutine.create(f)
- local t, n = {...}, select("#", waiter, ...)
- local proxies = {}
- for i = 1, n do
- local o = t[i]
- if canproxy(o) then
- local p = proxy({}, o)
- p.i = i
- t[i] = p
- end
- if isproxy(t[i]) then
- proxies[#proxies+1] = t[i]
- end
- end
- local alive, delay
- local refreshAndCall, call
- function call()
- -- run coroutine and get delay
- alive, delay = coroutine.resume(co, waiter, table.unpack(t, 1, n))
- -- coroutine ran to finish? end running
- if coroutine.status(co) == "dead" then return end
- -- wait for delay using waiter
- waiter:RegisterEvent(refreshAndCall, delay, 1)
- end
- function refreshAndCall()
- -- refresh proxies
- local errored = false
- for k,v in ipairs(proxies) do
- local f = v.fetch(waiter)
- if not f then
- t[v.i] = nil
- errored = true
- else
- proxy(v, f)
- end
- end
- if errored then
- if errf then return errf(waiter, table.unpack(t, 1, n)) end
- return
- end
- call()
- end
- call()
- end
- return {
- call = wrap,
- wait = coroutine.yield,
- canproxy = canproxy,
- proxy = proxy,
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement