98 lines
2.8 KiB
Lua
98 lines
2.8 KiB
Lua
--
|
|
-- formspec_anim SSCSM helper
|
|
--
|
|
-- Copyright © 2019 by luk3yx
|
|
-- License: https://git.minetest.land/luk3yx/formspec_anim/src/branch/master/LICENSE.md
|
|
--
|
|
|
|
local open_formname, open_formspec, elapsed, next_frame
|
|
|
|
local function cleanup()
|
|
open_formname, open_formspec, elapsed, next_frame = nil, nil, nil, nil
|
|
end
|
|
|
|
local function cmd(data)
|
|
minetest.run_server_chatcommand('formspec_anim', '\001' .. data)
|
|
end
|
|
|
|
local function send_formspec_input(formname, fields)
|
|
assert(not formname:find('\001', nil, true))
|
|
cmd(formname .. '\001' .. minetest.write_json(fields))
|
|
end
|
|
|
|
minetest.register_on_formspec_input(function(formname, fields)
|
|
if formname:sub(1, 14) ~= 'formspec_anim:' then return end
|
|
if fields.quit then
|
|
cleanup()
|
|
end
|
|
send_formspec_input(formname:sub(15), fields)
|
|
return true
|
|
end)
|
|
|
|
-- (Re)draw the formspec. This uses a primitive pattern that works with edge
|
|
-- cases because the formspec has been interpreted by formspec_ast on the
|
|
-- server.
|
|
-- Note that duration is in seconds here, it gets converted server-side.
|
|
local p = '(image%[[^;]+;[^;]+;)\\%[\001formspec_anim\001:([^,]+)([%+%.])' ..
|
|
'\\,([^,]+)\\,([^\001]*)\001'
|
|
local function redraw()
|
|
next_frame = math.huge
|
|
local formspec = open_formspec:gsub(p, function(prefix, count, one_shot,
|
|
duration, texture)
|
|
count, duration = tonumber(count), tonumber(duration)
|
|
local step = math.floor(elapsed / duration)
|
|
if one_shot == '.' then
|
|
-- One-shot
|
|
step = math.min(step + 1, count)
|
|
if step < count then
|
|
next_frame = math.min(next_frame, step * duration)
|
|
end
|
|
else
|
|
-- Loop
|
|
next_frame = math.min(next_frame, (step + 1) * duration)
|
|
step = (step % count) + 1
|
|
end
|
|
|
|
-- Numbers are casted to strings automatically.
|
|
return prefix .. texture .. step
|
|
end)
|
|
minetest.show_formspec('formspec_anim:' .. open_formname, formspec)
|
|
end
|
|
|
|
-- Draw the next frame when ready
|
|
minetest.register_globalstep(function(dtime)
|
|
if not open_formname then return end
|
|
elapsed = elapsed + dtime
|
|
if elapsed >= next_frame then
|
|
redraw()
|
|
end
|
|
end)
|
|
|
|
-- Handle formspec opens
|
|
local sscsm_msg_prefix = '\001FORMSPEC_ANIM\001'
|
|
minetest.register_on_receiving_chat_message(function(message)
|
|
if message:sub(1, #sscsm_msg_prefix) ~= sscsm_msg_prefix then
|
|
return
|
|
end
|
|
|
|
message = message:sub(#sscsm_msg_prefix + 1)
|
|
if message == '' then
|
|
cleanup()
|
|
return true
|
|
end
|
|
|
|
local s, e = message:find('\001', nil, true)
|
|
if not s or not e then return end
|
|
|
|
local formname = message:sub(1, s - 1)
|
|
if formname ~= open_formname then
|
|
elapsed = 0
|
|
open_formname = formname
|
|
end
|
|
open_formspec = message:sub(e + 1)
|
|
redraw()
|
|
return true
|
|
end)
|
|
|
|
cmd('OK')
|