Files
wnsrc/lua/pac3/libraries/urlobj/queueitem.lua

262 lines
5.8 KiB
Lua
Raw Normal View History

2024-08-04 22:55:00 +03:00
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
local urlobj = _G.pac_urlobj
local TIMEOUT_VALUE = CreateConVar('pac_objdl_timeout', '15', {FCVAR_ARCHIVE}, 'OBJ download timeout in seconds')
local CACHE_OBJS = CreateConVar('pac_obj_cache', '1', {FCVAR_ARCHIVE}, 'DEBUG: Cache Object files on disk. Disables disk cache access (like cache does not exist in code)')
local QUEUEITEM = {}
-- Warning: This code is concurrency hell
-- Either the decode from the cache or the decode from the web could finish first / last
-- And the web request handler will often decide to not override the cache
local function CreateQueueItem(url)
local queueItem = {}
setmetatable (queueItem, { __index = QUEUEITEM })
queueItem:Initialize (url)
return queueItem
end
function QUEUEITEM:Initialize (url)
self.Url = url
self.Data = nil
self.UsingCachedData = false
-- Cache
self.CacheDecodeFinished = false
-- Download
self.DownloadAttemptCount = 0
self.DownloadTimeoutTime = 0
self.Downloading = false
self.DownloadFinished = false
-- Status
self.Status = nil
self.Finished = false
-- Model
self.Model = nil
-- Decoding parameters
self.GenerateNormals = false
-- Callbacks
self.CallbackSet = {}
self.DownloadCallbackSet = {}
self.StatusCallbackSet = {}
end
function QUEUEITEM:GetUrl ()
return self.Url
end
-- Cache
function QUEUEITEM:BeginCacheRetrieval ()
if not CACHE_OBJS:GetBool() then return end
self.Data = urlobj.DataCache:GetItem(self.Url)
if not self.Data then return end
self.Model = urlobj.CreateModelFromObjData(self.Data, self.GenerateNormals,
function (finished, statusMessage)
if self:IsFinished () then return end
if self.DownloadFinished and not self.UsingCachedData then return end
if finished and not self.DownloadFinished then
self:SetStatus ("")
else
self:SetStatus ("Cached model: " .. statusMessage)
end
if self.DownloadFinished and self.UsingCachedData then
self:SetFinished (finished)
end
if finished then
self.CacheDecodeFinished = true
end
end
)
self:DispatchCallbacks (self.Model)
end
function QUEUEITEM:IsCacheDecodeFinished ()
return self.CacheDecodeFinished
end
-- Download
function QUEUEITEM:AbortDownload ()
self.Downloading = false
self:SetStatus ("Download aborted")
end
function QUEUEITEM:BeginDownload ()
if self:IsDownloading () then return end
self:SetStatus ("Downloading")
self.Downloading = true
self.DownloadTimeoutTime = pac.RealTime + TIMEOUT_VALUE:GetFloat()
self.DownloadAttemptCount = self.DownloadAttemptCount + 1
local function success(data)
if not self.Downloading then return end
self.Downloading = false
self.DownloadFinished = true
pac.dprint("downloaded model %q %s", self.Url, string.NiceSize(#data))
pac.dprint("%s", data)
self:DispatchDownloadCallbacks ()
self:ClearDownloadCallbacks ()
self.UsingCachedData = self.Data == data
if self.UsingCachedData then
if self.CacheDecodeFinished then
self:SetFinished (true)
end
else
self.Data = data
if CACHE_OBJS:GetBool() then
urlobj.DataCache:AddItem (self.Url, self.Data)
end
self.Model = urlobj.CreateModelFromObjData(self.Data, self.GenerateNormals,
function (finished, statusMessage)
self:SetStatus (statusMessage)
self:SetFinished (finished)
if self:IsFinished () then
self:ClearStatusCallbacks ()
end
end
)
end
self:DispatchCallbacks (self.Model)
self:ClearCallbacks ()
end
local function failure(err, fatal)
-- dont bother with servezilf he said No
if fatal then
self.DownloadAttemptCount = 100
end
self.DownloadTimeoutTime = 0
self:SetStatus ("Failed - " .. err)
end
pac.HTTPGet(self.Url, success, failure)
end
function QUEUEITEM:GetDownloadAttemptCount ()
return self.DownloadAttemptCount
end
function QUEUEITEM:IsDownloading ()
return self.Downloading
end
function QUEUEITEM:HasDownloadTimedOut ()
return self:IsDownloading () and pac.RealTime > self.DownloadTimeoutTime
end
-- Status
function QUEUEITEM:GetStatus ()
return self.Status
end
function QUEUEITEM:IsFinished ()
return self.Finished
end
function QUEUEITEM:SetStatus (status)
if self.Status == status then return self end
self.Status = status
self:DispatchStatusCallbacks (self.Finished, self.Status)
return self
end
function QUEUEITEM:SetFinished (finished)
if self.Finished == finished then return self end
self.Finished = finished
self:DispatchStatusCallbacks (self.Finished, self.Status)
return self
end
-- Model
function QUEUEITEM:GetModel ()
return self.Model
end
-- Callbacks
function QUEUEITEM:AddCallback (callback)
self.CallbackSet [callback] = true
if self.Model then
callback (self.Model)
end
end
function QUEUEITEM:AddDownloadCallback (downloadCallback)
self.DownloadCallbackSet [downloadCallback] = true
end
function QUEUEITEM:AddStatusCallback (statusCallback)
self.StatusCallbackSet [statusCallback] = true
statusCallback (self.Finished, self.Status)
end
function QUEUEITEM:ClearCallbacks ()
self.CallbackSet = {}
end
function QUEUEITEM:ClearDownloadCallbacks ()
self.DownloadCallbackSet = {}
end
function QUEUEITEM:ClearStatusCallbacks ()
self.StatusCallbackSet = {}
end
function QUEUEITEM:DispatchCallbacks (...)
for callback, _ in pairs (self.CallbackSet) do
callback (...)
end
end
function QUEUEITEM:DispatchDownloadCallbacks (...)
for downloadCallback, _ in pairs (self.DownloadCallbackSet) do
downloadCallback (...)
end
end
function QUEUEITEM:DispatchStatusCallbacks (...)
for statusCallback, _ in pairs (self.StatusCallbackSet) do
statusCallback (...)
end
end
return CreateQueueItem