Port mod package manager

This commit is contained in:
Lucas Schwiderski 2018-12-05 21:12:05 +01:00
parent 70e726f090
commit 4b6827f688
3 changed files with 166 additions and 2 deletions

View file

@ -0,0 +1,160 @@
local vmf = get_mod("VMF")
local _initialized = false
local _mod_handles = {}
local _queued_packages = {}
local _loading_package = nil
local _loaded_packages = {}
function VMFMod:load_package(package_name, callback)
if not _initialized then
self:error("Package manager has not been initialized yet. It can only be used after the `all_mods_loaded` event has been processed.")
return
elseif self:has_package_loaded(package_name) then
self:error("Package '%s' has already been loaded", package_name)
return
end
if not _loaded_packages[self] then
_loaded_packages[self] = {}
end
local package_handle = string.format("resource_packages/%s/%s", self:get_name(), package_name)
local workshop_id = self:get_internal_data("workshop_id")
local resource_package = Mod.resource_package(_mod_handles[workshop_id], package_handle)
local is_loading = self:is_package_loading(package_name)
if not callback then
if not is_loading then
resource_package:load()
end
resource_package:flush()
_loaded_packages[self][package_name] = resource_package
self:debug("Loaded package '%s' synchronously", package_name)
else
if is_loading then
self:error("Package '%s' is currently loading", package_name)
return
end
table.insert(_queued_packages, {
mod = self,
package_name = package_name,
resource_package = resource_package,
callback = callback,
})
self:debug("Queued package '%s'", package_name)
end
end
function VMFMod:unload_package(package_name)
if not _initialized then
self:error("Package manager has not been initialized yet. It can only be used after the `all_mods_loaded` event has been processed.")
return
end
if not self:has_package_loaded(package_name) then
self:error("Package '%s' has not been loaded", package_name)
return
end
local resource_package = _loaded_packages[self][package_name]
resource_package:unload()
Mod.release_resource_package(resource_package)
_loaded_packages[self][package_name] = nil
self:debug("Unloaded package '%s'", package_name)
end
function VMFMod:is_package_loading(package_name)
if not _initialized then
self:error("Package manager has not been initialized yet. It can only be used after the `all_mods_loaded` event has been processed.")
return
end
if _loading_package and _loading_package.mod == self and _loading_package.package_name == package_name then
return true
end
for _, queued_package in ipairs(_queued_packages) do
if queued_package.mod == self and queued_package.package_name == package_name then
return true
end
end
return false
end
function VMFMod:has_package_loaded(package_name)
if not _initialized then
self:error("Package manager has not been initialized yet. It can only be used after the `all_mods_loaded` event has been processed.")
return
end
local loaded_packages = _loaded_packages[self]
return loaded_packages and loaded_packages[package_name] ~= nil
end
function VMFMod:is_package_manager_initialized()
return _initialized
end
function vmf.initialize_package_manager()
vmf:debug("Initializing package manager")
for _, mod_data in ipairs(Managers.mod._mods) do
_mod_handles[mod_data.id] = mod_data.handle
end
_initialized = true
end
function vmf.update_package_manager()
local loading_package = _loading_package
if loading_package then
if loading_package.resource_package:has_loaded() then
vmf:debug("Finished loading package '%s/%s' asynchronously", loading_package.mod:get_name(), loading_package.package_name)
_loaded_packages[loading_package.mod][loading_package.package_name] = loading_package.resource_package
_loading_package = nil
-- The callback has to be called last, so that any calls to `has_package_loaded` or `is_package_loading` return the correct value
loading_package.callback()
else
vmf:debug("Package '%s/%s' is still loading asynchronously", loading_package.mod:get_name(), loading_package.package_name)
end
return
-- else
-- vmf:debug("No package to load asynchronously")
end
local queued_package = _queued_packages[1]
if queued_package then
_loading_package = queued_package
table.remove(_queued_packages, 1)
_loading_package.resource_package:load()
vmf:debug("Started loading package '%s/%s' asynchronously", _loading_package.mod:get_name(), _loading_package.package_name)
end
end
function VMFMod:dump_package_manager()
self:debug("initialized = %s", _initialized)
self:dump(_mod_handles, "_mod_handles", 2)
self:dump(_queued_packages, "_queued_packages", 2)
if _loading_package then
self:dump(_loading_package, "_loading_package", 2)
else
self:debug("_loading_package = nil")
end
self:dump(_loaded_packages, "_loaded_packages", 2)
end

View file

@ -115,6 +115,7 @@ function vmf.initialize_mod_data(mod, mod_data)
vmf.set_internal_data(mod, "is_togglable", mod_data.is_togglable or mod_data.is_mutator)
vmf.set_internal_data(mod, "is_mutator", mod_data.is_mutator)
vmf.set_internal_data(mod, "allow_rehooking", mod_data.allow_rehooking)
vmf.set_internal_data(mod, "workshop_id", mod_data.workshop_id)
-- Register mod as mutator @TODO: calling this after options initialization would be better, I guess?
if mod_data.is_mutator then
@ -163,4 +164,4 @@ end
-- VARIABLES
vmf.mods = _mods
vmf.mods_unloading_order = _mods_unloading_order
vmf.mods_unloading_order = _mods_unloading_order

View file

@ -29,6 +29,7 @@ function vmf_mod_object:init()
dofile("scripts/mods/vmf/modules/core/options")
dofile("scripts/mods/vmf/modules/legacy/options")
dofile("scripts/mods/vmf/modules/core/network")
dofile("scripts/mods/vmf/modules/core/packages")
dofile("scripts/mods/vmf/modules/core/commands")
dofile("scripts/mods/vmf/modules/gui/custom_textures")
dofile("scripts/mods/vmf/modules/gui/custom_views")
@ -55,6 +56,7 @@ end
-- #####################################################################################################################
function vmf_mod_object:update(dt)
vmf.update_package_manager()
vmf.mods_update_event(dt)
vmf.check_keybinds()
vmf.execute_queued_chat_command()
@ -63,6 +65,7 @@ function vmf_mod_object:update(dt)
if not vmf.all_mods_were_loaded and Managers.mod._state == "done" then
vmf.generate_keybinds()
vmf.initialize_package_manager()
vmf.initialize_vmf_options_view()
vmf.create_network_dictionary()
vmf.ping_vmf_users()
@ -111,4 +114,4 @@ end
-- ##### Return ########################################################################################################
-- #####################################################################################################################
return vmf_mod_object
return vmf_mod_object