diff --git a/README.md b/README.md index 9609efe6..c78e995b 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,7 @@ All are welcome to make pull requests and issues for this scenario, if you are i | Scenario Version* | Version Name | Factorio Version** | |---|---|---| +| [v5.7][s5.8] | Home and Chat Bot | [v0.17.47][f0.17.49] | | [v5.7][s5.7] | Warp System | [v0.17.47][f0.17.47] | | [v5.6][s5.6] | Information Guis | [v0.17.44][f0.17.44] | | [v5.5][s5.5] | Gui System | [v0.17.43][f0.17.43] | @@ -74,6 +75,7 @@ All are welcome to make pull requests and issues for this scenario, if you are i \*\* Factorio versions show the version they were made for, often the minimum requirement. +[s5.8]: https://github.com/explosivegaming/scenario/releases/tag/5.8.0 [s5.7]: https://github.com/explosivegaming/scenario/releases/tag/5.7.0 [s5.6]: https://github.com/explosivegaming/scenario/releases/tag/5.6.0 [s5.5]: https://github.com/explosivegaming/scenario/releases/tag/5.5.0 @@ -88,6 +90,7 @@ All are welcome to make pull requests and issues for this scenario, if you are i [s1.0]: https://github.com/explosivegaming/scenario/releases/tag/v1.0 [s0.1]: https://github.com/explosivegaming/scenario/releases/tag/v0.1 +[f0.17.49]: https://wiki.factorio.com/Version_history/0.17.0#0.17.49 [f0.17.47]: https://wiki.factorio.com/Version_history/0.17.0#0.17.47 [f0.17.44]: https://wiki.factorio.com/Version_history/0.17.0#0.17.44 [f0.17.43]: https://wiki.factorio.com/Version_history/0.17.0#0.17.43 diff --git a/config/_file_loader.lua b/config/_file_loader.lua index f30d0368..f6c11fcb 100644 --- a/config/_file_loader.lua +++ b/config/_file_loader.lua @@ -24,6 +24,7 @@ return { 'modules.commands.warnings', 'modules.commands.find', 'modules.commands.bonus', + 'modules.commands.home', -- QoL Addons 'modules.addons.chat-popups', 'modules.addons.damage-popups', @@ -35,6 +36,7 @@ return { 'modules.addons.pollution-grading', 'modules.addons.random-player-colours', 'modules.addons.discord-alerts', + 'modules.addons.chat-reply', -- GUI 'modules.gui.rocket-info', 'modules.gui.science-info', diff --git a/config/chat_reply.lua b/config/chat_reply.lua new file mode 100644 index 00000000..aff00871 --- /dev/null +++ b/config/chat_reply.lua @@ -0,0 +1,66 @@ +--- This file defines the different triggers for the chat bot +local format_time = ext_require('expcore.common','format_time') +return { + allow_command_prefix_for_messages = true, -- when true any message trigger will print to all player when prefixed + messages = { -- will trigger when ever the word is said + ['discord']={'info.discord'}, + ['expgaming']={'info.website'}, + ['website']={'info.website'}, + ['wiki']={'info.wiki'}, + ['status']={'info.status'}, + ['github']={'info.github'}, + ['command']={'info.custom-commands'}, + ['commands']={'info.custom-commands'}, + ['softmod']={'info.softmod'}, + ['script']={'info.softmod'}, + ['loop']={'chat-bot.loops'}, + ['loops']={'chat-bot.loops'}, + ['rhd']={'chat-bot.lhd'}, + ['lhd']={'chat-bot.lhd'}, + ['roundabout']={'chat-bot.loops'}, + ['roundabouts']={'chat-bot.loops'}, + ['redmew']={'chat-bot.redmew'}, + ['afk']=function(player) + local max=player + for _,next_player in pairs(game.connected_players) do + if max.afk_time < next_player.afk_time then + max=next_player + end + end + return {'chat-bot.afk',max.name,format_time(max.afk_time,{minutes=true,seconds=true,long=true})} + end, + ['players']=function() + return {'chat-bot.players',#game.players} + end, + ['online']=function() + return {'chat-bot.players-online',#game.connected_players} + end, + ['time']=function() + return {'chat-bot.map-time',format_time(game.tick,{days=true,hours=true,minutes=true,seconds=true,long=true})} + end, + }, + command_admin_only = false, -- when true will only allow chat commands for admins + command_permission = 'command/chat-bot', -- the permision used to allow command prefixs + command_prefix = '!', -- prefix used for commands below and to print to all players (if enabled above) + commands = { -- will trigger only when command prefix is given + ['dev']={'chat-bot.not-real-dev'}, + ['blame']=function(player) + local names = {'Cooldude2606','arty714','badgamernl',player.name} + for _,next_player in pairs(game.connected_players) do + names[#names + 1] = next_player.name + end + return {'chat-bot.blame',table.get_random_dictionary_entry(names)} + end, + ['magic']={'chat-bot.magic'}, + ['aids']={'chat-bot.aids'}, + ['riot']={'chat-bot.riot'}, + ['lenny']={'chat-bot.lenny'}, + ['hodor']=function() + local options = {'?','.','!','!!!'} + return {'chat-bot.hodor',table.get_random_dictionary_entry(options)} + end, + ['evolution']=function() + return {'chat-bot.current-evolution',string.format('%.2f',game.forces['enemy'].evolution_factor)} + end, + } +} \ No newline at end of file diff --git a/config/compilatron.lua b/config/compilatron.lua index 47ffccb3..116eb5b6 100644 --- a/config/compilatron.lua +++ b/config/compilatron.lua @@ -6,17 +6,17 @@ return { }, messages={ -- the messages that each one will say, must be same name as its location ['Spawn']={ - {'info.website-message'}, + {'info.website'}, {'info.read-readme'}, - {'info.discord-message'}, + {'info.discord'}, {'info.softmod'}, - {'info.wiki-message'}, + {'info.wiki'}, {'info.redmew'}, - {'info.feedback-message'}, + {'info.feedback'}, {'info.custom-commands'}, - {'info.status-message'}, + {'info.status'}, {'info.lhd'}, - {'info.github-message'}, + {'info.github'}, } } } \ No newline at end of file diff --git a/config/roles.lua b/config/roles.lua index c51e7d0e..a17c7966 100644 --- a/config/roles.lua +++ b/config/roles.lua @@ -82,6 +82,10 @@ Roles.new_role('Moderator','Mod') 'command/clear-temp-ban', 'command/clear-inventory', 'command/bonus', + 'command/home', + 'command/home-set', + 'command/home-get', + 'command/return', 'gui/rocket-info/toggle-active', 'gui/rocket-info/remote_launch', } @@ -128,6 +132,10 @@ Roles.new_role('Pay to Win','P2W') 'gui/rocket-info/toggle-active', 'gui/rocket-info/remote_launch', 'command/bonus', + 'command/home', + 'command/home-set', + 'command/home-get', + 'command/return', } Roles.new_role('Donator','Don') @@ -155,6 +163,7 @@ Roles.new_role('Veteran','Vet') :set_custom_color{r=140,g=120,b=200} :set_parent('Member') :allow{ + 'command/chat-bot', } :set_auto_promote_condition(function(player) if player.online_time > 10*216000 then diff --git a/config/warnings.lua b/config/warnings.lua index 6e6c9211..7fd627a4 100644 --- a/config/warnings.lua +++ b/config/warnings.lua @@ -11,7 +11,7 @@ return { {'warnings.received',{'warnings.pre-pre-ban'}}, {'warnings.received',{'warnings.pre-ban'}}, function(player,by_player_name,number_of_warnings) - game.ban_player(player,{'warnings.received',by_player_name,number_of_warnings,{'warnings.ban',{'info.website-link'}}}) + game.ban_player(player,{'warnings.received',by_player_name,number_of_warnings,{'warnings.ban',{'links.website'}}}) end }, temp_warning_cool_down=30, -- time for a temp warning (given by script) to be removed (in minutes) diff --git a/control.lua b/control.lua index e4ed6c3f..29d79064 100644 --- a/control.lua +++ b/control.lua @@ -41,7 +41,6 @@ for index,path in pairs(files) do if not success then -- Failed to load a file log('[ERROR] Failed to load file: '..path) - log('[ERROR] '..file) table.insert(errors,'[ERROR] '..path..' :: '..file) elseif type(file) == 'string' and file:find('not found') then -- Returned a file not found message diff --git a/expcore/gui.lua b/expcore/gui.lua index 9bfe8171..6da96bbb 100644 --- a/expcore/gui.lua +++ b/expcore/gui.lua @@ -3,43 +3,49 @@ local Gui = require 'expcore.gui.core' --[[ - Gui._prototype_factory(tbl) --- Used internally to create new prototypes for element defines - Gui._event_factory(name) --- Used internally to create event handler adders for element defines - Gui._store_factory(callback) --- Used internally to create store adders for element defines - Gui._sync_store_factory(callback) --- Used internally to create synced store adders for element defines - Gui._define_factory(prototype) --- Used internally to create new element defines from a class prototype + Core - Gui._prototype:uid() --- Gets the uid for the element define - Gui._prototype:debug_name(name) --- Sets a debug alias for the define - Gui._prototype:set_caption(caption) --- Sets the caption for the element define - Gui._prototype:set_tooltip(tooltip) --- Sets the tooltip for the element define - Gui._prototype:set_style(style,callback) --- Sets the style for the element define - Gui._prototype:set_embeded_flow(state) --- Sets the element to be drawn inside a nameless flow, can be given a name using a function - Gui._prototype:on_element_update(callback) --- Add a hander to run on the general value update event, different classes will handle this event differently - - Gui._prototype:set_pre_authenticator(callback) --- Sets an authenticator that blocks the draw function if check fails - Gui._prototype:set_post_authenticator(callback) --- Sets an authenticator that disables the element if check fails - Gui._prototype:draw_to(element) --- Draws the element using what is in the draw_data table, allows use of authenticator if present, registers new instances if store present + Gui.new_define(prototype) --- Used internally to create new element defines from a class prototype Gui.draw(name,element) --- Draws a copy of the element define to the parent element, see draw_to - Gui._prototype:add_store(categorize) --- Adds a store location for the define that will save the state of the element, categorize is a function that returns a string - Gui._prototype:add_sync_store(location,categorize) --- Adds a store location for the define that will sync between games, categorize is a function that returns a string - Gui._prototype:on_store_update(callback) --- Adds a event callback for when the store changes are other events are not gauenteted to be raised - Gui.player_store(element) --- A categorize function to be used with add_store, each player has their own value - Gui.force_store(element) --- A categorize function to be used with add_store, each force has its own value - Gui.surface_store(element) --- A categorize function to be used with add_store, each surface has its own value + Gui.categorize_by_player(element) --- A categorize function to be used with add_store, each player has their own value + Gui.categorize_by_force(element) --- A categorize function to be used with add_store, each force has its own value + Gui.categorize_by_surface(element) --- A categorize function to be used with add_store, each surface has its own value - Gui._prototype:get_store(category) --- Gets the value in this elements store, category needed if categorize function used - Gui._prototype:set_store(category,value) --- Sets the value in this elements store, category needed if categorize function used - Gui.get_store(name,category) --- Gets the value that is stored for a given element define, category needed if categorize function used - Gui.set_store(name,category,value) --- Sets the value stored for a given element define, category needed if categorize function used - - Gui.toggle_enable(element) --- Will toggle the enabled state of an element + Gui.toggle_enabled(element) --- Will toggle the enabled state of an element Gui.toggle_visible(element) --- Will toggle the visiblity of an element Gui.set_padding(element,up,down,left,right) --- Sets the padding for a gui element Gui.set_padding_style(style,up,down,left,right) --- Sets the padding for a gui style - Gui.create_right_align(element,flow_name) --- Allows the creation of a right align flow to place elements into + Gui.create_alignment(element,flow_name) --- Allows the creation of a right align flow to place elements into Gui.destory_if_valid(element) --- Destroies an element but tests for it being present and valid first + Gui.create_scroll_table(element,table_size,maximal_height,name) --- Creates a scroll area with a table inside, table can be any size + Gui.create_header(element,caption,tooltip,right_align,name) --- Creates a header section with a label and button area + + Prototype Constructor + + Constructor.event(event_name) --- Creates a new function to add functions to an event handler + Constructor.extend(new_prototype) --- Extents a prototype with the base functions of all gui prototypes, no metatables + Constructor.store(sync,callback) --- Creates a new function which adds a store to a gui define + Constructor.setter(value_type,key,second_key) --- Creates a setter function that checks the type when a value is set + + Base Prototype + + Prototype:uid() --- Gets the uid for the element define + Prototype:debug_name(value) --- Sets a debug alias for the define + Prototype:set_caption(value) --- Sets the caption for the element define + Prototype:set_tooltip(value) --- Sets the tooltip for the element define + Prototype:set_style(style,callback) --- Sets the style for the element define + Prototype:set_embeded_flow(state) --- Sets the element to be drawn inside a nameless flow, can be given a name using a function + + Prototype:set_pre_authenticator --- Sets an authenticator that blocks the draw function if check fails + Prototype:set_post_authenticator --- Sets an authenticator that disables the element if check fails + + Prototype:raise_event(event_name,...) --- Raises a custom event for this define, any number of params can be given + Prototype:draw_to(element,...) --- The main function for defines, when called will draw an instance of this define to the given element + + Prototype:get_store(category) --- Gets the value in this elements store, category needed if categorize function used + Prototype:set_store(category,value) --- Sets the value in this elements store, category needed if categorize function used + Prototype:clear_store(category) --- Sets the value in this elements store to nil, category needed if categorize function used ]] local Instances = require 'expcore.gui.instances' @@ -48,8 +54,20 @@ Gui.get_instances = Instances.get_elements Gui.add_instance = Instances.get_elements Gui.update_instances = Instances.apply_to_elements Gui.classes.instances = Instances +--[[ + Instances.has_categories(name) --- Returns if a instnace group has a categorise function; must be registerd + Instances.is_registered(name) --- Returns if the given name is a registered instance group + Instances.register(name,categorise) --- Registers the name of an instance group to allow for storing element instances -local Button = require 'expcore.gui.buttons' + Instances.add_element(name,element) --- Adds an element to the instance group under the correct category; must be registered + Instances.get_elements_raw(name,category) --- Gets all element instances without first removing any invalid ones; used internally and must be registered + Instances.get_valid_elements(name,category,callback) --- Gets all valid element instances and has the option of running a callback on those that are valid + + Instances.unregistered_add_element(name,category,element) --- A version of add_element that does not require the group to be registered + Instances.unregistered_get_elements(name,category,callback) --- A version of get_elements that does not require the group to be registered +]] + +local Button = require 'expcore.gui.elements.buttons' Gui.new_button = Button.new_button Gui.classes.button = Button --[[ @@ -64,7 +82,7 @@ Gui.classes.button = Button Button._prototype:set_key_filter(filter,...) --- Adds a control key filter to the button ]] -local Checkbox = require 'expcore.gui.checkboxs' +local Checkbox = require 'expcore.gui.elements.checkboxs' Gui.new_checkbox = Checkbox.new_checkbox Gui.new_radiobutton = Checkbox.new_radiobutton Gui.new_radiobutton_option_set = Checkbox.new_option_set @@ -86,7 +104,7 @@ Gui.classes.checkbox = Checkbox Checkbox.reset_radiobutton(element,exclude,recursive) --- Sets all radiobutotn in a element to false (unless excluded) and can act recursivly ]] -local Dropdown = require 'expcore.gui.dropdown' +local Dropdown = require 'expcore.gui.elements.dropdown' Gui.new_dropdown = Dropdown.new_dropdown Gui.new_list_box = Dropdown.new_list_box Gui.classes.dropdown = Dropdown @@ -105,7 +123,7 @@ Gui.classes.dropdown = Dropdown Dropdown.get_selected_value(element) --- Returns the currently selected value rather than index ]] -local Slider = require 'expcore.gui.slider' +local Slider = require 'expcore.gui.elements.slider' Gui.new_slider = Slider.new_slider Gui.classes.slider = Slider --[[ @@ -114,13 +132,12 @@ Gui.classes.slider = Slider Slider._prototype:on_element_update(callback) --- Registers a handler for when an element instance updates Slider._prototype:on_store_update(callback) --- Registers a handler for when the stored value updates - Slider._prototype:use_notches(state) --- Adds notches to the slider Slider._prototype:set_range(min,max) --- Sets the range of a slider, if not used will use default values for a slider Slider._prototype:draw_label(element) --- Draws a new label and links its value to the value of this slider, if no store then it will only show one value per player Slider._prototype:enable_auto_draw_label(state) --- Enables auto draw of the label, the label will share the same parent element as the slider ]] -local Text = require 'expcore.gui.text' +local Text = require 'expcore.gui.elements.text' Gui.new_text_filed = Text.new_text_field Gui.new_text_box = Text.new_text_box Gui.classes.text = Text @@ -137,7 +154,7 @@ Gui.classes.text = Text Text._prototype_box:set_read_only(state) --- Sets the text box to be read only ]] -local ElemButton = require 'expcore.gui.elem-button' +local ElemButton = require 'expcore.gui.elements.elem-button' Gui.new_elem_button = ElemButton.new_elem_button Gui.classes.elem_button = ElemButton --[[ @@ -150,7 +167,7 @@ Gui.classes.elem_button = ElemButton ElemButton._prototype:set_default(value) --- Sets the default value for the elem button, this may be a function or a string ]] -local ProgressBar = require 'expcore.gui.progress-bar' +local ProgressBar = require 'expcore.gui.elements.progress-bar' Gui.new_progressbar = ProgressBar.new_progressbar Gui.set_progressbar_maximum = ProgressBar.set_maximum Gui.increment_progressbar = ProgressBar.increment @@ -177,7 +194,7 @@ Gui.classes.progressbar = ProgressBar ProgressBar._prototype:event_countdown(filter) --- Event handler factory that counts down by 1 every time the event triggeres, can filter which elements are decremented ]] -local Toolbar = require 'expcore.gui.toolbar' +local Toolbar = require 'expcore.gui.concepts.toolbar' Gui.new_toolbar_button = Toolbar.new_button Gui.add_button_to_toolbar = Toolbar.add_button Gui.update_toolbar = Toolbar.update @@ -188,7 +205,7 @@ Gui.classes.toolbar = Toolbar Toolbar.update(player) --- Updates the player's toolbar with an new buttons or expected change in auth return ]] -local LeftFrames = require 'expcore.gui.left' +local LeftFrames = require 'expcore.gui.concepts.left' Gui.get_left_frame_flow = LeftFrames.get_flow Gui.toggle_left_frame = LeftFrames.toggle_frame Gui.new_left_frame = LeftFrames.new_frame @@ -217,7 +234,7 @@ Gui.classes.left_frames = LeftFrames LeftFrames._prototype:event_handler(action) --- Creates an event handler that will trigger one of its functions, use with Event.add ]] -local CenterFrames = require 'expcore.gui.center' +local CenterFrames = require 'expcore.gui.concepts.center' Gui.get_center_flow = CenterFrames.get_flow Gui.toggle_center_frame = CenterFrames.toggle_frame Gui.draw_center_frame = CenterFrames.draw_frame @@ -240,7 +257,7 @@ Gui.classes.center_frames = CenterFrames CenterFrames._prototype:event_handler(action) --- Creates an event handler that will trigger one of its functions, use with Event.add ]] -local PopupFrames = require 'expcore.gui.popups' +local PopupFrames = require 'expcore.gui.concepts.popups' Gui.get_popup_flow = PopupFrames.get_flow Gui.open_popup = PopupFrames.open Gui.new_popup = PopupFrames.new_popup diff --git a/expcore/gui/center.lua b/expcore/gui/concepts/center.lua similarity index 96% rename from expcore/gui/center.lua rename to expcore/gui/concepts/center.lua index 2788e804..c7eb5e34 100644 --- a/expcore/gui/center.lua +++ b/expcore/gui/concepts/center.lua @@ -16,12 +16,13 @@ CenterFrames._prototype:event_handler(action) --- Creates an event handler that will trigger one of its functions, use with Event.add ]] local Gui = require 'expcore.gui.core' -local Toolbar = require 'expcore.gui.toolbar' +local Prototype = require 'expcore.gui.prototype' +local Toolbar = require 'expcore.gui.concepts.toolbar' local Game = require 'utils.game' local CenterFrames = { - _prototype = Gui._prototype_factory{ - on_draw = Gui._event_factory('on_draw') + _prototype = Prototype.extend{ + on_creation = Prototype.event } } @@ -141,9 +142,7 @@ function CenterFrames._prototype:draw_frame(player) player.opened = frame end - if self.events.on_draw then - self.events.on_draw(player,frame) - end + self:raise_event('on_creation',player,frame) return frame end diff --git a/expcore/gui/left.lua b/expcore/gui/concepts/left.lua similarity index 87% rename from expcore/gui/left.lua rename to expcore/gui/concepts/left.lua index 77c67c94..d7c25263 100644 --- a/expcore/gui/left.lua +++ b/expcore/gui/concepts/left.lua @@ -49,18 +49,19 @@ LeftFrames._prototype:event_handler(action) --- Creates an event handler that will trigger one of its functions, use with Event.add ]] local Gui = require 'expcore.gui.core' -local Toolbar = require 'expcore.gui.toolbar' -local Buttons = require 'expcore.gui.buttons' +local Prototype = require 'expcore.gui.prototype' +local Toolbar = require 'expcore.gui.concepts.toolbar' +local Buttons = require 'expcore.gui.elements.buttons' local mod_gui = require 'mod-gui' local Game = require 'utils.game' local Event = require 'utils.event' local LeftFrames = { frames={}, - _prototype=Gui._prototype_factory{ - on_draw = Gui._event_factory('on_draw'), - on_update = Gui._event_factory('on_update'), - on_player_toggle = Gui._event_factory('on_player_toggle') + _prototype=Prototype.extend{ + on_creation = Prototype.event, + on_update = Prototype.event, + on_player_toggle = Prototype.event } } setmetatable(LeftFrames._prototype, { @@ -132,7 +133,6 @@ end -- @tparam string permision_name the name that can be used with the permision system -- @treturn table the new left frame define function LeftFrames.new_frame(permision_name) - local self = Toolbar.new_button(permision_name) local mt = getmetatable(self) @@ -141,11 +141,8 @@ function LeftFrames.new_frame(permision_name) self:on_click(function(player,_element) local visible = self:toggle(player) - - if self.events.on_player_toggle then - local frame = self:get_frame(player) - self.events.on_player_toggle(player,frame,visible) - end + local frame = self:get_frame(player) + self:raise_event('on_player_toggle',player,frame,visible) end) LeftFrames.frames[self.name] = self @@ -176,6 +173,34 @@ function LeftFrames._prototype:set_direction(direction) return self end +--- Creates the gui for the first time, used internally +-- @tparam LuaPlayer player the player to draw the frame to +-- @treturn LuaGuiElement the frame that was made +function LeftFrames._prototype:_internal_draw(player) + local flow = LeftFrames.get_flow(player) + local frame = flow.add{ + type='frame', + name=self.name..'-frame', + direction=self.direction + } + + self:raise_event('on_creation',player,frame) + + if not self.open_by_default then + frame.visible = false + elseif type(self.open_by_default) == 'function' then + if not self.open_by_default(player,self.name) then + frame.visible = false + end + end + + if not Toolbar.allowed(player,self.name) then + frame.visible = false + end + + return frame +end + --- Gets the frame for this define from the left frame flow -- @tparam LuaPlayer player the player to get the frame of -- @treturn LuaGuiElement the frame in the left frame flow for this define @@ -183,6 +208,8 @@ function LeftFrames._prototype:get_frame(player) local flow = LeftFrames.get_flow(player) if flow[self.name..'-frame'] and flow[self.name..'-frame'].valid then return flow[self.name..'-frame'] + else + return self:_internal_draw(player) end end @@ -208,11 +235,9 @@ end -- @tparam LuaPlayer player the player to update the frame of function LeftFrames._prototype:update(player) local frame = self:get_frame(player) - if self.events.on_update then - self.events.on_update(player,frame) - elseif self.events.on_draw then + if self:raise_event('on_update',player,frame) == 0 then frame.clear() - self.events.on_draw(player,frame) + self:raise_event('on_creation',player,frame) end end @@ -230,9 +255,7 @@ end function LeftFrames._prototype:redraw(player) local frame = self:get_frame(player) frame.clear() - if self.events.on_draw then - self.events.on_draw(player,frame) - end + self:raise_event('on_creation',player,frame) end --- Redraws the frame for all players, see redraw @@ -265,10 +288,7 @@ Buttons.new_button() for _,define in pairs(LeftFrames.frames) do local frame = LeftFrames.get_frame(define.name,player) frame.visible = false - - if define.events.on_player_toggle then - define.events.on_player_toggle(player,frame,false) - end + define:raise_event('on_player_toggle',player,frame,false) end element.visible = false end) @@ -285,28 +305,7 @@ Event.add(defines.events.on_player_created,function(event) style.font = 'default-small-bold' for _,define in pairs(LeftFrames.frames) do - local frame = flow.add{ - type='frame', - name=define.name..'-frame', - direction=define.direction - } - - if define.events.on_draw then - define.events.on_draw(player,frame) - end - - if not define.open_by_default then - frame.visible = false - elseif type(define.open_by_default) == 'function' then - if not define.open_by_default(player,define.name) then - frame.visible = false - end - end - - if not Toolbar.allowed(player,define.name) then - frame.visible = false - end - + define:_internal_draw(player) end LeftFrames.get_open(player) diff --git a/expcore/gui/popups.lua b/expcore/gui/concepts/popups.lua similarity index 94% rename from expcore/gui/popups.lua rename to expcore/gui/concepts/popups.lua index b324f0c0..91da73ed 100644 --- a/expcore/gui/popups.lua +++ b/expcore/gui/concepts/popups.lua @@ -12,10 +12,11 @@ PopupFrames._prototype:open(player,open_time,...) --- Opens this define for a player, can be given open time and any other params for the draw function ]] local Gui = require 'expcore.gui.core' +local Prototype = require 'expcore.gui.prototype' local Game = require 'utils.game' local Event = require 'utils.event' -local ProgressBar = require 'expcore.gui.progress-bar' -local Button = require 'expcore.gui.buttons' +local ProgressBar = require 'expcore.gui.elements.progress-bar' +local Button = require 'expcore.gui.elements.buttons' local mod_gui = require 'mod-gui' local Color = require 'resources.color_presets' local Global = require 'utils.global' @@ -25,8 +26,8 @@ local PopupFrames = { popup_flow_name = Gui.uid_name(), main_frame_name = Gui.uid_name(), close_frame_name = Gui.uid_name(), - _prototype = Gui._prototype_factory{ - on_draw = Gui._event_factory('on_draw') + _prototype = Prototype.extend{ + on_creation = Prototype.event } } Global.register(PopupFrames.paused_popups,function(tbl) @@ -120,20 +121,16 @@ end) -- @tparam[opt] string name the optional debug name that can be added -- @treturn table the new popup frame define function PopupFrames.new_popup(name) - local self = Gui._define_factory(PopupFrames._prototype) + local self = Gui.new_define(PopupFrames._prototype,name) self.draw_data.type = 'flow' self.draw_data.direction = 'vertical' - if name then - self:debug_name(name) - end - local mt = getmetatable(self) mt.__call = function(tbl,player,open_time,...) return tbl:open(player,open_time,...) end - self.post_draw = function(element,maximum,...) + self:on_draw(function(player,element,maximum,...) -- main content frame local frame = element.add{ type='flow', @@ -172,11 +169,8 @@ function PopupFrames.new_popup(name) close_button_style.height = 20 -- event trigger to draw the gui content - if self.events.on_draw then - local player = Game.get_player_by_index(element.player_index) - self.events.on_draw(player,frame,...) - end - end + self:raise_event('on_creation',player,frame,...) + end) return self end diff --git a/expcore/gui/toolbar.lua b/expcore/gui/concepts/toolbar.lua similarity index 95% rename from expcore/gui/toolbar.lua rename to expcore/gui/concepts/toolbar.lua index 9c83541d..ff1e0f06 100644 --- a/expcore/gui/toolbar.lua +++ b/expcore/gui/concepts/toolbar.lua @@ -14,8 +14,8 @@ Toolbar.add_button(button) --- Adds an existing buttton to the toolbar Toolbar.update(player) --- Updates the player's toolbar with an new buttons or expected change in auth return ]] -local Buttons = require 'expcore.gui.buttons' local Gui = require 'expcore.gui.core' +local Buttons = require 'expcore.gui.elements.buttons' local Roles = require 'expcore.roles' local Event = require 'utils.event' local Game = require 'utils.game' @@ -92,13 +92,13 @@ Event.add(defines.events.on_player_created,function(event) end) --- When a player gets a new role they will have the toolbar updated -Event.add(Roles.player_role_assigned,function(event) +Event.add(Roles.events.on_role_assigned,function(event) local player = Game.get_player_by_index(event.player_index) Toolbar.update(player) end) --- When a player loses a role they will have the toolbar updated -Event.add(Roles.player_role_unassigned,function(event) +Event.add(Roles.events.on_role_unassigned,function(event) local player = Game.get_player_by_index(event.player_index) Toolbar.update(player) end) diff --git a/expcore/gui/core.lua b/expcore/gui/core.lua index a3456e15..97719e96 100644 --- a/expcore/gui/core.lua +++ b/expcore/gui/core.lua @@ -16,12 +16,7 @@ Note that all event handlers will include event.player as a valid player and that if the player or the element is not valid then the callback will not be run. ->>>> Interal factory functions - There are a few factory function that are used by the class definations the use of these function are important to - know about but should only be used when making a new class deination rather than an element defination. See one of - the existing class definations for an example of when to use these. - ->>>> Basic prototype functions +>>>> Basic prototype functions (see expcore.gui.prototype) Using a class defination you can create a new element dinfation in our examples we will be using the checkbox. local checkbox_example = Gui.new_checkbox() @@ -74,14 +69,14 @@ return global.checkbox_example_allow_post_auth end) ->>>> Using store +>>>> Using store (see expcore.gui.prototype and expcore.gui.instances) A powerful assept of this gui system is allowing an automatic store for the state of a gui element, this means that when a gui is closed and re-opened the elements which have a store will retain they value even if the element was previously destroied. The store is not limited to only per player and can be catergorised by any method you want such as one that is shared between all players or by all players on a force. Using a method that is not limited to one player means that when one player changes the state of the element it will be automaticlly updated for all other player (even if the element is already drawn) and so this is a powerful and easy way to sync gui elements. - -- note the example below is the same as checkbox_example:add_store(Gui.player_store) + -- note the example below is the same as checkbox_example:add_store(Gui.categorize_by_player) checkbox_example:add_store(function(element) local player = Game.get_player_by_index(element.player_index) return player.force.name @@ -89,7 +84,7 @@ Of course this tool is not limited to only player interactions; the current satate of a define can be gotten using a number of methods and the value can even be updated by the script and have all instances of the element define be updated. When you use a category then we must give a category to the get - and set functions; in our case we used Gui.player_store which uses the player's name as the category which is why 'Cooldude2606' is given as a argument, + and set functions; in our case we used Gui.categorize_by_player which uses the player's name as the category which is why 'Cooldude2606' is given as a argument, if we did not set a function for add_store then all instances for all players have the same value and so a category is not required. checkbox_example:get_store('Cooldude2606') @@ -112,333 +107,57 @@ Gui.new_checkbox() :set_caption('Example Checkbox') :set_tooltip('Example checkbox') - :add_store(Gui.player_store) + :add_store(Gui.categorize_by_player) :on_element_update(function(player,element,value) player.print('Example checkbox is now: '..tostring(value)) end) >>>> Functions - Gui._prototype_factory(tbl) --- Used internally to create new prototypes for element defines - Gui._event_factory(name) --- Used internally to create event handler adders for element defines - Gui._store_factory(callback) --- Used internally to create store adders for element defines - Gui._sync_store_factory(callback) --- Used internally to create synced store adders for element defines - Gui._define_factory(prototype) --- Used internally to create new element defines from a class prototype - - Gui._prototype:uid() --- Gets the uid for the element define - Gui._prototype:debug_name(name) --- Sets a debug alias for the define - Gui._prototype:set_caption(caption) --- Sets the caption for the element define - Gui._prototype:set_tooltip(tooltip) --- Sets the tooltip for the element define - Gui._prototype:set_style(style,callback) --- Sets the style for the element define - Gui._prototype:set_embeded_flow(state) --- Sets the element to be drawn inside a nameless flow, can be given a name using a function - Gui._prototype:on_element_update(callback) --- Add a hander to run on the general value update event, different classes will handle this event differently - - Gui._prototype:set_pre_authenticator(callback) --- Sets an authenticator that blocks the draw function if check fails - Gui._prototype:set_post_authenticator(callback) --- Sets an authenticator that disables the element if check fails - Gui._prototype:draw_to(element) --- Draws the element using what is in the draw_data table, allows use of authenticator if present, registers new instances if store present + Gui.new_define(prototype) --- Used internally to create new element defines from a class prototype Gui.draw(name,element) --- Draws a copy of the element define to the parent element, see draw_to - Gui._prototype:add_store(categorize) --- Adds a store location for the define that will save the state of the element, categorize is a function that returns a string - Gui._prototype:add_sync_store(location,categorize) --- Adds a store location for the define that will sync between games, categorize is a function that returns a string - Gui._prototype:on_store_update(callback) --- Adds a event callback for when the store changes are other events are not gauenteted to be raised - Gui.player_store(element) --- A categorize function to be used with add_store, each player has their own value - Gui.force_store(element) --- A categorize function to be used with add_store, each force has its own value - Gui.surface_store(element) --- A categorize function to be used with add_store, each surface has its own value + Gui.categorize_by_player(element) --- A categorize function to be used with add_store, each player has their own value + Gui.categorize_by_force(element) --- A categorize function to be used with add_store, each force has its own value + Gui.categorize_by_surface(element) --- A categorize function to be used with add_store, each surface has its own value - Gui._prototype:get_store(category) --- Gets the value in this elements store, category needed if categorize function used - Gui._prototype:set_store(category,value) --- Sets the value in this elements store, category needed if categorize function used - Gui.get_store(name,category) --- Gets the value that is stored for a given element define, category needed if categorize function used - Gui.set_store(name,category,value) --- Sets the value stored for a given element define, category needed if categorize function used - - Gui.toggle_enable(element) --- Will toggle the enabled state of an element + Gui.toggle_enabled(element) --- Will toggle the enabled state of an element Gui.toggle_visible(element) --- Will toggle the visiblity of an element Gui.set_padding(element,up,down,left,right) --- Sets the padding for a gui element Gui.set_padding_style(style,up,down,left,right) --- Sets the padding for a gui style - Gui.create_right_align(element,flow_name) --- Allows the creation of a right align flow to place elements into + Gui.create_alignment(element,flow_name) --- Allows the creation of a right align flow to place elements into Gui.destory_if_valid(element) --- Destroies an element but tests for it being present and valid first + Gui.create_scroll_table(element,table_size,maximal_height,name) --- Creates a scroll area with a table inside, table can be any size + Gui.create_header(element,caption,tooltip,right_align,name) --- Creates a header section with a label and button area ]] local Gui = require 'utils.gui' local Game = require 'utils.game' -local Store = require 'expcore.store' -local Instances = require 'expcore.gui.instances' -Gui._prototype = {} -- Stores the base prototype of all element defines Gui.classes = {} -- Stores the class definations used to create element defines Gui.defines = {} -- Stores the indivdual element definations Gui.names = {} -- Stores debug names to link to gui uids ---- Used internally to create new prototypes for element defines --- @tparam table tbl table a that will have functions added to it --- @treturn table the new table with the keys added to it -function Gui._prototype_factory(tbl) - for k,v in pairs(Gui._prototype) do - if not tbl[k] then tbl[k] = v end - end - return tbl -end - ---- Used internally to create event handler adders for element defines --- @tparam string name the key that the event will be stored under, should be the same as the event name --- @treturn function the function that can be used to add an event handler -function Gui._event_factory(name) - --- Gui._prototype:on_event(callback) - --- Add a hander to run on this event, replace event with the event, different classes have different events - -- @tparam function callback the function that will be called on the event - -- callback param - player LuaPlayer - the player who owns the gui element - -- callback param - element LuaGuiElement - the element that caused the event - -- callback param - value any - (not always present) the updated value for the element - -- callback param - ... any - other class defines may add more params - -- @treturn self the element define to allow chaining - return function(self,callback) - if type(callback) ~= 'function' then - return error('Event callback must be a function',2) - end - - self.events[name] = callback - return self - end -end - ---- Used internally to create store adders for element defines --- @tparam callback a callback is called when there is an update to the stored value and stould set the state of the element --- @treturn function the function that can be used to add a store the the define -function Gui._store_factory(callback) - --- Gui._prototype:add_store(categorize) - --- Adds a store location for the define that will save the state of the element, categorize is a function that returns a string - -- @tparam[opt] function categorize if present will be called to convert an element into a category string - -- categorize param - element LuaGuiElement - the element that needs to be converted - -- categorize return - string - a determistic string that referses to a category such as player name or force name - -- @treturn self the element define to allow chaining - return function(self,categorize) - if self.store then return end - - self.store = Store.uid_location() - self.categorize = categorize - - Instances.register(self.name,self.categorize) - - Store.register(self.store,function(value,category) - if self.events.on_store_update then - self.events.on_store_update(value,category) - end - - if Instances.is_registered(self.name) then - Instances.apply_to_elements(self.name,category,function(element) - callback(self,element,value) - end) - end - end) - - return self - end -end - ---- Used internally to create synced store adders for element defines --- @tparam callback a callback is called when there is an update to the stored value and stould set the state of the element --- @treturn function the function that can be used to add a sync store the the define -function Gui._sync_store_factory(callback) - --- Gui._prototype:add_sync_store(location,categorize) - --- Adds a store location for the define that will sync between games, categorize is a function that returns a string - -- @tparam string location string a unique location, unlike add_store a uid location should not be used to avoid migration problems - -- @tparam[opt] function categorize if present will be called to convert an element into a category string - -- categorize param - element LuaGuiElement - the element that needs to be converted - -- categorize return - string - a determistic string that referses to a category such as player name or force name - -- @treturn self the element define to allow chaining - return function(self,location,categorize) - if self.store then return end - - if Store.is_registered(location) then - return error('Location for store is already registered: '..location,2) - end - - self.store = location - self.categorize = categorize - - Instances.register(self.name,self.categorize) - - Store.register(self.store,true,function(value,category) - if self.events.on_store_update then - self.events.on_store_update(value,category) - end - - if Instances.is_registered(self.name) then - Instances.apply_to_elements(self,category,function(element) - callback(self,element,value) - end) - end - end) - - return self - end -end - ---- Used internally to create new element defines from a class prototype +--- Used to create new element defines from a class prototype, please use the own given by the class -- @tparam table prototype the class prototype that will be used for the element define -- @treturn table the new element define with all functions accessed via __index metamethod -function Gui._define_factory(prototype) - local uid = Gui.uid_name() +function Gui.new_define(prototype,debug_name) + local name = Gui.uid_name() local define = setmetatable({ - name=uid, - events={}, - draw_data={ - name=uid + debug_name = debug_name, + name = name, + events = {}, + draw_data = { + name = name } },{ - __index=prototype, - __call=function(self,element,...) - return self:draw_to(element,...) + __index = prototype, + __call = function(self,...) + return self:draw_to(...) end }) Gui.defines[define.name] = define return define end ---- Gets the uid for the element define --- @treturn string the uid of this element define -function Gui._prototype:uid() - return self.name -end - ---- Sets a debug alias for the define --- @tparam string name the debug name for the element define that can be used to get this element define --- @treturn self the element define to allow chaining -function Gui._prototype:debug_name(name) - self.debug_name = name - return self -end - ---- Sets the caption for the element define --- @tparam string caption the caption that will be drawn with the element --- @treturn self the element define to allow chaining -function Gui._prototype:set_caption(caption) - self.draw_data.caption = caption - return self -end - ---- Sets the tooltip for the element define --- @tparam string tooltip the tooltip that will be displayed for this element when drawn --- @treturn self the element define to allow chaining -function Gui._prototype:set_tooltip(tooltip) - self.draw_data.tooltip = tooltip - return self -end - ---- Sets the style for the element define --- @tparam string style the style that will be used for this element when drawn --- @tparam[opt] callback function function is called when element is drawn to alter its style --- @treturn self the element define to allow chaining -function Gui._prototype:set_style(style,callback) - self.draw_data.style = style - self.events.on_style = callback - return self -end - ---- Sets the element to be drawn inside a nameless flow, can be given a name using a function --- @tparam state ?boolean|function when true a padless flow is created to contain the element --- @treturn self the element define to allow chaining -function Gui._prototype:set_embeded_flow(state) - if state == false or type(state) == 'function' then - self.embeded_flow = state - else - self.embeded_flow = true - end - return self -end - ---- Sets an authenticator that blocks the draw function if check fails --- @tparam function callback the function that will be ran to test if the element should be drawn or not --- callback param - player LuaPlayer - the player that the element is being drawn to --- callback param - define_name string - the name of the define that is being drawn --- callback return - boolean - false will stop the element from being drawn --- @treturn self the element define to allow chaining -function Gui._prototype:set_pre_authenticator(callback) - if type(callback) ~= 'function' then - return error('Pre authenticator callback must be a function') - end - - self.pre_authenticator = callback - return self -end - ---- Sets an authenticator that disables the element if check fails --- @tparam function callback the function that will be ran to test if the element should be enabled or not --- callback param - player LuaPlayer - the player that the element is being drawn to --- callback param - define_name string - the name of the define that is being drawn --- callback return - boolean - false will disable the element --- @treturn self the element define to allow chaining -function Gui._prototype:set_post_authenticator(callback) - if type(callback) ~= 'function' then - return error('Authenicater callback must be a function') - end - - self.post_authenticator = callback - return self -end - ---- Draws the element using what is in the draw_data table, allows use of authenticator if present, registers new instances if store present --- the data with in the draw_data is set up through the use of all the other functions --- @tparam LuaGuiElement element the element that the define will draw a copy of its self onto --- @treturn LuaGuiElement the new element that was drawn so styles can be applied -function Gui._prototype:draw_to(element,...) - if element[self.name] then return end - local player = Game.get_player_by_index(element.player_index) - - if self.pre_authenticator then - if not self.pre_authenticator(player,self.name) then return end - end - - if self.embeded_flow then - local embeded_name - if type(self.embeded_flow) == 'function' then - embeded_name = self.embeded_flow(element,...) - end - element = element.add{type='flow',name=embeded_name} - Gui.set_padding(element) - end - - local new_element = element.add(self.draw_data) - - if self.events.on_style then - self.events.on_style(new_element.style) - end - - if self.post_authenticator then - new_element.enabled = self.post_authenticator(player,self.name) - end - - if Instances.is_registered(self.name) then - Instances.add_element(self.name,new_element) - end - - if self.post_draw then self.post_draw(new_element,...) end - - return new_element -end - ---- Gets the value in this elements store, category needed if categorize function used --- @tparam string category[opt] the category to get such as player name or force name --- @treturn any the value that is stored for this define -function Gui._prototype:get_store(category) - if not self.store then return end - return Store.get(self.store,category) -end - ---- Sets the value in this elements store, category needed if categorize function used --- @tparam string category[opt] the category to get such as player name or force name --- @tparam any value the value to set for this define, must be valid for its type ie for checkbox etc --- @treturn boolean true if the value was set -function Gui._prototype:set_store(category,value) - if not self.store then return end - return Store.set(self.store,category,value) -end - ---- Sets the value in this elements store to nil, category needed if categorize function used --- @tparam[opt] string category the category to get such as player name or force name --- @treturn boolean true if the value was set -function Gui._prototype:clear_store(category) - if not self.store then return end - return Store.clear(self.store,category) -end - --- Gets an element define give the uid, debug name or a copy of the element define -- @tparam name ?string|table the uid, debug name or define for the element define to get -- @tparam[opt] boolean internal when true the error trace is one level higher (used internally) @@ -463,29 +182,10 @@ function Gui.get_define(name,internal) return define end ---- Gets the value that is stored for a given element define, category needed if categorize function used --- @tparam name ?string|table the uid, debug name or define for the element define to get --- @tparam[opt] string category the category to get the value for --- @treturn any the value that is stored for this define -function Gui.get_store(name,category) - local define = Gui.get_define(name,true) - return define:get_store(category) -end - ---- Sets the value stored for a given element define, category needed if categorize function used --- @tparam name ?string|table the uid, debug name or define for the element define to set --- @tparam[opt] string category the category to set the value for --- @tparam boolean any value the value to set for the define, must be valid for its type ie for a checkbox --- @treturn boolean true if the value was set -function Gui.set_store(name,category,value) - local define = Gui.get_define(name,true) - return define:get_store(category,value) -end - --- A categorize function to be used with add_store, each player has their own value -- @tparam LuaGuiElement element the element that will be converted to a string -- @treturn string the player's name who owns this element -function Gui.player_store(element) +function Gui.categorize_by_player(element) local player = Game.get_player_by_index(element.player_index) return player.name end @@ -493,7 +193,7 @@ end --- A categorize function to be used with add_store, each force has its own value -- @tparam LuaGuiElement element the element that will be converted to a string -- @treturn string the player's force name who owns this element -function Gui.force_store(element) +function Gui.categorize_by_force(element) local player = Game.get_player_by_index(element.player_index) return player.force.name end @@ -501,7 +201,7 @@ end --- A categorize function to be used with add_store, each surface has its own value -- @tparam LuaGuiElement element the element that will be converted to a string -- @treturn string the player's surface name who owns this element -function Gui.surface_store(element) +function Gui.categorize_by_surface(element) local player = Game.get_player_by_index(element.player_index) return player.surface.name end @@ -518,7 +218,7 @@ end --- Will toggle the enabled state of an element -- @tparam LuaGuiElement element the gui element to toggle -- @treturn boolean the new state that the element has -function Gui.toggle_enable(element) +function Gui.toggle_enabled(element) if not element or not element.valid then return end if not element.enabled then element.enabled = true @@ -568,20 +268,21 @@ function Gui.set_padding_style(style,up,down,left,right) style.right_padding = right or 0 end ---- Allows the creation of a right align flow to place elements into --- @tparam LuaGuiElement element the element to add this flow to, --- @tparam[opt] string flow_name the name of the flow can be nil --- @treturn LuaGuiElement the flow that was created -function Gui.create_right_align(element,flow_name) - local right_flow = - element.add{ - name=flow_name, - type='flow' - } - Gui.set_padding(right_flow,1,1,2,2) - right_flow.style.horizontal_align = 'right' - right_flow.style.horizontally_stretchable = true - return right_flow +--- Allows the creation of an alignment flow to place elements into +-- @tparam LuaGuiElement element the element to add this alignment into +-- @tparam[opt] string name the name to use for the alignment +-- @tparam[opt='right'] string horizontal_align the horizontal alignment of the elements in this flow +-- @tparam[opt='center'] string vertical_align the vertical alignment of the elements in this flow +-- @treturn LuaGuiElement the new flow that was created +function Gui.create_alignment(element,name,horizontal_align,vertical_align) + local flow = element.add{name=name,type='flow'} + local style = flow.style + Gui.set_padding(flow,1,1,2,2) + style.horizontal_align = horizontal_align or 'right' + style.vertical_align = vertical_align or 'center' + style.horizontally_stretchable =style.horizontal_align ~= 'center' + style.vertically_stretchable = style.vertical_align ~= 'center' + return flow end --- Destroies an element but tests for it being present and valid first @@ -594,4 +295,65 @@ function Gui.destory_if_valid(element) end end +--- Creates a scroll area with a table inside, table can be any size +-- @tparam LuaGuiElement element the element to add this scroll into +-- @tparam number table_size the number of columns in the table +-- @tparam number maximal_height the max hieght of the scroll +-- @tparam[opt='scroll'] string name the name of the scoll element +-- @treturn LuaGuiElement the table that was made +function Gui.create_scroll_table(element,table_size,maximal_height,name) + local list_scroll = + element.add{ + name=name or 'scroll', + type='scroll-pane', + direction='vertical', + horizontal_scroll_policy='never', + vertical_scroll_policy='auto-and-reserve-space' + } + Gui.set_padding(list_scroll,1,1,2,2) + list_scroll.style.horizontally_stretchable = true + list_scroll.style.maximal_height = maximal_height + + local list_table = + list_scroll.add{ + name='table', + type='table', + column_count=table_size + } + Gui.set_padding(list_table) + list_table.style.horizontally_stretchable = true + list_table.style.vertical_align = 'center' + list_table.style.cell_padding = 0 + + return list_table +end + +--- Creates a header section with a label and button area +-- @tparam LuaGuiElement element the element to add this header into +-- @tparam localeString caption the caption that is used as the title +-- @tparam[opt] localeString tooltip the tooltip that is shown on the caption +-- @tparam[opt] boolean right_align when true will include the right align area +-- @tparam[opt='header'] string name the name of the header area +-- @treturn LuaGuiElement the header that was made, or the align area if that was created +function Gui.create_header(element,caption,tooltip,right_align,name) + local header = + element.add{ + name=name or 'header', + type='frame', + style='subheader_frame' + } + Gui.set_padding(header,2,2,4,4) + header.style.horizontally_stretchable = true + header.style.use_header_filler = false + + header.add{ + type='label', + style='heading_1_label', + caption=caption, + tooltip=tooltip + } + + return right_align and Gui.create_alignment(header,'header-align') or header +end + return Gui \ No newline at end of file diff --git a/expcore/gui/buttons.lua b/expcore/gui/elements/buttons.lua similarity index 85% rename from expcore/gui/buttons.lua rename to expcore/gui/elements/buttons.lua index 9a5d794b..66aa957e 100644 --- a/expcore/gui/buttons.lua +++ b/expcore/gui/elements/buttons.lua @@ -15,12 +15,14 @@ ]] local mod_gui = require 'mod-gui' local Gui = require 'expcore.gui.core' +local Prototype = require 'expcore.gui.prototype' local Button = { - _prototype=Gui._prototype_factory{ - on_click = Gui._event_factory('on_click'), - on_left_click = Gui._event_factory('on_left_click'), - on_right_click = Gui._event_factory('on_right_click'), + _prototype=Prototype.extend{ + on_raw_click = Prototype.event, + on_click = Prototype.event, + on_left_click = Prototype.event, + on_right_click = Prototype.event, } } @@ -29,27 +31,26 @@ local Button = { -- @treturn table the new button element define function Button.new_button(name) - local self = Gui._define_factory(Button._prototype) + local self = Gui.new_define(Button._prototype,name) self.draw_data.type = 'button' self.draw_data.style = mod_gui.button_style - if name then - self:debug_name(name) - end - Gui.on_click(self.name,function(event) local mouse_button = event.button local keys = {alt=event.alt,control=event.control,shift=event.shift} + local player,element = event.player,event.element event.keys = keys + self:raise_event('on_raw_click',event) + if self.post_authenticator then if not self.post_authenticator(event.player,self.name) then return end end - if mouse_button == defines.mouse_button_type.left and self.events.on_left_click then - self.events.on_left_click(event.player,event.element) + if mouse_button == defines.mouse_button_type.left then + self:raise_event('on_left_click',player,element) elseif mouse_button == defines.mouse_button_type.right and self.events.on_right_click then - self.events.on_right_click(event.player,event.element) + self:raise_event('on_right_click',player,element) end if self.mouse_button_filter and not self.mouse_button_filter[mouse_button] then return end @@ -59,9 +60,7 @@ function Button.new_button(name) end end - if self.events.on_click then - self.events.on_click(event.player,event.element,event) - end + self:raise_event('on_click',player,element) end) return self diff --git a/expcore/gui/checkboxs.lua b/expcore/gui/elements/checkboxs.lua similarity index 87% rename from expcore/gui/checkboxs.lua rename to expcore/gui/elements/checkboxs.lua index 02769360..0b68952a 100644 --- a/expcore/gui/checkboxs.lua +++ b/expcore/gui/elements/checkboxs.lua @@ -10,7 +10,7 @@ local example_option_set = Gui.new_option_set('example-option-set',function(value,category) game.print('Example options set '..category..' is now: '..tostring(value)) - end,Gui.player_store) + end,Gui.categorize_by_player) Then you must register some radiobutton defines and include them in the option set: @@ -46,43 +46,34 @@ Other functions present from expcore.gui.core ]] local Gui = require 'expcore.gui.core' +local Prototype = require 'expcore.gui.prototype' local Store = require 'expcore.store' local Game = require 'utils.game' ---- Event call for on_checked_state_changed and store update --- @tparam table define the define that this is acting on --- @tparam LuaGuiElement element the element that triggered the event --- @tparam boolean value the new state of the checkbox -local function event_call(define,element,value) - if define.events.on_element_update then - local player = Game.get_player_by_index(element.player_index) - define.events.on_element_update(player,element,value) - end -end - --- Store call for store update -- @tparam table define the define that this is acting on -- @tparam LuaGuiElement element the element that triggered the event -- @tparam boolean value the new state of the checkbox -local function store_call(define,element,value) +local function store_update(define,element,value) element.state = value - event_call(define,element,value) + local player = Game.get_player_by_index(element.player_index) + define:raise_event('on_element_update',player,element,value) end local Checkbox = { option_sets={}, option_categorize={}, - _prototype_checkbox=Gui._prototype_factory{ - on_element_update = Gui._event_factory('on_element_update'), - on_store_update = Gui._event_factory('on_store_update'), - add_store = Gui._store_factory(store_call), - add_sync_store = Gui._sync_store_factory(store_call) + _prototype_checkbox=Prototype.extend{ + on_element_update = Prototype.event, + on_store_update = Prototype.event, + add_store = Prototype.store(false,store_update), + add_sync_store = Prototype.store(true,store_update) }, - _prototype_radiobutton=Gui._prototype_factory{ - on_element_update = Gui._event_factory('on_element_update'), - on_store_update = Gui._event_factory('on_store_update'), - add_store = Gui._store_factory(store_call), - add_sync_store = Gui._sync_store_factory(store_call) + _prototype_radiobutton=Prototype.extend{ + on_element_update = Prototype.event, + on_store_update = Prototype.event, + add_store = Prototype.store(false,store_update), + add_sync_store = Prototype.store(true,store_update) } } @@ -91,21 +82,17 @@ local Checkbox = { -- @treturn table the new checkbox element define function Checkbox.new_checkbox(name) - local self = Gui._define_factory(Checkbox._prototype_checkbox) + local self = Gui.new_define(Checkbox._prototype_checkbox,name) self.draw_data.type = 'checkbox' self.draw_data.state = false - if name then - self:debug_name(name) - end - - self.post_draw = function(element) + self:on_draw(function(player,element) if self.store then local category = self.categorize and self.categorize(element) or nil local state = self:get_store(category,true) if state then element.state = true end end - end + end) Gui.on_checked_state_changed(self.name,function(event) local element = event.element @@ -121,8 +108,7 @@ function Checkbox.new_checkbox(name) self:set_store(category,value) else - local value = element.state - event_call(self,element,value) + self:raise_event('on_element_update',event.player,element,element.state) end end) diff --git a/expcore/gui/dropdown.lua b/expcore/gui/elements/dropdown.lua similarity index 85% rename from expcore/gui/dropdown.lua rename to expcore/gui/elements/dropdown.lua index 8d976162..847492f5 100644 --- a/expcore/gui/dropdown.lua +++ b/expcore/gui/elements/dropdown.lua @@ -17,40 +17,30 @@ Other functions present from expcore.gui.core ]] local Gui = require 'expcore.gui.core' +local Prototype = require 'expcore.gui.prototype' local Game = require 'utils.game' ---- Event call for on_selection_state_changed and store update +local select_value +--- Store call for store update -- @tparam table define the define that this is acting on -- @tparam LuaGuiElement element the element that triggered the event -- @tparam string value the new option for the dropdown -local function event_call(define,element,value) +local function store_update(define,element,value) + select_value(element,value) local player = Game.get_player_by_index(element.player_index) - - if define.events.on_element_update then - define.events.on_element_update(player,element,value) - end + define:raise_event('on_element_update',player,element,value) if define.option_callbacks and define.option_callbacks[value] then define.option_callbacks[value](player,element,value) end end -local _select_value ---- Store call for store update --- @tparam table define the define that this is acting on --- @tparam LuaGuiElement element the element that triggered the event --- @tparam string value the new option for the dropdown -local function store_call(define,element,value) - _select_value(element,value) - event_call(define,element,value) -end - local Dropdown = { - _prototype=Gui._prototype_factory{ - on_element_update = Gui._event_factory('on_element_update'), - on_store_update = Gui._event_factory('on_store_update'), - add_store = Gui._store_factory(store_call), - add_sync_store = Gui._sync_store_factory(store_call) + _prototype=Prototype.extend{ + on_element_update = Prototype.event, + on_store_update = Prototype.event, + add_store = Prototype.store(false,store_update), + add_sync_store = Prototype.store(true,store_update) } } @@ -59,16 +49,11 @@ local Dropdown = { -- @treturn table the new dropdown element define function Dropdown.new_dropdown(name) - local self = Gui._define_factory(Dropdown._prototype) + local self = Gui.new_define(Dropdown._prototype,name) self.draw_data.type = 'drop-down' - if name then - self:debug_name(name) - end - - self.post_draw = function(element) + self:on_draw(function(player,element) if self.dynamic_options then - local player = Game.get_player_by_index(element.player_index) local dynamic_options = self.dynamic_options(player,element) local items = element.items for _,v in pairs(dynamic_options) do @@ -82,7 +67,7 @@ function Dropdown.new_dropdown(name) local value = self:get_store(category) if value then Dropdown.select_value(element,value) end end - end + end) Gui.on_selection_state_changed(self.name,function(event) local element = event.element @@ -93,7 +78,12 @@ function Dropdown.new_dropdown(name) self:set_store(category,value) else - event_call(self,element,value) + local player = event.player + local option_callbacks = self.option_callbacks + self:raise_event('on_element_update',player,element,value) + if option_callbacks and option_callbacks[value] then + option_callbacks[value](player,element,value) + end end @@ -176,7 +166,7 @@ function Dropdown.select_value(element,value) end end end -_select_value = Dropdown.select_value +select_value = Dropdown.select_value --- Returns the currently selected value rather than index -- @tparam LuaGuiElement element the gui element that you want to get the value of diff --git a/expcore/gui/elem-button.lua b/expcore/gui/elements/elem-button.lua similarity index 70% rename from expcore/gui/elem-button.lua rename to expcore/gui/elements/elem-button.lua index b20cae59..c70c1aa6 100644 --- a/expcore/gui/elem-button.lua +++ b/expcore/gui/elements/elem-button.lua @@ -12,36 +12,25 @@ Other functions present from expcore.gui.core ]] local Gui = require 'expcore.gui.core' +local Prototype = require 'expcore.gui.prototype' local Game = require 'utils.game' ---- Event call for on_elem_changed and store update --- @tparam table define the define that this is acting on --- @tparam LuaGuiElement element the element that triggered the event --- @tparam string value the new value for the elem button -local function event_call(define,element,value) - local player = Game.get_player_by_index(element.player_index) - - if define.events.on_element_update then - define.events.on_element_update(player,element,value) - end - -end - --- Store call for store update -- @tparam table define the define that this is acting on -- @tparam LuaGuiElement element the element that triggered the event -- @tparam string value the new value for the elem button -local function store_call(define,element,value) +local function store_update(define,element,value) element.elem_value = value - event_call(define,element,value) + local player = Game.get_player_by_index(element.player_index) + define:raise_event('on_element_update',player,element,value) end local ElemButton = { - _prototype=Gui._prototype_factory{ - on_element_update = Gui._event_factory('on_element_update'), - on_store_update = Gui._event_factory('on_store_update'), - add_store = Gui._store_factory(store_call), - add_sync_store = Gui._sync_store_factory(store_call) + _prototype=Prototype.extend{ + on_element_update = Prototype.event, + on_store_update = Prototype.event, + add_store = Prototype.store(false,store_update), + add_sync_store = Prototype.store(true,store_update) } } @@ -50,16 +39,10 @@ local ElemButton = { -- @treturn table the new elem button element define function ElemButton.new_elem_button(name) - local self = Gui._define_factory(ElemButton._prototype) + local self = Gui.new_define(ElemButton._prototype,name) self.draw_data.type = 'choose-elem-button' - if name then - self:debug_name(name) - end - - self.post_draw = function(element) - local player = Game.get_player_by_index(element.player_index) - + self:on_draw(function(player,element) if type(self.default) == 'function' then element.elem_value = self.default(player,element) end @@ -69,7 +52,7 @@ function ElemButton.new_elem_button(name) local value = self:get_store(category) if value then element.elem_value = value end end - end + end) Gui.on_elem_changed(self.name,function(event) local element = event.element @@ -80,7 +63,7 @@ function ElemButton.new_elem_button(name) self:set_store(category,value) else - event_call(self,element,value) + self:raise_event('on_element_update',event.player,element,value) end @@ -92,10 +75,7 @@ end --- Sets the type of the elem button, the type is required so this must be called at least once -- @tparam string type the type that this elem button is see factorio api -- @treturn the element define to allow for chaining -function ElemButton._prototype:set_type(type) - self.draw_data.elem_type = type - return self -end +ElemButton._prototype.set_type = Prototype.setter('string','draw_data','elem_type') --- Sets the default value for the elem button, this may be a function or a string -- @tparam ?string|function value string a will be a static default and a function will be called when drawn to get the default diff --git a/expcore/gui/progress-bar.lua b/expcore/gui/elements/progress-bar.lua similarity index 93% rename from expcore/gui/progress-bar.lua rename to expcore/gui/elements/progress-bar.lua index 2200019d..020ab2a3 100644 --- a/expcore/gui/progress-bar.lua +++ b/expcore/gui/elements/progress-bar.lua @@ -21,6 +21,7 @@ ProgressBar._prototype:event_countdown(filter) --- Event handler factory that counts down by 1 every time the event triggeres, can filter which elements are decremented ]] local Gui = require 'expcore.gui.core' +local Prototype = require 'expcore.gui.prototype' local Global = require 'utils.global' local Game = require 'utils.game' @@ -29,20 +30,17 @@ local Game = require 'utils.game' -- @tparam LuaGuiElement element the element that triggered the event local function event_call(define,element) local player = Game.get_player_by_index(element.player_index) - - if define.events.on_complete then - define.events.on_complete(player,element,function() - define:add_element(element) - define:reset_element(element) - end) - end + define:raise_event('on_complete',player,element,function() + define:add_element(element) + define:reset_element(element) + end) end --- Store call for store update -- @tparam table define the define that this is acting on -- @tparam LuaGuiElement element the element that triggered the event -- @tparam number value the new value for the progress bar -local function store_call(define,element,value) +local function store_update(define,element,value) if value then element.value = value if define.count_down and value <= 0 @@ -55,14 +53,14 @@ end local ProgressBar = { unregistered={}, -- elements with no callbacks independent={}, -- elements with a link to a deinfe - _prototype=Gui._prototype_factory{ - -- note both events will recive a reset function that can be used to reset the progress of the element/store - on_complete = Gui._event_factory('on_complete'), - on_store_complete = Gui._event_factory('on_store_complete'), - add_store = Gui._store_factory(store_call), - add_sync_store = Gui._sync_store_factory(store_call) + _prototype=Prototype.extend{ + on_complete = Prototype.event, + on_store_complete = Prototype.event, + add_store = Prototype.store(false,store_update), + add_sync_store = Prototype.store(true,store_update) } } + Global.register({ unregistered = ProgressBar.unregistered, independent = ProgressBar.independent @@ -182,14 +180,11 @@ end -- @tparam[opt] string name the optional debug name that can be added -- @treturn table the new progressbar elemente define function ProgressBar.new_progressbar(name) - local self = Gui._define_factory(ProgressBar._prototype) + + local self = Gui.new_define(ProgressBar._prototype,name) self.draw_data.type = 'progressbar' - if name then - self:debug_name(name) - end - - self.post_draw = function(element,maximum) + self:on_draw(function(player,element,maximum) if self.store then local category = self.categorize and self.categorize(element) or nil local value = self:get_store(category) @@ -215,7 +210,7 @@ function ProgressBar.new_progressbar(name) end - end + end) return self end @@ -263,11 +258,7 @@ local function change_value_prototype(self,amount,category,filter) if self.count_down and new_value <= 0 or not self.count_down and new_value >= 1 then self:clear_store(category) - - if self.events.on_store_complete then - self.events.on_store_complete(category,reset_store) - end - + self:raise_event('on_store_complete',category,reset_store) return end diff --git a/expcore/gui/slider.lua b/expcore/gui/elements/slider.lua similarity index 82% rename from expcore/gui/slider.lua rename to expcore/gui/elements/slider.lua index f8bdef5e..abd34f29 100644 --- a/expcore/gui/slider.lua +++ b/expcore/gui/elements/slider.lua @@ -6,7 +6,6 @@ Slider._prototype:on_element_update(callback) --- Registers a handler for when an element instance updates Slider._prototype:on_store_update(callback) --- Registers a handler for when the stored value updates - Slider._prototype:use_notches(state) --- Adds notches to the slider Slider._prototype:set_range(min,max) --- Sets the range of a slider, if not used will use default values for a slider Slider._prototype:draw_label(element) --- Draws a new label and links its value to the value of this slider, if no store then it will only show one value per player Slider._prototype:enable_auto_draw_label(state) --- Enables auto draw of the label, the label will share the same parent element as the slider @@ -14,6 +13,7 @@ Other functions present from expcore.gui.core ]] local Gui = require 'expcore.gui.core' +local Prototype = require 'expcore.gui.prototype' local Instances = require 'expcore.gui.instances' local Game = require 'utils.game' @@ -28,9 +28,7 @@ local function event_call(define,element,value) local delta = max-min local percent = delta == 0 and 0 or (value-min)/delta - if define.events.on_element_update then - define.events.on_element_update(player,element,value,percent) - end + define:raise_event('on_element_update',player,element,value,percent) local category = player.name if define.categorize then @@ -46,17 +44,17 @@ end -- @tparam table define the define that this is acting on -- @tparam LuaGuiElement element the element that triggered the event -- @tparam number value the new value for the slider -local function store_call(define,element,value) +local function store_update(define,element,value) element.slider_value = value event_call(define,element,value) end local Slider = { - _prototype=Gui._prototype_factory{ - on_element_update = Gui._event_factory('on_element_update'), - on_store_update = Gui._event_factory('on_store_update'), - add_store = Gui._store_factory(store_call), - add_sync_store = Gui._sync_store_factory(store_call) + _prototype=Prototype.extend{ + on_element_update = Prototype.event, + on_store_update = Prototype.event, + add_store = Prototype.store(false,store_update), + add_sync_store = Prototype.store(true,store_update) } } @@ -65,15 +63,10 @@ local Slider = { -- @treturn table the new slider element define function Slider.new_slider(name) - local self = Gui._define_factory(Slider._prototype) + local self = Gui.new_define(Slider._prototype,name) self.draw_data.type = 'slider' - if name then - self:debug_name(name) - end - - self.post_draw = function(element) - local player = Game.get_player_by_index(element.player_index) + self:on_draw(function(player,element) local min,max = element.get_slider_minimum(),element.get_slider_maximum() if type(self.min) == 'function' then @@ -95,7 +88,7 @@ function Slider.new_slider(name) if self.auto_label then self:draw_label(element.parent) end - end + end) Gui.on_value_changed(self.name,function(event) local element = event.element @@ -115,17 +108,6 @@ function Slider.new_slider(name) return self end ---- Adds notches to the slider --- @tparam[opt] boolean state when true will draw notches onto the slider -function Slider._prototype:use_notches(state) - if state == false then - self.draw_data.style = nil - else - self.draw_data.style = 'notched_slider' - end - return self -end - --- Sets the range of a slider, if not used will use default values for a slider -- @tparam[opt] number min the minimum value that the slider can take -- @tparam[opt] number max the maximum value that the slider can take @@ -164,7 +146,7 @@ function Slider._prototype:draw_label(element) caption=tostring(math.round(value,2)) } - local categorise = self.categorise or Gui.player_store + local categorise = self.categorise or Gui.categorize_by_player local category = categorise(new_element) Instances.unregistered_add_element(name,category,new_element) diff --git a/expcore/gui/text.lua b/expcore/gui/elements/text.lua similarity index 75% rename from expcore/gui/text.lua rename to expcore/gui/elements/text.lua index 4fb5b43f..0c38895a 100644 --- a/expcore/gui/text.lua +++ b/expcore/gui/elements/text.lua @@ -15,42 +15,31 @@ Other functions present from expcore.gui.core ]] local Gui = require 'expcore.gui.core' +local Prototype = require 'expcore.gui.prototype' local Game = require 'utils.game' ---- Event call for on_text_changed and store update --- @tparam table define the define that this is acting on --- @tparam LuaGuiElement element the element that triggered the event --- @tparam string value the new text for the text field -local function event_call(define,element,value) - local player = Game.get_player_by_index(element.player_index) - - if define.events.on_element_update then - define.events.on_element_update(player,element,value) - end - -end - --- Store call for store update -- @tparam table define the define that this is acting on -- @tparam LuaGuiElement element the element that triggered the event -- @tparam string value the new text for the text field -local function store_call(define,element,value) +local function store_update(define,element,value) element.text = value - event_call(define,element,value) + local player = Game.get_player_by_index(element.player_index) + define:raise_event('on_element_update',player,element,value) end local Text = { - _prototype_field=Gui._prototype_factory{ - on_element_update = Gui._event_factory('on_element_update'), - on_store_update = Gui._event_factory('on_store_update'), - add_store = Gui._store_factory(store_call), - add_sync_store = Gui._sync_store_factory(store_call) + _prototype_field=Prototype.extend{ + on_element_update = Prototype.event, + on_store_update = Prototype.event, + add_store = Prototype.store(false,store_update), + add_sync_store = Prototype.store(true,store_update) }, - _prototype_box=Gui._prototype_factory{ - on_element_update = Gui._event_factory('on_element_update'), - on_store_update = Gui._event_factory('on_store_update'), - add_store = Gui._store_factory(store_call), - add_sync_store = Gui._sync_store_factory(store_call) + _prototype_box=Prototype.extend{ + on_element_update = Prototype.event, + on_store_update = Prototype.event, + add_store = Prototype.store(false,store_update), + add_sync_store = Prototype.store(true,store_update) } } @@ -59,14 +48,10 @@ local Text = { -- @treturn table the new text field element define function Text.new_text_field(name) - local self = Gui._define_factory(Text._prototype_field) + local self = Gui.new_define(Text._prototype_field,name) self.draw_data.type = 'textfield' - if name then - self:debug_name(name) - end - - self.post_draw = function(element) + self:on_draw(function(player,element) if self.selectable then element.selectable = true end @@ -84,7 +69,7 @@ function Text.new_text_field(name) local value = self:get_store(category) if value then element.text = value end end - end + end) Gui.on_text_changed(self.name,function(event) local element = event.element @@ -95,7 +80,7 @@ function Text.new_text_field(name) self:set_store(category,value) else - event_call(self,element,value) + self:raise_event('on_element_update',event.player,element,value) end diff --git a/expcore/gui/instances.lua b/expcore/gui/instances.lua index 1bb502b9..cd3616d8 100644 --- a/expcore/gui/instances.lua +++ b/expcore/gui/instances.lua @@ -12,7 +12,7 @@ -- categorise works in the same way as store categorise -- so the function will worl here but no value is stored only gui elements - Instances.register('score',Gui.force_store) + Instances.register('score',Gui.categorize_by_force) Then when you draw the new element to a gui you will want to add the element to the group: @@ -38,7 +38,7 @@ instance group would work when registered vs unregistered: -- Registered with category - Instances.register('score',Gui.force_store) -- force_store will return the force name of an element + Instances.register('score',Gui.categorize_by_force) -- force_store will return the force name of an element Instances.add_element('score',new_element) -- the new element is added to the category based on in force Instances.apply_to_elements('score','player',function(element) element.caption = '0' diff --git a/expcore/gui/prototype.lua b/expcore/gui/prototype.lua new file mode 100644 index 00000000..bec61e8d --- /dev/null +++ b/expcore/gui/prototype.lua @@ -0,0 +1,303 @@ +--- Used to create new gui prototypes see elements and concepts +--[[ + >>>> Functions + Constructor.event(event_name) --- Creates a new function to add functions to an event handler + Constructor.extend(new_prototype) --- Extents a prototype with the base functions of all gui prototypes, no metatables + Constructor.store(sync,callback) --- Creates a new function which adds a store to a gui define + Constructor.setter(value_type,key,second_key) --- Creates a setter function that checks the type when a value is set + + Prototype:uid() --- Gets the uid for the element define + Prototype:debug_name(value) --- Sets a debug alias for the define + Prototype:set_caption(value) --- Sets the caption for the element define + Prototype:set_tooltip(value) --- Sets the tooltip for the element define + Prototype:set_style(style,callback) --- Sets the style for the element define + Prototype:set_embeded_flow(state) --- Sets the element to be drawn inside a nameless flow, can be given a name using a function + + Prototype:set_pre_authenticator --- Sets an authenticator that blocks the draw function if check fails + Prototype:set_post_authenticator --- Sets an authenticator that disables the element if check fails + + Prototype:raise_event(event_name,...) --- Raises a custom event for this define, any number of params can be given + Prototype:draw_to(element,...) --- The main function for defines, when called will draw an instance of this define to the given element + + Prototype:get_store(category) --- Gets the value in this elements store, category needed if categorize function used + Prototype:set_store(category,value) --- Sets the value in this elements store, category needed if categorize function used + Prototype:clear_store(category) --- Sets the value in this elements store to nil, category needed if categorize function used +]] +local Game = require 'utils.game' +local Store = require 'expcore.store' +local Instances = require 'expcore.gui.instances' + +local Constructor = {} +local Prototype = {} + +--- Creates a new function to add functions to an event handler +-- @tparam string event_name the name of the event that callbacks will be added to +-- @treturn function the function used to register handlers +function Constructor.event(event_name) + --- Adds a callback as a handler for an event + -- @tparam table self the gui define being acted on + -- @tparam function callback the function that will be added as a handler for the event + -- @treturn table self returned to allowing chaining of functions + return function(self,callback) + if type(callback) ~= 'function' then + return error('Event callback for '..event_name..' must be a function',2) + end + + local handlers = self.events[event_name] + if not handlers then + handlers = {} + self.events[event_name] = handlers + end + + handlers[#handlers+1] = callback + return self + end +end + +--- Extents a prototype with the base functions of all gui prototypes, no metatables +-- @tparam table new_prototype the prototype that you want to add the functions to +-- @treturn table the same prototype but with the new functions added +function Constructor.extend(new_prototype) + for key,value in pairs(Prototype) do + if type(value) == 'table' then + new_prototype[key] = table.deepcopy(value) + else + new_prototype[key] = value + end + end + for key,value in pairs(new_prototype) do + if value == Constructor.event then + new_prototype[key] = Constructor.event(key) + end + end + return new_prototype +end + +--- Creates a new function which adds a store to a gui define +-- @tparam boolean sync if the function should create a synced store +-- @tparam function callback the function called when needing to update the value of an element +-- @treturn function the function that will add a store for this define +function Constructor.store(sync,callback) + --- Adds a store for the define that is shared between all instances of the define in the same category, categorize is a function that returns a string + -- @tparam self table the gui define being acted on + -- @tparam[opt] string location a unique location identifier, when omited a uid location will be used, use when sync is set to true + -- @tparam[opt] function categorize function used to determine the category of a LuaGuiElement, when omited all share one single category + -- categorize param - LuaGuiElement element - the element that needs to be converted + -- categorize return - string - a determistic string that referses to a category such as player name or force name + -- @treturn self the element define to allow chaining + return function(self,location,categorize) + if self.store then return end + + if not sync then + categorize = location + location = Store.uid_location() + end + + if Store.is_registered(location) then + return error('Location for store is already registered: '..location,2) + end + + self.store = location + self.categorize = categorize + + Instances.register(self.name,self.categorize) + + Store.register(self.store,sync,function(value,category) + self:raise_event('on_store_update',value,category) + + if Instances.is_registered(self.name) then + Instances.apply_to_elements(self.name,category,function(element) + callback(self,element,value) + end) + end + end) + + return self + end +end + +--- Creates a setter function that checks the type when a value is set +-- @tparam string value_type the type that the value should be when it is set +-- @tparam string key the key of the define that will be set +-- @tparam[opt] string second_key allows for setting of a key in a sub table +-- @treturn function the function that will check the type and set the value +function Constructor.setter(value_type,key,second_key) + local display_message = 'Gui define '..key..' must be of type '..value_type + if second_key then + display_message = 'Gui define '..second_key..' must be of type '..value_type + end + + local locale = false + if value_type == 'locale-string' then + locale = true + value_type = 'table' + end + + return function(self,value) + local vtype = type(value) + if vtype ~= value_type and (not locale or vtype ~= 'string') then + error(display_message,2) + end + + if second_key then + self[key][second_key] = value + else + self[key] = value + end + + return self + end +end + +--- Gets the uid for the element define +-- @treturn string the uid of this element define +function Prototype:uid() + return self.name +end + +--- Sets a debug alias for the define +-- @tparam string name the debug name for the element define that can be used to get this element define +-- @treturn self the element define to allow chaining +Prototype.debug_name = Constructor.setter('string','debug_name') + +--- Sets the caption for the element define +-- @tparam string caption the caption that will be drawn with the element +-- @treturn self the element define to allow chaining +Prototype.set_caption = Constructor.setter('locale-string','draw_data','caption') + +--- Sets the tooltip for the element define +-- @tparam string tooltip the tooltip that will be displayed for this element when drawn +-- @treturn self the element define to allow chaining +Prototype.set_tooltip = Constructor.setter('locale-string','draw_data','tooltip') + +--- Sets an authenticator that blocks the draw function if check fails +-- @tparam function callback the function that will be ran to test if the element should be drawn or not +-- callback param - LuaPlayer player - the player that the element is being drawn to +-- callback param - string define_name - the name of the define that is being drawn +-- callback return - boolean - false will stop the element from being drawn +-- @treturn self the element define to allow chaining +Prototype.set_pre_authenticator = Constructor.setter('function','pre_authenticator') + +--- Sets an authenticator that disables the element if check fails +-- @tparam function callback the function that will be ran to test if the element should be enabled or not +-- callback param - LuaPlayer player - the player that the element is being drawn to +-- callback param - string define_name - the name of the define that is being drawn +-- callback return - boolean - false will disable the element +-- @treturn self the element define to allow chaining +Prototype.set_post_authenticator = Constructor.setter('function','post_authenticator') + +--- Registers a callback to the on_draw event +-- @tparam function callback +-- callback param - LuaPlayer player - the player that the element was drawn to +-- callback param - LuaGuiElement element - the element that was drawn +-- callback param - any ... - any other params passed by the draw_to function +Prototype.on_draw = Constructor.event('on_draw') + +--- Registers a callback to the on_style_update event +-- @tparam function callback +-- callback param - LuaStyle style - the style that was changed and/or needs changing +Prototype.on_style_update = Constructor.event('on_style_update') + +--- Sets the style for the element define +-- @tparam string style the style that will be used for this element when drawn +-- @tparam[opt] callback function function is called when element is drawn to alter its style +-- @treturn self the element define to allow chaining +function Prototype:set_style(style,callback) + self.draw_data.style = style + if callback then + self:on_style_update(callback) + end + return self +end + +--- Sets the element to be drawn inside a nameless flow, can be given a name using a function +-- @tparam state ?boolean|function when true a padless flow is created to contain the element +-- @treturn self the element define to allow chaining +function Prototype:set_embeded_flow(state) + if state == false or type(state) == 'function' then + self.embeded_flow = state + else + self.embeded_flow = true + end + return self +end + +--- Raises a custom event for this define, any number of params can be given +-- @tparam string event_name the name of the event that you want to raise +-- @tparam any ... any params that you want to pass to the event +-- @treturn number the number of handlers that were registered +function Prototype:raise_event(event_name,...) + local handlers = self.events[event_name] + if handlers then + for _,handler in pairs(handlers) do + handler(...) + end + end + return handlers and #handlers or 0 +end + +--- The main function for defines, when called will draw an instance of this define to the given element +-- what is drawn is based on the data in draw_data which is set using other functions +-- @tparam LuaGuiElement element the element that the define will draw a instance of its self onto +-- @treturn LuaGuiElement the new element that was drawn +function Prototype:draw_to(element,...) + local name = self.name + if element[name] then return end + local player = Game.get_player_by_index(element.player_index) + + if self.pre_authenticator then + if not self.pre_authenticator(player,self.name) then return end + end + + if self.embeded_flow then + local embeded_name + if type(self.embeded_flow) == 'function' then + embeded_name = self.embeded_flow(element,...) + end + element = element.add{type='flow',name=embeded_name} + element.style.padding = 0 + end + + local new_element = element.add(self.draw_data) + + self:raise_event('on_style_update',new_element.style) + + if self.post_authenticator then + new_element.enabled = self.post_authenticator(player,self.name) + end + + if Instances.is_registered(self.name) then + Instances.add_element(self.name,new_element) + end + + self:raise_event('on_draw',player,new_element) + + return new_element +end + +--- Gets the value in this elements store, category needed if categorize function used +-- @tparam string category[opt] the category to get such as player name or force name +-- @treturn any the value that is stored for this define +function Prototype:get_store(category) + if not self.store then return end + return Store.get(self.store,category) +end + +--- Sets the value in this elements store, category needed if categorize function used +-- @tparam string category[opt] the category to get such as player name or force name +-- @tparam any value the value to set for this define, must be valid for its type ie for checkbox etc +-- @treturn boolean true if the value was set +function Prototype:set_store(category,value) + if not self.store then return end + return Store.set(self.store,category,value) +end + +--- Sets the value in this elements store to nil, category needed if categorize function used +-- @tparam[opt] string category the category to get such as player name or force name +-- @treturn boolean true if the value was set +function Prototype:clear_store(category) + if not self.store then return end + return Store.clear(self.store,category) +end + +return Constructor \ No newline at end of file diff --git a/expcore/gui/test.lua b/expcore/gui/test.lua index ec4a77a2..ed6545dd 100644 --- a/expcore/gui/test.lua +++ b/expcore/gui/test.lua @@ -55,7 +55,7 @@ Gui.new_center_frame('gui-test-open') return global.show_test_gui end) -:on_draw(function(player,frame) +:on_creation(function(player,frame) for test_group_name,test_group in pairs(tests) do player.print('Starting tests for: '..format_chat_colour(test_group_name,Colors.cyan)) @@ -106,7 +106,7 @@ Gui.new_left_frame('test-left-frame') end) :set_open_by_default() -:on_draw(function(_player,frame) +:on_creation(function(_player,frame) for _,player in pairs(game.connected_players) do frame.add{ type='label', @@ -125,7 +125,7 @@ Event.add(defines.events.on_player_left_game,left_frame 'update_all') local test_popup = Gui.new_popup('test-popup') -:on_draw(function(player,frame) +:on_creation(function(player,frame) frame.add{ type='label', caption=player.name @@ -225,7 +225,7 @@ local checkbox_force = Gui.new_checkbox('test-checkbox-store-force') :set_tooltip('Checkboc store force') :set_caption('Checkbox Store Force') -:add_store(Gui.force_store) +:add_store(Gui.categorize_by_force) :on_element_update(function(player,element,state) player.print('Checkbox store force: '..tostring(state)) end) @@ -234,7 +234,7 @@ local checkbox_player = Gui.new_checkbox('test-checkbox-store-player') :set_tooltip('Checkbox store player') :set_caption('Checkbox Store Player') -:add_store(Gui.player_store) +:add_store(Gui.categorize_by_player) :on_element_update(function(player,element,state) player.print('Checkbox store player: '..tostring(state)) end) @@ -265,7 +265,7 @@ local radiobutton_player = Gui.new_radiobutton('test-radiobutton-store') :set_tooltip('Radiobutton store') :set_caption('Radiobutton Store') -:add_store(Gui.player_store) +:add_store(Gui.categorize_by_player) :on_element_update(function(player,element,state) player.print('Radiobutton store: '..tostring(state)) end) @@ -273,7 +273,7 @@ end) local radiobutton_option_set = Gui.new_radiobutton_option_set('gui.test.share',function(value,category) game.print('Radiobutton option set for: '..category..' is now: '..tostring(value)) -end,Gui.player_store) +end,Gui.categorize_by_player) local radiobutton_option_one = Gui.new_radiobutton('test-radiobutton-option-one') @@ -332,7 +332,7 @@ local dropdown_player_static_general = Gui.new_dropdown('test-dropdown-store-static-general') :set_tooltip('Dropdown store static general') :add_options('One','Two','Three','Four') -:add_store(Gui.player_store) +:add_store(Gui.categorize_by_player) :on_element_update(function(player,element,value) player.print('Dropdown store static general: '..tostring(value)) end) @@ -360,7 +360,7 @@ end local dropdown_player_static_case = Gui.new_dropdown('test-dropdown-store-static-case') :set_tooltip('Dropdown store static case') -:add_store(Gui.player_store) +:add_store(Gui.categorize_by_player) :add_options('One','Two') :add_option_callback('One',print_option_selected_2) :add_option_callback('Two',print_option_selected_2) @@ -388,7 +388,7 @@ Gui.new_dropdown('test-dropdown-store-dynamic') :add_dynamic(function(player,element) return table_keys(Colors) end) -:add_store(Gui.player_store) +:add_store(Gui.categorize_by_player) :on_element_update(function(player,element,value) player.print('Dropdown store dynamic: '..tostring(value)) end) @@ -420,7 +420,7 @@ local list_box_player = Gui.new_list_box('test-list-box-store') :set_tooltip('List box store') :add_options('One','Two','Three','Four') -:add_store(Gui.player_store) +:add_store(Gui.categorize_by_player) :on_element_update(function(player,element,value) player.print('Dropdown store: '..tostring(value)) end) @@ -433,7 +433,6 @@ tests["List Boxs"] = { --[[ Slider Tests > Local default -- Simple slider with default range - > Local notched -- Simple slider with notches > Store default -- Slider with default range that stores value between re-draws > Static range -- Simple slider with a static range > Dynamic range -- Slider with a dynamic range @@ -448,18 +447,11 @@ Gui.new_slider('test-slider-local-default') player.print('Slider local default: '..tostring(math.round(value))..' '..tostring(math.round(percent,1))) end) -local slider_notched_default = -Gui.new_slider('test-slider-notched-default') -:set_tooltip('Silder notched default') -:use_notches() -:on_element_update(function(player,element,value,percent) - player.print('Slider notched default: '..tostring(math.round(value))..' '..tostring(math.round(percent,1))) -end) local slider_player_default = Gui.new_slider('test-slider-store-default') :set_tooltip('Silder store default') -:add_store(Gui.player_store) +:add_store(Gui.categorize_by_player) :on_element_update(function(player,element,value,percent) player.print('Slider store default: '..tostring(math.round(value))..' '..tostring(math.round(percent,1))) end) @@ -496,14 +488,13 @@ local label_slider_player = Gui.new_slider('test-slider-store-label') :set_tooltip('Silder store label') :enable_auto_draw_label() -:add_store(Gui.player_store) +:add_store(Gui.categorize_by_player) :on_element_update(function(player,element,value,percent) player.print('Slider store label: '..tostring(math.round(value))..' '..tostring(math.round(percent,1))) end) tests.Sliders = { ['Local default']=slider_local_default, - ['Local notched']=slider_notched_default, ['Player default']=slider_player_default, ['Static range']=slider_static, ['Dynamic range']=slider_dynamic, @@ -535,7 +526,7 @@ end) local text_filed_store = Gui.new_text_filed('test-text-field-store') :set_tooltip('Text field store') -:add_store(Gui.player_store) +:add_store(Gui.categorize_by_player) :on_element_update(function(player,element,value) player.print('Text field store: '..value) end) @@ -603,7 +594,7 @@ local elem_store = Gui.new_elem_button('test-elem-store') :set_tooltip('Elem store') :set_type('item') -:add_store(Gui.player_store) +:add_store(Gui.categorize_by_player) :on_element_update(function(player,element,value) player.print('Elem store: '..value) end) @@ -632,7 +623,7 @@ end) local progressbar_two = Gui.new_progressbar('test-prog-one') :set_default_maximum(300) -:add_store(Gui.force_store) +:add_store(Gui.categorize_by_force) :on_complete(function(player,element,reset_element) reset_element() end) diff --git a/expcore/roles.lua b/expcore/roles.lua index 3a5c3b7b..c5edd15f 100644 --- a/expcore/roles.lua +++ b/expcore/roles.lua @@ -163,6 +163,7 @@ local Colours = require 'resources.color_presets' local write_json = ext_require('expcore.common','write_json') local Roles = { + _prototype={}, config={ order={}, -- Contains the order of the roles, lower index is better roles={}, -- Contains the raw info for the roles, indexed by role name @@ -170,9 +171,10 @@ local Roles = { internal={}, -- Contains all internally accessed roles, such as root, default players={} }, - player_role_assigned=script.generate_event_name(), - player_role_unassigned=script.generate_event_name(), - _prototype={} + events = { + on_role_assigned=script.generate_event_name(), + on_role_unassigned=script.generate_event_name(), + } } --- When global is loaded it will have the metatable re-assigned to the roles @@ -195,9 +197,9 @@ local function emit_player_roles_updated(player,type,roles,by_player_name,skip_g local by_player = Game.get_player_from_any(by_player_name) local by_player_index = by_player and by_player.index or 0 -- get the event id from the type of emit - local event = Roles.player_role_assigned + local event = Roles.events.on_role_assigned if type == 'unassign' then - event = Roles.player_role_unassigned + event = Roles.events.on_role_unassigned end -- convert the roles to objects and get the names of the roles local role_names = {} @@ -775,8 +777,8 @@ local function role_update(event) end --- When a player joined or has a role change then the update is triggered -Event.add(Roles.player_role_assigned,role_update) -Event.add(Roles.player_role_unassigned,role_update) +Event.add(Roles.events.on_role_assigned,role_update) +Event.add(Roles.events.on_role_unassigned,role_update) Event.add(defines.events.on_player_joined_game,role_update) -- Every 60 seconds the auto promote check is preformed Event.on_nth_tick(3600,function() diff --git a/expcore/store.lua b/expcore/store.lua index b2b25b78..459ccaf3 100644 --- a/expcore/store.lua +++ b/expcore/store.lua @@ -79,8 +79,11 @@ local Store = { registered={}, synced={}, callbacks={}, - on_value_update=script.generate_event_name() + events = { + on_value_update=script.generate_event_name() + } } + Global.register(Store.data,function(tbl) Store.data = tbl end) @@ -184,7 +187,7 @@ function Store.set(location,child,value,from_sync) data[location] = value end - script.raise_event(Store.on_value_update,{ + script.raise_event(Store.events.on_value_update,{ tick=game.tick, location=location, child=child, @@ -215,7 +218,7 @@ function Store.clear(location,child,from_sync) data[location] = nil end - script.raise_event(Store.on_value_update,{ + script.raise_event(Store.events.on_value_update,{ tick=game.tick, location=location, child=child, @@ -235,7 +238,7 @@ function Store.get_children(location) end -- Handels syncing -Event.add(Store.on_value_update,function(event) +Event.add(Store.events.on_value_update,function(event) if Store.callbacks[event.location] then Store.callbacks[event.location](event.value,event.child) end diff --git a/locale/en/addons.cfg b/locale/en/addons.cfg index 2f205308..444a8cbf 100644 --- a/locale/en/addons.cfg +++ b/locale/en/addons.cfg @@ -6,21 +6,23 @@ ping=You have been mentioned in chat by __1__. player-health=__1__ player-damage=__1__ +[links] +discord=https://discord.explosivegaming.nl +website=https://www.explosivegaming.nl +wiki=https://wiki.explosivegaming.nl/ +feedback=https://exp.fider.io/ +status=https://status.explosivegaming.nl +github=https://github.com/explosivegaming/scenario + [info] players-online=There are __1__ players online total-map-time=This map has been on for __1__ -discord-link=https://discord.explosivegaming.nl -discord-message=Join use on our discord at: https://discord.explosivegaming.nl -website-link=https://www.explosivegaming.nl -website-message=Please vist our website at: https://www.explosivegaming.nl -wiki-link=https://wiki.explosivegaming.nl/ -wiki-message=You can get more information about us and the custom scenario from our wiki: https://wiki.explosivegaming.nl/ -feedback-link=https://exp.fider.io/ -feedback-message=Do you have feedback? leave it at https://exp.fider.io/ -status-link=https://status.explosivegaming.nl -status-message=Want to check if out servers are down, vist: https://status.explosivegaming.nl -github-link=https://github.com/explosivegaming/scenario -github-message=Want to help improve our server with some extra features? Help us at: https://github.com/explosivegaming/scenario +discord=Join use on our discord at: https://discord.explosivegaming.nl +website=Please vist our website at: https://www.explosivegaming.nl +wiki=You can get more information about us and the custom scenario from our wiki: https://wiki.explosivegaming.nl/ +feedback=Do you have feedback? leave it at https://exp.fider.io/ +status=Want to check if out servers are down, vist: https://status.explosivegaming.nl +github=Want to help improve our server with some extra features? Help us at: https://github.com/explosivegaming/scenario custom-commands=We use custom commands, such as /tag and /me, use /chelp for more info. read-readme=Make sure you have read the Readme (It can be found through the question mark on the top left) softmod=We run a softmod on our servers. A softmod is a custom scenario that runs on this server, example is the player list. @@ -36,4 +38,22 @@ pre-ban=This your LAST warning before you are BANNED! successful ban appeals are ban=You were banned for having too many warnings; Vist __1__ to request a ban appeal. script-warning=You are reciving script warnings; if you recive too many you will recive a permiment warning (__1__/__2__) script-wrning-removed=A script warning has expired (__1__/__2__) -script-warning-limit=__1__ has recived a permiment warning from the script. \ No newline at end of file +script-warning-limit=__1__ has recived a permiment warning from the script. + +[chat-bot] +reply=[Chat Bot] __1__ +disallow=You cant use global chat commands +players-online=There are __1__ players online +players=There have been __1__ players on this map +map-time=This map has been on for __1__ +not-real-dev=Cooldude2606 is a dev for this server and makes the softmod (look top left) and is not a factorio dev. +softmod=A softmod is a custom scenario that runs on this server, example is the player list. +blame=Blame __1__ for what just happend! +afk=Your afk? Look at __1__, that player has been afk for: __2__ +current-evolution=Current evolution factor is __1__ +magic=Fear the admin magic (ノ゚∀゚)ノ⌒・*:.。. .。.:*・゜゚・*☆ +aids=≖ ‿ ≖ Fear the aids of a public server ≖ ‿ ≖ +riot=(admins) ┬┴┬┴┤ᵒ_ᵒ)├┬┴┬┴ ‹ ‹\(´ω` )/››‹‹\ (  ´)/››‹‹\ ( ´ω`)/›› (rest of server) +loops=NO LOOPS; LOOPS ARE BAD; JUST NO LOOPS!!!!!; IF YOU MAKE A LOOP.... IT WILL NOT END WELL!!!!!!! +lenny=( ͡° ͜ʖ ͡°) +hodor=Hodor \ No newline at end of file diff --git a/locale/en/commands.cfg b/locale/en/commands.cfg index 12812c63..bd4725c9 100644 --- a/locale/en/commands.cfg +++ b/locale/en/commands.cfg @@ -53,4 +53,15 @@ cleared=__1__ had all they warnings cleared by __2__. unavailable=They was a problem getting you to spawn, please try again later. [expcom-repair] -result=__1__ entites were revived and __2__ were healed to max health. \ No newline at end of file +result=__1__ entites were revived and __2__ were healed to max health. + +[expcom-bonus] +set=Your bonus has been set to __1__. +wip=This command is tempary and will be replaced at some point in the future. + +[expcom-home] +no-home=You have no home set. +no-return=You cant return when home has not yet been used. +home-set=Your home point has been set to x: __1__ y: __2__ +return-set=Your return point has been set to x: __1__ y: __2__ +home-get=Your home point is at x: __1__ y: __2__ \ No newline at end of file diff --git a/modules/addons/chat-reply.lua b/modules/addons/chat-reply.lua new file mode 100644 index 00000000..4dc40662 --- /dev/null +++ b/modules/addons/chat-reply.lua @@ -0,0 +1,51 @@ +local Event = require 'utils.event' +local Game = require 'utils.game' +local Roles = require 'expcore.roles' +local config = require 'config.chat_reply' + +Event.add(defines.events.on_console_chat,function(event) + local player_index = event.player_index + if not player_index or player_index < 1 then return end + local player = Game.get_player_by_index(player_index) + local message = event.message:lower():gsub("%s+", "") + local allowed = true + if config.command_admin_only and not player.admin then allowed = false end + if config.command_permission and not Roles.player_allowed(player,config.command_permission) then allowed = false end + + local prefix = config.command_prefix + for key_word,reply in pairs(config.messages) do + if message:find(key_word) then + if type(reply) == 'function' then + reply = reply(player) + end + + if message:find(prefix..key_word) then + if allowed then + game.print{'chat-bot.reply',reply} + else + player.print{'chat-bot.disallow'} + end + else + player.print{'chat-bot.reply',reply} + end + end + end + + if not allowed then return end + + for key_word,reply in pairs(config.commands) do + if message:find(prefix..key_word) then + if type(reply) == 'function' then + reply = reply(player) + + if reply then + game.print{'chat-bot.reply',reply} + end + + else + game.print{'chat-bot.reply',reply} + end + + end + end +end) \ No newline at end of file diff --git a/modules/addons/discord-alerts.lua b/modules/addons/discord-alerts.lua index fbc70d9c..720e0251 100644 --- a/modules/addons/discord-alerts.lua +++ b/modules/addons/discord-alerts.lua @@ -13,7 +13,7 @@ local function to_hex(color) local hex_digits = '0123456789ABCDEF' local function hex(bit) local major, minor = math.modf(bit/16) - minor = minor*16 + major,minor = major+1,minor*16+1 return hex_digits:sub(major,major)..hex_digits:sub(minor,minor) end @@ -77,7 +77,7 @@ end --- Reports added and removed if config.player_reports then local Reports = require 'modules.addons.reports-control' - Event.add(Reports.player_report_added,function(event) + Event.add(Reports.events.on_player_reported,function(event) local player_name,by_player_name = get_player_name(event) emit_event{ title='Report', @@ -88,7 +88,7 @@ if config.player_reports then ['Reason:']=event.reason } end) - Event.add(Reports.player_report_removed,function(event) + Event.add(Reports.events.on_player_report_removed,function(event) local player_name,by_player_name = get_player_name(event) emit_event{ title='Report Removed', @@ -103,7 +103,7 @@ end --- Warnings added and removed if config.player_warnings then local Warnings = require 'modules.addons.warnings-control' - Event.add(Warnings.player_warning_added,function(event) + Event.add(Warnings.events.on_player_warned,function(event) local player_name,by_player_name = get_player_name(event) emit_event{ title='Warning', @@ -113,7 +113,7 @@ if config.player_warnings then ['By:']=''..by_player_name } end) - Event.add(Warnings.player_warning_removed,function(event) + Event.add(Warnings.events.on_player_warning_removed,function(event) local player_name,by_player_name = get_player_name(event) emit_event{ title='Warning Removed', diff --git a/modules/addons/jail-control.lua b/modules/addons/jail-control.lua index 054e7dd9..41d5c910 100644 --- a/modules/addons/jail-control.lua +++ b/modules/addons/jail-control.lua @@ -3,21 +3,23 @@ local Game = require 'utils.game' local Global = require 'utils.global' local move_items = ext_require('expcore.common','move_items') -local Public = { +local Jail = { old_roles = {}, temp_bans = {}, - player_jailed=script.generate_event_name(), - player_unjailed=script.generate_event_name(), - player_temp_banned=script.generate_event_name(), - player_clear_temp_ban=script.generate_event_name() + events = { + on_player_jailed=script.generate_event_name(), + on_player_unjailed=script.generate_event_name(), + on_player_temp_banned=script.generate_event_name(), + on_player_temp_ban_cleared=script.generate_event_name() + } } Global.register({ - old_roles = Public.old_roles, - temp_bans = Public.temp_bans + old_roles = Jail.old_roles, + temp_bans = Jail.temp_bans },function(tbl) - Public.old_roles = tbl.old_roles - Public.temp_bans = tbl.temp_bans + Jail.old_roles = tbl.old_roles + Jail.temp_bans = tbl.temp_bans end) local function event_emit(event,player,by_player_name,reason) @@ -34,15 +36,15 @@ end -- @tparam LuaPlayer player the player that will be jailed, must not be in jail -- @tparam[opt=''] string by_player_name the name of the player doing the action used in logs -- @treturn the number of roles that were removed, nil if there was an error -function Public.jail_player(player,by_player_name) +function Jail.jail_player(player,by_player_name) player = Game.get_player_from_any(player) if not player then return end if Roles.player_has_role(player,'Jail') then return end local old_roles = Roles.get_player_roles(player) - Public.old_roles[player.name] = old_roles + Jail.old_roles[player.name] = old_roles Roles.unassign_player(player,old_roles,by_player_name,true) Roles.assign_player(player,'Jail',by_player_name,true) - event_emit(Public.player_jailed,player,by_player_name) + event_emit(Jail.events.on_player_jailed,player,by_player_name) return #old_roles end @@ -50,14 +52,14 @@ end -- @tparam LuaPlayer player the player that will be unjailed, must be in jail -- @tparam[opt=''] string string by_player_name the name of the player who is doing the action -- @treturn the number of roles that were added, nil if there was an error -function Public.unjail_player(player,by_player_name) +function Jail.unjail_player(player,by_player_name) player = Game.get_player_from_any(player) if not player then return end if not Roles.player_has_role(player,'Jail') then return end - local old_roles = Public.old_roles[player.name] + local old_roles = Jail.old_roles[player.name] Roles.unassign_player(player,'Jail',by_player_name,true) Roles.assign_player(player,old_roles,by_player_name,true) - event_emit(Public.player_unjailed,player,by_player_name) + event_emit(Jail.events.on_player_unjailed,player,by_player_name) return #old_roles end @@ -66,17 +68,17 @@ end -- @tparam[opt=''] string by_player_name the name of the player that is doing the action -- @tparam[opt='None string Given.'] reason the reason that will be stored for this temp ban -- @treturn boolean true if successful else will return nil -function Public.temp_ban_player(player,by_player_name,reason) +function Jail.temp_ban_player(player,by_player_name,reason) player = Game.get_player_from_any(player) reason = reason or 'None Given.' if not player then return end - if Public.temp_bans[player.name] then return end - Public.jail_player(player,by_player_name) - Public.temp_bans[player.name] = {reason,by_player_name} + if Jail.temp_bans[player.name] then return end + Jail.jail_player(player,by_player_name) + Jail.temp_bans[player.name] = {reason,by_player_name} local inv = player.get_main_inventory() move_items(inv.get_contents()) inv.clear() - event_emit(Public.player_temp_banned,player,by_player_name,reason) + event_emit(Jail.events.on_player_temp_banned,player,by_player_name,reason) return true end @@ -84,14 +86,14 @@ end -- @tparam LuaPlayer player the player that will be cleared from temp baned, must be temp banned -- @tparam[opt=''] string by_player_name the name of the player that is doing the action -- @treturn boolean true if successful else will return nil -function Public.clear_temp_ban_player(player,by_player_name) +function Jail.clear_temp_ban_player(player,by_player_name) player = Game.get_player_from_any(player) if not player then return end - if not Public.temp_bans[player.name] then return end - Public.unjail_player(player,by_player_name) - Public.temp_bans[player.name] = nil - event_emit(Public.player_clear_temp_ban,player,by_player_name) + if not Jail.temp_bans[player.name] then return end + Jail.unjail_player(player,by_player_name) + Jail.temp_bans[player.name] = nil + event_emit(Jail.events.on_player_temp_ban_cleared,player,by_player_name) return true end -return Public \ No newline at end of file +return Jail \ No newline at end of file diff --git a/modules/addons/reports-control.lua b/modules/addons/reports-control.lua index 673f3f3c..5de027ce 100644 --- a/modules/addons/reports-control.lua +++ b/modules/addons/reports-control.lua @@ -1,18 +1,20 @@ local Game = require 'utils.game' local Global = require 'utils.global' -local Public = { +local Reports = { user_reports={}, - player_report_added = script.generate_event_name(), - player_report_removed = script.generate_event_name() + events = { + on_player_reported = script.generate_event_name(), + on_player_report_removed = script.generate_event_name() + } } -Global.register(Public.user_reports,function(tbl) - Public.user_reports = tbl +Global.register(Reports.user_reports,function(tbl) + Reports.user_reports = tbl end) local function event_emit(event,player,by_player_name) - local reports = Public.user_reports[player.name] + local reports = Reports.user_reports[player.name] local reason = reports and reports[by_player_name] script.raise_event(event,{ name=event, @@ -28,20 +30,20 @@ end -- @tparam[opt='Non string Given.'] reason the reason that the player is being reported -- @tparam[opt=''] string by_player_name the name of the player doing the action -- @treturn boolean true if the report was added, nil if there is an error -function Public.report_player(player,reason,by_player_name) +function Reports.report_player(player,reason,by_player_name) player = Game.get_player_from_any(player) if not player then return end reason = reason or 'Non Given.' by_player_name = by_player_name or '' - local reports = Public.user_reports[player.name] + local reports = Reports.user_reports[player.name] if not reports then - Public.user_reports[player.name] = { + Reports.user_reports[player.name] = { [by_player_name] = reason } elseif not reports[by_player_name] then reports[by_player_name] = reason else return false end - event_emit(Public.player_report_added,player,by_player_name) + event_emit(Reports.events.on_player_reported,player,by_player_name) return true end @@ -49,16 +51,16 @@ end -- @tparam LuaPlayer player the player that will have the report removed -- @tparam[opt=''] string by_player_name the name of the player doing the action -- @treturn boolean true if the report was removed, nil if there was an error -function Public.remove_player_report(player,by_player_name) +function Reports.remove_player_report(player,by_player_name) player = Game.get_player_from_any(player) if not player then return end by_player_name = by_player_name or '' - local reports = Public.user_reports[player.name] + local reports = Reports.user_reports[player.name] if reports and reports[by_player_name] then - event_emit(Public.player_report_removed,player,by_player_name) + event_emit(Reports.events.on_player_report_removed,player,by_player_name) reports[by_player_name] = nil - if Public.count_player_reports(player) == 0 then - Public.user_reports[player.name] = nil + if Reports.count_player_reports(player) == 0 then + Reports.user_reports[player.name] = nil end return true end @@ -68,15 +70,15 @@ end --- Clears all reports from a player, will emit an event for each individual report as if remove_player_report was used -- @tparam LuaPlayer player the player to clear the reports of -- @treturn boolean true if the reports were cleared, nil if error -function Public.clear_player_reports(player) +function Reports.clear_player_reports(player) player = Game.get_player_from_any(player) if not player then return end - local reports = Public.user_reports[player.name] + local reports = Reports.user_reports[player.name] if reports then for by_player_name,reason in pairs(reports) do - event_emit(Public.player_report_removed,player,by_player_name) + event_emit(Reports.events.on_player_report_removed,player,by_player_name) end - Public.user_reports[player.name] = nil + Reports.user_reports[player.name] = nil return true end return false @@ -87,10 +89,10 @@ end -- @tparam string by_player_name the player that made if the report if present (note server is not default here) -- @tparam[opt=false] boolean rtn_reason true will return the reason for the report rather than a boolean -- @treturn boolean true if a report from the player is present unless rtn_reason is true when a string is returned (or false) -function Public.player_is_reported_by(player,by_player_name,rtn_reason) +function Reports.player_is_reported_by(player,by_player_name,rtn_reason) player = Game.get_player_from_any(player) if not player then return end - local reports = Public.user_reports[player.name] + local reports = Reports.user_reports[player.name] if reports and reports[by_player_name] then return rtn_reason and reports[by_player_name] or true end @@ -100,10 +102,10 @@ end --- Gets all the reports that are on a player -- @tparam LuaPlayer player the player to get the reports of -- @treturn table a table of all the reports for this player, empty table if no reports -function Public.get_player_reports(player) +function Reports.get_player_reports(player) player = Game.get_player_from_any(player) if not player then return end - return Public.user_reports[player.name] or {} + return Reports.user_reports[player.name] or {} end --- Counts all reports on a player returning a number, a custom count function can be given which should return a number @@ -113,10 +115,10 @@ end -- count_callback param - reason string - the reason the reason was made -- count_callback return - number or boolean - if number then this will be added to the count, if boolean then false = 0 and true = 1 -- @treturn number the number of reports on the player -function Public.count_player_reports(player,count_callback) +function Reports.count_player_reports(player,count_callback) player = Game.get_player_from_any(player) if not player then return end - local reports = Public.user_reports[player.name] or {} + local reports = Reports.user_reports[player.name] or {} if not count_callback then local ctn = 0 for _ in pairs(reports) do @@ -136,4 +138,4 @@ function Public.count_player_reports(player,count_callback) end end -return Public \ No newline at end of file +return Reports \ No newline at end of file diff --git a/modules/addons/warnings-control.lua b/modules/addons/warnings-control.lua index 616ef3d1..44b07cfd 100644 --- a/modules/addons/warnings-control.lua +++ b/modules/addons/warnings-control.lua @@ -5,26 +5,28 @@ local config = require 'config.warnings' local format_chat_player_name = ext_require('expcore.common','format_chat_player_name') require 'utils.table' -local Public = { +local Warnings = { user_warnings={}, user_temp_warnings={}, - player_warning_added = script.generate_event_name(), - player_warning_removed = script.generate_event_name(), - player_temp_warning_added = script.generate_event_name(), - player_temp_warning_removed = script.generate_event_name() + events = { + on_player_warned = script.generate_event_name(), + on_player_warning_removed = script.generate_event_name(), + on_temp_warning_added = script.generate_event_name(), + on_temp_warning_removed = script.generate_event_name(), + } } Global.register({ - user_warnings = Public.user_warnings, - user_temp_warnings = Public.user_temp_warnings + user_warnings = Warnings.user_warnings, + user_temp_warnings = Warnings.user_temp_warnings },function(tbl) - Public.user_warnings = tbl.user_warnings - Public.user_temp_warnings = tbl.user_temp_warnings + Warnings.user_warnings = tbl.user_warnings + Warnings.user_temp_warnings = tbl.user_temp_warnings end) local function event_emit(event,player,by_player_name) - local warnings = Public.user_warnings[player.name] or {} - local temp_warnings = Public.user_temp_warnings[player.name] or {} + local warnings = Warnings.user_warnings[player.name] or {} + local temp_warnings = Warnings.user_temp_warnings[player.name] or {} script.raise_event(event,{ name=event, tick=game.tick, @@ -40,19 +42,19 @@ end -- @tparam[opt=''] string by_player_name the name of the player doing the action -- @tparam[opt=1] number count the number of warnings to add -- @treturn number the new number of warnings -function Public.add_warnings(player,by_player_name,count) +function Warnings.add_warnings(player,by_player_name,count) player = Game.get_player_from_any(player) if not player then return end count = count or 1 by_player_name = by_player_name or '' - local warnings = Public.user_warnings[player.name] + local warnings = Warnings.user_warnings[player.name] if not warnings then - Public.user_warnings[player.name] = {} - warnings = Public.user_warnings[player.name] + Warnings.user_warnings[player.name] = {} + warnings = Warnings.user_warnings[player.name] end for _=1,count do table.insert(warnings,by_player_name) - event_emit(Public.player_warning_added,player,by_player_name) + event_emit(Warnings.events.on_player_warned,player,by_player_name) end return #warnings end @@ -62,20 +64,20 @@ end -- @tparam[opt=''] string by_playey_name the name of the player doing the action -- @tparam[opt=1] number count the number of warnings to remove (if greater than current warning count then all are removed) -- @treturn number the new number of warnings -function Public.remove_warnings(player,by_player_name,count) +function Warnings.remove_warnings(player,by_player_name,count) player = Game.get_player_from_any(player) if not player then return end count = count or 1 by_player_name = by_player_name or '' - local warnings = Public.user_warnings[player.name] + local warnings = Warnings.user_warnings[player.name] if not warnings then return end for _=1,count do if #warnings == 0 then break end table.remove(warnings,1) - event_emit(Public.player_warning_removed,player,by_player_name) + event_emit(Warnings.events.on_player_warning_removed,player,by_player_name) end if #warnings == 0 then - Public.user_warnings[player.name] = nil + Warnings.user_warnings[player.name] = nil return 0 end return #warnings @@ -85,16 +87,16 @@ end -- @tparam LuaPlayer player the player to clear the warnings of -- @tparam[oot=''] string by_player_name the name of the player who is doing the action -- @treturn boolean true if the warnings were cleared, nil if error -function Public.clear_warnings(player,by_player_name) +function Warnings.clear_warnings(player,by_player_name) player = Game.get_player_from_any(player) if not player then return end - local warnings = Public.user_warnings[player.name] + local warnings = Warnings.user_warnings[player.name] if not warnings then return end by_player_name = by_player_name or '' for _=1,#warnings do - event_emit(Public.player_warning_removed,player,by_player_name) + event_emit(Warnings.events.on_player_warning_removed,player,by_player_name) end - Public.user_warnings[player.name] = {} + Warnings.user_warnings[player.name] = {} return true end @@ -102,10 +104,10 @@ end -- @tparam LuaPlayer player the player to get the warnings of -- @tparam[opt=false] table table raw_table when true will return a which contains who gave warnings (the stored in global) -- @treturn number the number of warnings a player has, a table if raw_table is true -function Public.get_warnings(player,raw_table) +function Warnings.get_warnings(player,raw_table) player = Game.get_player_from_any(player) if not player then return end - local warnings = Public.user_warnings[player.name] or {} + local warnings = Warnings.user_warnings[player.name] or {} if raw_table then return warnings else @@ -117,18 +119,18 @@ end -- @tparam LuaPlayer player the player to give the warnings to -- @tparam[opt=1] number count the number of warnings to give to the player -- @treturn number the new number of warnings -function Public.add_temp_warnings(player,count) +function Warnings.add_temp_warnings(player,count) player = Game.get_player_from_any(player) if not player then return end count = count or 1 - local warnings = Public.user_temp_warnings[player.name] + local warnings = Warnings.user_temp_warnings[player.name] if not warnings then - Public.user_temp_warnings[player.name] = {} - warnings = Public.user_temp_warnings[player.name] + Warnings.user_temp_warnings[player.name] = {} + warnings = Warnings.user_temp_warnings[player.name] end for _=1,count do table.insert(warnings,game.tick) - event_emit(Public.player_temp_warning_added,player,'') + event_emit(Warnings.events.on_temp_warning_added,player,'') end return #warnings end @@ -137,17 +139,17 @@ end local temp_warning_cool_down = config.temp_warning_cool_down*3600 Event.on_nth_tick(temp_warning_cool_down/4,function() local check_time = game.tick-temp_warning_cool_down - for player_name,temp_warnings in pairs(Public.user_temp_warnings) do + for player_name,temp_warnings in pairs(Warnings.user_temp_warnings) do local player = Game.get_player_from_any(player) for index,time in pairs(temp_warnings) do if time <= check_time then table.remove(temp_warnings,index) player.print{'warnings.script-warning-removed',#temp_warnings,config.temp_warning_limit} - event_emit(Public.player_temp_warning_removed,player,'') + event_emit(Warnings.events.on_temp_warning_removed,player,'') end end if #temp_warnings == 0 then - Public.user_temp_warnings[player_name] = nil + Warnings.user_temp_warnings[player_name] = nil end end end) @@ -156,16 +158,16 @@ end) -- @tparam LuaPlayer player the player to clear the warnings of -- @tparam[opt=''] string by_player_name the name of the player doing the action -- @treturn boolean true if the warnings were cleared, nil for error -function Public.clear_temp_warnings(player,by_player_name) +function Warnings.clear_temp_warnings(player,by_player_name) player = Game.get_player_from_any(player) if not player then return end - local warnings = Public.user_temp_warnings[player.name] + local warnings = Warnings.user_temp_warnings[player.name] if not warnings then return end by_player_name = by_player_name or '' for _=1,#warnings do - event_emit(Public.player_temp_warning_removed,player,by_player_name) + event_emit(Warnings.events.on_temp_warning_removed,player,by_player_name) end - Public.user_temp_warnings[player.name] = {} + Warnings.user_temp_warnings[player.name] = {} return true end @@ -173,10 +175,10 @@ end -- @tparam LuaPlayer player the player to get the warnings of -- @tparam[opt=false] table raw_table if true will return a of ticks when warnings were added (the global table) -- @treturn number the number of warnings which the player has, a table if raw_table is true -function Public.get_temp_warnings(player,raw_table) +function Warnings.get_temp_warnings(player,raw_table) player = Game.get_player_from_any(player) if not player then return end - local warnings = Public.user_temp_warnings[player.name] or {} + local warnings = Warnings.user_temp_warnings[player.name] or {} if raw_table then return warnings else @@ -185,7 +187,7 @@ function Public.get_temp_warnings(player,raw_table) end -- when a player gets a warning the actions in config are ran -Event.add(Public.player_warning_added,function(event) +Event.add(Warnings.events.on_player_warned,function(event) local action = config.actions[event.warning_count] if not action then return end local player = Game.get_player_by_index(event.player_index) @@ -205,10 +207,10 @@ Event.add(Public.player_warning_added,function(event) end) -- when a player gets a tempo warnings it is checked that it is not above the max -Event.add(Public.player_temp_warning_added,function(event) +Event.add(Warnings.events.on_temp_warning_added,function(event) local player = Game.get_player_by_index(event.player_index) if event.temp_warning_count > config.temp_warning_limit then - Public.add_warnings(event.player_index,event.by_player_name) + Warnings.add_warnings(event.player_index,event.by_player_name) local player_name_color = format_chat_player_name(player) game.print{'warnings.script-warning-limit',player_name_color} else @@ -216,4 +218,4 @@ Event.add(Public.player_temp_warning_added,function(event) end end) -return Public \ No newline at end of file +return Warnings \ No newline at end of file diff --git a/modules/commands/bonus.lua b/modules/commands/bonus.lua index 2e02b706..8b3e6517 100644 --- a/modules/commands/bonus.lua +++ b/modules/commands/bonus.lua @@ -20,6 +20,8 @@ Commands.new_command('bonus','Changes the amount of bonus you receive') :register(function(player,amount) local percent = amount/100 Store.set(bonus_store,player.name,percent) + Commands.print{'expcom-bonus.set',amount} + Commands.print({'expcom-bonus.wip'},'orange') end) Event.add(defines.events.on_player_respawned,function(event) @@ -54,5 +56,5 @@ local function role_update(event) end end -Event.add(Roles.player_role_assigned,role_update) -Event.add(Roles.player_role_unassigned,role_update) \ No newline at end of file +Event.add(Roles.events.on_role_assigned,role_update) +Event.add(Roles.events.on_role_unassigned,role_update) \ No newline at end of file diff --git a/modules/commands/home.lua b/modules/commands/home.lua new file mode 100644 index 00000000..be733517 --- /dev/null +++ b/modules/commands/home.lua @@ -0,0 +1,70 @@ +local Commands = require 'expcore.commands' +local Global = require 'utils.global' +require 'config.expcore-commands.parse_general' + +local homes = {} +Global.register(homes,function(tbl) + homes = tbl +end) + +local function teleport(player,position) + local surface = player.surface + local pos = surface.find_non_colliding_position('character',position,32,1) + if not position then return false end + if player.driving then player.driving = false end -- kicks a player out a vehicle if in one + player.teleport(pos,surface) + return true +end + +local function floor_pos(position) + return { + x=math.floor(position.x), + y=math.floor(position.y) + } +end + +Commands.new_command('home','Teleports you to your home location') +:register(function(player,raw) + local home = homes[player.index] + if not home or not home[1] then + return Commands.error{'expcom-home.no-home'} + end + local rtn = floor_pos(player.position) + teleport(player,home[1]) + home[2] = rtn + Commands.print{'expcom-home.return-set',rtn.x,rtn.y} +end) + +Commands.new_command('home-set','Sets your home location to your current position') +:register(function(player,raw) + local home = homes[player.index] + if not home then + home = {} + homes[player.index] = home + end + local pos = floor_pos(player.position) + home[1] = pos + Commands.print{'expcom-home.home-set',pos.x,pos.y} +end) + +Commands.new_command('home-get','Returns your current home location') +:register(function(player,raw) + local home = homes[player.index] + if not home or not home[1] then + return Commands.error{'expcom-home.no-home'} + end + local pos = home[1] + Commands.print{'expcom-home.home-get',pos.x,pos.y} +end) + +Commands.new_command('return','Teleports you to previous location') +:register(function(player,raw) + local home = homes[player.index] + if not home or not home[2] then + return Commands.error{'expcom-home.no-return'} + end + local rtn = floor_pos(player.position) + teleport(player,home[2]) + home[2] = rtn + Commands.print{'expcom-home.return-set',rtn.x,rtn.y} +end) \ No newline at end of file diff --git a/modules/gui/player-list.lua b/modules/gui/player-list.lua index 0681c985..ad320bd6 100644 --- a/modules/gui/player-list.lua +++ b/modules/gui/player-list.lua @@ -111,30 +111,8 @@ local function generate_container(player,element) } Gui.set_padding(container) - -- a scroll bar which allows 8 players to be seen at once - local list_scroll = - container.add{ - name='scroll', - type='scroll-pane', - direction='vertical', - horizontal_scroll_policy='never', - vertical_scroll_policy='auto-and-reserve-space' - } - Gui.set_padding(list_scroll,1,1,2,2) - list_scroll.style.horizontally_stretchable = true - list_scroll.style.maximal_height = 188 - -- 3 wide table to contain: action button, player name, and play time - local list_table = - list_scroll.add{ - name='table', - type='table', - column_count=3 - } - Gui.set_padding(list_table) - list_table.style.horizontally_stretchable = true - list_table.style.vertical_align = 'center' - list_table.style.cell_padding = 0 + local list_table = Gui.create_scroll_table(container,3,188) -- action bar which contains the different action buttons local action_bar = @@ -258,7 +236,7 @@ local function add_player(list_table,player,role_name) player_name.style.font_color = player.chat_color -- flow which allows right align for the play time - local time_flow = Gui.create_right_align(list_table,'player-time-'..player.index) + local time_flow = Gui.create_alignment(list_table,'player-time-'..player.index) -- time given in Xh Ym and is right aligned local tick = game.tick > 0 and game.tick or 1 @@ -295,7 +273,7 @@ Gui.new_left_frame('gui/player-list') :set_tooltip{'player-list.main-tooltip'} :set_open_by_default() :set_direction('vertical') -:on_draw(function(player,element) +:on_creation(function(player,element) local list_table,action_bar = generate_container(player,element) generate_action_bar(player,action_bar) @@ -378,7 +356,7 @@ end) Event.on_nth_tick(1800,player_list 'update_all') Event.add(defines.events.on_player_joined_game,player_list 'redraw_all') Event.add(defines.events.on_player_left_game,player_list 'redraw_all') -Event.add(Roles.player_role_assigned,player_list 'redraw_all') -Event.add(Roles.player_role_unassigned,player_list 'redraw_all') +Event.add(Roles.events.on_role_assigned,player_list 'redraw_all') +Event.add(Roles.events.on_role_unassigned,player_list 'redraw_all') return player_list \ No newline at end of file diff --git a/modules/gui/rocket-info.lua b/modules/gui/rocket-info.lua index bee8d005..9e38475c 100644 --- a/modules/gui/rocket-info.lua +++ b/modules/gui/rocket-info.lua @@ -145,52 +145,21 @@ end) --- Used to create the three different sections local function create_section(container,section_name,table_size) --- Header for the section - local header = - container.add{ - type='frame', - name=section_name..'-header', - style='subheader_frame', - } - Gui.set_padding(header,4,1,4,4) - header.style.horizontally_stretchable = true - - --- Caption for the header bar - header.add{ - type='label', - style='heading_1_label', - caption={'rocket-info.section-caption-'..section_name}, - tooltip={'rocket-info.section-tooltip-'..section_name} - } + local header_area = Gui.create_header( + container, + {'rocket-info.section-caption-'..section_name}, + {'rocket-info.section-tooltip-'..section_name}, + true, + section_name..'-header' + ) --- Right aligned button to toggle the section - local expand_flow = Gui.create_right_align(header,section_name) - toggle_section(expand_flow) - - --- The area which contains the section content - local flow = - container.add{ - name=section_name, - type='scroll-pane', - direction='vertical', - horizontal_scroll_policy='never', - vertical_scroll_policy='auto-and-reserve-space' - } - Gui.set_padding(flow,1,1,2,2) - flow.style.horizontally_stretchable = true - flow.style.maximal_height = 215 - flow.visible = false + toggle_section(header_area) --- Table used to store the data - local flow_table = - flow.add{ - name='table', - type='table', - column_count=table_size - } - Gui.set_padding(flow_table) - flow_table.style.horizontally_stretchable = true - flow_table.style.vertical_align = 'center' - flow_table.style.cell_padding = 0 + local flow_table = Gui.create_scroll_table(container,table_size,215,section_name) + flow_table.parent.visible = false + end --[[ Creates the main structure for the gui @@ -272,7 +241,7 @@ local function create_label_value_pair(element,data_name,value,tooltip,extra) tooltip={'rocket-info.data-tooltip-'..data_name,extra} } --- Right aligned label to store the data - local right_flow = Gui.create_right_align(element,data_name_extra) + local right_flow = Gui.create_alignment(element,data_name_extra) right_flow.add{ type='label', name='label', @@ -328,7 +297,7 @@ local function generate_stats(player,frame) local rocket_count = avg_over local first_rocket = 0 if avg_over < force_rockets then - first_rocket = rocket_times[player.force.name][force_rockets-avg_over] + first_rocket = rocket_times[player.force.name][force_rockets-avg_over+1] else rocket_count = force_rockets end @@ -347,9 +316,9 @@ local function generate_milestones(player,frame) for _,milestone in ipairs(config.milestones) do if milestone <= force_rockets then local time = rocket_times[player.force.name][milestone] - create_label_value_pair_time(element,'milstone-n',time,true,milestone) + create_label_value_pair_time(element,'milstone-n',time,false,milestone) else - create_label_value_pair_time(element,'milstone-n',0,true,milestone) + create_label_value_pair_time(element,'milstone-n',0,false,milestone) break end end @@ -470,7 +439,7 @@ local function generate_progress(player,frame) } --- Creates the progress value which is right aligned - local right_flow = Gui.create_right_align(element,silo_name) + local right_flow = Gui.create_alignment(element,silo_name) right_flow.add{ type='label', name='label', @@ -517,7 +486,7 @@ end) return player.force.rockets_launched > 0 end) :set_direction('vertical') -:on_draw(function(player,element) +:on_creation(function(player,element) generate_container(player,element) generate_stats(player,element) generate_milestones(player,element) @@ -631,7 +600,7 @@ Event.on_nth_tick(150,function() end) --- Makes sure the right buttons are present when role changes -Event.add(Roles.player_role_assigned,rocket_info 'redraw') -Event.add(Roles.player_role_unassigned,rocket_info 'redraw') +Event.add(Roles.events.on_role_assigned,rocket_info 'redraw') +Event.add(Roles.events.on_role_unassigned,rocket_info 'redraw') return rocket_info \ No newline at end of file diff --git a/modules/gui/science-info.lua b/modules/gui/science-info.lua index 775035aa..6fd522d2 100644 --- a/modules/gui/science-info.lua +++ b/modules/gui/science-info.lua @@ -75,33 +75,18 @@ local function generate_container(player,element) Gui.set_padding(container) -- main header for the gui - local header = - container.add{ - name='header', - type='frame', - caption={'science-info.main-caption'}, - style='subheader_frame' - } - Gui.set_padding(header,2,2,4,4) - header.style.horizontally_stretchable = true - header.style.use_header_filler = false + Gui.create_header( + container, + {'science-info.main-caption'}, + {'science-info.main-tooltip'} + ) - -- main flow for the data - local flow = - container.add{ - name='scroll', - type='scroll-pane', - direction='vertical', - horizontal_scroll_policy='never', - vertical_scroll_policy='auto-and-reserve-space' - } - Gui.set_padding(flow,1,1,2,2) - flow.style.horizontally_stretchable = true - flow.style.maximal_height = 185 + -- table that stores all the data + local flow_table = Gui.create_scroll_table(container,4,185) -- message to say that you have not made any packs yet local non_made = - flow.add{ + flow_table.parent.add{ name='non_made', type='label', caption={'science-info.no-packs'} @@ -109,17 +94,6 @@ local function generate_container(player,element) non_made.style.width = 200 non_made.style.single_line = false - -- table that stores all the data - local flow_table = - flow.add{ - name='table', - type='table', - column_count=4 - } - Gui.set_padding(flow_table) - flow_table.style.horizontally_stretchable = true - flow_table.style.vertical_align = 'center' - local eta if config.show_eta then -- footer used to store the eta @@ -142,7 +116,7 @@ local function generate_container(player,element) } -- data for the footer - local right_align = Gui.create_right_align(footer,'eta') + local right_align = Gui.create_alignment(footer,'eta') eta = right_align.add{ name='label', @@ -191,7 +165,7 @@ local function add_data_label(element,name,value,secondary,tooltip) else -- right aligned number - local right_align = Gui.create_right_align(element,name) + local right_align = Gui.create_alignment(element,name) local data = right_align.add{ name='label', @@ -341,7 +315,7 @@ Gui.new_left_frame('gui/science-info') :set_sprites('entity/lab') :set_direction('vertical') :set_tooltip{'science-info.main-tooltip'} -:on_draw(function(player,element) +:on_creation(function(player,element) local table, eta = generate_container(player,element) for _,science_pack in ipairs(config) do diff --git a/modules/gui/task-list.lua b/modules/gui/task-list.lua index e613b03c..2a4a4374 100644 --- a/modules/gui/task-list.lua +++ b/modules/gui/task-list.lua @@ -211,7 +211,7 @@ function generate_task(player,element,task_id) Gui.set_padding(task_area) -- if the player can edit then it adds the edit and delete button - local flow = Gui.create_right_align(element,'edit-'..task_id) + local flow = Gui.create_alignment(element,'edit-'..task_id) local sub_flow = flow.add{type='flow',name=task_id} edit_task(sub_flow) @@ -310,46 +310,28 @@ local function generate_container(player,element) container.style.vertically_stretchable = false -- main header for the gui - local header = - container.add{ - name='header', - type='frame', - style='subheader_frame' - } - Gui.set_padding(header,2,2,4,4) - header.style.horizontally_stretchable = true - header.style.use_header_filler = false - - --- Caption for the header bar - header.add{ - type='label', - style='heading_1_label', - caption={'task-list.main-caption'}, - tooltip={'task-list.sub-tooltip'} - } + local header_area = Gui.create_header( + container, + {'task-list.main-caption'}, + {'task-list.sub-tooltip'}, + true + ) --- Right aligned button to toggle the section if player_allowed_edit(player) then - local right_align = Gui.create_right_align(header) - add_new_task(right_align) + add_new_task(header_area) end - -- main flow for the data - local flow = - container.add{ - name='scroll', - type='scroll-pane', - direction='vertical', - horizontal_scroll_policy='never', - vertical_scroll_policy='auto-and-reserve-space' - } - Gui.set_padding(flow,1,1,2,2) - flow.style.horizontally_stretchable = true - flow.style.maximal_height = 185 + -- table that stores all the data + local flow_table = Gui.create_scroll_table(container,3,185) + flow_table.draw_horizontal_lines = true + flow_table.vertical_centering = false + flow_table.style.top_cell_padding = 3 + flow_table.style.bottom_cell_padding = 3 -- message to say that you have no tasks local non_made = - flow.add{ + flow_table.parent.add{ name='no_tasks', type='label', caption={'task-list.no-tasks'} @@ -357,20 +339,6 @@ local function generate_container(player,element) non_made.style.width = 200 non_made.style.single_line = false - -- table that stores all the data - local flow_table = - flow.add{ - name='table', - type='table', - column_count=3, - draw_horizontal_lines=true, - vertical_centering=false - } - Gui.set_padding(flow_table) - flow_table.style.horizontally_stretchable = true - flow_table.style.top_cell_padding = 3 - flow_table.style.bottom_cell_padding = 3 - return flow_table end @@ -381,7 +349,7 @@ Gui.new_left_frame('gui/task-list') :set_direction('vertical') :set_tooltip{'task-list.main-tooltip'} :set_open_by_default() -:on_draw(function(player,element) +:on_creation(function(player,element) local data_table = generate_container(player,element) local force_name = player.force.name @@ -415,7 +383,7 @@ Store.register(task_store,function(value,task_id) end) --- Makess sure the right buttons are present when roles change -Event.add(Roles.player_role_assigned,task_list 'redraw') -Event.add(Roles.player_role_unassigned,task_list 'redraw') +Event.add(Roles.events.on_role_assigned,task_list 'redraw') +Event.add(Roles.events.on_role_unassigned,task_list 'redraw') return task_list \ No newline at end of file diff --git a/modules/gui/warp-list.lua b/modules/gui/warp-list.lua index 64eab9bd..eb9688b6 100644 --- a/modules/gui/warp-list.lua +++ b/modules/gui/warp-list.lua @@ -254,7 +254,7 @@ local warp_timer = Gui.new_progressbar() :set_tooltip{'warp-list.timer-tooltip',config.recharge_time} :set_default_maximum(math.floor(config.recharge_time*config.update_smothing)) -:add_store(Gui.player_store) +:add_store(Gui.categorize_by_player) :set_style(nil,function(style) style.horizontally_stretchable = true style.color = Colors.light_blue @@ -449,7 +449,7 @@ function generate_warp(player,element,warp_id) Gui.set_padding(warp_area) -- if the player can edit then it adds the edit and delete button - local flow = Gui.create_right_align(element,'edit-'..warp_id) + local flow = Gui.create_alignment(element,'edit-'..warp_id) local sub_flow = flow.add{type='flow',name=warp_id} edit_warp(sub_flow) @@ -493,6 +493,7 @@ function generate_warp(player,element,warp_id) local timer = warp_timer:get_store(player.name) local enabled = not timer and Store.get(warp_player_in_range_store,player.name) + or Roles.player_allowed(player,config.bypass_warp_limits_permision) if not enabled then btn.enabled = false btn.tooltip = {'warp-list.goto-disabled'} @@ -577,52 +578,20 @@ local function generate_container(player,element) container.style.vertically_stretchable = false -- main header for the gui - local header = - container.add{ - name='header', - type='frame', - style='subheader_frame' - } - Gui.set_padding(header,2,2,4,4) - header.style.horizontally_stretchable = true - header.style.use_header_filler = false - - --- Caption for the header bar - header.add{ - type='label', - style='heading_1_label', - caption={'warp-list.main-caption'}, - tooltip={'warp-list.sub-tooltip',config.recharge_time,config.activation_range} - } + local header_area = Gui.create_header( + container, + {'warp-list.main-caption'}, + {'warp-list.sub-tooltip',config.recharge_time,config.activation_range}, + true + ) --- Right aligned button to toggle the section if player_allowed_edit(player) then - local right_align = Gui.create_right_align(header) - add_new_warp(right_align) + add_new_warp(header_area) end - -- main flow for the data - local flow = - container.add{ - name='scroll', - type='scroll-pane', - direction='vertical', - horizontal_scroll_policy='never', - vertical_scroll_policy='auto-and-reserve-space' - } - Gui.set_padding(flow,1,1,2,2) - flow.style.horizontally_stretchable = true - flow.style.maximal_height = 258 - -- table that stores all the data - local flow_table = - flow.add{ - name='table', - type='table', - column_count=3 - } - Gui.set_padding(flow_table) - flow_table.style.horizontally_stretchable = true + local flow_table = Gui.create_scroll_table(container,3,258) flow_table.style.top_cell_padding = 3 flow_table.style.bottom_cell_padding = 3 @@ -637,7 +606,7 @@ Gui.new_left_frame('gui/warp-list') :set_sprites('item/'..config.default_icon) :set_tooltip{'warp-list.main-tooltip',config.activation_range} :set_direction('vertical') -:on_draw(function(player,element) +:on_creation(function(player,element) local data_table = generate_container(player,element) local force_name = player.force.name @@ -716,6 +685,10 @@ Store.register(warp_player_in_range_store,function(value,player_name) Gui.toggle_left_frame(warp_list.name,player,value) end + if Roles.player_allowed(player,config.bypass_warp_limits_permision) then + return + end + if force_warps[force.name] then for _,warp_id in pairs(force_warps[force.name]) do local element = table_area['icon-'..warp_id][goto_warp.name] @@ -789,4 +762,24 @@ Event.add(defines.events.on_player_created,function(event) end end) +local function maintain_tag(event) + local tag = event.tag + local force = event.force + local warps = force_warps[force.name] + if warps then + for _,warp_id in pairs(warps) do + local warp = warp_details[warp_id] + if not warp.tag or not warp.tag.valid or warp.tag == tag then + if event.name == defines.events.on_chart_tag_removed then + warp.tag = nil + end + make_warp_tag(warp_id) + end + end + end +end + +Event.add(defines.events.on_chart_tag_modified,maintain_tag) +Event.add(defines.events.on_chart_tag_removed,maintain_tag) + return warp_list \ No newline at end of file diff --git a/old/modules/ExpGamingBot/autoChat/control.lua b/old/modules/DONE/Bot/autoChat/control.lua similarity index 100% rename from old/modules/ExpGamingBot/autoChat/control.lua rename to old/modules/DONE/Bot/autoChat/control.lua diff --git a/old/modules/ExpGamingBot/autoChat/locale/de.cfg b/old/modules/DONE/Bot/autoChat/locale/de.cfg similarity index 100% rename from old/modules/ExpGamingBot/autoChat/locale/de.cfg rename to old/modules/DONE/Bot/autoChat/locale/de.cfg diff --git a/old/modules/ExpGamingBot/autoChat/locale/en.cfg b/old/modules/DONE/Bot/autoChat/locale/en.cfg similarity index 100% rename from old/modules/ExpGamingBot/autoChat/locale/en.cfg rename to old/modules/DONE/Bot/autoChat/locale/en.cfg diff --git a/old/modules/ExpGamingBot/autoChat/locale/fr.cfg b/old/modules/DONE/Bot/autoChat/locale/fr.cfg similarity index 100% rename from old/modules/ExpGamingBot/autoChat/locale/fr.cfg rename to old/modules/DONE/Bot/autoChat/locale/fr.cfg diff --git a/old/modules/ExpGamingBot/autoChat/locale/nl.cfg b/old/modules/DONE/Bot/autoChat/locale/nl.cfg similarity index 100% rename from old/modules/ExpGamingBot/autoChat/locale/nl.cfg rename to old/modules/DONE/Bot/autoChat/locale/nl.cfg diff --git a/old/modules/ExpGamingBot/autoChat/locale/sv-SE.cfg b/old/modules/DONE/Bot/autoChat/locale/sv-SE.cfg similarity index 100% rename from old/modules/ExpGamingBot/autoChat/locale/sv-SE.cfg rename to old/modules/DONE/Bot/autoChat/locale/sv-SE.cfg diff --git a/old/modules/ExpGamingBot/autoChat/softmod.json b/old/modules/DONE/Bot/autoChat/softmod.json similarity index 100% rename from old/modules/ExpGamingBot/autoChat/softmod.json rename to old/modules/DONE/Bot/autoChat/softmod.json diff --git a/old/modules/ExpGamingCommands/softmod.json b/old/modules/DONE/Commands/ExpGamingCommands/softmod.json similarity index 100% rename from old/modules/ExpGamingCommands/softmod.json rename to old/modules/DONE/Commands/ExpGamingCommands/softmod.json diff --git a/old/modules/ExpGamingCommands/home/control.lua b/old/modules/DONE/Commands/home/control.lua similarity index 100% rename from old/modules/ExpGamingCommands/home/control.lua rename to old/modules/DONE/Commands/home/control.lua diff --git a/old/modules/ExpGamingCommands/home/locale/en.cfg b/old/modules/DONE/Commands/home/locale/en.cfg similarity index 100% rename from old/modules/ExpGamingCommands/home/locale/en.cfg rename to old/modules/DONE/Commands/home/locale/en.cfg diff --git a/old/modules/ExpGamingCommands/home/softmod.json b/old/modules/DONE/Commands/home/softmod.json similarity index 100% rename from old/modules/ExpGamingCommands/home/softmod.json rename to old/modules/DONE/Commands/home/softmod.json diff --git a/old/modules/ExpGamingBot/softmod.json b/old/modules/DONE/ExpGamingBot/softmod.json similarity index 100% rename from old/modules/ExpGamingBot/softmod.json rename to old/modules/DONE/ExpGamingBot/softmod.json