From 391c1ca65f2da423abbdce8467934490296007ae Mon Sep 17 00:00:00 2001 From: bi Date: Tue, 19 Jun 2018 16:56:15 +0300 Subject: [PATCH 1/4] VMF Mod Data: refactoring, adding modification protection --- .../core/mutators/mutators_manager.lua | 24 ++++----- .../mods/vmf/modules/core/toggling.lua | 2 +- .../vmf/modules/ui/mutators/mutators_gui.lua | 2 +- vmf/scripts/mods/vmf/modules/vmf_mod_data.lua | 53 +++++++++++++++++++ .../mods/vmf/modules/vmf_mod_manager.lua | 53 ++----------------- vmf/scripts/mods/vmf/vmf_loader.lua | 1 + 6 files changed, 73 insertions(+), 62 deletions(-) create mode 100644 vmf/scripts/mods/vmf/modules/vmf_mod_data.lua diff --git a/vmf/scripts/mods/vmf/modules/core/mutators/mutators_manager.lua b/vmf/scripts/mods/vmf/modules/core/mutators/mutators_manager.lua index 4989455..b56b156 100644 --- a/vmf/scripts/mods/vmf/modules/core/mutators/mutators_manager.lua +++ b/vmf/scripts/mods/vmf/modules/core/mutators/mutators_manager.lua @@ -48,7 +48,7 @@ end -- Called after mutator is enabled local function on_enabled(mutator) - local config = mutator:get_config() + local config = mutator:get_internal_data("mutator_config") dice_manager.addDice(config.dice) set_lobby_data() print("[MUTATORS] Enabled " .. mutator:get_name() .. " (" .. tostring(get_index(_mutators, mutator)) .. ")") @@ -59,7 +59,7 @@ end -- Called after mutator is disabled 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 if not initial_call then @@ -138,7 +138,7 @@ end local function mutator_can_be_enabled(mutator) -- 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 except = mutator_compatibility_config.except 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 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_after_these = raw_config.enable_after_these local mutator_name = mutator:get_name() @@ -225,8 +225,8 @@ end -- Uses raw_config to determine if mutators are compatible both ways local function is_compatible(mutator, other_mutator) - local raw_config = mutator:get_config().raw_config - local other_raw_config = other_mutator:get_config().raw_config + local raw_config = mutator:get_internal_data("mutator_config").raw_config + local other_raw_config = other_mutator:get_internal_data("mutator_config").raw_config local mutator_name = mutator:get_name() local other_mutator_name = other_mutator:get_name() @@ -274,7 +274,7 @@ end local function update_compatibility(mutator) -- Create default 'compatibility' entry - local config = mutator:get_config() + local config = mutator:get_internal_data("mutator_config") config.compatibility = {} local compatibility = config.compatibility @@ -287,7 +287,7 @@ local function update_compatibility(mutator) 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_except = other_config.compatibility.except @@ -338,9 +338,9 @@ local function initialize_mutator_config(mutator, _raw_config) end if raw_config.short_title == "" then raw_config.short_title = nil end - mutator._data.config = {} + rawset(mutator._data, "mutator_config", {}) - local config = mutator._data.config + local config = mutator:get_internal_data("mutator_config") config.dice = raw_config.dice 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 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()) if config.title_placement == "before" then if before then @@ -485,7 +485,7 @@ end -- Removes all raw_configs which won't be used anymore function vmf.mutators_delete_raw_config() for _, mutator in ipairs(_mutators) do - mutator:get_config().raw_config = nil + mutator:get_internal_data("mutator_config").raw_config = nil end end diff --git a/vmf/scripts/mods/vmf/modules/core/toggling.lua b/vmf/scripts/mods/vmf/modules/core/toggling.lua index 3239584..4d40d2b 100644 --- a/vmf/scripts/mods/vmf/modules/core/toggling.lua +++ b/vmf/scripts/mods/vmf/modules/core/toggling.lua @@ -8,7 +8,7 @@ local _disabled_mods = vmf:get("disabled_mods_list") or {} vmf.set_mod_state = function (mod, is_enabled, initial_call) - mod._data.is_enabled = is_enabled + rawset(mod._data, "is_enabled", is_enabled) if is_enabled then mod:enable_all_hooks() diff --git a/vmf/scripts/mods/vmf/modules/ui/mutators/mutators_gui.lua b/vmf/scripts/mods/vmf/modules/ui/mutators/mutators_gui.lua index 7819cb2..e060525 100644 --- a/vmf/scripts/mods/vmf/modules/ui/mutators/mutators_gui.lua +++ b/vmf/scripts/mods/vmf/modules/ui/mutators/mutators_gui.lua @@ -125,7 +125,7 @@ local function offset_function_callback(ui_scenegraph_, style, content, ui_rende -- Find out if mutator can be enabled. 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 except = mutator_compatibility_config.except diff --git a/vmf/scripts/mods/vmf/modules/vmf_mod_data.lua b/vmf/scripts/mods/vmf/modules/vmf_mod_data.lua new file mode 100644 index 0000000..f905601 --- /dev/null +++ b/vmf/scripts/mods/vmf/modules/vmf_mod_data.lua @@ -0,0 +1,53 @@ +-- Defining VMFMod class. +VMFMod = class(VMFMod) + +-- Creating mod data table when object of vmf mod is instantiated. +function VMFMod:init(mod_name) + self._data = {} + setmetatable(self._data, { + __newindex = function(t_, k) + self:warning("Attempt to change internal mod data value (\"%s\"). Changing internal mod data is forbidden.", k) + end + }) + rawset(self._data, "name", mod_name) + rawset(self._data, "readable_name", mod_name) + rawset(self._data, "is_enabled", true) + rawset(self._data, "is_togglable", false) + rawset(self._data, "is_mutator", false) +end + +-- ##################################################################################################################### +-- ##### VMFMod ######################################################################################################## +-- ##################################################################################################################### + +--[[ + Universal function for getting any internal mod data. Returned table values shouldn't be modified, because it lead to + unexpected VMF behaviour. + * key [string]: data entry name +--]] +function VMFMod:get_internal_data(key) + return self._data[key] +end + + +--[[ + Predefined functions for getting 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 +function VMFMod:is_togglable() + return self._data.is_togglable +end +function VMFMod:is_mutator() + return self._data.is_mutator +end \ No newline at end of file diff --git a/vmf/scripts/mods/vmf/modules/vmf_mod_manager.lua b/vmf/scripts/mods/vmf/modules/vmf_mod_manager.lua index d515fc1..0376590 100644 --- a/vmf/scripts/mods/vmf/modules/vmf_mod_manager.lua +++ b/vmf/scripts/mods/vmf/modules/vmf_mod_manager.lua @@ -17,16 +17,9 @@ local function create_mod(mod_name) table.insert(_mods_unloading_order, 1, mod_name) - local mod = VMFMod:new() + local mod = VMFMod:new(mod_name) _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 end @@ -96,42 +89,6 @@ function get_mod(mod_name) return _mods[mod_name] 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 ############################################################################################ -- ##################################################################################################################### @@ -152,11 +109,11 @@ function vmf.initialize_mod_data(mod, mod_data) end if mod_data.name then - mod._data.readable_name = mod_data.name + rawset(mod._data, "readable_name", mod_data.name) end - mod._data.description = mod_data.description - mod._data.is_togglable = mod_data.is_togglable or mod_data.is_mutator - mod._data.is_mutator = mod_data.is_mutator + rawset(mod._data, "description", mod_data.description) + rawset(mod._data, "is_togglable", mod_data.is_togglable or mod_data.is_mutator) + rawset(mod._data, "is_mutator", mod_data.is_mutator) if mod_data.is_mutator then vmf.register_mod_as_mutator(mod, mod_data.mutator_settings) diff --git a/vmf/scripts/mods/vmf/vmf_loader.lua b/vmf/scripts/mods/vmf/vmf_loader.lua index ecda424..72a89fd 100644 --- a/vmf/scripts/mods/vmf/vmf_loader.lua +++ b/vmf/scripts/mods/vmf/vmf_loader.lua @@ -11,6 +11,7 @@ local vmf_mod_object = {} -- ##################################################################################################################### 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/core/safe_calls") dofile("scripts/mods/vmf/modules/core/events") From b5a9699bd8a7b2eac433b2410d975a79a2414e89 Mon Sep 17 00:00:00 2001 From: bi Date: Tue, 19 Jun 2018 17:38:17 +0300 Subject: [PATCH 2/4] VMF Mod Data: changed several comments --- vmf/scripts/mods/vmf/modules/vmf_mod_data.lua | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/vmf/scripts/mods/vmf/modules/vmf_mod_data.lua b/vmf/scripts/mods/vmf/modules/vmf_mod_data.lua index f905601..90401bb 100644 --- a/vmf/scripts/mods/vmf/modules/vmf_mod_data.lua +++ b/vmf/scripts/mods/vmf/modules/vmf_mod_data.lua @@ -1,7 +1,7 @@ -- Defining VMFMod class. VMFMod = class(VMFMod) --- Creating mod data table when object of vmf mod is instantiated. +-- Creating mod data table when object of VMFMod class is created. function VMFMod:init(mod_name) self._data = {} setmetatable(self._data, { @@ -21,9 +21,18 @@ end -- ##################################################################################################################### --[[ - Universal function for getting any internal mod data. Returned table values shouldn't be modified, because it lead to - unexpected VMF behaviour. + 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] @@ -31,7 +40,7 @@ end --[[ - Predefined functions for getting specific internal mod data. + Predefined functions for retrieving specific internal mod data. --]] function VMFMod:get_name() return self._data.name From a172f72c0a8ada8ea833cd476976ed6979b9b85c Mon Sep 17 00:00:00 2001 From: bi Date: Wed, 20 Jun 2018 00:26:33 +0300 Subject: [PATCH 3/4] VMF Mod Data: updated external change protection --- .../core/mutators/mutators_manager.lua | 2 +- .../mods/vmf/modules/core/toggling.lua | 2 +- vmf/scripts/mods/vmf/modules/vmf_mod_data.lua | 32 ++++++++++++++----- .../mods/vmf/modules/vmf_mod_manager.lua | 8 ++--- 4 files changed, 30 insertions(+), 14 deletions(-) diff --git a/vmf/scripts/mods/vmf/modules/core/mutators/mutators_manager.lua b/vmf/scripts/mods/vmf/modules/core/mutators/mutators_manager.lua index b56b156..d3aa78a 100644 --- a/vmf/scripts/mods/vmf/modules/core/mutators/mutators_manager.lua +++ b/vmf/scripts/mods/vmf/modules/core/mutators/mutators_manager.lua @@ -338,7 +338,7 @@ local function initialize_mutator_config(mutator, _raw_config) end if raw_config.short_title == "" then raw_config.short_title = nil end - rawset(mutator._data, "mutator_config", {}) + vmf.set_internal_data(mutator, "mutator_config", {}) local config = mutator:get_internal_data("mutator_config") diff --git a/vmf/scripts/mods/vmf/modules/core/toggling.lua b/vmf/scripts/mods/vmf/modules/core/toggling.lua index 4d40d2b..c236545 100644 --- a/vmf/scripts/mods/vmf/modules/core/toggling.lua +++ b/vmf/scripts/mods/vmf/modules/core/toggling.lua @@ -8,7 +8,7 @@ local _disabled_mods = vmf:get("disabled_mods_list") or {} vmf.set_mod_state = function (mod, is_enabled, initial_call) - rawset(mod._data, "is_enabled", is_enabled) + vmf.set_internal_data(mod, "is_enabled", is_enabled) if is_enabled then mod:enable_all_hooks() diff --git a/vmf/scripts/mods/vmf/modules/vmf_mod_data.lua b/vmf/scripts/mods/vmf/modules/vmf_mod_data.lua index 90401bb..4c060b3 100644 --- a/vmf/scripts/mods/vmf/modules/vmf_mod_data.lua +++ b/vmf/scripts/mods/vmf/modules/vmf_mod_data.lua @@ -1,19 +1,35 @@ +-- ##################################################################################################################### +-- ##### 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) - self._data = {} - setmetatable(self._data, { + 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 }) - rawset(self._data, "name", mod_name) - rawset(self._data, "readable_name", mod_name) - rawset(self._data, "is_enabled", true) - rawset(self._data, "is_togglable", false) - rawset(self._data, "is_mutator", false) + 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 -- ##################################################################################################################### @@ -55,7 +71,7 @@ function VMFMod:is_enabled() return self._data.is_enabled end function VMFMod:is_togglable() - return self._data.is_togglable + return self._data.is_togglable end function VMFMod:is_mutator() return self._data.is_mutator diff --git a/vmf/scripts/mods/vmf/modules/vmf_mod_manager.lua b/vmf/scripts/mods/vmf/modules/vmf_mod_manager.lua index 0376590..9171698 100644 --- a/vmf/scripts/mods/vmf/modules/vmf_mod_manager.lua +++ b/vmf/scripts/mods/vmf/modules/vmf_mod_manager.lua @@ -109,11 +109,11 @@ function vmf.initialize_mod_data(mod, mod_data) end if mod_data.name then - rawset(mod._data, "readable_name", mod_data.name) + vmf.set_internal_data(mod, "readable_name", mod_data.name) end - rawset(mod._data, "description", mod_data.description) - rawset(mod._data, "is_togglable", mod_data.is_togglable or mod_data.is_mutator) - rawset(mod._data, "is_mutator", mod_data.is_mutator) + vmf.set_internal_data(mod, "description", mod_data.description) + 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) if mod_data.is_mutator then vmf.register_mod_as_mutator(mod, mod_data.mutator_settings) From 13727c1adcc04f8fc28ba75382fd908420166e9d Mon Sep 17 00:00:00 2001 From: bi Date: Thu, 21 Jun 2018 09:40:02 +0300 Subject: [PATCH 4/4] VMF Mod Data: got rid of 'is_togglable' and 'is_mutator' methods --- vmf/scripts/mods/vmf/modules/core/keybindings.lua | 2 +- vmf/scripts/mods/vmf/modules/core/toggling.lua | 8 ++++---- .../mods/vmf/modules/ui/options/vmf_options_view.lua | 2 +- vmf/scripts/mods/vmf/modules/vmf_mod_data.lua | 6 ------ vmf/scripts/mods/vmf/modules/vmf_mod_manager.lua | 2 +- 5 files changed, 7 insertions(+), 13 deletions(-) diff --git a/vmf/scripts/mods/vmf/modules/core/keybindings.lua b/vmf/scripts/mods/vmf/modules/core/keybindings.lua index 68a9f18..cbafbc8 100644 --- a/vmf/scripts/mods/vmf/modules/core/keybindings.lua +++ b/vmf/scripts/mods/vmf/modules/core/keybindings.lua @@ -141,7 +141,7 @@ vmf.check_pressed_keybinds = function() 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()) diff --git a/vmf/scripts/mods/vmf/modules/core/toggling.lua b/vmf/scripts/mods/vmf/modules/core/toggling.lua index c236545..638d467 100644 --- a/vmf/scripts/mods/vmf/modules/core/toggling.lua +++ b/vmf/scripts/mods/vmf/modules/core/toggling.lua @@ -18,7 +18,7 @@ vmf.set_mod_state = function (mod, is_enabled, initial_call) vmf.mod_disabled_event(mod, initial_call) 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 _disabled_mods[mod:get_name()] = nil else @@ -32,7 +32,7 @@ end vmf.initialize_mod_state = function (mod) 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.is_mutator_enabled(mod:get_name()) then state = true @@ -50,11 +50,11 @@ vmf.mod_state_changed = function (mod_name, is_enabled) 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 end - if mod:is_mutator() then + if mod:get_internal_data("is_mutator") then vmf.set_mutator_state(mod, is_enabled, false) else vmf.set_mod_state(mod, is_enabled, false) diff --git a/vmf/scripts/mods/vmf/modules/ui/options/vmf_options_view.lua b/vmf/scripts/mods/vmf/modules/ui/options/vmf_options_view.lua index a700f14..ac3dd9e 100644 --- a/vmf/scripts/mods/vmf/modules/ui/options/vmf_options_view.lua +++ b/vmf/scripts/mods/vmf/modules/ui/options/vmf_options_view.lua @@ -4324,7 +4324,7 @@ vmf.create_options = function (mod, widgets_definition) new_widget_definition.readable_mod_name = mod:get_readable_name() new_widget_definition.tooltip = mod:get_description() 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 new_widget_definition.is_widget_collapsed = mod_collapsed_widgets[mod:get_name()] diff --git a/vmf/scripts/mods/vmf/modules/vmf_mod_data.lua b/vmf/scripts/mods/vmf/modules/vmf_mod_data.lua index 4c060b3..394aa82 100644 --- a/vmf/scripts/mods/vmf/modules/vmf_mod_data.lua +++ b/vmf/scripts/mods/vmf/modules/vmf_mod_data.lua @@ -69,10 +69,4 @@ function VMFMod:get_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 \ No newline at end of file diff --git a/vmf/scripts/mods/vmf/modules/vmf_mod_manager.lua b/vmf/scripts/mods/vmf/modules/vmf_mod_manager.lua index 9171698..a12a3ae 100644 --- a/vmf/scripts/mods/vmf/modules/vmf_mod_manager.lua +++ b/vmf/scripts/mods/vmf/modules/vmf_mod_manager.lua @@ -79,7 +79,7 @@ function new_mod(mod_name, mod_resources) end -- Initialize mod state - if mod:is_togglable() then + if mod:get_internal_data("is_togglable") then vmf.initialize_mod_state(mod) end end