logistica-cd2025/guide_api/history_stack.lua
2024-03-24 16:38:45 +00:00

76 lines
2.9 KiB
Lua

-- the stack is a volatile, in-memory concept
local stackInfos = {}
-- a history stack implementation, much like browser history works like
local HistoryStack = {}
-- gets (or creates an empty one) the current history stack for the given player/stack names
-- `optStackSizeLimit` enforces how far back to keep history, if nil, it defaults to 100
function HistoryStack.get(playerName, stackName, optStackSizeLimit)
local self = {}
local stackSizeLimit = optStackSizeLimit or 100
if not stackInfos[playerName] then stackInfos[playerName] = {} end
if not stackInfos[playerName][stackName] then stackInfos[playerName][stackName] = {currentPage = 0, stack = {}} end
local mStackInfo = stackInfos[playerName][stackName]
-- returns a string representation of the current stack item, or empty string if there isn't one
self.get_current = function()
return mStackInfo.stack[mStackInfo.currentPage] or ""
end
-- goes back to the prevous page of the stack, if possible, and returns its name (a string or empty string if stack is empty)
self.go_back = function()
if mStackInfo.currentPage > 1 then mStackInfo.currentPage = mStackInfo.currentPage - 1 end
return mStackInfo.stack[mStackInfo.currentPage] or ""
end
-- goes forward to the next page of the stack, if possible, and returns its name (a string, or empty string if empty)
self.go_forward = function()
if mStackInfo.currentPage < #mStackInfo.stack then mStackInfo.currentPage = mStackInfo.currentPage + 1 end
return mStackInfo.stack[mStackInfo.currentPage] or ""
end
-- adds a new page to the stack, after the current one, erasing any following stack.
-- Returns `newPagName`, or `nil` if newPageName wasn't pushed for any reason
self.push_new = function(newPageName)
if type(newPageName) ~= "string" or newPageName == "" then return nil end
local currPageName = mStackInfo.stack[mStackInfo.currentPage]
if newPageName == currPageName then return nil end
local newPageIndex = mStackInfo.currentPage + 1
mStackInfo.currentPage = newPageIndex
mStackInfo.stack[newPageIndex] = newPageName
-- erase anything after it
for i = newPageIndex + 1, #mStackInfo.stack do
mStackInfo.stack[i] = nil
end
-- now check if we have exceeded limit
if #mStackInfo.stack > stackSizeLimit then
table.remove(mStackInfo.stack, 1)
mStackInfo.currentPage = mStackInfo.currentPage - 1
end
return newPageName
end
-- returns true if there's a previous page to go to, false if there isn't
self.has_prev = function()
return mStackInfo.currentPage > 1
end
-- returns true if there's a next page to go to, false if there isn't
self.has_next = function()
return mStackInfo.currentPage > 0 and mStackInfo.currentPage < #mStackInfo.stack
end
return self
end
-- clears all stacks for given player from memory
function HistoryStack.on_player_leave(playerName)
stackInfos[playerName] = nil
end
-- export it
logistica.HistoryStack = HistoryStack