Merge pull request #20 from Vermintide-Mod-Framework/vmf_mod_data_refactoring

VMF Mod Data: refactoring, adding modification protection
This commit is contained in:
Azumgi 2018-06-21 09:45:16 +03:00 committed by GitHub
commit 35458fd7f3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 99 additions and 69 deletions

View file

@ -141,7 +141,7 @@ vmf.check_pressed_keybinds = function()
local mod = get_mod(binding_info[1]) local mod = get_mod(binding_info[1])
if binding_info[2] == "toggle_mod_state" and not mod:is_mutator() then if binding_info[2] == "toggle_mod_state" and not mod:get_internal_data("is_mutator") then
vmf.mod_state_changed(mod:get_name(), not mod:is_enabled()) vmf.mod_state_changed(mod:get_name(), not mod:is_enabled())

View file

@ -48,7 +48,7 @@ end
-- Called after mutator is enabled -- Called after mutator is enabled
local function on_enabled(mutator) local function on_enabled(mutator)
local config = mutator:get_config() local config = mutator:get_internal_data("mutator_config")
dice_manager.addDice(config.dice) dice_manager.addDice(config.dice)
set_lobby_data() set_lobby_data()
print("[MUTATORS] Enabled " .. mutator:get_name() .. " (" .. tostring(get_index(_mutators, mutator)) .. ")") print("[MUTATORS] Enabled " .. mutator:get_name() .. " (" .. tostring(get_index(_mutators, mutator)) .. ")")
@ -59,7 +59,7 @@ end
-- Called after mutator is disabled -- Called after mutator is disabled
local function on_disabled(mutator, initial_call) local function on_disabled(mutator, initial_call)
local config = mutator:get_config() local config = mutator:get_internal_data("mutator_config")
-- All mutators run on_disabled on initial call, so there's no need to remove dice and set lobby data -- All mutators run on_disabled on initial call, so there's no need to remove dice and set lobby data
if not initial_call then if not initial_call then
@ -138,7 +138,7 @@ end
local function mutator_can_be_enabled(mutator) local function mutator_can_be_enabled(mutator)
-- If conflicting mutators are enabled -- If conflicting mutators are enabled
local mutator_compatibility_config = mutator:get_config().compatibility local mutator_compatibility_config = mutator:get_internal_data("mutator_config").compatibility
local is_mostly_compatible = mutator_compatibility_config.is_mostly_compatible local is_mostly_compatible = mutator_compatibility_config.is_mostly_compatible
local except = mutator_compatibility_config.except local except = mutator_compatibility_config.except
for _, other_mutator in ipairs(_mutators) do for _, other_mutator in ipairs(_mutators) do
@ -189,7 +189,7 @@ end
-- Adds mutator names from enable_these_after to the list of mutators that should be enabled after the mutator_name -- Adds mutator names from enable_these_after to the list of mutators that should be enabled after the mutator_name
local function update_mutators_sequence(mutator) local function update_mutators_sequence(mutator)
local raw_config = mutator:get_config().raw_config local raw_config = mutator:get_internal_data("mutator_config").raw_config
local enable_before_these = raw_config.enable_before_these local enable_before_these = raw_config.enable_before_these
local enable_after_these = raw_config.enable_after_these local enable_after_these = raw_config.enable_after_these
local mutator_name = mutator:get_name() local mutator_name = mutator:get_name()
@ -225,8 +225,8 @@ end
-- Uses raw_config to determine if mutators are compatible both ways -- Uses raw_config to determine if mutators are compatible both ways
local function is_compatible(mutator, other_mutator) local function is_compatible(mutator, other_mutator)
local raw_config = mutator:get_config().raw_config local raw_config = mutator:get_internal_data("mutator_config").raw_config
local other_raw_config = other_mutator:get_config().raw_config local other_raw_config = other_mutator:get_internal_data("mutator_config").raw_config
local mutator_name = mutator:get_name() local mutator_name = mutator:get_name()
local other_mutator_name = other_mutator:get_name() local other_mutator_name = other_mutator:get_name()
@ -274,7 +274,7 @@ end
local function update_compatibility(mutator) local function update_compatibility(mutator)
-- Create default 'compatibility' entry -- Create default 'compatibility' entry
local config = mutator:get_config() local config = mutator:get_internal_data("mutator_config")
config.compatibility = {} config.compatibility = {}
local compatibility = config.compatibility local compatibility = config.compatibility
@ -287,7 +287,7 @@ local function update_compatibility(mutator)
for _, other_mutator in ipairs(_mutators) do for _, other_mutator in ipairs(_mutators) do
local other_config = other_mutator:get_config() local other_config = other_mutator:get_internal_data("mutator_config")
local other_mostly_compatible = other_config.compatibility.is_mostly_compatible local other_mostly_compatible = other_config.compatibility.is_mostly_compatible
local other_except = other_config.compatibility.except local other_except = other_config.compatibility.except
@ -338,9 +338,9 @@ local function initialize_mutator_config(mutator, _raw_config)
end end
if raw_config.short_title == "" then raw_config.short_title = nil end if raw_config.short_title == "" then raw_config.short_title = nil end
mutator._data.config = {} vmf.set_internal_data(mutator, "mutator_config", {})
local config = mutator._data.config local config = mutator:get_internal_data("mutator_config")
config.dice = raw_config.dice config.dice = raw_config.dice
config.short_title = raw_config.short_title config.short_title = raw_config.short_title
@ -376,7 +376,7 @@ function vmf.add_mutator_titles_to_string(mutators, separator, is_short)
local replace = nil local replace = nil
for _, mutator in ipairs(mutators) do for _, mutator in ipairs(mutators) do
local config = mutator:get_config() local config = mutator:get_internal_data("mutator_config")
local added_name = (is_short and config.short_title or mutator:get_readable_name()) local added_name = (is_short and config.short_title or mutator:get_readable_name())
if config.title_placement == "before" then if config.title_placement == "before" then
if before then if before then
@ -485,7 +485,7 @@ end
-- Removes all raw_configs which won't be used anymore -- Removes all raw_configs which won't be used anymore
function vmf.mutators_delete_raw_config() function vmf.mutators_delete_raw_config()
for _, mutator in ipairs(_mutators) do for _, mutator in ipairs(_mutators) do
mutator:get_config().raw_config = nil mutator:get_internal_data("mutator_config").raw_config = nil
end end
end end

