diff --git a/README.md b/README.md index 2c9d02e7..8ff71f05 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ Explosive Gaming (often ExpGaming) is a server hosting community with a strong f ## Contributing -All are welcome to make pull requests and issues for this scenario, if you are in any doubt please ask someone in our [discord]. If you do not know lua and don't feel like learning you can always make a [feature request]. Please keep in mind while making code changes: +All are welcome to make pull requests and issues for this scenario, if you are in any doubt please ask someone in our [discord]. If you do not know lua and don't feel like learning you can always make a [feature request]. All our docs can be found [here][docs]. Please keep in mind while making code changes: * New features should have the branch names: `feature/feature-name` * New features are merged into `dev` after it has been completed. @@ -111,6 +111,7 @@ All are welcome to make pull requests and issues for this scenario, if you are i The Explosive Gaming codebase is licensed under the [GNU General Public License v3.0](LICENSE) +[docs]: https://explosivegaming.github.io/scenario/ [issues]: https://github.com/explosivegaming/scenario/issues/new/choose [website]: https://explosivegaming.nl [discord]: https://discord.explosivegaming.nl diff --git a/docs/addons/Advanced-Start.html b/docs/addons/Advanced-Start.html index 0b56fc11..17a11fd8 100644 --- a/docs/addons/Advanced-Start.html +++ b/docs/addons/Advanced-Start.html @@ -348,7 +348,7 @@ generated by LDoc
diff --git a/docs/addons/Chat-Popups.html b/docs/addons/Chat-Popups.html index 75114dcc..ec447b0d 100644 --- a/docs/addons/Chat-Popups.html +++ b/docs/addons/Chat-Popups.html @@ -349,7 +349,7 @@ generated by LDoc diff --git a/docs/addons/Chat-Reply.html b/docs/addons/Chat-Reply.html index be18394a..227a2701 100644 --- a/docs/addons/Chat-Reply.html +++ b/docs/addons/Chat-Reply.html @@ -376,7 +376,7 @@ generated by LDoc diff --git a/docs/addons/Compilatron.html b/docs/addons/Compilatron.html index 3ad91922..dc49b78b 100644 --- a/docs/addons/Compilatron.html +++ b/docs/addons/Compilatron.html @@ -585,7 +585,7 @@ generated by LDoc diff --git a/docs/addons/Damage-Popups.html b/docs/addons/Damage-Popups.html index 42cd4094..c5d5f078 100644 --- a/docs/addons/Damage-Popups.html +++ b/docs/addons/Damage-Popups.html @@ -349,7 +349,7 @@ generated by LDoc diff --git a/docs/addons/Death-Logger.html b/docs/addons/Death-Logger.html index 01b1f797..71cc9bde 100644 --- a/docs/addons/Death-Logger.html +++ b/docs/addons/Death-Logger.html @@ -404,7 +404,7 @@ generated by LDoc diff --git a/docs/addons/Discord-Alerts.html b/docs/addons/Discord-Alerts.html index cce518e8..27d0af48 100644 --- a/docs/addons/Discord-Alerts.html +++ b/docs/addons/Discord-Alerts.html @@ -460,7 +460,7 @@ generated by LDoc diff --git a/docs/addons/Player-Colours.html b/docs/addons/Player-Colours.html index d17bb676..7d67adeb 100644 --- a/docs/addons/Player-Colours.html +++ b/docs/addons/Player-Colours.html @@ -404,7 +404,7 @@ generated by LDoc diff --git a/docs/addons/Pollution-Grading.html b/docs/addons/Pollution-Grading.html index bfc08f0d..d488a111 100644 --- a/docs/addons/Pollution-Grading.html +++ b/docs/addons/Pollution-Grading.html @@ -320,7 +320,7 @@ generated by LDoc diff --git a/docs/addons/Scorched-Earth.html b/docs/addons/Scorched-Earth.html index 09d37fe9..55bea826 100644 --- a/docs/addons/Scorched-Earth.html +++ b/docs/addons/Scorched-Earth.html @@ -404,7 +404,7 @@ generated by LDoc diff --git a/docs/addons/Spawn-Area.html b/docs/addons/Spawn-Area.html index 3ba5ee0d..13dfba39 100644 --- a/docs/addons/Spawn-Area.html +++ b/docs/addons/Spawn-Area.html @@ -376,7 +376,7 @@ generated by LDoc diff --git a/docs/commands/Admin-Chat.html b/docs/commands/Admin-Chat.html index e8b3303d..731be00d 100644 --- a/docs/commands/Admin-Chat.html +++ b/docs/commands/Admin-Chat.html @@ -388,7 +388,7 @@ generated by LDoc diff --git a/docs/commands/Bonus.html b/docs/commands/Bonus.html index 4b41076e..d49279c2 100644 --- a/docs/commands/Bonus.html +++ b/docs/commands/Bonus.html @@ -500,7 +500,7 @@ generated by LDoc diff --git a/docs/commands/Cheat-Mode.html b/docs/commands/Cheat-Mode.html index cb0d0a09..accc40eb 100644 --- a/docs/commands/Cheat-Mode.html +++ b/docs/commands/Cheat-Mode.html @@ -361,7 +361,7 @@ generated by LDoc diff --git a/docs/commands/Clear-Inventory.html b/docs/commands/Clear-Inventory.html index 27f45940..e20883e3 100644 --- a/docs/commands/Clear-Inventory.html +++ b/docs/commands/Clear-Inventory.html @@ -388,7 +388,7 @@ generated by LDoc diff --git a/docs/commands/Debug.html b/docs/commands/Debug.html index e2f78d24..af847b74 100644 --- a/docs/commands/Debug.html +++ b/docs/commands/Debug.html @@ -365,7 +365,7 @@ generated by LDoc diff --git a/docs/commands/Find.html b/docs/commands/Find.html index c727cd0e..fc61f8cf 100644 --- a/docs/commands/Find.html +++ b/docs/commands/Find.html @@ -360,7 +360,7 @@ generated by LDoc diff --git a/docs/commands/Help.html b/docs/commands/Help.html index d5178346..c5d73042 100644 --- a/docs/commands/Help.html +++ b/docs/commands/Help.html @@ -404,7 +404,7 @@ generated by LDoc diff --git a/docs/commands/Home.html b/docs/commands/Home.html index a1ba8bce..05da9559 100644 --- a/docs/commands/Home.html +++ b/docs/commands/Home.html @@ -458,7 +458,7 @@ generated by LDoc diff --git a/docs/commands/Interface.html b/docs/commands/Interface.html index c38850c0..bc2e0590 100644 --- a/docs/commands/Interface.html +++ b/docs/commands/Interface.html @@ -416,7 +416,7 @@ generated by LDoc diff --git a/docs/commands/Jail.html b/docs/commands/Jail.html index 2f087f4c..6ff4802e 100644 --- a/docs/commands/Jail.html +++ b/docs/commands/Jail.html @@ -611,7 +611,7 @@ generated by LDoc diff --git a/docs/commands/Kill.html b/docs/commands/Kill.html index 33cd787e..a16c18b0 100644 --- a/docs/commands/Kill.html +++ b/docs/commands/Kill.html @@ -389,7 +389,7 @@ generated by LDoc diff --git a/docs/commands/Me.html b/docs/commands/Me.html index ee42acca..2f8cb3f4 100644 --- a/docs/commands/Me.html +++ b/docs/commands/Me.html @@ -360,7 +360,7 @@ generated by LDoc diff --git a/docs/commands/Rainbow.html b/docs/commands/Rainbow.html index b7f2a851..83127954 100644 --- a/docs/commands/Rainbow.html +++ b/docs/commands/Rainbow.html @@ -388,7 +388,7 @@ generated by LDoc diff --git a/docs/commands/Repair.html b/docs/commands/Repair.html index 19e506ca..dfc8fde0 100644 --- a/docs/commands/Repair.html +++ b/docs/commands/Repair.html @@ -321,7 +321,7 @@ generated by LDoc diff --git a/docs/commands/Reports.html b/docs/commands/Reports.html index c0f17772..bb852d95 100644 --- a/docs/commands/Reports.html +++ b/docs/commands/Reports.html @@ -585,7 +585,7 @@ generated by LDoc diff --git a/docs/commands/Roles.html b/docs/commands/Roles.html index d9a1f285..338a0c5e 100644 --- a/docs/commands/Roles.html +++ b/docs/commands/Roles.html @@ -557,7 +557,7 @@ generated by LDoc diff --git a/docs/commands/Spawn.html b/docs/commands/Spawn.html index bb58d8a9..9eba8a8f 100644 --- a/docs/commands/Spawn.html +++ b/docs/commands/Spawn.html @@ -389,7 +389,7 @@ generated by LDoc diff --git a/docs/commands/Tag.html b/docs/commands/Tag.html index 43fab495..b8609e4a 100644 --- a/docs/commands/Tag.html +++ b/docs/commands/Tag.html @@ -443,7 +443,7 @@ generated by LDoc diff --git a/docs/commands/Teleport.html b/docs/commands/Teleport.html index 42089cc1..eeed3aa0 100644 --- a/docs/commands/Teleport.html +++ b/docs/commands/Teleport.html @@ -484,7 +484,7 @@ generated by LDoc diff --git a/docs/commands/Warnings.html b/docs/commands/Warnings.html index 0bb7d855..337f8b93 100644 --- a/docs/commands/Warnings.html +++ b/docs/commands/Warnings.html @@ -569,7 +569,7 @@ generated by LDoc diff --git a/docs/config.ld b/docs/config.ld index f5a7a308..d3b5fe24 100644 --- a/docs/config.ld +++ b/docs/config.ld @@ -1,5 +1,5 @@ file = '../' -dir = '../doc' +dir = '../docs' project = 'ExpGaming Scenario' title = 'ExpGaming Scenario' description = 'Explosive Gaming\'s server scenario for 0.17' @@ -10,8 +10,8 @@ not_luadoc = true no_lua_ref = true template_escape = ">" topics = {"../README.md", "../LICENSE"} -style = '../doc' -template = '../doc' +style = '../docs' +template = '../docs' no_space_before_args = true merge=true @@ -23,8 +23,8 @@ new_type("gui", "Guis", true) new_type("config", "Configs", true, "Settings") new_type("dep", "Dependencies", false) -new_type("element", "Elements", false) new_type("setting", "Settings", false) +new_type("element", "Elements", false, "Properties / Events") new_type("event", "Events", false, "Event Parameters") new_type("command", "Commands", false, "Command Parameters") diff --git a/docs/configs/Advanced-Start.html b/docs/configs/Advanced-Start.html index 46ef69a1..72c02f54 100644 --- a/docs/configs/Advanced-Start.html +++ b/docs/configs/Advanced-Start.html @@ -506,7 +506,7 @@ generated by LDoc diff --git a/docs/configs/Bonuses.html b/docs/configs/Bonuses.html index e1806bce..31d8e33c 100644 --- a/docs/configs/Bonuses.html +++ b/docs/configs/Bonuses.html @@ -237,7 +237,7 @@ generated by LDoc diff --git a/docs/configs/Chat-Reply.html b/docs/configs/Chat-Reply.html index c8ef6dfa..da119978 100644 --- a/docs/configs/Chat-Reply.html +++ b/docs/configs/Chat-Reply.html @@ -485,7 +485,7 @@ generated by LDoc diff --git a/docs/configs/Commands-Auth-Admin.html b/docs/configs/Commands-Auth-Admin.html index ffc290aa..fa578e05 100644 --- a/docs/configs/Commands-Auth-Admin.html +++ b/docs/configs/Commands-Auth-Admin.html @@ -294,7 +294,7 @@ generated by LDoc diff --git a/docs/configs/Commands-Auth-Roles.html b/docs/configs/Commands-Auth-Roles.html index 1f3c18d9..2e83f8aa 100644 --- a/docs/configs/Commands-Auth-Roles.html +++ b/docs/configs/Commands-Auth-Roles.html @@ -320,7 +320,7 @@ generated by LDoc diff --git a/docs/configs/Commands-Auth-Runtime-Disable.html b/docs/configs/Commands-Auth-Runtime-Disable.html index f68dc361..e908fa8c 100644 --- a/docs/configs/Commands-Auth-Runtime-Disable.html +++ b/docs/configs/Commands-Auth-Runtime-Disable.html @@ -442,7 +442,7 @@ generated by LDoc diff --git a/docs/configs/Commands-Parse-Roles.html b/docs/configs/Commands-Parse-Roles.html index d18424fa..3206b122 100644 --- a/docs/configs/Commands-Parse-Roles.html +++ b/docs/configs/Commands-Parse-Roles.html @@ -354,7 +354,7 @@ generated by LDoc diff --git a/docs/configs/Commands-Parse.html b/docs/configs/Commands-Parse.html index 2f413722..14f65272 100644 --- a/docs/configs/Commands-Parse.html +++ b/docs/configs/Commands-Parse.html @@ -338,7 +338,7 @@ see ./expcore/commands.lua for more details generated by LDoc diff --git a/docs/configs/Compilatron.html b/docs/configs/Compilatron.html index 5bf4b1ba..2d0f47b4 100644 --- a/docs/configs/Compilatron.html +++ b/docs/configs/Compilatron.html @@ -354,7 +354,7 @@ generated by LDoc diff --git a/docs/configs/Death-Logger.html b/docs/configs/Death-Logger.html index 76aec8f5..f03d13cd 100644 --- a/docs/configs/Death-Logger.html +++ b/docs/configs/Death-Logger.html @@ -416,7 +416,7 @@ generated by LDoc diff --git a/docs/configs/Discord-Alerts.html b/docs/configs/Discord-Alerts.html index 03ca2c6d..e7cc6d8b 100644 --- a/docs/configs/Discord-Alerts.html +++ b/docs/configs/Discord-Alerts.html @@ -237,7 +237,7 @@ generated by LDoc diff --git a/docs/configs/File-Loader.html b/docs/configs/File-Loader.html index 58c755b1..25d76c3b 100644 --- a/docs/configs/File-Loader.html +++ b/docs/configs/File-Loader.html @@ -240,7 +240,7 @@ generated by LDoc diff --git a/docs/configs/Permission-Groups.html b/docs/configs/Permission-Groups.html index 7043ae72..5798d322 100644 --- a/docs/configs/Permission-Groups.html +++ b/docs/configs/Permission-Groups.html @@ -295,7 +295,7 @@ generated by LDoc diff --git a/docs/configs/Player-List.html b/docs/configs/Player-List.html index c6e1c748..28764dd5 100644 --- a/docs/configs/Player-List.html +++ b/docs/configs/Player-List.html @@ -812,7 +812,7 @@ generated by LDoc diff --git a/docs/configs/Pollution-Grading.html b/docs/configs/Pollution-Grading.html index 9eb9892f..3f407af5 100644 --- a/docs/configs/Pollution-Grading.html +++ b/docs/configs/Pollution-Grading.html @@ -384,7 +384,7 @@ generated by LDoc diff --git a/docs/configs/Popup-Messages.html b/docs/configs/Popup-Messages.html index 39690dd2..e217cb89 100644 --- a/docs/configs/Popup-Messages.html +++ b/docs/configs/Popup-Messages.html @@ -414,7 +414,7 @@ generated by LDoc diff --git a/docs/configs/Preset-Player-Colours.html b/docs/configs/Preset-Player-Colours.html index 9d37a9a8..6ded0dd1 100644 --- a/docs/configs/Preset-Player-Colours.html +++ b/docs/configs/Preset-Player-Colours.html @@ -324,7 +324,7 @@ generated by LDoc diff --git a/docs/configs/Repair.html b/docs/configs/Repair.html index 8625da88..04430dd7 100644 --- a/docs/configs/Repair.html +++ b/docs/configs/Repair.html @@ -414,7 +414,7 @@ generated by LDoc diff --git a/docs/configs/Rockets.html b/docs/configs/Rockets.html index 9be2580d..2a142796 100644 --- a/docs/configs/Rockets.html +++ b/docs/configs/Rockets.html @@ -834,7 +834,7 @@ generated by LDoc diff --git a/docs/configs/Roles.html b/docs/configs/Roles.html index c1aebec6..3fbacb0e 100644 --- a/docs/configs/Roles.html +++ b/docs/configs/Roles.html @@ -292,7 +292,7 @@ generated by LDoc diff --git a/docs/configs/Science.html b/docs/configs/Science.html index d279267e..873dbf53 100644 --- a/docs/configs/Science.html +++ b/docs/configs/Science.html @@ -354,7 +354,7 @@ generated by LDoc diff --git a/docs/configs/Scorched-Earth.html b/docs/configs/Scorched-Earth.html index 508bde53..5f2f2131 100644 --- a/docs/configs/Scorched-Earth.html +++ b/docs/configs/Scorched-Earth.html @@ -388,7 +388,7 @@ generated by LDoc diff --git a/docs/configs/Spawn-Area.html b/docs/configs/Spawn-Area.html index 9b9a9a5a..ebefadb6 100644 --- a/docs/configs/Spawn-Area.html +++ b/docs/configs/Spawn-Area.html @@ -744,7 +744,7 @@ generated by LDoc diff --git a/docs/configs/Tasks.html b/docs/configs/Tasks.html index 6072ae03..2ea51a33 100644 --- a/docs/configs/Tasks.html +++ b/docs/configs/Tasks.html @@ -384,7 +384,7 @@ generated by LDoc diff --git a/docs/configs/Warnings.html b/docs/configs/Warnings.html index f3edf5aa..1971da7d 100644 --- a/docs/configs/Warnings.html +++ b/docs/configs/Warnings.html @@ -355,7 +355,7 @@ generated by LDoc diff --git a/docs/configs/Warps.html b/docs/configs/Warps.html index 8800c822..c90c3b4f 100644 --- a/docs/configs/Warps.html +++ b/docs/configs/Warps.html @@ -684,7 +684,7 @@ generated by LDoc diff --git a/docs/control/Jail.html b/docs/control/Jail.html index 5f68c34b..8b2073fa 100644 --- a/docs/control/Jail.html +++ b/docs/control/Jail.html @@ -1208,7 +1208,7 @@ generated by LDoc diff --git a/docs/control/Production.html b/docs/control/Production.html index ccfd8f5f..cfc5135f 100644 --- a/docs/control/Production.html +++ b/docs/control/Production.html @@ -1329,7 +1329,7 @@ generated by LDoc diff --git a/docs/control/Reports.html b/docs/control/Reports.html index ddcdfb3e..02a29320 100644 --- a/docs/control/Reports.html +++ b/docs/control/Reports.html @@ -1110,7 +1110,7 @@ generated by LDoc diff --git a/docs/control/Rockets.html b/docs/control/Rockets.html index 431f9815..4cd079d7 100644 --- a/docs/control/Rockets.html +++ b/docs/control/Rockets.html @@ -984,7 +984,7 @@ generated by LDoc diff --git a/docs/control/Tasks.html b/docs/control/Tasks.html index 7fa706cc..0a82275c 100644 --- a/docs/control/Tasks.html +++ b/docs/control/Tasks.html @@ -1039,7 +1039,7 @@ generated by LDoc diff --git a/docs/control/Warnings.html b/docs/control/Warnings.html index c1ac81e7..cca92779 100644 --- a/docs/control/Warnings.html +++ b/docs/control/Warnings.html @@ -1465,7 +1465,7 @@ generated by LDoc diff --git a/docs/control/Warps.html b/docs/control/Warps.html index 5fa18a14..4af6171d 100644 --- a/docs/control/Warps.html +++ b/docs/control/Warps.html @@ -1413,7 +1413,7 @@ generated by LDoc diff --git a/docs/core/Commands.html b/docs/core/Commands.html index 683bf908..b6e82a2c 100644 --- a/docs/core/Commands.html +++ b/docs/core/Commands.html @@ -1972,7 +1972,7 @@ generated by LDoc diff --git a/docs/core/Common-Library.html b/docs/core/Common-Library.html index 44c6136e..ee9e8780 100644 --- a/docs/core/Common-Library.html +++ b/docs/core/Common-Library.html @@ -357,6 +357,22 @@Returns a desync safe file path for the current file
+ + + + Parameters: + +Much faster method for inserting items into an array
+ + + + Parameters: + +-- Adding 1000 values into the middle of the array
+local tbl = {}
+local values = {}
+for i = 1,1000 do tbl[i] = i values[i] = i end
+Common.array_insert(tbl,500,values) -- around 0.4ms
+
+
+
+ Much faster method for inserting keys into a table
+ + + + Parameters: + +-- Merging two tables
+local tbl = {}
+local tbl2 = {}
+for i = 1,100 do tbl[i] = i tbl['_'..i] = i tbl2[i] = i tbl2['__'..i] = i end
+Common.table_insert(tbl,50,tbl2)
+
+
+
+ Used to resolve a value that could also be a function returning that value
+ + + + Parameters: + +-- Default value handling
+-- if default value is not a function then it is returned
+-- if it is a function then it is called with the first argument being self
+local value = Common.resolve_value(self.defaut_value,self)
+
+
@@ -2418,7 +2746,7 @@
generated by LDoc
Core Module - ExpStyle
+ + + + + + + + + + + + +| expcore.gui | +
| gui.concept.frame | +
| gui.concept.flow | +
| gui.concept.table | +
| gui.concept.scroll | +
| expcore.common | +
| alignment | +A flow which can be used to align text and other elements | +
| container | +A container frame that can be used to add a boader around your content | +
| data_label | +A label pair which has a static label and a data label which can be changed | +
| footer | +A frame that acts as a footer to a section of content | +
| header | +A frame that acts as a header to a section of content | +
| scroll_table | +A table that is inside a vertical scroll area | +
| time_label | +A label that show time in a nice, user friendly way | +
| toggle_button | +A button that will toggle its caption each time it is pressed | +
| unit_label | +A label triplet which has a static label, a data label which can be changed, and a unit label | +
| data_label:update_data_element(element, data) | +Updates the caption and tooltip of the data label using the data format function | +
| data_label:update_from_parent(parent, data) | +Updates the caption and tooltip of the data label using the data format function, given the parent of the data label | +
| time_label:update_time(element, time) | +Updates the time that is on a label | +
| unit_label:update_data_element(element, data) | +Updates the caption and tooltip and unit of the data label using the data format function | +
| unit_label:update_from_parent(parent, data) | +Updates the caption and tooltip and unit of the unit label using the data format function, given the parent of the unit label | +
A flow which can be used to align text and other elements
+ + + + + + + + + + + See also: +-- Concept Structure
+-- Root
+--> [alignment] - the alignment area
+Gui.new_concept('alignment')
+:set_horizontal_align('center')
+
+
+
+ A container frame that can be used to add a boader around your content
+ + + + + + + + + + + See also: +-- Concept Structure
+-- Root
+--> [container] - the outer frame
+-->> container - the content area
+Gui.new_concept('container')
+
+
+
+ A label pair which has a static label and a data label which can be changed
+ + + + + + + + + + + See also: +-- Concept Structure
+-- Root
+--> [data_label] - the static label
+--> [properties.data_name] - the data label which can be updated
+Gui.new_concept('data_label')
+:set_data_label_name('game_ticks')
+:set_data_caption('0')
+:set_data_format(function(concept,element,data,...)
+ -- This is used with update_data_element and update_from_parent
+ local caption = tostirng('data')
+ local tooltip = 'This game has beeing running for: '..caption..' ticks'
+ return caption, tooltip
+end)
+
+
+
+ A frame that acts as a footer to a section of content
+ + + + Properties / Events: + +-- Concept Structure
+-- Root
+--> [footer] - the footer frame
+-->> footer_caption - the lable with the title in it
+-->> footer_content - the area to contain butons
+Gui.new_concept('footer')
+:set_title('Example Footer')
+
+
+
+ A frame that acts as a header to a section of content
+ + + + Properties / Events: + +-- Concept Structure
+-- Root
+--> [header] - the header frame
+-->> header_caption - the lable with the title in it
+-->> header_content - the area to contain butons
+Gui.new_concept('header')
+:set_title('Example Header')
+
+
+
+ A table that is inside a vertical scroll area
+ + + + Properties / Events: + +-- Concept Structure
+-- Root
+--> [scroll_table] - the scroll area
+-->> table - the table area
+Gui.new_concept('scroll_table')
+:set_height(200)
+:set_column_count(2)
+
+
+
+ A label that show time in a nice, user friendly way
+ + + + Properties / Events: + +-- Concept Structure
+-- Root
+--> [time_label] - the label with the time
+local time_label =
+Gui.new_concept('time_label')
+:set_use_hours(true)
+:set_time(game.tick)
+
+time_label:update_time(element,game.tick)
+
+
+
+ A button that will toggle its caption each time it is pressed
+ + + + Properties / Events: + +-- Concept Structure
+-- Root
+--> [toggle_button] - the header button
+Gui.new_concept('toggle_button')
+:set_caption('<')
+:set_tooltip('Press to close.')
+:set_alt_caption('>')
+:set_alt_tooltip('Press to open.')
+:on_click(function(event)
+ local state = event.state and 'close' or 'open'
+ event.player.print('Toggle button is now: '..state)
+end)
+
+
+
+ A label triplet which has a static label, a data label which can be changed, and a unit label
+ + + + + + + + + + + See also: +-- Concept Structure
+-- Root
+--> [unit_label] - the static label
+--> [properties.data_name] - the data label which can be updated
+--> [properties.data_name..'_unit'] - the data label unit which can be updated
+Gui.new_concept('unit_label')
+:set_data_label_name('game_ticks')
+:set_data_caption('0')
+:set_data_unit('ticks')
+:set_data_format(function(concept,element,data,...)
+ -- This is used with update_data_element and update_from_parent
+ local caption = tostirng(data)
+ local unit = data > 1 and 'ticks' or 'tick'
+ local tooltip = 'This game has beeing running for: '..caption..' ticks'
+ return caption, unit, tooltip
+end)
+
+
+
+
+ Updates the caption and tooltip of the data label using the data format function
+ + + + Parameters: + +-- Updating the data to the current game tick
+data_label:update_data_element(element,game.tick)
+
+
+
+ Updates the caption and tooltip of the data label using the data format function, given the parent of the data label
+ + + + Parameters: + +-- Updating the data to the current game tick
+data_label:update_from_parent(parent,game.tick)
+
+
+
+ Updates the time that is on a label
+ + + + Parameters: + +-- Update the time to show game time
+time_label:update_time(element,game.time)
+
+
+
+ Updates the caption and tooltip and unit of the data label using the data format function
+ + + + Parameters: + +-- Updating the data to the current game tick
+unit_label:update_data_element(element,game.tick)
+
+
+
+ Updates the caption and tooltip and unit of the unit label using the data format function, given the parent of the unit label
+ + + + Parameters: + +-- Updating the data to the current game tick
+unit_label:update_from_parent(parent,game.tick)
+
+
+
+
+
+
+
+
----- Basic Use
- -- At the most basic level this allows for the naming of locations to store in the global table, the second feature is that you are
- -- able to listen for updates of this value, which means that when ever the set function is called it will trigger the update callback.
-
- -- This may be useful when storing config values and when they get set you want to make sure it is taken care of, or maybe you want
- -- to have a value that you can trigger an update of from different places.
-
- -- This will register a new location called 'scenario.difficulty'
- -- note that setting a start value is optional and we could take nil to mean normal
- Store.register('scenario.difficulty',function(value)
- game.print('The scenario difficulty has be set to: '..value)
- end)
+-- The data store module is designed to be an alterative way to store data in the global table
+-- each piece of data is stored at a location and optional key of that location
+-- it is recomented that you use a local varible to store the location
+local scenario_difficuly = Store.uid_location()
+local team_scores = 'team-scores'
- -- This will set the value in the store to 'hard' and will trigger the update callback which will print a message to the game
- Store.set('scenario.difficulty','hard')
+-- Setting and getting data is then as simple as
+-- note that when storing a table you must use Store.update
+Store.set(scenario_difficuly,'Hard')
+Store.set(team_scores,game.player.force.name,20)
- -- This will return 'hard'
- Store.get('scenario.difficulty')
-
----- Using Children
- -- One limitation of store is that all locations must be registered to avoid desyncs, to get round this issue "children" can be used.
- -- When you set the value of a child it does not have its own update callback so rather the "parent" location which has been registered
- -- will have its update value called with a second param of the name of that child.
+Store.get(scenario_difficuly) -- returns 'Hard'
+Store.get(team_scores,game.player.force.name) -- returns 20
- -- This may be useful when you want a value of each player or force and since you cant register every player at the start you must use
- -- the players name as the child name.
-
- -- This will register the location 'scenario.score' where we plan to use force names as the child
- Store.register('scenario.score',function(value,child)
- game.print(child..' now has a score of '..value)
- end)
+Store.update(team_scores,game.player.force.name,function(value,key)
+ return value + 10 -- add 10 to the score
+end)
- -- This will return nil, but will not error as children don't need to be registered
- Store.get('scenario.score','player')
+-- The reason for using stores over global is the abilty to watch for updates
+-- for stores to work you must register them, often at the end of the file
+Store.register(scenario_difficuly,function(value)
+ game.print('Scenario difficulty has been set to: '..value)
+end)
- -- This will set 'player' to have a value of 10 for 'scenario.score' and trigger the game message print
- Store.set('scenario.score','player',10)
+Store.register(team_scores,function(value,key)
+ game.print('Team '..key..' now has a score of '..value)
+end)
- -- This would be the similar to Store.get however this will return the names of all the children
- Store.get_children('scenario.score')
-
----- Using Sync
- -- There is the option to use synced values which is the same as a normal value however you can combine this with an external script
- -- which can read the output from 'script-output/log/store.log' and have it send rcon commands back to the game allowing for cross instance
- -- syncing of values.
-
- -- This may be useful when you want to have a value change effect multiple instances or even if you just want a database to store values so
- -- you can sync data between map resets.
-
- -- This example will register the location 'statistics.total-play-time' where we plan to use plan names as the child
- -- note that the location must be the same across instances
- Store.register('statistics.total-play-time',true,function(value,child)
- game.print(child..' now has now played for '..value)
- end)
+-- This can be very powerful when working with data that can be changed for a number of locations
+-- with this module you can enable any location to output its changes to a file
+-- say we wanted team scores to be synced across servers or between saves
+-- although you will need to set up a method of storing the data outside the game
+Store.register(team_scores,true,function(value,key)
+ game.print('Team '..key..' now has a score of '..value)
+end)
- -- Use of set and are all the same as non synced but you should include from_sync as true
-
-
----- Alternative method
- -- Some people may prefer to use a variable rather than a string for formating reasons here is an example. Also for any times when
- -- there will be little external input Store.uid_location() can be used to generate non conflicting locations, uid_location will also
- -- be used if you give a nil location.
-
- local store_game_speed =
- Store.register(function(value)
- game.print('The game speed has been set to: '..value)
- end)
+-- If you want multiple handlers on one store location then you can register to the raw event
+Event.add(Store.events.on_value_changed,function(event)
+ game.print('Store '..event.location..'/'..event.key..' was updated to: '..event.value)
+end)
@@ -333,33 +306,41 @@
Registers a new location with an update callback which is triggered when the value updates
+ + + + Parameters: + +-- Registering a new store location
+local store_id = Store.register()
+ -- Registering a new store location, with custom update callback
+local store_id = Store.uid_location()
+Store.register(store_id,function(value,key)
+ game.print('Store '..store_id..'/'..key..' was updated to: '..value)
+end)
+
+
+
+ Gets the value stored at a location, this location must be registered
+ + + + Parameters: + +-- Getting the data at a store location
+local data = Store.get(store_id_no_keys)
+local data = Store.get(store_id_with_keys,'key_one')
+
+
+
+ Sets the value at a location, this location must be registered
+ + + + Parameters: + +-- Setting the data at a store location
+Store.set(store_id_no_keys,'Hello, World!')
+Store.set(store_id_with_keys,'key_one','Hello, World!')
+
+
+
+ Allows for updating a value based on the current value; only valid way to change tables in a store
+ + + + Parameters: + +-- Updating a value stored at a location
+Store.update(store_id_no_keys,function(value)
+ return value + 1
+end)
+Store.update(store_id_with_keys,'key_one',function(value)
+ return value + 1
+end)
+ -- Updating a table stored at a location
+Store.update(store_id_no_keys,function(value)
+ value.ctn = value.ctn + 1
+end)
+Store.update(store_id_with_keys,'key_one',function(value)
+ value.ctn = value.ctn + 1
+end)
+
+
+
+ Allows for updating all values at a location based on the current value; only valid way to change tables in a store
+ + + + Parameters: + +-- Updating all values at a location
+Store.update(store_id_with_keys,function(value)
+ return value + 1
+end)
+ -- Updating all tables at a location
+Store.update(store_id_with_keys,function(value)
+ value.ctn = value.ctn + 1
+end)
+
+
+
+ Sets the value at a location to nil, this location must be registered
+ + + + Parameters: + +-- Clear the data at a location
+Store.clear(store_id_no_keys)
+Store.clear(store_id_with_keys,'key_one')
+
+
+
+ Gets all non nil keys at a location, keys can be added and removed during runtime +this is similar to Store.get but will always return a table even if it is empty
+ + + + Parameters: + +-- Get all keys at a store location
+local keys = Store.get_keys(store_id_with_keys)
+
+
+
+ -- Check that a store is registered
+local registerd = Store.is_registered(store_id)
@@ -561,445 +1182,9 @@
-
-
-
- Registers a new location with an update callback which is triggered when the value updates
- - - - Parameters: - -Gets the value stored at a location, this location must be registered
- - - - Parameters: - -Sets the value at a location, this location must be registered
- - - - Parameters: - -Sets the value at a location to nil, this location must be registered
- - - - Parameters: - -Gets all non nil children at a location, children can be added and removed during runtime - this is similar to Store.get but will always return a table even if it is empty
- - - - Parameters: - --- Get a new unique store id
+local store_id = Store.uid_location()
@@ -1018,7 +1203,7 @@
generated by LDoc
Core Module - Toolbar
+ + + + + + + + + + + + +| expcore.gui | +
| expcore.roles | +
| utils.event | +
| utils.game | +
| mod-gui | +
| Gui.concept.button | +
| allowed(player, concept_name) | +Used to test if a player is allowed to use a button on the toolbar, if you are not using expcore.roles then change this function | +
| set_permission_alias(concept_name, alias) | +Use to add an alias for the allowed test, alias is what is tested for rather than the concept name | +
| add_button_concept(concept) | +Adds a concept to be drawn to the button area and allows it to be toggled with the toggle toolbar button | +
| update_buttons(player) | +Updates all the buttons for a player, this means hide and show buttons based on permissions | +
| get_visible_buttons(player) | +Returns an array of buttons names that the given player is able to see, returns none if toolbar hidden | +
| toolbar-button | +The base element to be used with the toolbar, others can be used but this is recomented | +
| add_frame_concept(concept) | +Adds a frame concept to the toolbar frame area, this will not add a button to the toolbar | +
| hide_frames(player) | +Hides all the frames for a player | +
| get_visible_frames(player) | +Gets an array of the names of all the visible frames for a player | +
| toolbar-frame | +The base toolbar frame, others can be used but this is recomented | +
| Toolbar.frame:get_content(player) | +Gets the content area of the frame concept for this player, each player only has one area | +
| Toolbar.frame:toggle_visible_state(player) | +Toggles the visibilty of this concept for the given player | +
| Toolbar.frame:get_visible_state(player) | +Gets the current visibilty state of this conept for this player | +
| Toolbar.frame:update(player[, event]) | +Triggers an update of the content within the concept for this player, uses on_update handlers | +
| Toolbar.frame:update_all([event]) | +Triggers an update of the content with in this frame for all players | +
| toolbar | +The main toolbar element, draws, updates, and controls the other concepts | +
| toolbar-toggle | +Button which toggles the the visible state of all toolbar buttons, triggers on_button_update | +
| toolbar-clear | +Button which hides all visible toolbar frames, triggers on_hide_frames | +
Used to test if a player is allowed to use a button on the toolbar, if you are not using expcore.roles then change this function
+ + + + Parameters: + +-- Test if a player can use 'test-player-list'
+local allowed = Toolbar.allowed(game.player,'test-player-list')
+
+
+
+ Use to add an alias for the allowed test, alias is what is tested for rather than the concept name
+ + + + Parameters: + +-- Adding an alias for the 'test-player-list' concept
+Toolbar.set_permission_alias('test-player-list','gui/player-list')
+
+
+
+
+ Adds a concept to be drawn to the button area and allows it to be toggled with the toggle toolbar button
+ + + + Parameters: + +-- Adding a basic button to the toolbar
+local new_button =
+Gui.new_concept('button')
+:set_caption('Click Me')
+:on_click(function(event)
+ event.player.print('You Clicked Me!!')
+end)
+
+Toolbar.add_button_concept(new_button)
+
+
+
+ Updates all the buttons for a player, this means hide and show buttons based on permissions
+ + + + Parameters: + +-- Updating your toolbar
+Toolbar.update_buttons(player)
+
+
+
+ Returns an array of buttons names that the given player is able to see, returns none if toolbar hidden
+ + + + Parameters: + +-- Get a list of all your visible buttons
+Toolbar.get_visible_buttons(game.player)
+
+
+
+ The base element to be used with the toolbar, others can be used but this is recomented
+ + + + Properties / Events: + +-- Adding a basic button to the toolbar, note no need to call Toolbar.add_button_concept
+Gui.new_concept('toolbar-button')
+:set_caption('Click Me')
+:on_click(function(event)
+ event.player.print('You Clicked Me!!')
+end)
+
+
+
+
+ Adds a frame concept to the toolbar frame area, this will not add a button to the toolbar
+ + + + Parameters: + +-- Adding a basic frame to the frame area
+local new_frame =
+Gui.new_concept('frame')
+:set_title('Test')
+
+Toolbar.add_frame_concept(new_frame)
+
+
+
+ Hides all the frames for a player
+ + + + Parameters: + +-- Hiding all your frames
+Toolbar.hide_frames(game.player)
+
+
+
+ Gets an array of the names of all the visible frames for a player
+ + + + Parameters: + +-- Get all your visible frames
+Toolbar.get_visible_frames(game.player)
+
+
+
+ The base toolbar frame, others can be used but this is recomented
+ + + + Properties / Events: + +-- Adding a basic player list
+local player_list =
+Gui.new_concept('toolbar-frame')
+:set_permission_alias('player_list')
+:set_caption('Player List')
+:toggle_with_click()
+
+:define_draw(function(properties,parent,element)
+ local list_area =
+ element.add{
+ name = 'scroll',
+ type = 'scroll-pane',
+ direction = 'vertical',
+ horizontal_scroll_policy = 'never',
+ vertical_scroll_policy = 'auto-and-reserve-space'
+ }
+ Gui.set_padding(list_area,1,1,2,2)
+ list_area.style.horizontally_stretchable = true
+ list_area.style.maximal_height = 200
+
+ for _,player in pairs(game.connected_players) do
+ list_area.add{
+ type='label',
+ caption=player.name
+ }
+ end
+end)
+
+:on_update(function(event)
+ local list_area = event.element.scroll
+ list_area.clear()
+
+ for _,player in pairs(game.connected_players) do
+ list_area.add{
+ type='label',
+ caption=player.name
+ }
+ end
+end)
+
+
+
+ Gets the content area of the frame concept for this player, each player only has one area
+ + + + Parameters: + +-- Get the content area of a concept
+local frame = player_list:get_content(game.player)
+
+
+
+ Toggles the visibilty of this concept for the given player
+ + + + Parameters: + +-- Toggle the frame for your self
+player_list:toggle_visible_state(game.player)
+
+
+
+ Gets the current visibilty state of this conept for this player
+ + + + Parameters: + +-- Getting the current visiblity state
+
+
+
+ Triggers an update of the content within the concept for this player, uses on_update handlers
+ + + + Parameters: + +-- Updating the frame for your player
+player_list:update(game.player)
+
+
+
+ Triggers an update of the content with in this frame for all players
+ + + + Parameters: + +-- Update the grame for all players
+player_list:update_all()
+
+
+
+
+ The main toolbar element, draws, updates, and controls the other concepts
+ + + + Properties / Events: + +Button which toggles the the visible state of all toolbar buttons, triggers on_button_update
+ + + + + + + + + + + + + + + + +Button which hides all visible toolbar frames, triggers on_hide_frames
+ + + + + + + + + + + + + + + + + + + + +Core Module - ExpStyle
+ + + + + + + + + + + + +| expcore.gui | +
| gui.concept.frame | +
| expcore.gui | +
| gui.concept.frame | +
| expcore.gui | +
| gui.concept.table | +
| expcore.gui | +
| gui.concept.table | +
| expcore.gui | +
| gui.concept.table | +
| gui.concept.scroll | +
| expcore.gui | +
| expcore.common | +
| expcore.gui | +
| gui.concept.table | +
| expcore.gui | +
| gui.concept.frame | +
| container | +A container frame that can be used to add a boader around your content | +
| data_label | +A label pair which has a static label and a data label which can be changed | +
| footer | +A frame that acts as a footer to a section of content | +
| header | +A frame that acts as a header to a section of content | +
| scroll_table | +A table that is inside a vertical scroll area | +
| time_label | +A label that show time in a nice, user friendly way | +
| toggle_button | +A button that will toggle its caption each time it is pressed | +
| unit_label | +A label triplet which has a static label, a data label which can be changed, and a unit label | +
| time_label:update_time(element, time) | +Updates the time that is on a label | +
A container frame that can be used to add a boader around your content
+ + + + + + + + + + + See also: +-- Concept Structure
+-- Root
+--> [container] - the outer frame
+-->> container - the content area
+Gui.new_concept('container')
+
+
+
+ A label pair which has a static label and a data label which can be changed
+ + + + + + + + + + + See also: +-- Concept Structure
+-- Root
+--> [data_label] - the static label
+--> [properties.data_name] - the data label which can be updated
+Gui.new_concept('data_label')
+:set_data_label_name('game_ticks')
+:set_data_caption('0')
+:set_data_format(function(concept,element,data,...)
+ -- This is used with update_data_element and update_from_parent
+ local caption = tostirng('data')
+ local tooltip = 'This game has beeing running for: '..caption..' ticks'
+ return caption, tooltip
+end)
+
+
+
+ A frame that acts as a footer to a section of content
+ + + + Properties / Events: + +-- Concept Structure
+-- Root
+--> [footer] - the footer frame
+-->> footer_caption - the lable with the title in it
+-->> footer_content - the area to contain butons
+Gui.new_concept('footer')
+:set_title('Example Footer')
+
+
+
+ A frame that acts as a header to a section of content
+ + + + Properties / Events: + +-- Concept Structure
+-- Root
+--> [header] - the header frame
+-->> header_caption - the lable with the title in it
+-->> header_content - the area to contain butons
+Gui.new_concept('header')
+:set_title('Example Header')
+
+
+
+ A table that is inside a vertical scroll area
+ + + + Properties / Events: + +-- Concept Structure
+-- Root
+--> [scroll_table] - the scroll area
+-->> table - the table area
+Gui.new_concept('scroll_table')
+:set_height(200)
+:set_column_count(2)
+
+
+
+ A label that show time in a nice, user friendly way
+ + + + Properties / Events: + +-- Concept Structure
+-- Root
+--> [time_label] - the label with the time
+local time_label =
+Gui.new_concept('time_label')
+:set_use_hours(true)
+:set_time(game.tick)
+
+time_label:update_time(element,game.tick)
+
+
+
+ A button that will toggle its caption each time it is pressed
+ + + + Properties / Events: + +-- Concept Structure
+-- Root
+--> [toggle_button] - the header button
+Gui.new_concept('toggle_button')
+:set_caption('<')
+:set_tooltip('Press to close.')
+:set_alt_caption('>')
+:set_alt_tooltip('Press to open.')
+:on_click(function(event)
+ local state = event.state and 'close' or 'open'
+ event.player.print('Toggle button is now: '..state)
+end)
+
+
+
+ A label triplet which has a static label, a data label which can be changed, and a unit label
+ + + + + + + + + + + See also: +-- Concept Structure
+-- Root
+--> [unit_label] - the static label
+--> [properties.data_name] - the data label which can be updated
+--> [properties.data_name..'_unit'] - the data label unit which can be updated
+Gui.new_concept('unit_label')
+:set_data_label_name('game_ticks')
+:set_data_caption('0')
+:set_data_unit('ticks')
+:set_data_format(function(concept,element,data,...)
+ -- This is used with update_data_element and update_from_parent
+ local caption = tostirng(data)
+ local unit = data > 1 and 'ticks' or 'tick'
+ local tooltip = 'This game has beeing running for: '..caption..' ticks'
+ return caption, unit, tooltip
+end)
+
+
+
+
+ Updates the time that is on a label
+ + + + Parameters: + +-- Update the time to show game time
+time_label:update_time(element,game.time)
+
+
+
+
+
+
+
+ Core Module - Gui - - This file is used to require all the different elements of the gui module - - each module has an outline here but for more details see their separate files in ./gui
+Core Module - Gui
@@ -254,71 +236,17 @@| expcore.gui.core | +on_custom_event(handler) | +Adds a custom event handler, replace with the name of the event |
| expcore.gui.instances | -||
| expcore.gui.elements.buttons | -||
| expcore.gui.elements.checkbox | -||
| expcore.gui.elements.dropdown | -||
| expcore.gui.elements.slider | -||
| expcore.gui.elements.text | -||
| expcore.gui.elements.elem-button | -||
| expcore.gui.elements.progress-bar | -||
| expcore.gui.concepts.toolbar | -||
| expcore.gui.concepts.left | -||
| expcore.gui.concepts.center | -||
| expcore.gui.concepts.popups | -
| expcore.gui | -||
| expcore.common | -||
| resources.color_presets | -||
| utils.event | -||
| expcore.store | +set_custom_property(value) | +Sets a new value for a property, triggers setter method if provided, replace with property name |
Adds a custom event handler, replace with the name of the event
+ + Parameters: + +Sets a new value for a property, triggers setter method if provided, replace with property name
+ + Parameters: + +This file is used to require all the different elements of the gui module - each module has an outline here but for more details see their separate files in ./gui
+This file combines all the other gui files
@@ -250,389 +219,11 @@ -| expcore.gui.core | -
| expcore.gui.instances | -
| expcore.gui.elements.buttons | -
| expcore.gui.elements.checkbox | -
| expcore.gui.elements.dropdown | -
| expcore.gui.elements.slider | -
| expcore.gui.elements.text | -
| expcore.gui.elements.elem-button | -
| expcore.gui.elements.progress-bar | -
| expcore.gui.concepts.toolbar | -
| expcore.gui.concepts.left | -
| expcore.gui.concepts.center | -
| expcore.gui.concepts.popups | -
-[[
- - - - - - - - - - - - - - - -Core Module - ExpStyle
+ + + + + + + + + + + + +| expcore.gui | +
| gui.concept.flow | +
| alignment | +A flow which can be used to align text and other elements | +
A flow which can be used to align text and other elements
+ + + + + + + + + + + See also: +-- Concept Structure
+-- Root
+--> [alignment] - the alignment area
+Gui.new_concept('alignment')
+:set_horizontal_align('center')
+
+
+
+
+
+
+
+ 5) Once you have made any config changes that you wish to make open factorio, select play, then start scenario (or host scenario from within multiplayer tab), and select the scenario which will be called `scenario-master` if you have downloaded the latest stable release and have not changed the folder name.
6) The scenario will now load all the selected modules and start the map, any errors or exceptions raised in the scenario should not cause a game/server crash so if any features don't work as expected then it may be returning an error in the log, please report these errors to [the issues page](issues).
## Contributing -
All are welcome to make pull requests and issues for this scenario, if you are in any doubt please ask someone in our [discord]. If you do not know lua and don't feel like learning you can always make a [feature request]. Please keep in mind while making code changes: +
All are welcome to make pull requests and issues for this scenario, if you are in any doubt please ask someone in our [discord]. If you do not know lua and don't feel like learning you can always make a [feature request]. All our docs can be found [here][docs]. Please keep in mind while making code changes:
* New features should have the branch names: `feature/feature-name` * New features are merged into `dev` after it has been completed. * After a number of features have been added a release branch is made: `release/X.Y.0`; this branch should have no new features and only bug fixes or localization. @@ -248,7 +248,8 @@
## Releases
| Scenario Version* | Version Name | Factorio Version** | |---|---|---| -| [v5.7][s5.8] | Home and Chat Bot | [v0.17.47][f0.17.49] | +| [v5.9][s5.9] | Control Modules and Documentation | [v0.17.63][f0.17.63] | +| [v5.8][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] | @@ -264,7 +265,8 @@ | [v0.1][s0.1] | First Tracked Version | [v0.14][f0.14] |
\* Scenario patch versions have been omitted.
\*\* 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.9]: https://github.com/explosivegaming/scenario/releases/tag/5.9.0 +[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 @@ -278,7 +280,8 @@ [s2.0]: https://github.com/explosivegaming/scenario/releases/tag/v2.0 [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.63]: https://wiki.factorio.com/Version_history/0.17.0#0.17.63 +[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 @@ -293,7 +296,8 @@ [f0.14]: https://wiki.factorio.com/Version_history/0.14.0
## License
The Explosive Gaming codebase is licensed under the [GNU General Public License v3.0](LICENSE) -
[issues]: https://github.com/explosivegaming/scenario/issues/new/choose +
[docs]: https://explosivegaming.github.io/scenario/ +[issues]: https://github.com/explosivegaming/scenario/issues/new/choose [website]: https://explosivegaming.nl [discord]: https://discord.explosivegaming.nl [wiki]: https://wiki.explosivegaming.nl @@ -329,7 +333,7 @@ generated by LDoc
diff --git a/expcore/common.lua b/expcore/common.lua index 19cd711b..1d9ebef0 100644 --- a/expcore/common.lua +++ b/expcore/common.lua @@ -611,4 +611,93 @@ function Common.format_chat_player_name(player,raw_string) end end +--- Returns a desync safe file path for the current file +-- @tparam[opt=0] number offset the offset in the stack to get, 0 is current file +-- @treturn string the file path +function Common.get_file_path(offset) + offset = offset or 0 + return debug.getinfo(offset+2, 'S').source:match('^.+/currently%-playing/(.+)$'):sub(1, -5) +end + +--[[-- Much faster method for inserting items into an array +@tparam table tbl the table that will have the values added to it +@tparam[opt] number start_index the index at which values will be added, nil means end of the array +@tparam table values the new values that will be added to the table +@treturn table the table that was passed as the first argument +@usage-- Adding 1000 values into the middle of the array +local tbl = {} +local values = {} +for i = 1,1000 do tbl[i] = i values[i] = i end +Common.array_insert(tbl,500,values) -- around 0.4ms +]] +function Common.array_insert(tbl,start_index,values) + if not values then + values = start_index + start_index = nil + end + + if start_index then + local starting_length = #tbl + local adding_length = #values + local move_to = start_index+adding_length+1 + for offset = starting_length-start_index, 0, -1 do + tbl[move_to+offset] = tbl[starting_length+offset] + end + start_index = start_index-1 + else + start_index = #tbl + end + + for offset, item in ipairs(values) do + tbl[start_index+offset] = item + end + + return tbl +end + +--[[-- Much faster method for inserting keys into a table +@tparam table tbl the table that will have keys added to it +@tparam[opt] number start_index the index at which values will be added, nil means end of the array, numbered indexs only +@tparam table tbl2 the table that may contain both string and numbered keys +@treturn table the table passed as the first argument +@usage-- Merging two tables +local tbl = {} +local tbl2 = {} +for i = 1,100 do tbl[i] = i tbl['_'..i] = i tbl2[i] = i tbl2['__'..i] = i end +Common.table_insert(tbl,50,tbl2) +]] +function Common.table_insert(tbl,start_index,tbl2) + if not tbl2 then + tbl2 = start_index + start_index = nil + end + + Common.array_insert(tbl,start_index,tbl2) + for key, value in pairs(tbl2) do + if not tonumber(key) then + tbl[key] = value + end + end + + return tbl +end + +--[[-- Used to resolve a value that could also be a function returning that value +@tparam any value the value which you want to test is not nil and if it is a function then call the function +@treturn any the value given or returned by value if it is a function +@usage-- Default value handling +-- if default value is not a function then it is returned +-- if it is a function then it is called with the first argument being self +local value = Common.resolve_value(self.defaut_value,self) +]] +function Common.resolve_value(value,...) + if value then + if type(value) == 'function' then + return value(...) + else + return value + end + end +end + return Common \ No newline at end of file diff --git a/expcore/store.lua b/expcore/store.lua index 83d2ed26..5d3f80ce 100644 --- a/expcore/store.lua +++ b/expcore/store.lua @@ -4,121 +4,87 @@ @alias Store @usage ----- Basic Use - -- At the most basic level this allows for the naming of locations to store in the global table, the second feature is that you are - -- able to listen for updates of this value, which means that when ever the set function is called it will trigger the update callback. +-- The data store module is designed to be an alterative way to store data in the global table +-- each piece of data is stored at a location and optional key of that location +-- it is recomented that you use a local varible to store the location +local scenario_difficuly = Store.uid_location() +local team_scores = 'team-scores' - -- This may be useful when storing config values and when they get set you want to make sure it is taken care of, or maybe you want - -- to have a value that you can trigger an update of from different places. +-- Setting and getting data is then as simple as +-- note that when storing a table you must use Store.update +Store.set(scenario_difficuly,'Hard') +Store.set(team_scores,game.player.force.name,20) - -- This will register a new location called 'scenario.difficulty' - -- note that setting a start value is optional and we could take nil to mean normal - Store.register('scenario.difficulty',function(value) - game.print('The scenario difficulty has be set to: '..value) - end) +Store.get(scenario_difficuly) -- returns 'Hard' +Store.get(team_scores,game.player.force.name) -- returns 20 - -- This will set the value in the store to 'hard' and will trigger the update callback which will print a message to the game - Store.set('scenario.difficulty','hard') +Store.update(team_scores,game.player.force.name,function(value,key) + return value + 10 -- add 10 to the score +end) - -- This will return 'hard' - Store.get('scenario.difficulty') +-- The reason for using stores over global is the abilty to watch for updates +-- for stores to work you must register them, often at the end of the file +Store.register(scenario_difficuly,function(value) + game.print('Scenario difficulty has been set to: '..value) +end) - @usage ----- Using Children - -- One limitation of store is that all locations must be registered to avoid desyncs, to get round this issue "children" can be used. - -- When you set the value of a child it does not have its own update callback so rather the "parent" location which has been registered - -- will have its update value called with a second param of the name of that child. +Store.register(team_scores,function(value,key) + game.print('Team '..key..' now has a score of '..value) +end) - -- This may be useful when you want a value of each player or force and since you cant register every player at the start you must use - -- the players name as the child name. +-- This can be very powerful when working with data that can be changed for a number of locations +-- with this module you can enable any location to output its changes to a file +-- say we wanted team scores to be synced across servers or between saves +-- although you will need to set up a method of storing the data outside the game +Store.register(team_scores,true,function(value,key) + game.print('Team '..key..' now has a score of '..value) +end) - -- This will register the location 'scenario.score' where we plan to use force names as the child - Store.register('scenario.score',function(value,child) - game.print(child..' now has a score of '..value) - end) - - -- This will return nil, but will not error as children don't need to be registered - Store.get('scenario.score','player') - - -- This will set 'player' to have a value of 10 for 'scenario.score' and trigger the game message print - Store.set('scenario.score','player',10) - - -- This would be the similar to Store.get however this will return the names of all the children - Store.get_children('scenario.score') - - @usage ----- Using Sync - -- There is the option to use synced values which is the same as a normal value however you can combine this with an external script - -- which can read the output from 'script-output/log/store.log' and have it send rcon commands back to the game allowing for cross instance - -- syncing of values. - - -- This may be useful when you want to have a value change effect multiple instances or even if you just want a database to store values so - -- you can sync data between map resets. - - -- This example will register the location 'statistics.total-play-time' where we plan to use plan names as the child - -- note that the location must be the same across instances - Store.register('statistics.total-play-time',true,function(value,child) - game.print(child..' now has now played for '..value) - end) - - -- Use of set and are all the same as non synced but you should include from_sync as true - - @usage ----- Alternative method - -- Some people may prefer to use a variable rather than a string for formating reasons here is an example. Also for any times when - -- there will be little external input Store.uid_location() can be used to generate non conflicting locations, uid_location will also - -- be used if you give a nil location. - - local store_game_speed = - Store.register(function(value) - game.print('The game speed has been set to: '..value) - end) +-- If you want multiple handlers on one store location then you can register to the raw event +Event.add(Store.events.on_value_changed,function(event) + game.print('Store '..event.location..'/'..event.key..' was updated to: '..event.value) +end) ]] local Global = require 'utils.global' --- @dep utils.global local Event = require 'utils.event' --- @dep utils.event -local table_keys,write_json = ext_require('expcore.common','table_keys','write_json') --- @dep expcore.common +local table_keys,write_json,get_file_path = ext_require('expcore.common','table_keys','write_json','get_file_path') --- @dep expcore.common local Token = require 'utils.token' --- @dep utils.token local Store = { - data={}, registered={}, synced={}, callbacks={}, events = { - on_value_update=script.generate_event_name() + on_value_changed=script.generate_event_name() } } +local store_data = {} Global.register(Store.data,function(tbl) - Store.data = tbl + store_data = tbl end) local function error_not_table(value) if type(value) ~= 'table' then - error('Location is not a table can not use child locations',3) + error('Location is not a table can not use key locations',3) end end ---- Check for if a location is registered --- @tparam string location the location to test for --- @treturn boolean true if registered -function Store.is_registered(location) - return Store.registered[location] -end - ---- Returns a unique name that can be used for a store --- @treturn string a unique name -function Store.uid_location() - return tostring(Token.uid()) -end - ---- Registers a new location with an update callback which is triggered when the value updates --- @tparam[opt] string location string a unique that points to the data, string used rather than token to allow migration --- @tparam[opt] boolean synced when true will output changes to a file so it can be synced --- @tparam[opt] function callback when given the callback will be automatically registered to the update of the value --- @treturn string the location that is being used +--[[-- Registers a new location with an update callback which is triggered when the value updates +@tparam[opt] string location string a unique that points to the data, string used rather than token to allow migration +@tparam[opt=false] boolean synced when true will output changes to a file so it can be synced +@tparam[opt] function callback when given the callback will be automatically registered to the update of the value +@treturn string the location that is being used +@usage-- Registering a new store location +local store_id = Store.register() +@usage-- Registering a new store location, with custom update callback +local store_id = Store.uid_location() +Store.register(store_id,function(value,key) + game.print('Store '..store_id..'/'..key..' was updated to: '..value) +end) +]] function Store.register(location,synced,callback) if _LIFECYCLE ~= _STAGE.control then return error('Can only be called during the control stage', 2) @@ -136,125 +102,247 @@ function Store.register(location,synced,callback) location = type(location) == 'string' and location or Store.uid_location() if Store.registered[location] then - return error('Location is already registered', 2) + return error('Location '..location..' is already registered by '..Store.registered[location], 2) end - Store.registered[location] = true + Store.registered[location] = get_file_path(1) Store.synced[location] = synced and true or nil Store.callbacks[location] = callback or nil return location end ---- Gets the value stored at a location, this location must be registered --- @tparam string location the location to get the data from --- @tparam[opt] string child the child location if required --- @tparam[opt=false] boolean allow_unregistered when true no error is returned if the location is not registered --- @treturn any the data which was stored at the location -function Store.get(location,child,allow_unregistered) - if not Store.callbacks[location] and not allow_unregistered then +--[[-- Gets the value stored at a location, this location must be registered +@tparam string location the location to get the data from +@tparam[opt] string key the key location if used +@treturn any the data which was stored at the location +@usage-- Getting the data at a store location +local data = Store.get(store_id_no_keys) +local data = Store.get(store_id_with_keys,'key_one') +]] +function Store.get(location,key) + if not Store.registered[location] then return error('Location is not registered', 2) end - local data = Store.data[location] - if child and data then + local data = store_data[location] + if key and data then error_not_table(data) - return data[child] + return data[key] end return data end ---- Sets the value at a location, this location must be registered --- @tparam string location the location to set the data to --- @tparam[opt] string child the child location if required --- @tparam any value the new value to set at the location, value may be reverted if there is a watch callback, cant be nil --- @tparam[opt] boolean from_sync set this true to avoid an output to the sync file --- @treturn boolean true if it was successful -function Store.set(location,child,value,from_sync) - if not Store.callbacks[location] then - return error('Location is not registered', 2) +--[[-- Sets the value at a location, this location must be registered +@tparam string location the location to set the data to +@tparam[opt] string key the key location if used +@tparam any value the new value to set at the location, value may be reverted if there is a watch callback, cant be nil +@tparam[opt=false] boolean from_sync set this true to avoid an output to the sync file +@tparam[opt=false] boolean from_internal set this true to add one to the error stack offset +@treturn boolean true if it was successful +@usage-- Setting the data at a store location +Store.set(store_id_no_keys,'Hello, World!') +Store.set(store_id_with_keys,'key_one','Hello, World!') +]] +function Store.set(location,key,value,from_sync,from_internal) + if not Store.registered[location] then + return error('Location is not registered', from_internal and 3 or 2) end - if child == nil or value == nil then - value = child or value - child = nil + if value == nil then + value = key + key = nil end - local data = Store.data - if child then - data = data[location] + if key then + local data = store_data[location] if not data then data = {} - Store.data[location] = data + store_data[location] = data end error_not_table(data) - data[child] = value + data[key] = value else - data[location] = value + store_data[location] = value end - script.raise_event(Store.events.on_value_update,{ + script.raise_event(Store.events.on_value_changed,{ tick=game.tick, location=location, - child=child, + key=key, value=value, - from_sync=from_sync + from_sync=from_sync or false }) return true end ---- Sets the value at a location to nil, this location must be registered --- @tparam string location the location to set the data to --- @tparam[opt] string child the child location if required --- @tparam[opt] boolean from_sync set this true to avoid an output to the sync file --- @treturn boolean true if it was successful -function Store.clear(location,child,from_sync) +--[[-- Allows for updating a value based on the current value; only valid way to change tables in a store +@tparam string location the location to set the data to +@tparam[opt] string key the key location if required +@tparam[opt] function update_callback the function called to update the value stored, rtn value to set new value +@usage-- Updating a value stored at a location +Store.update(store_id_no_keys,function(value) + return value + 1 +end) +Store.update(store_id_with_keys,'key_one',function(value) + return value + 1 +end) +@usage-- Updating a table stored at a location +Store.update(store_id_no_keys,function(value) + value.ctn = value.ctn + 1 +end) +Store.update(store_id_with_keys,'key_one',function(value) + value.ctn = value.ctn + 1 +end) +]] +function Store.update(location,key,update_callback,...) + local value = Store.get(location,key) + + local args + if type(key) == 'function' then + args = {update_callback,...} + update_callback = key + key = nil + end + + local rtn + if update_callback and type(update_callback) == 'function' then + if args then + rtn = update_callback(value,key,unpack(args)) + else + rtn = update_callback(value,key,...) + end + end + + if rtn then + Store.set(location,key,rtn,nil,true) + else + script.raise_event(Store.events.on_value_changed,{ + tick=game.tick, + location=location, + key=key, + value=value, + from_sync=false + }) + end + +end + +--[[-- Allows for updating all values at a location based on the current value; only valid way to change tables in a store +@tparam string location the location to set the data to +@tparam[opt] function update_callback the function called to update the value stored +@usage-- Updating all values at a location +Store.update(store_id_with_keys,function(value) + return value + 1 +end) +@usage-- Updating all tables at a location +Store.update(store_id_with_keys,function(value) + value.ctn = value.ctn + 1 +end) +]] +function Store.update_all(location,update_callback,...) + local data = Store.get(location) + + error_not_table(data) + + for key,value in pairs(data) do + local rtn + if update_callback and type(update_callback) == 'function' then + rtn = update_callback(value,key,...) + end + + if rtn then + Store.set(location,key,rtn,nil,true) + else + script.raise_event(Store.events.on_value_changed,{ + tick=game.tick, + location=location, + key=key, + value=value, + from_sync=false + }) + end + end + +end + +--[[-- Sets the value at a location to nil, this location must be registered +@tparam string location the location to set the data to +@tparam[opt] string key the key location if used +@tparam[opt=false] boolean from_sync set this true to avoid an output to the sync file +@treturn boolean true if it was successful +@usage-- Clear the data at a location +Store.clear(store_id_no_keys) +Store.clear(store_id_with_keys,'key_one') +]] +function Store.clear(location,key,from_sync) if not Store.callbacks[location] then return error('Location is not registered', 2) end - local data = Store.data - if child then - data = data[location] + if key then + local data = store_data[location] if not data then return end error_not_table(data) - data[child] = nil + data[key] = nil else - data[location] = nil + store_data[location] = nil end - script.raise_event(Store.events.on_value_update,{ + script.raise_event(Store.events.on_value_changed,{ tick=game.tick, location=location, - child=child, - from_sync=from_sync + key=key, + from_sync=from_sync or false }) return true end ---- Gets all non nil children at a location, children can be added and removed during runtime --- this is similar to Store.get but will always return a table even if it is empty --- @tparam string location the location to get the children of --- @treturn table a table containing all the children names -function Store.get_children(location) +--[[-- Gets all non nil keys at a location, keys can be added and removed during runtime +this is similar to Store.get but will always return a table even if it is empty +@tparam string location the location to get the keys of +@treturn table a table containing all the keys names +@usage-- Get all keys at a store location +local keys = Store.get_keys(store_id_with_keys) +]] +function Store.get_keys(location) local data = Store.get(location) return type(data) == 'table' and table_keys(data) or {} end +--[[-- Check for if a location is registered +@tparam string location the location to test for +@treturn boolean true if registered +@usage-- Check that a store is registered +local registerd = Store.is_registered(store_id) +]] +function Store.is_registered(location) + return Store.registered[location] +end + +--[[-- Returns a unique name that can be used for a store +@treturn string a unique name +@usage-- Get a new unique store id +local store_id = Store.uid_location() +]] +function Store.uid_location() + return tostring(Token.uid()) +end + -- Handles syncing -Event.add(Store.events.on_value_update,function(event) +Event.add(Store.events.on_value_changed,function(event) if Store.callbacks[event.location] then - Store.callbacks[event.location](event.value,event.child) + Store.callbacks[event.location](event.value,event.key) end if not event.from_sync and Store.synced[event.location] then write_json('log/store.log',{ tick=event.tick, location=event.location, - child=event.child, + key=event.key, value=event.value, }) end diff --git a/modules/gui/warp-list.lua b/modules/gui/warp-list.lua index 4e06b335..9fb9e390 100644 --- a/modules/gui/warp-list.lua +++ b/modules/gui/warp-list.lua @@ -478,7 +478,7 @@ end) local r2 = config.activation_range^2 local rs2 = config.spawn_activation_range^2 Event.on_nth_tick(math.floor(60/config.update_smoothing),function() - local categories = Store.get_children(warp_timer.store) + local categories = Store.get_keys(warp_timer.store) for _,category in pairs(categories) do warp_timer:increment(1,category) end diff --git a/utils/debug.lua b/utils/debug.lua index 1c1a3633..98f85a28 100644 --- a/utils/debug.lua +++ b/utils/debug.lua @@ -31,7 +31,7 @@ end ---Shows the given message if debug is enabled. Uses serpent to print non scalars. -- @param message