View file

@ -8,7 +8,7 @@ local _disabled_mods = vmf:get("disabled_mods_list") or {}
vmf.set_mod_state = function (mod, is_enabled, initial_call) vmf.set_mod_state = function (mod, is_enabled, initial_call)
mod._data.is_enabled = is_enabled vmf.set_internal_data(mod, "is_enabled", is_enabled)
if is_enabled then if is_enabled then
mod:enable_all_hooks() mod:enable_all_hooks()
@ -18,7 +18,7 @@ vmf.set_mod_state = function (mod, is_enabled, initial_call)
vmf.mod_disabled_event(mod, initial_call) vmf.mod_disabled_event(mod, initial_call)
end end
if not (initial_call or mod:is_mutator()) then if not (initial_call or mod:get_internal_data("is_mutator")) then
if is_enabled then if is_enabled then
_disabled_mods[mod:get_name()] = nil _disabled_mods[mod:get_name()] = nil
else else
@ -32,7 +32,7 @@ end
vmf.initialize_mod_state = function (mod) vmf.initialize_mod_state = function (mod)
local state local state
if mod:is_mutator() then if mod:get_internal_data("is_mutator") then
-- if VMF was reloaded and mutator was activated -- if VMF was reloaded and mutator was activated
if vmf.is_mutator_enabled(mod:get_name()) then if vmf.is_mutator_enabled(mod:get_name()) then
state = true state = true
@ -50,11 +50,11 @@ vmf.mod_state_changed = function (mod_name, is_enabled)
local mod = get_mod(mod_name) local mod = get_mod(mod_name)
if not mod:is_togglable() or is_enabled == mod:is_enabled() then if not mod:get_internal_data("is_togglable") or is_enabled == mod:is_enabled() then
return return
end end
if mod:is_mutator() then if mod:get_internal_data("is_mutator") then
vmf.set_mutator_state(mod, is_enabled, false) vmf.set_mutator_state(mod, is_enabled, false)
else else
vmf.set_mod_state(mod, is_enabled, false) vmf.set_mod_state(mod, is_enabled, false)

View file

@ -125,7 +125,7 @@ local function offset_function_callback(ui_scenegraph_, style, content, ui_rende
-- Find out if mutator can be enabled. -- Find out if mutator can be enabled.
local can_be_enabled = true local can_be_enabled = true
local mutator_compatibility_config = mutator:get_config().compatibility local mutator_compatibility_config = mutator:get_internal_data("mutator_config").compatibility
local is_mostly_compatible = mutator_compatibility_config.is_mostly_compatible local is_mostly_compatible = mutator_compatibility_config.is_mostly_compatible
local except = mutator_compatibility_config.except local except = mutator_compatibility_config.except

View file

@ -4324,7 +4324,7 @@ vmf.create_options = function (mod, widgets_definition)
new_widget_definition.readable_mod_name = mod:get_readable_name() new_widget_definition.readable_mod_name = mod:get_readable_name()
new_widget_definition.tooltip = mod:get_description() new_widget_definition.tooltip = mod:get_description()
new_widget_definition.default = true new_widget_definition.default = true
new_widget_definition.is_mod_toggable = mod:is_togglable() and not mod:is_mutator() new_widget_definition.is_mod_toggable = mod:get_internal_data("is_togglable") and not mod:get_internal_data("is_mutator")
if mod_collapsed_widgets then if mod_collapsed_widgets then
new_widget_definition.is_widget_collapsed = mod_collapsed_widgets[mod:get_name()] new_widget_definition.is_widget_collapsed = mod_collapsed_widgets[mod:get_name()]

View file

@ -0,0 +1,72 @@
-- #####################################################################################################################
-- ##### Local functions ###############################################################################################
-- #####################################################################################################################
local function set_internal_data(mod, key, value)
getmetatable(mod._data).__index[key] = value
end
-- #####################################################################################################################
-- ##### VMFMod (not API) ##############################################################################################
-- #####################################################################################################################
-- Defining VMFMod class.
VMFMod = class(VMFMod)
-- Creating mod data table when object of VMFMod class is created.
function VMFMod:init(mod_name)
if mod_name == "VMF" then
self.set_internal_data = set_internal_data
end
self._data = setmetatable({}, {
__index = {},
__newindex = function(t_, k)
self:warning("Attempt to change internal mod data value (\"%s\"). Changing internal mod data is forbidden.", k)
end
})
set_internal_data(self, "name", mod_name)
set_internal_data(self, "readable_name", mod_name)
set_internal_data(self, "is_enabled", true)
set_internal_data(self, "is_togglable", false)
set_internal_data(self, "is_mutator", false)
end
-- #####################################################################################################################
-- ##### VMFMod ########################################################################################################
-- #####################################################################################################################
--[[
Universal function for retrieving any internal mod data. Returned table values shouldn't be modified, because it can
lead to unexpected VMF behaviour.
* key [string]: data entry name
Possible entry names:
- name (system mod name)
- readable_name (readable mod name)
- description (mod description)
- is_togglable (if the mod can be disabled/enabled)
- is_enabled (if the mod is curently enabled)
- is_mutator (if the mod is mutator)
- mutator_config (mutator config)
--]]
function VMFMod:get_internal_data(key)
return self._data[key]
end
--[[
Predefined functions for retrieving specific internal mod data.
--]]
function VMFMod:get_name()
return self._data.name
end
function VMFMod:get_readable_name()
return self._data.readable_name
end
function VMFMod:get_description()
return self._data.description
end
function VMFMod:is_enabled()
return self._data.is_enabled
end

View file

@ -17,16 +17,9 @@ local function create_mod(mod_name)
table.insert(_mods_unloading_order, 1, mod_name) table.insert(_mods_unloading_order, 1, mod_name)
local mod = VMFMod:new() local mod = VMFMod:new(mod_name)
_mods[mod_name] = mod _mods[mod_name] = mod
mod._data = {}
mod._data.name = mod_name
mod._data.readable_name = mod_name
mod._data.is_enabled = true
mod._data.is_togglable = false
mod._data.is_mutator = false
return mod return mod
end end
@ -86,7 +79,7 @@ function new_mod(mod_name, mod_resources)
end end
-- Initialize mod state -- Initialize mod state
if mod:is_togglable() then if mod:get_internal_data("is_togglable") then
vmf.initialize_mod_state(mod) vmf.initialize_mod_state(mod)
end end
end end
@ -96,42 +89,6 @@ function get_mod(mod_name)
return _mods[mod_name] return _mods[mod_name]
end end
-- #####################################################################################################################
-- ##### VMFMod ########################################################################################################
-- #####################################################################################################################
VMFMod = class(VMFMod)
-- DATA
function VMFMod:get_name()
return self._data.name
end
function VMFMod:get_readable_name()
return self._data.readable_name
end
function VMFMod:get_description()
return self._data.description
end
function VMFMod:is_enabled()
return self._data.is_enabled
end
function VMFMod:is_togglable()
return self._data.is_togglable
end
function VMFMod:is_mutator()
return self._data.is_mutator
end
function VMFMod:get_config()
return self._data.config
end
-- ##################################################################################################################### -- #####################################################################################################################
-- ##### VMF Initialization ############################################################################################ -- ##### VMF Initialization ############################################################################################
-- ##################################################################################################################### -- #####################################################################################################################
@ -152,11 +109,11 @@ function vmf.initialize_mod_data(mod, mod_data)
end end
if mod_data.name then if mod_data.name then
mod._data.readable_name = mod_data.name vmf.set_internal_data(mod, "readable_name", mod_data.name)
end end
mod._data.description = mod_data.description vmf.set_internal_data(mod, "description", mod_data.description)
mod._data.is_togglable = mod_data.is_togglable or mod_data.is_mutator vmf.set_internal_data(mod, "is_togglable", mod_data.is_togglable or mod_data.is_mutator)
mod._data.is_mutator = mod_data.is_mutator vmf.set_internal_data(mod, "is_mutator", mod_data.is_mutator)
if mod_data.is_mutator then if mod_data.is_mutator then
vmf.register_mod_as_mutator(mod, mod_data.mutator_settings) vmf.register_mod_as_mutator(mod, mod_data.mutator_settings)

View file

@ -11,6 +11,7 @@ local vmf_mod_object = {}
-- ##################################################################################################################### -- #####################################################################################################################
function vmf_mod_object:init() function vmf_mod_object:init()
dofile("scripts/mods/vmf/modules/vmf_mod_data")
dofile("scripts/mods/vmf/modules/vmf_mod_manager") dofile("scripts/mods/vmf/modules/vmf_mod_manager")
dofile("scripts/mods/vmf/modules/core/safe_calls") dofile("scripts/mods/vmf/modules/core/safe_calls")
dofile("scripts/mods/vmf/modules/core/events") dofile("scripts/mods/vmf/modules/core/events")