diff --git a/.gitignore b/.gitignore index 9a140dc8..b23b7166 100644 --- a/.gitignore +++ b/.gitignore @@ -82,7 +82,4 @@ $RECYCLE.BIN/ *.msp # Windows shortcuts -*.lnk - -.vscode -*luacheckrc +*.lnk \ No newline at end of file diff --git a/.luacheckrc b/.luacheckrc index c3e0c5cf..98d8fa3e 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -1,947 +1,1641 @@ -------------------------------------------------------------------------------- ---[LICENSE]-- -------------------------------------------------------------------------------- --- .luacheckrc --- This file is free and unencumbered software released into the public domain. --- --- Anyone is free to copy, modify, publish, use, compile, sell, or --- distribute this file, either in source code form or as a compiled --- binary, for any purpose, commercial or non-commercial, and by any --- means. --- --- In jurisdictions that recognize copyright laws, the author or authors --- of this file dedicate any and all copyright interest in the --- software to the public domain. We make this dedication for the benefit --- of the public at large and to the detriment of our heirs and --- successors. We intend this dedication to be an overt act of --- relinquishment in perpetuity of all present and future rights to this --- software under copyright law. --- --- THE FILE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, --- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF --- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. --- IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR --- OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, --- ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR --- OTHER DEALINGS IN THE SOFTWARE. --- --- For more information, please refer to --- ]] +--[[---------------------------------------------------------------------------- + LICENSE + .luacheckrc for Factorio Version 0.18.8, luacheck version 0.23.0 + This file is free and unencumbered software released into the public domain. -------------------------------------------------------------------------------- ---[.luacheckrc]-- Current Factorio Version .16 -------------------------------------------------------------------------------- --- Set up the the standards for this file. -files['.luacheckrc'] = { - std = 'lua52c', - globals = {'files', 'exclude_files', 'not_globals', 'stds', 'std', 'max_line_length', 'ignore', 'quiet', "max_cyclomatic_complexity", "codes"}, - max_line_length = false --turn of line length warnings for this file -} + Anyone is free to copy, modify, publish, use, compile, sell, or + distribute this file, either in source code form or as a compiled + binary, for any purpose, commercial or non-commercial, and by any + means. + + In jurisdictions that recognize copyright laws, the author or authors + of this file dedicate any and all copyright interest in the + software to the public domain. We make this dedication for the benefit + of the public at large and to the detriment of our heirs and + successors. We intend this dedication to be an overt act of + relinquishment in perpetuity of all present and future rights to this + software under copyright law. + + THE FILE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + + For more information, please refer to +------------------------------------------------------------------------------]] +local LINE_LENGTH = false -------------------------------------------------------------------------------- ---[Set Defaults]-- -------------------------------------------------------------------------------- -local LINE_LENGTH = false -- It is 2017 limits on length are a waste local IGNORE = {'21./%w+_$', '21./^_%w+$', '213/[ijk]', '213/index', '213/key'} -local NOT_GLOBALS = {'coroutine', 'io', 'socket', 'dofile', 'loadfile'} -- These globals are not available to the factorio API -local STD_CONTROL = 'lua52c+factorio+factorio_control+stdlib+factorio_defines' -local STD_DATA = 'lua52c+factorio+factorio_data+stdlib+stdlib_data+factorio_defines' +-- These globals are not available to the factorio API +local NOT_GLOBALS = {'coroutine', 'io', 'socket', 'dofile', 'loadfile'} --- In a perfect world these would be STD_DATA and STD_CONTROL (mostly) -local STD_BASE_DATA = 'lua52c+factorio+factorio_data+factorio_defines+factorio_base_data' -local STD_BASE_CONTROL = 'lua52c+factorio+factorio_control+factorio_defines+factorio_base_control' +local STD_CONTROL = 'lua52+factorio+factorio_control+stdlib+factorio_defines' +local STD_DATA = 'lua52+factorio+factorio_data+stdlib+stdlib_data+factorio_defines' -------------------------------------------------------------------------------- ---[Assume Factorio Control stage as default]-- -------------------------------------------------------------------------------- -std = STD_CONTROL -max_line_length = LINE_LENGTH +-- For Base and Core Mods +local STD_BASE_DATA = 'lua52+factorio+factorio_data+factorio_defines+factorio_base_data' +local STD_BASE_CONTROL = 'lua52+factorio+factorio_control+factorio_defines+factorio_base_control' -not_globals = NOT_GLOBALS -ignore = IGNORE -quiet = 1 -- pass -q option -max_cyclomatic_complexity = 75 -codes = true - ---List of files and directories to exclude -exclude_files = { - --Ignore special folders - '**/.*/*', --Ignore if path starts with . - '**/mod/stdlib/', --Ignore from symlinked - '**/vendor/', - - --Ignore development mods - '**/combat-tester/', - '**/test-maker/', - '**/trailer/', -} - -------------------------------------------------------------------------------- ---[Mod Prototypes]-- -------------------------------------------------------------------------------- ---Set default prototype files -files['**/data.lua'].std = STD_DATA -files['**/data-updates.lua'].std = STD_DATA -files['**/data-final-fixes.lua'].std = STD_DATA -files['**/settings.lua'].std = STD_DATA -files['**/settings-updates.lua'].std = STD_DATA -files['**/settings-final-fixes.lua'].std = STD_DATA -files['**/prototypes/'].std = STD_DATA -files['**/settings/'].std = STD_DATA - -------------------------------------------------------------------------------- ---[Base]-- -------------------------------------------------------------------------------- ---Find and replace ignores *.cfg, migrations, *.txt, control.lua, *.json, trailer, scenarios, campaigns, *.glsl - -local base_scenarios = { - std = STD_BASE_CONTROL .. '+factorio_base_scenarios+factorio_base_story', - --Ignore these, Klonan is on his own! - --ignore = {'212/event', '111', '112', '113', '211', '212', '213', '311', '411', '412', '421', '422', '423', '431', '432', '512'} - ignore = {'...'} -} -files['**/base/scenarios/'] = base_scenarios -files['**/base/tutorials/'] = base_scenarios -files['**/base/campaigns/'] = base_scenarios -files['**/wip-scenario/'] = base_scenarios - -files['**/base/migrations/'] = {std = STD_BASE_CONTROL} - -files['**/core/lualib/'] = {std = STD_BASE_CONTROL} -files['**/core/lualib/util.lua'] = {globals = {'util', 'table'}, ignore = {'432/object'}} -files['**/core/lualib/silo-script.lua'] = {globals = {'silo_script'}, ignore = {'4../player'}} -files['**/core/lualib/production-score.lua'] = {globals = {'production_score', 'get_price_recursive'}, ignore = {'4../player'}} -files['**/core/lualib/story*'] = {std = '+factorio_base_story', ignore = {'42./k', '42./filter'}} -files['**/core/lualib/mod-gui.lua'] = {globals = {'mod_gui'}} -files['**/core/lualib/camera.lua'] = {globals = {'camera'}} -files['**/core/lualib/builder.lua'] = {globals = {'Builder', 'builder', 'action', 'down', 'right'}} - -files['**/core/lualib/bonus-gui-ordering/'] = {std = STD_BASE_DATA} -files['**/core/lualib/dataloader.lua'] = {globals = {'data'}} -files['**/core/lualib/circuit-connector-*'] = {std = STD_BASE_DATA..'+factorio_circuit_connector_generated'} -files['**/core/lualib/bonus-gui-ordering.lua'] = {globals = {'bonus_gui_ordering'}} - -files['**/base/prototypes/'] = {std = STD_BASE_DATA} -files['**/core/prototypes/'] = {std = STD_BASE_DATA} -files['**/core/prototypes/noise-programs.lua'] = {ignore = {'212/x', '212/y', '212/tile', '212/map'}} - -------------------------------------------------------------------------------- ---[Set STDLIB project modules]-- -------------------------------------------------------------------------------- -local stdlib_control = { - std = 'lua52c+factorio+factorio_control+stdlib+factorio_defines', +do -- Assume Factorio Control Stage as Default + std = STD_CONTROL + --cache = true + not_globals = NOT_GLOBALS + ignore = IGNORE + quiet = 1 -- pass -q option + max_cyclomatic_complexity = false + codes = true max_line_length = LINE_LENGTH -} + max_code_line_length = LINE_LENGTH + max_string_line_length = LINE_LENGTH + max_comment_line_length = LINE_LENGTH -local stdlib_data = { - std = 'lua52c+factorio+factorio_data+stdlib+factorio_defines', - max_line_length = LINE_LENGTH -} + --List of files and directories to exclude + exclude_files = { + --Ignore special folders + '**/.trash/', + '**/.history/', + '**/stdlib/vendor/', --- Assume control stage for stdlib -files['**/stdlib/'] = stdlib_control + --Ignore development mods + '**/combat-tester/', + '**/test-maker/', + '**/trailer/', -files['**/stdlib/utils/math.lua'].std = 'lua52c' -files['**/stdlib/utils/string.lua'].std = 'lua52c' -files['**/stdlib/utils/table.lua'].std = 'lua52c' -files['**/stdlib/utils/iterator.lua'].std = 'lua52c' -files['**/stdlib/utils/is.lua'].std = 'lua52c' + --Ignore love Includes + '**/love/includes/' + } +end --- STDLIB data files -files['**/stdlib/data/'] = stdlib_data -files['**/creative'].ignore = {'...'} +do -- Set default prototype files + files['**/data.lua'].std = STD_DATA + files['**/data-updates.lua'].std = STD_DATA + files['**/data-final-fixes.lua'].std = STD_DATA + files['**/settings.lua'].std = STD_DATA + files['**/settings-updates.lua'].std = STD_DATA + files['**/settings-final-fixes.lua'].std = STD_DATA + files['**/prototypes/'].std = STD_DATA + files['**/settings/'].std = STD_DATA +end --- STDLIB Busted Spec -files['**/spec/**'] = { - globals = {'serpent', 'log', 'SLOG', 'RESET'}, - std = 'lua52c+busted+factorio_defines+factorio_control+stdlib' -} +do -- Base and Core mod files + local base_scenarios = { + std = STD_BASE_CONTROL .. '+factorio_base_scenarios+factorio_base_story', + --ignore = {'212/event', '111', '112', '113', '211', '212', '213', '311', '411', '412', '421', '422', '423', '431', '432', '512'} + ignore = {'...'} + } + files['**/base/scenarios/'] = base_scenarios + files['**/base/tutorials/'] = base_scenarios + files['**/base/campaigns/'] = base_scenarios + files['**/wip-scenario/'] = base_scenarios + files['**/base/migrations/'] = {std = STD_BASE_CONTROL} -------------------------------------------------------------------------------- ---[STDS FACTORIO]-- -------------------------------------------------------------------------------- -stds.factorio = { - --Set the read only variables - read_globals = { - -- @log@: Gives writing access to Factorio's logger instance. - "log", - -- @serpent@: Lua serializer and pretty printer. (https://github.com/pkulchenko/serpent) - "serpent", - -- @table_size@: Returns the number of elements inside an LUA table - "table_size", - util = { - fields = { - "by_pixel", "distance", "findfirstentity", "positiontostr", "formattime", "moveposition", "oppositedirection", - "ismoduleavailable", "multiplystripes", "format_number", "increment", "color", "conditional_return", - "add_shift", "merge", "premul_color", "encode", "decode", - table = { - fields = { - "compare", "deepcopy" + files['**/core/lualib/'] = {std = STD_BASE_CONTROL} + files['**/core/lualib/util.lua'] = {globals = {'util', 'table'}, ignore = {'432/object'}} + files['**/core/lualib/silo-script.lua'] = {globals = {'silo_script'}, ignore = {'4../player'}} + files['**/core/lualib/production-score.lua'] = {globals = {'production_score', 'get_price_recursive'}, ignore = {'4../player'}} + files['**/core/lualib/story*'] = {std = '+factorio_base_story', ignore = {'42./k', '42./filter'}} + files['**/core/lualib/mod-gui.lua'] = {globals = {'mod_gui'}} + files['**/core/lualib/camera.lua'] = {globals = {'camera'}} + files['**/core/lualib/builder.lua'] = {globals = {'Builder', 'builder', 'action', 'down', 'right'}} + + files['**/core/lualib/bonus-gui-ordering/'] = {std = STD_BASE_DATA} + files['**/core/lualib/dataloader.lua'] = {globals = {'data'}} + files['**/core/lualib/circuit-connector-*'] = {std = STD_BASE_DATA..'+factorio_circuit_connector_generated'} + files['**/core/lualib/bonus-gui-ordering.lua'] = {globals = {'bonus_gui_ordering'}} + + files['**/base/prototypes/'] = {std = STD_BASE_DATA} + files['**/core/prototypes/'] = {std = STD_BASE_DATA} + files['**/core/prototypes/noise-programs.lua'] = {ignore = {'212/x', '212/y', '212/tile', '212/map'}} +end + +do -- Stdlib Files + local stdlib_control = { + std = 'lua52+factorio+factorio_control+stdlib+factorio_defines', + max_line_length = LINE_LENGTH + } + + local stdlib_data = { + std = 'lua52+factorio+factorio_data+stdlib+factorio_defines', + max_line_length = LINE_LENGTH + } + + -- Assume control stage for stdlib + files['**/stdlib/'] = stdlib_control + + -- Assume generic lua for stdlib utils + files['**/stdlib/utils/**'].std = 'lua52+stdlib' + + -- STDLIB data stage files + files['**/stdlib/data/'] = stdlib_data + + -- STDLIB Busted Spec + files['**/spec/**'] = { + globals = {'serpent', 'log', 'package.remove_stdlib'}, + std = 'lua52c+busted+factorio_defines+factorio_control+stdlib' + } + + -- Love + files['**/love/'].std = 'luajit+love+love_extra+stdlib+stdlib_data' +end + +do -- Factorio STDs-- + stds.factorio = { + --Set the read only variables + read_globals = { + -- @log@: Gives writing access to Factorio's logger instance. + "log", + -- @serpent@: Lua serializer and pretty printer. (https://github.com/pkulchenko/serpent). + "serpent", + -- @table_size@: Returns the number of elements inside an LUA table. + "table_size", + -- @lldebugger@: Provided by lua local debugger vscode extension. + lldebugger = { + fields = {'requestBreak'}, + other_fields = true, + read_only = false, + }, + -- @__DebugAdapter@: Provided by Factorio Mod Debug vscode extension. + __DebugAdapter = { + fields = {'print', 'stepIgnoreAll', 'stepIgnore', 'breakpoint'}, + other_fields = true, + read_only = false + }, + util = { + fields = { + "by_pixel", "distance", "findfirstentity", "positiontostr", "formattime", "moveposition", "oppositedirection", + "ismoduleavailable", "multiplystripes", "format_number", "increment", "color", "conditional_return", + "add_shift", "merge", "premul_color", "encode", "decode", "insert_safe", + table = { + fields = { + "compare", "deepcopy" + }, }, }, }, - }, - table = { - fields = { - "compare", "deepcopy" + table = { + fields = { + "compare", "deepcopy" + }, }, }, - }, -} + } -stds.factorio_control = { - read_globals = { + stds.factorio_control = { + read_globals = { - -- @commands@: - commands = { - fields = { - "add_command", "commands", "game_commands", "remove_command", + -- @commands@: + commands = { + fields = { + "add_command", "commands", "game_commands", "remove_command" + }, }, - }, - -- @settings@: - settings = { - fields = { - "get_player_settings", - startup = {read_only = false, other_fields = true}, - global = {read_only = false, other_fields = true}, - player = {read_only = false, other_fields = true}, + -- @settings@: + settings = { + fields = { + "get_player_settings", + startup = {other_fields = true}, + global = {other_fields = true}, + player = {other_fields = true}, + get = {read_only = false}, -- stdlib added + get_startup = {read_only = false} -- stdlib added + }, }, - }, - -- @script@: Provides an interface for registering event handlers. - -- (http://lua-api.factorio.com/latest/LuaBootstrap.html) - script = { - fields = { - "on_event", "on_nth_tick", "on_configuration_changed", "on_init", "on_load", "generate_event_name", - "raise_event", "get_event_handler", "mod_name", "get_event_order" + -- @script@: Provides an interface for registering event handlers. + -- (http://lua-api.factorio.com/latest/LuaBootstrap.html) + script = { + fields = { + "on_event", "on_nth_tick", "on_configuration_changed", "on_init", "on_load", "generate_event_name", + "raise_event", "get_event_handler", "mod_name", "get_event_order", + "is_game_in_debug_mode", "object_name", "set_event_filter", "get_event_filter", + active_mods = {read_only = true, other_fields = true}, + }, + other_fields = false, }, - }, - -- @remote@: Allows inter-mod communication by providing a repository of interfaces that is shared by all mods. - -- (http://lua-api.factorio.com/latest/LuaRemote.html) - remote = { - fields = { - "add_interface", "remove_interface", "call", "interfaces" + -- @remote@: Allows inter-mod communication by providing a repository of interfaces that is shared by all mods. + -- (http://lua-api.factorio.com/latest/LuaRemote.html) + remote = { + fields = { + interfaces = {read_only = false, other_fields = true}, + "add_interface", "remove_interface", "call" + }, + read_only = true, + other_fields = false, }, - }, - -- @game@: Main object through which most of the API is accessed. - -- It is, however, not available inside handlers registered with @script.on_load@. - -- (http://lua-api.factorio.com/latest/LuaGameScript.html) - game ={ - other_fields = true, - read_only = false, - fields = { - "set_game_state", "get_entity_by_tag", "show_message_dialog", "disable_tips_and_tricks", "is_demo", "reload_script", - "save_atlas", "check_consistency", "regenerate_entity", "take_screenshot", "write_file", "remove_path", - "remove_offline_players", "force_crc", "merge_forces", "player", "server_save", "delete_surface", "disable_replay", - "direction_to_string", "print", "tick", "finished", "difficulty", - speed = { - --rw - read_only = false, - }, - player = { - --luaPlayer - --The player typing at the console, nil in all other cases - read_only = false, - other_fields = true, - }, - players = { - --array of luaPlayer - read_only = false, - other_fields = true, - }, - connected_players = { - --array of luaPlayer - read_only = false, - other_fields = true, - }, - surfaces = { - --array of luaSurface - read_only = false, - other_fields = true, - }, - create_surface = { - --luaSurface - read_only = false, - other_fields = true, - }, - forces = { - --array of luaForce - read_only = false, - other_fields = true, - }, - create_force = { - --luaForce - read_only = false, - other_fields = true, - }, - entity_prototypes = { - --string dictionary - > luaEntityPrototype - read_only = true, - other_fields = true - }, - item_prototypes = { - --string dictionary - > luaItemPrototype - read_only = true, - other_fields = true - }, - fluid_prototypes = { - --string dictionary - > luaFluidPrototype - read_only = true, - other_fields = true - }, - tile_prototypes = { - --string dictionary - > luaTilePrototype - read_only = true, - other_fields = true - }, - equipment_prototypes = { - --string dictionary - > luaEquipmentPrototype - read_only = true, - other_fields = true - }, - recipe_prototypes = { - --string dictionary - > luaRecipePrototype - read_only = true, - other_fields = true - }, - technology_prototypes = { - --string dictionary - > luaTechnologyPrototype - read_only = true, - other_fields = true - }, - damage_prototypes = { - --string dictionary - > luaDamagePrototype - read_only = true, - other_fields = true - }, - virtual_signal_prototypes = { - --string dictionary - > luaVirtualSignalPrototype - read_only = true, - other_fields = true - }, - equipment_grid_prototypes = { - --string dictionary - > luaEquipmentGridPrototype - read_only = true, - other_fields = true - }, - decorative_prototypes = { - --string dictionary -> LuaDecorativePrototype - read_only = true, - other_fields = true - }, - map_settings = { - --custom -> mapsettings - read_only = false, - other_fields = true - }, - active_mods = { - --string dictionary -> string version - read_only = true, - other_fields = true - }, - permissions = { - read_only = true, - other_fields = true - }, - backer_names = { - read_only = true, - other_fields = true + rcon = { + fields = {'print'} + }, + + rendering = { + other_fields = false, + read_only = true, + fields = { + 'draw_animation', + 'draw_line', + 'draw_text', + 'draw_circle', + 'draw_rectangle', + 'draw_arc', + 'draw_polygon', + 'draw_sprite', + 'draw_light', + 'destroy', + 'is_font_valid', + 'is_valid', + 'get_all_ids', + 'clear', + 'get_type', + 'get_surface', + 'get_time_to_live', + 'set_time_to_live', + 'get_forces', + 'set_forces', + 'get_players', + 'set_players', + 'get_color', + 'set_color', + 'get_width', + 'set_width', + 'get_from', + 'set_from', + 'get_to', + 'set_to', + 'get_gap_amount', + 'set_gap_amount', + 'get_gap_length', + 'set_gap_length', + 'get_target', + 'set_target', + 'get_orientation', + 'set_orientation', + 'get_scale', + 'set_scale', + 'get_text', + 'set_text', + 'get_font', + 'set_font', + 'get_alignment', + 'set_alignment', + 'get_scale_with_zoom', + 'set_scale_with_zoom', + 'get_filled', + 'set_filled', + 'get_radius', + 'set_radius', + 'get_left_top', + 'set_left_top', + 'get_right_bottom', + 'set_right_bottom', + 'get_max_radius', + 'set_max_radius', + 'get_min_radius', + 'set_min_radius', + 'get_start_angle', + 'set_start_angle', + 'get_angle', + 'set_angle', + 'get_vertices', + 'set_vertices', + 'get_sprite', + 'set_sprite', + 'get_x_scale', + 'set_x_scale', + 'get_y_scale', + 'set_y_scale', + 'get_render_layer', + 'set_render_layer', + 'get_orientation_target', + 'set_orientation_target', + 'get_oriented_offset', + 'set_oriented_offset', + 'get_intensity', + 'set_intensity', + 'get_minimum_darkness', + 'set_minimum_darkness' } }, - }, - }, - globals = { - -- @global@: The global dictionary, useful for storing data persistent across a save-load cycle. - -- Writing access is given to the mod-id field (for mod-wise saved data). - -- (http://lua-api.factorio.com/latest/Global.html) - "global", + -- @game@: Main object through which most of the API is accessed. + -- It is, however, not available inside handlers registered with @script.on_load@. + -- (http://lua-api.factorio.com/latest/LuaGameScript.html) + game ={ + other_fields = false, + read_only = false, + fields = { + 'auto_save', + 'ban_player', + 'check_consistency', + 'check_prototype_translations', + 'count_pipe_groups', + 'create_force', + 'create_profiler', + 'create_random_generator', + 'create_surface', + 'decode_string', + 'delete_surface', + 'direction_to_string', + 'disable_replay', + 'disable_tips_and_tricks', + 'disable_tutorial_triggers', + 'encode_string', + 'evaluate_expression', + 'force_crc', + 'get_active_entities_count', + 'get_entity_by_tag', + 'get_filtered_achievement_prototypes', + 'get_filtered_decorative_prototypes', + 'get_filtered_entity_prototypes', + 'get_filtered_equipment_prototypes', + 'get_filtered_fluid_prototypes', + 'get_filtered_item_prototypes', + 'get_filtered_mod_setting_prototypes', + 'get_filtered_recipe_prototypes', + 'get_filtered_technology_prototypes', + 'get_filtered_tile_prototypes', + 'get_map_exchange_string', + 'get_player', + 'get_surface', + 'get_train_stops', + 'help', + 'is_demo', + 'is_multiplayer', + 'is_valid_sound_path', + 'is_valid_sprite_path', + 'json_to_table', + 'kick_player', + 'log_recipe_locale', + 'merge_forces', + 'mute_player', + 'parse_map_exchange_string', + 'play_sound', + 'print', + 'print_stack_size', + 'purge_player', + 'regenerate_entity', + 'reload_mods', + 'reload_script', + 'remove_offline_players', + 'remove_path', + 'reset_time_played', + 'save_atlas', + 'server_save', + 'set_game_state', + 'set_wait_for_screenshots_to_finish', + 'show_message_dialog', + 'table_to_json', + 'take_screenshot', + 'take_technology_screenshot', + 'unban_player', + 'unmute_player', + 'write_file', - -- @MOD@: Keep it organized, use this variable for anything that "NEEDS" to be global for some reason. - "MOD" - }, -} + achievement_prototypes = {read_only = true, other_fields = true}, + active_mods = {read_only = true, other_fields = true}, + ammo_category_prototypes = {read_only = true, other_fields = true}, + autoplace_control_prototypes = {read_only = true, other_fields = true}, + backer_names = {read_only = true, other_fields = true}, + connected_players = {read_only = true, other_fields = true}, + custom_input_prototypes = {read_only = true, other_fields = true}, + damage_prototypes = {read_only = true, other_fields = true}, + decorative_prototypes = {read_only = true, other_fields = true}, + default_map_gen_settings = {read_only = true, other_fields = true}, + difficulty = {read_only = true, other_fields = true}, + difficulty_settings = {read_only = true, other_fields = true}, + entity_prototypes = {read_only = true, other_fields = true}, + equipment_category_prototypes = {read_only = true, other_fields = true}, + equipment_grid_prototypes = {read_only = true, other_fields = true}, + equipment_prototypes = {read_only = true, other_fields = true}, + finished = {read_only = true, other_fields = true}, + fluid_prototypes = {read_only = true, other_fields = true}, + forces = {read_only = true, other_fields = true}, + fuel_category_prototypes = {read_only = true, other_fields = true}, + item_group_prototypes = {read_only = true, other_fields = true}, + item_prototypes = {read_only = true, other_fields = true}, + item_subgroup_prototypes = {read_only = true, other_fields = true}, + map_settings = {read_only = true, other_fields = true}, + mod_setting_prototypes = {read_only = true, other_fields = true}, + module_category_prototypes = {read_only = true, other_fields = true}, + named_noise_expressions = {read_only = true, other_fields = true}, + noise_layer_prototypes = {read_only = true, other_fields = true}, + object_name = {read_only = true, other_fields = true}, + particle_prototypes = {read_only = true, other_fields = true}, + permissions = {read_only = true, other_fields = true}, + player = {read_only = true, other_fields = true}, + players = {read_only = true, other_fields = true}, + pollution_statistics = {read_only = true, other_fields = true}, + recipe_category_prototypes = {read_only = true, other_fields = true}, + recipe_prototypes = {read_only = true, other_fields = true}, + resource_category_prototypes = {read_only = true, other_fields = true}, + shortcut_prototypes = {read_only = true, other_fields = true}, + styles = {read_only = true, other_fields = true}, + surfaces = {read_only = true, other_fields = true}, + technology_prototypes = {read_only = true, other_fields = true}, + tick = {read_only = true, other_fields = true}, + ticks_played = {read_only = true, other_fields = true}, + tile_prototypes = {read_only = true, other_fields = true}, + trivial_smoke_prototypes = {read_only = true, other_fields = true}, + virtual_signal_prototypes = {read_only = true, other_fields = true}, -stds.factorio_data = { - - read_globals = { - data = { - fields = { - raw = { - other_fields = true, - read_only = false + autosave_enabled = {read_only = false, other_fields = false}, + draw_resource_selection = {read_only = false, other_fields = false}, + enemy_has_vision_on_land_mines = {read_only = false, other_fields = false}, + speed = {read_only = false, other_fields = false}, + tick_paused = {read_only = false, other_fields = false}, + ticks_to_run = {read_only = false, other_fields = false} }, - "extend", "is_demo" }, }, - settings = { - fields = { - "startup", "global", "player", + globals = { + -- @global@: The global dictionary, useful for storing data persistent across a save-load cycle. + -- Writing access is given to the mod-id field (for mod-wise saved data). + -- (http://lua-api.factorio.com/latest/Global.html) + "global", + + -- @MOD@: Keep it organized, use this variable for anything that "NEEDS" to be global for some reason. + "MOD" + }, + } + + stds.factorio_data = { + + read_globals = { + data = { + fields = { + raw = { + other_fields = true, + read_only = false + }, + "extend", "is_demo" + }, }, - }, - --Popular mods - angelsmods = { - other_fields = true - }, + settings = { + fields = { + "startup", "global", "player", "get", "get_startup" + }, + }, + + mods = { + other_fields = true + }, + + -- Popular mods that think they need globals! + angelsmods = { + other_fields = true + }, + + -- Popular mods that think they need globals! + bobmods = { + other_fields = true + }, - bobmods = { - other_fields = true - }, - mods = { - other_fields = true } } -} +end -------------------------------------------------------------------------------- ---[Factorio Data]-------------------------------------------------------------- -------------------------------------------------------------------------------- -stds.factorio_base_control = { - read_globals = {"silo_script", "mod_gui", "camera"} -} - -stds.factorio_base_scenarios = { - globals = { - "check_automate_science_packs_advice", "check_research_hints", "check_supplies", "manage_attacks", "all_dead", - "on_win", "difficulty_number", "init_attack_data", "handle_attacks", "count_items_in_container", "progress", "scanned", - "check_light", "check_machine_gun", "level", "story_table", - - "tightspot_prices", "tightspot_make_offer", "tightspot_init", "tightspot_get_required_balance", - "tightspot_init_level", "tightspot_init_spending_frame", "tightspot_init_progress_frame", "tightspot_update_progress", "tightspot_update_spending", - "tightspot_get_missing_to_win", "tightspot_sell_back", "tightspot_start_level", "tightspot_show_level_description", "tightspot_update_speed_label", - "map_ignore", "tightspot_check_level", "land_price", - - "transport_belt_madness_init", "transport_belt_madness_init_level", "transport_belt_madness_create_chests", "transport_belt_madness_fill_chests", - "transport_belt_madness_start_level", "map_ignore", "map_clear", "map_load", "map_save", "transport_belt_madness_show_level_description", - "transport_belt_madness_check_level", "transport_belt_madness_next_level", "transport_belt_madness_clear_level", "transport_belt_madness_contains_next_level", - - "restricted", "check_built_items", "result", "disable_combat_technologies", "apply_character_modifiers", "apply_combat_modifiers", "apply_balance", - "load_config", "starting_area_constant", "create_next_surface", "end_round", "prepare_next_round", "silo_died","choose_joining_gui", - "destroy_joining_guis", "create_random_join_gui", "create_auto_assign_gui", "create_pick_join_gui", "create_config_gui", "make_config_table", "default", - "make_team_gui", "make_team_gui_config", "add_team_button_press", "trash_team_button_press", "remove_team_from_team_table", "add_team_to_team_table", - "set_teams_from_gui", "on_team_button_press", "make_color_dropdown", "create_balance_option", "create_disable_frame", "disable_frame", "parse_disabled_items", - "set_balance_settings", "config_confirm", "parse_config_from_gui", "get_color", "roll_starting_area", "delete_roll_surfaces", "auto_assign", - "destroy_config_for_all", "prepare_map", "set_evolution_factor", "update_players_on_team_count", "random_join", "init_player_gui", - "destroy_player_gui", "objective_button_press", "admin_button_press", "admin_frame_button_press", "diplomacy_button_press", "update_diplomacy_frame", - "diplomacy_frame_button_press", "team_changed_diplomacy", "diplomacy_check_press", "get_stance", "give_inventory", "setup_teams", "disable_items_for_all", - "set_random_team", "set_diplomacy", "create_spawn_positions", "set_spawn_position", "set_team_together_spawns", "chart_starting_area_for_force_spawns", - "check_starting_area_chunks_are_generated", "check_player_color", "check_round_start", "clear_starting_area_enemies", "check_no_rush_end", "check_no_rush_players", - "finish_setup", "chart_area_for_force", "setup_start_area_copy", "update_copy_progress", "update_progress_bar", "copy_paste_starting_area_tiles", - "copy_paste_starting_area_entities", "create_silo_for_force", "setup_research", "on_chunk_generated", "get_distance_to_nearest_spawn", - "create_wall_for_force", "fpn", "give_items", "create_item_frame", "create_technologies_frame", "create_cheat_frame", "create_day_frame", - "time_modifier", "points_per_second_start", "points_per_second_level_subtract", "levels", "update_info", "get_time_left", "update_time_left", - "on_joined", "make_frame", "update_frame", "update_table", "calculate_task_item_multiplayer", "setup_config", "select_from_probability_table", - "select_inventory", "select_equipment", "select_challange_type", "save_round_statistics", "start_challenge", "create_teams", "set_areas", - "decide_player_team", "set_teams", "refresh_leaderboard", "set_player", "generate_technology_list", "generate_research_task","setup_unlocks", - "check_technology_progress", "generate_production_task", "generate_shopping_list_task", "set_gui_flow_table", "create_visibility_button", - "check_item_lists", "update_task_gui", "check_end_of_round", "end_round_gui_update", "try_to_check_victory", "update_gui", "check_start_round", - "check_start_set_areas", "check_start_setting_entities", "check_set_areas", "check_clear_areas", "check_chests", "check_chests_shopping_list", - "check_chests_production", "check_input_chests", "fill_input_chests", "check_victory", "shopping_task_finished", "calculate_force_points", - "update_research_task_table", "update_production_task_table", "update_shopping_list_task_table", "create_joined_game_gui", "pre_ending_round", - "player_ending_prompt", "update_end_timer", "update_begin_timer", "team_finished", "save_points_list", "give_force_players_points", - "update_winners_list", "set_spectator", "set_character", "give_starting_inventory", "give_equipment", "shuffle_table", "format_time", - "spairs", "fill_leaderboard", "create_grid", "simple_entities", "save_map_data", "clear_map", "create_tiles", "recreate_entities", - "map_sets", "give_points", "init_forces", "init_globals", "init_unit_settings", "check_next_wave", "next_wave", "calculate_wave_power", - "wave_end", "make_next_spawn_tick", "check_spawn_units", "get_wave_units", "spawn_units", "randomize_ore", "set_command", "command_straglers", - "unit_config", "make_next_wave_tick", "time_to_next_wave", "time_to_wave_end", "rocket_died", "unit_died", "get_bounty_price", "setup_waypoints", - "insert_items", "give_starting_equipment", "give_spawn_equipment", "next_round_button_visible", "gui_init", "create_wave_frame", "create_money_frame", - "create_upgrade_gui", "update_upgrade_listing", "upgrade_research", "get_upgrades", "get_money", "update_connected_players", "update_round_number", - "set_research", "set_recipes", "check_deconstruction", "check_blueprint_placement", "loop_entities", "experiment_items", - "setup", "story_gui_click", "clear_surface", "add_run_trains_button", "puzzle_condition", "basic_signals", - "loop_trains", "Y_offset", "ghosts_1", "ghosts_2", "required_path", "through_wall_path", "count", "check_built_real_rail", - "current_ghosts_count", "other", "rails", "set_rails", "straight_section", "late_entities", "entities", "stop", - "get_spawn_coordinate", - - --tutorials - "intermission", "create_entities_on_tick", "on_player_created", "required_count", "non_player_entities", "clear_rails", - "chest", "damage", "furnace", "init_prototypes", "build_infi_table", "junk", "update_player_tags", "time_left", "team_production", - "create_task_frame", "create_visibilty_buttons", "update_leaderboard", "in_in_area" +do -- Factorio Base/Core STDs-- + stds.factorio_base_control = { + read_globals = {"silo_script", "mod_gui", "camera"} } -} -stds.factorio_base_data = { - globals = { - --Style - "make_cursor_box", "make_full_cursor_box", - "default_container_padding", "default_orange_color", "default_light_orange_color", "warning_red_color", - "achievement_green_color", "achievement_tan_color", "orangebuttongraphcialset", "bluebuttongraphcialset", - "bonus_gui_ordering", "trivial_smoke", "technology_slot_base_width", "technology_slot_base_height", "default_frame_font_vertical_compensation", + stds.factorio_base_scenarios = { + globals = { + "check_automate_science_packs_advice", "check_research_hints", "check_supplies", "manage_attacks", "all_dead", + "on_win", "difficulty_number", "init_attack_data", "handle_attacks", "count_items_in_container", "progress", "scanned", + "check_light", "check_machine_gun", "level", "story_table", - --Belts - "transport_belt_connector_frame_sprites", "transport_belt_circuit_wire_connection_point", "transport_belt_circuit_wire_max_distance", - "transport_belt_circuit_connector_sprites", "ending_patch_prototype", "basic_belt_horizontal", "basic_belt_vertical", - "basic_belt_ending_top", "basic_belt_ending_bottom", "basic_belt_ending_side", "basic_belt_starting_top", "basic_belt_starting_bottom", - "basic_belt_starting_side", "fast_belt_horizontal", "fast_belt_vertical", "fast_belt_ending_top", "fast_belt_ending_bottom", - "fast_belt_ending_side", "fast_belt_starting_top", "fast_belt_starting_bottom", "fast_belt_starting_side", "express_belt_horizontal", - "express_belt_vertical", "express_belt_ending_top", "express_belt_ending_bottom", "express_belt_ending_side", "express_belt_starting_top", - "express_belt_starting_bottom", "express_belt_starting_side", + "tightspot_prices", "tightspot_make_offer", "tightspot_init", "tightspot_get_required_balance", + "tightspot_init_level", "tightspot_init_spending_frame", "tightspot_init_progress_frame", "tightspot_update_progress", "tightspot_update_spending", + "tightspot_get_missing_to_win", "tightspot_sell_back", "tightspot_start_level", "tightspot_show_level_description", "tightspot_update_speed_label", + "map_ignore", "tightspot_check_level", "land_price", - --Circuit Connectors - "circuit_connector_definitions", "default_circuit_wire_max_distance", "inserter_circuit_wire_max_distance", - "universal_connector_template", "belt_connector_template", "belt_frame_connector_template", "inserter_connector_template", + "transport_belt_madness_init", "transport_belt_madness_init_level", "transport_belt_madness_create_chests", "transport_belt_madness_fill_chests", + "transport_belt_madness_start_level", "map_ignore", "map_clear", "map_load", "map_save", "transport_belt_madness_show_level_description", + "transport_belt_madness_check_level", "transport_belt_madness_next_level", "transport_belt_madness_clear_level", "transport_belt_madness_contains_next_level", - --Inserter Circuit Connectors - "inserter_circuit_wire_max_distance", "inserter_default_stack_control_input_signal", + "restricted", "check_built_items", "result", "disable_combat_technologies", "apply_character_modifiers", "apply_combat_modifiers", "apply_balance", + "load_config", "starting_area_constant", "create_next_surface", "end_round", "prepare_next_round", "silo_died","choose_joining_gui", + "destroy_joining_guis", "create_random_join_gui", "create_auto_assign_gui", "create_pick_join_gui", "create_config_gui", "make_config_table", "default", + "make_team_gui", "make_team_gui_config", "add_team_button_press", "trash_team_button_press", "remove_team_from_team_table", "add_team_to_team_table", + "set_teams_from_gui", "on_team_button_press", "make_color_dropdown", "create_balance_option", "create_disable_frame", "disable_frame", "parse_disabled_items", + "set_balance_settings", "config_confirm", "parse_config_from_gui", "get_color", "roll_starting_area", "delete_roll_surfaces", "auto_assign", + "destroy_config_for_all", "prepare_map", "set_evolution_factor", "update_players_on_team_count", "random_join", "init_player_gui", + "destroy_player_gui", "objective_button_press", "admin_button_press", "admin_frame_button_press", "diplomacy_button_press", "update_diplomacy_frame", + "diplomacy_frame_button_press", "team_changed_diplomacy", "diplomacy_check_press", "get_stance", "give_inventory", "setup_teams", "disable_items_for_all", + "set_random_team", "set_diplomacy", "create_spawn_positions", "set_spawn_position", "set_team_together_spawns", "chart_starting_area_for_force_spawns", + "check_starting_area_chunks_are_generated", "check_player_color", "check_round_start", "clear_starting_area_enemies", "check_no_rush_end", "check_no_rush_players", + "finish_setup", "chart_area_for_force", "setup_start_area_copy", "update_copy_progress", "update_progress_bar", "copy_paste_starting_area_tiles", + "copy_paste_starting_area_entities", "create_silo_for_force", "setup_research", "on_chunk_generated", "get_distance_to_nearest_spawn", + "create_wall_for_force", "fpn", "give_items", "create_item_frame", "create_technologies_frame", "create_cheat_frame", "create_day_frame", + "time_modifier", "points_per_second_start", "points_per_second_level_subtract", "levels", "update_info", "get_time_left", "update_time_left", + "on_joined", "make_frame", "update_frame", "update_table", "calculate_task_item_multiplayer", "setup_config", "select_from_probability_table", + "select_inventory", "select_equipment", "select_challange_type", "save_round_statistics", "start_challenge", "create_teams", "set_areas", + "decide_player_team", "set_teams", "refresh_leaderboard", "set_player", "generate_technology_list", "generate_research_task","setup_unlocks", + "check_technology_progress", "generate_production_task", "generate_shopping_list_task", "set_gui_flow_table", "create_visibility_button", + "check_item_lists", "update_task_gui", "check_end_of_round", "end_round_gui_update", "try_to_check_victory", "update_gui", "check_start_round", + "check_start_set_areas", "check_start_setting_entities", "check_set_areas", "check_clear_areas", "check_chests", "check_chests_shopping_list", + "check_chests_production", "check_input_chests", "fill_input_chests", "check_victory", "shopping_task_finished", "calculate_force_points", + "update_research_task_table", "update_production_task_table", "update_shopping_list_task_table", "create_joined_game_gui", "pre_ending_round", + "player_ending_prompt", "update_end_timer", "update_begin_timer", "team_finished", "save_points_list", "give_force_players_points", + "update_winners_list", "set_spectator", "set_character", "give_starting_inventory", "give_equipment", "shuffle_table", "format_time", + "spairs", "fill_leaderboard", "create_grid", "simple_entities", "save_map_data", "clear_map", "create_tiles", "recreate_entities", + "map_sets", "give_points", "init_forces", "init_globals", "init_unit_settings", "check_next_wave", "next_wave", "calculate_wave_power", + "wave_end", "make_next_spawn_tick", "check_spawn_units", "get_wave_units", "spawn_units", "randomize_ore", "set_command", "command_straglers", + "unit_config", "make_next_wave_tick", "time_to_next_wave", "time_to_wave_end", "rocket_died", "unit_died", "get_bounty_price", "setup_waypoints", + "insert_items", "give_starting_equipment", "give_spawn_equipment", "next_round_button_visible", "gui_init", "create_wave_frame", "create_money_frame", + "create_upgrade_gui", "update_upgrade_listing", "upgrade_research", "get_upgrades", "get_money", "update_connected_players", "update_round_number", + "set_research", "set_recipes", "check_deconstruction", "check_blueprint_placement", "loop_entities", "experiment_items", + "setup", "story_gui_click", "clear_surface", "add_run_trains_button", "puzzle_condition", "basic_signals", + "loop_trains", "Y_offset", "ghosts_1", "ghosts_2", "required_path", "through_wall_path", "count", "check_built_real_rail", + "current_ghosts_count", "other", "rails", "set_rails", "straight_section", "late_entities", "entities", "stop", + "get_spawn_coordinate", - --Sounds/beams - "make_heavy_gunshot_sounds", "make_light_gunshot_sounds", "make_laser_sounds", - - --Gun/Laser - "gun_turret_extension", "gun_turret_extension_shadow", "gun_turret_extension_mask", "gun_turret_attack", - "laser_turret_extension", "laser_turret_extension_shadow", "laser_turret_extension_mask", - - --Pipes - "pipecoverspictures", "pipepictures", "assembler2pipepictures", "assembler3pipepictures", "make_heat_pipe_pictures", - - --Combinators - "generate_arithmetic_combinator", "generate_decider_combinator", "generate_constant_combinator", - - --Rail - "destroyed_rail_pictures", "rail_pictures", "rail_pictures_internal", "standard_train_wheels", "drive_over_tie", - "rolling_stock_back_light", "rolling_stock_stand_by_light", - - --Enemies - "make_enemy_autoplace", "make_enemy_spawner_autoplace", "make_enemy_worm_autoplace", - "make_spitter_attack_animation", "make_spitter_run_animation", "make_spitter_dying_animation", - "make_spitter_attack_parameters", "make_spitter_roars", "make_spitter_dying_sounds", - "make_spawner_idle_animation", "make_spawner_die_animation", - "make_biter_run_animation", "make_biter_attack_animation", "make_biter_die_animation", - "make_biter_roars", "make_biter_dying_sounds", "make_biter_calls", - "make_worm_roars", "make_worm_dying_sounds", "make_worm_folded_animation", "make_worm_preparing_animation", - "make_worm_prepared_animation", "make_worm_attack_animation", "make_worm_die_animation", - - --Other - "tile_variations_template", "make_water_autoplace_settings", - "make_unit_melee_ammo_type", "make_trivial_smoke", "make_4way_animation_from_spritesheet", "flying_robot_sounds", - "productivitymodulelimitation", "crash_trigger", "capsule_smoke", "make_beam", "playeranimations", - "make_blood_tint", "make_shadow_tint", - - --tiles - "water_transition_template", "make_water_transition_template", "water_autoplace_settings", "water_tile_type_names", - "patch_for_inner_corner_of_transition_between_transition", + --tutorials + "intermission", "create_entities_on_tick", "on_player_created", "required_count", "non_player_entities", "clear_rails", + "chest", "damage", "furnace", "init_prototypes", "build_infi_table", "junk", "update_player_tags", "time_left", "team_production", + "create_task_frame", "create_visibilty_buttons", "update_leaderboard", "in_in_area" + } } -} -stds.factorio_base_story = { - globals = { - "story_init_helpers", "story_update_table", "story_init", "story_update", "story_on_tick", "story_add_update", - "story_remove_update", "story_jump_to", "story_elapsed", "story_elapsed_check", "story_show_message_dialog", - "set_goal", "player_set_goal", "on_player_joined", "flash_goal", "set_info", "player_set_info", "export_entities", - "list", "recreate_entities", "entity_to_connect", "limit_camera", "find_gui_recursive", "enable_entity_export", - "add_button", "on_gui_click", "set_continue_button_style", "add_message_log", "story_add_message_log", - "player_add_message_log", "message_log_frame", "message_log_scrollpane", "message_log_close_button", - "message_log_table", "toggle_message_log_button", "toggle_objective_button", "message_log_init", - "add_gui_recursive", "add_toggle_message_log_button", "add_toggle_objective_button", "mod_gui", - "flash_message_log_button", "flash_message_log_on_tick", "story_gui_click", "story_points_by_name", "story_branches", - "player", "surface", "deconstruct_on_tick", "recreate_entities_on_tick", "flying_congrats", "story_table" + stds.factorio_base_data = { + globals = { + --Style + "make_cursor_box", "make_full_cursor_box", + "default_container_padding", "default_orange_color", "default_light_orange_color", "warning_red_color", + "achievement_green_color", "achievement_tan_color", "orangebuttongraphcialset", "bluebuttongraphcialset", + "bonus_gui_ordering", "trivial_smoke", "technology_slot_base_width", "technology_slot_base_height", "default_frame_font_vertical_compensation", + + --Belts + "transport_belt_connector_frame_sprites", "transport_belt_circuit_wire_connection_point", "transport_belt_circuit_wire_max_distance", + "transport_belt_circuit_connector_sprites", "ending_patch_prototype", "basic_belt_horizontal", "basic_belt_vertical", + "basic_belt_ending_top", "basic_belt_ending_bottom", "basic_belt_ending_side", "basic_belt_starting_top", "basic_belt_starting_bottom", + "basic_belt_starting_side", "fast_belt_horizontal", "fast_belt_vertical", "fast_belt_ending_top", "fast_belt_ending_bottom", + "fast_belt_ending_side", "fast_belt_starting_top", "fast_belt_starting_bottom", "fast_belt_starting_side", "express_belt_horizontal", + "express_belt_vertical", "express_belt_ending_top", "express_belt_ending_bottom", "express_belt_ending_side", "express_belt_starting_top", + "express_belt_starting_bottom", "express_belt_starting_side", + + --Circuit Connectors + "circuit_connector_definitions", "default_circuit_wire_max_distance", "inserter_circuit_wire_max_distance", + "universal_connector_template", "belt_connector_template", "belt_frame_connector_template", "inserter_connector_template", + + --Inserter Circuit Connectors + "inserter_circuit_wire_max_distance", "inserter_default_stack_control_input_signal", + + --Sounds/beams + "make_heavy_gunshot_sounds", "make_light_gunshot_sounds", "make_laser_sounds", + + --Gun/Laser + "gun_turret_extension", "gun_turret_extension_shadow", "gun_turret_extension_mask", "gun_turret_attack", + "laser_turret_extension", "laser_turret_extension_shadow", "laser_turret_extension_mask", + + --Pipes + "pipecoverspictures", "pipepictures", "assembler2pipepictures", "assembler3pipepictures", "make_heat_pipe_pictures", + + --Combinators + "generate_arithmetic_combinator", "generate_decider_combinator", "generate_constant_combinator", + + --Rail + "destroyed_rail_pictures", "rail_pictures", "rail_pictures_internal", "standard_train_wheels", "drive_over_tie", + "rolling_stock_back_light", "rolling_stock_stand_by_light", + + --Enemies + "make_enemy_autoplace", "make_enemy_spawner_autoplace", "make_enemy_worm_autoplace", + "make_spitter_attack_animation", "make_spitter_run_animation", "make_spitter_dying_animation", + "make_spitter_attack_parameters", "make_spitter_roars", "make_spitter_dying_sounds", + "make_spawner_idle_animation", "make_spawner_die_animation", + "make_biter_run_animation", "make_biter_attack_animation", "make_biter_die_animation", + "make_biter_roars", "make_biter_dying_sounds", "make_biter_calls", + "make_worm_roars", "make_worm_dying_sounds", "make_worm_folded_animation", "make_worm_preparing_animation", + "make_worm_prepared_animation", "make_worm_attack_animation", "make_worm_die_animation", + + --Other + "tile_variations_template", "make_water_autoplace_settings", + "make_unit_melee_ammo_type", "make_trivial_smoke", "make_4way_animation_from_spritesheet", "flying_robot_sounds", + "productivitymodulelimitation", "crash_trigger", "capsule_smoke", "make_beam", "playeranimations", + "make_blood_tint", "make_shadow_tint", + + --tiles + "water_transition_template", "make_water_transition_template", "water_autoplace_settings", "water_tile_type_names", + "patch_for_inner_corner_of_transition_between_transition", + } } -} -stds.factorio_circuit_connector_generated = { - globals = { - 'default_circuit_wire_max_distance', 'circuit_connector_definitions', 'universal_connector_template', - 'belt_connector_template', 'belt_frame_connector_template', 'inserter_connector_template', 'inserter_connector_template', - 'inserter_circuit_wire_max_distance', 'inserter_default_stack_control_input_signal', 'transport_belt_connector_frame_sprites', - 'transport_belt_circuit_wire_max_distance', + stds.factorio_base_story = { + globals = { + "story_init_helpers", "story_update_table", "story_init", "story_update", "story_on_tick", "story_add_update", + "story_remove_update", "story_jump_to", "story_elapsed", "story_elapsed_check", "story_show_message_dialog", + "set_goal", "player_set_goal", "on_player_joined", "flash_goal", "set_info", "player_set_info", "export_entities", + "list", "recreate_entities", "entity_to_connect", "limit_camera", "find_gui_recursive", "enable_entity_export", + "add_button", "on_gui_click", "set_continue_button_style", "add_message_log", "story_add_message_log", + "player_add_message_log", "message_log_frame", "message_log_scrollpane", "message_log_close_button", + "message_log_table", "toggle_message_log_button", "toggle_objective_button", "message_log_init", + "add_gui_recursive", "add_toggle_message_log_button", "add_toggle_objective_button", "mod_gui", + "flash_message_log_button", "flash_message_log_on_tick", "story_gui_click", "story_points_by_name", "story_branches", + "player", "surface", "deconstruct_on_tick", "recreate_entities_on_tick", "flying_congrats", "story_table" + } } -} ---(( STDLIB ))-- -stds.stdlib = { - read_globals = { - table = { - fields = { - "map", "avg", "count_keys", "sum", "max", "remove", "insert", "invert", "first", "sort", "compare", "maxn", "any", "array_to_dictionary", - "each", "flatten", "keys", "filter", "remove_keys", "flexcopy", "find", "fullcopy", "values", "pack", "deepcopy", "concat", "clear", "min", - "is_empty", "merge", "size", "dictionary_merge", "unpack", "last" + stds.factorio_circuit_connector_generated = { + globals = { + 'default_circuit_wire_max_distance', 'circuit_connector_definitions', 'universal_connector_template', + 'belt_connector_template', 'belt_frame_connector_template', 'inserter_connector_template', 'inserter_connector_template', + 'inserter_circuit_wire_max_distance', 'inserter_default_stack_control_input_signal', 'transport_belt_connector_frame_sprites', + 'transport_belt_circuit_wire_max_distance', + } + } +end + +do -- STDLIB STDs-- + stds.stdlib = { + read_globals = {}, + globals = { + 'STDLIB', + 'prequire', + 'rawtostring', + 'traceback', + 'data_traceback', + 'inspect', + 'serpent', + 'inline_if', + 'install', + 'log', + 'concat', + 'GAME', + 'AREA', + 'POSITION', + 'TILE', + 'SURFACE', + 'CHUNK', + 'COLOR', + 'ENTITY', + 'INVENTORY', + 'RESOURCE', + 'CONFIG', + 'LOGGER', + 'QUEUE', + 'EVENT', + 'GUI', + 'PLAYER', + 'FORCE', + 'MATH', + 'STRING', + 'TABLE' + } + } + + stds.stdlib_control = {} + + stds.stdlib_data = { + globals = { + 'DATA', + 'RECIPE', + 'ITEM', + 'FLUID', + 'ENTITY', + 'TECHNOLOGY', + 'CATEGORY' + } + } +end + +do -- Love STDs + stds.love_extra = { + read_globals = { + love = { + fields = { + arg = { + fields = { + 'parseGameArguments', + 'parseOption', + 'getLow', + 'optionIndices', + 'options' + } + } + } }, + 'coroutine', + 'io', + 'socket', + 'dofile', + 'loadfile' }, - string = { - fields = { - "is_space", "is_empty", "match", "title", "upper", "gmatch", "trim", "split", "len", "ordinal_suffix", "dump", "shorten", "reverse", - "ends_with", "byte", "starts_with", "join", "is_alpha", "lower", "is_upper", "is_digit", "is_alnum", "rjust", "center", "ljust", "format", - "char", "is_lower", "contains", "gsub", "find", "rep", "sub" - }, - }, - math = { - fields = { - "asin", "max", "modf", "midrange_mean", "pow", "ldexp", "maxuint16", "fmod", "round_to", "randomseed", "huge", "harmonic_mean", "tan", - "maxint32", "quadratic_mean", "pi", "energetic_mean", "minint8", "frexp", "generalized_mean", "rad", "sin", "sinh", "min", "geometric_mean", - "atan", "avg", "cosh", "maxint8", "arithmetic_mean", "exp", "sum", "round", "maxuint64", "minint64", "ceil", "maxint64", "atan2", "floor_to", - "floor", "log", "maxint16", "minint16", "tanh", "acos", "deg", "cos", "log10", "maxuint8", "abs", "weighted_mean", "random", "maxuint32", - "sqrt", "minint32" + globals = { + love = { + fields = { + 'handlers' + } } - }, - }, - globals = { - "prequire", "rawtostring", "traceback", "inspect", "serpent", "inline_if", - "GAME", "AREA", "POSITION", "TILE", "SURFACE", "CHUNK", "COLOR", "ENTITY", "INVENTORY", "RESOURCE", "CONFIG", "LOGGER", "QUEUE", - "EVENT", "GUI", "PLAYER", "FORCE", - "_STDLIB_NO_DEFINES_COLOR", "_STDLIB_NO_DEFINES_TIME", "_STDLIB_NO_STRING", "_STDLIB_NO_TABLE", "_STDLIB_NO_MATH" - } -} - -stds.stdlib_control = { -} - -stds.stdlib_data = { - globals = { - 'DATA', 'RECIPE', 'ITEM', 'FLUID', 'ENTITY', 'TECHNOLOGY', 'CATEGORY' - } -} --)) - ---(( FACTORIO DEFINES ))-- -stds.factorio_defines = { - globals = {"creative_mode_defines"}, - read_globals = { - defines = { - fields = { - events = { - fields = { - "on_tick", "on_gui_click", "on_gui_text_changed", "on_gui_checked_state_changed", "on_entity_died", "on_entity_damaged", "on_picked_up_item", - "on_built_entity", "on_sector_scanned", "on_player_mined_item", "on_put_item", "on_rocket_launched", "on_pre_player_mined_item", "on_chunk_generated", - "on_player_crafted_item", "on_robot_built_entity", "on_robot_pre_mined", "on_robot_mined", "on_research_started", "on_research_finished", - "on_player_rotated_entity", "on_marked_for_deconstruction", "on_canceled_deconstruction", "on_trigger_created_entity", "on_train_changed_state", - "on_player_created", "on_resource_depleted", "on_player_driving_changed_state", "on_force_created", "on_forces_merging", "on_player_cursor_stack_changed", - "on_pre_entity_settings_pasted", "on_entity_settings_pasted", "on_player_main_inventory_changed", "on_player_quickbar_inventory_changed", - "on_player_tool_inventory_changed", "on_player_armor_inventory_changed", "on_player_ammo_inventory_changed", "on_player_gun_inventory_changed", - "on_player_placed_equipment", "on_player_removed_equipment", "on_pre_player_died", "on_player_died", "on_player_respawned", "on_player_joined_game", - "on_player_left_game", "on_player_built_tile", "on_player_mined_tile", "on_robot_built_tile", "on_robot_mined_tile", "on_player_selected_area", - "on_player_alt_selected_area", "on_player_changed_surface", "on_selected_entity_changed", "on_market_item_purchased", "on_player_dropped_item", - "on_biter_base_built", "on_player_changed_force", "on_entity_renamed", "on_gui_selection_state_changed", "on_runtime_mod_setting_changed", - "on_difficulty_settings_changed", "on_surface_created", "on_surface_deleted", "on_pre_surface_deleted", "on_player_mined_entity", "on_robot_mined_entity", - "on_train_created", "on_gui_elem_changed", "on_player_setup_blueprint", "on_player_deconstructed_area", "on_player_configured_blueprint", "on_console_chat", - "on_console_command", "on_player_removed", "on_player_used_capsule", "script_raised_built", "script_raised_destroy", "script_raised_revive", - "on_player_promoted", "on_player_demoted", "on_combat_robot_expired", "on_player_changed_position", "on_mod_item_opened", "on_gui_opened", - "on_gui_closed", "on_gui_value_changed", "on_player_muted", "on_player_unmuted", "on_player_cheat_mode_enabled", "on_player_cheat_mode_disabled", - "on_character_corpse_expired", "on_pre_ghost_deconstructed", "on_player_pipette", "on_player_display_resolution_changed", "on_player_display_scale_changed", - "on_pre_player_crafted_item", "on_player_cancelled_crafting", "on_chunk_charted", "on_technology_effects_reset", "on_land_mine_armed", "on_forces_merged", - "on_player_trash_inventory_changed", "on_pre_player_left_game" - }, - }, - alert_type = { - fields = { - "custom", "entity_destroyed", "entity_under_attack", "no_material_for_construction", - "no_storage", "not_enough_construction_robots", "not_enough_repair_packs", "turret_fire", - }, - }, - chain_signal_state = { - fields = { - "all_open", "none", "none_open", "partially_open", - }, - }, - chunk_generated_status = { - fields = { - "basic_tiles", "corrected_tiles", "custom_tiles", "entities", "nothing", "tiles", - }, - }, - circuit_condition_index = { - fields = { - "arithmetic_combinator", "constant_combinator", "decider_combinator", "inserter_circuit", - "inserter_logistic", "lamp", "offshore_pump", "pump", - }, - }, - circuit_connector_id = { - fields = { - "accumulator", "combinator_input", "combinator_output", "constant_combinator", "container", - "electric_pole", "inserter", "lamp", "offshore_pump", "programmable_speaker", "pump", - "rail_signal", "roboport", "storage_tank", "wall", - }, - }, - command = { - fields = { - "attack", "attack_area", "build_base", "compound", "go_to_location", "group", "wander", - }, - }, - compound_command = { - fields = { - "logical_and", "logical_or", "return_last", - }, - }, - control_behavior = { - fields = { - inserter = { - fields = { - circuit_mode_of_operation = { - fields = { - "enable_disable", "none", "read_hand_contents", "set_filters", "set_stack_size", - }, - }, - hand_read_mode = { - fields = { - "hold", "pulse", - } - }, - }, - }, - lamp = { - fields = { - circuit_mode_of_operation = { - fields = { - "use_colors", - } - }, - }, - }, - logistic_container = { - fields = { - circuit_mode_of_operation = { - fields = { - "send_contents", "set_requests", - } - }, - }, - }, - mining_drill = { - fields = { - resource_read_mode = { - fields = { - "entire_patch", "this_miner", - } - }, - }, - }, - roboport = { - fields = { - circuit_mode_of_operation = { - fields = { - "read_logistics", "read_robot_stats", - } - }, - }, - }, - train_stop = { - fields = { - circuit_mode_of_operation = { - fields = { - "enable_disable", "read_from_train", "send_to_train", - } - }, - }, - }, - type = { - fields = { - "accumulator", "arithmetic_combinator", "constant_combinator", "container", - "decider_combinator", "generic_on_off", "inserter", "lamp", "logistic_container", - "rail_signal", "roboport", "storage_tank", "train_stop", "transport_belt", - }, - }, - }, - }, - controllers = { - fields = { - "character", "ghost", "god", - }, - }, - deconstruction_item = { - fields = { - entity_filter_mode = { - fields = { - "blacklist", "whitelist", - }, - }, - tile_filter_mode = { - fields = { - "always", "never", "normal", "only", - } - }, - }, - }, - difficulty = { - fields = { - "easy", "hard", "normal", - }, - }, - difficulty_settings = { - fields = { - recipe_difficulty = { - fields = { - "expensive", "normal", - }, - }, - technology_difficulty = { - fields = { - "expensive", "normal", - } - }, - }, - }, - direction = { - fields = { - "east", "north", "northeast", "northwest", "south", "southeast", "southwest", "west", - }, - }, - distraction = { - fields = { - "by_anything", "by_damage", "by_enemy", "none", - }, - }, - group_state = { - fields = { - "attacking_distraction", "attacking_target", "finished", "gathering", "moving", - }, - }, - gui_type = { - fields = { - "achievement", "blueprint_library", "bonus", "controller", "entity", "equipment", "item", - "kills", "logistic", "none", "other_player", "permissions", "production", "research", - "trains", "tutorials", "custom", - }, - }, - input_action = { - fields = { - "add_permission_group", "alt_select_area", "alt_select_blueprint_entities", "begin_mining", - "begin_mining_terrain", "build_item", "build_rail", "build_terrain", "cancel_craft", - "cancel_deconstruct", "cancel_new_blueprint", "cancel_research", "change_active_item_group_for_crafting", - "change_active_item_group_for_filters", "change_active_quick_bar", "change_arithmetic_combinator_parameters", - "change_blueprint_book_record_label", "change_decider_combinator_parameters", "change_item_label", - "change_picking_state", "change_programmable_speaker_alert_parameters", "change_programmable_speaker_circuit_parameters", - "change_programmable_speaker_parameters", "change_riding_state", "change_shooting_state", - "change_single_blueprint_record_label", "change_train_stop_station", "change_train_wait_condition", - "change_train_wait_condition_data", "clean_cursor_stack", "clear_blueprint", "clear_selected_blueprint", - "clear_selected_deconstruction_item", "connect_rolling_stock", "copy_entity_settings", "craft", - "craft_blueprint_record", "create_blueprint_like", "cursor_split", "cursor_transfer", "custom_input", - "cycle_blueprint_book_backwards", "cycle_blueprint_book_forwards", "deconstruct", "delete_blueprint_record", - "delete_custom_tag", "delete_permission_group", "disconnect_rolling_stock", "drop_blueprint_record", - "drop_item", "drop_to_blueprint_book", "edit_custom_tag", "edit_permission_group", "edit_train_schedule", - "export_blueprint", "fast_entity_split", "fast_entity_transfer", "grab_blueprint_record", "gui_checked_state_changed", - "gui_click", "gui_elem_selected", "gui_selection_state_changed", "gui_text_changed", "import_blueprint", - "import_blueprint_string", "inventory_split", "inventory_transfer", "launch_rocket", "market_offer", - "mod_settings_changed", "open_achievements_gui", "open_blueprint_library_gui", "open_blueprint_record", - "open_bonus_gui", "open_character_gui", "open_equipment", "open_gui", "open_item", "open_kills_gui", - "open_logistic_gui", "open_production_gui", "open_technology_gui", "open_train_gui", "open_train_station_gui", - "open_trains_gui", "open_tutorials_gui", "paste_entity_settings", "place_equipment", "remove_cables", - "reset_assembling_machine", "reverse_rotate_entity", "rotate_entity", "select_area", "select_blueprint_entities", - "select_entity_slot", "select_gun", "select_item", "select_tile_slot", "set_auto_launch_rocket", "set_autosort_inventory", - "set_behavior_mode", "set_blueprint_icon", "set_circuit_condition", "set_circuit_mode_of_operation", - "set_deconstruction_item_tile_selection_mode", "set_deconstruction_item_trees_only", "set_entity_color", - "set_entity_energy_property", "set_filter", "set_inserter_max_stack_size", "set_inventory_bar", "set_logistic_filter_item", - "set_logistic_filter_signal", "set_logistic_trash_filter_item", "set_research_finished_stops_game", "set_signal", - "set_single_blueprint_record_icon", "set_train_stopped", "set_use_item_groups", "setup_assembling_machine", - "setup_blueprint", "setup_single_blueprint_record", "shortcut_quick_bar_transfer", "smart_pipette", "stack_split", - "stack_transfer", "start_repair", "start_research", "start_walking", "switch_connect_to_logistic_network", - "switch_constant_combinator_state", "switch_power_switch_state", "switch_to_rename_stop_gui", "take_equipment", - "toggle_connect_center_back_tank", "toggle_connect_front_center_tank", "toggle_deconstruction_item_entity_filter_mode", - "toggle_deconstruction_item_tile_filter_mode", "toggle_driving", "toggle_enable_vehicle_logistics_while_moving", - "toggle_entity_on_off_state", "toggle_show_entity_info", "use_ability", "use_item", "wire_dragging", "write_to_console", - }, - }, - inventory = { - fields = { - "assembling_machine_input", "assembling_machine_modules", "assembling_machine_output", "beacon_modules", - "burnt_result", "car_ammo", "car_trunk", "cargo_wagon", "chest", "fuel", "furnace_modules", - "furnace_result", "furnace_source", "god_main", "god_quickbar", "item_main", "lab_input", "lab_modules", - "mining_drill_modules", "player_ammo", "player_armor", "player_guns", "player_main", "player_quickbar", - "player_tools", "player_trash", "player_vehicle", "roboport_material", "roboport_robot", "rocket_silo_result", - "rocket_silo_rocket", "turret_ammo", "rocket", "character_corpse" - }, - }, - logistic_member_index = { - fields = { - "character_provider", "character_requester", "character_storage", "generic_on_off_behavior", "logistic_container", "vehicle_storage", - }, - }, - logistic_mode = { - fields = { - "active_provider", "none", "passive_provider", "requester", "storage", "buffer" - }, - }, - mouse_button_type = { - fields = { - "left", "middle", "none", "right", - }, - }, - rail_connection_direction = { - fields = { - "left", "none", "right", "straight", - }, - }, - rail_direction = { - fields = { - "back", "front", - }, - }, - riding = { - fields = { - acceleration = { - fields = { - "accelerating", "braking", "nothing", "reversing", - }, - }, - direction = { - fields = { - "left", "right", "straight", - } - }, - }, - }, - shooting = { - fields = { - "not_shooting", "shooting_enemies", "shooting_selected", - }, - }, - signal_state = { - fields = { - "closed", "open", "reserved", "reserved_by_circuit_network", - }, - }, - train_state = { - fields = { - "arrive_signal", "arrive_station", "manual_control", "manual_control_stop", "no_path", "no_schedule", - "on_the_path", "path_lost", "stop_for_auto_control", "wait_signal", "wait_station", - }, - }, - transport_line = { - fields = { - "left_line", "left_split_line", "left_underground_line", "right_line", "right_split_line", "right_underground_line", - "secondary_left_line", "secondary_left_split_line", "secondary_right_line", "secondary_right_split_line", - }, - }, - wire_type = { - fields = { - "copper", "green", "red", - } - }, - -- Deprecated - colors = { - other_fields = true, - }, - -- Deprecated - anticolors = { - other_fields = true, - }, - -- Deprecated - lightcolors = { - other_fields = true, - }, - color = { - other_fields = true, - }, - anticolor = { - other_fields = true, - }, - lightcolor = { - other_fields = true, - }, - time = { - fields = { - "second", "minute", "hour", "day", "week", "month", "year", - } - }, - }, } } -} --)) +end ---[[ +do -- Factorio Defines STDs-- + stds.factorio_defines = { + read_globals = { + defines = { + fields = { + alert_type = { + fields = { + 'entity_destroyed', + 'entity_under_attack', + 'not_enough_construction_robots', + 'no_material_for_construction', + 'not_enough_repair_packs', + 'turret_fire', + 'custom', + 'no_storage', + 'train_out_of_fuel', + 'fluid_mixing' + } + }, + behavior_result = { + fields = { + 'in_progress', + 'fail', + 'success', + 'deleted' + } + }, + build_check_type = { + fields = { + 'script', + 'manual', + 'ghost_place', + 'ghost_revive' + } + }, + chain_signal_state = { + fields = { + 'all_open', + 'partially_open', + 'none_open' + } + }, + chunk_generated_status = { + fields = { + 'nothing', + 'custom_tiles', + 'basic_tiles', + 'corrected_tiles', + 'tiles', + 'entities' + } + }, + circuit_condition_index = { + fields = { + 'inserter_circuit', + 'inserter_logistic', + 'lamp', + 'arithmetic_combinator', + 'decider_combinator', + 'constant_combinator', + 'offshore_pump', + 'pump' + } + }, + circuit_connector_id = { + fields = { + 'accumulator', + 'constant_combinator', + 'container', + 'programmable_speaker', + 'rail_signal', + 'rail_chain_signal', + 'roboport', + 'storage_tank', + 'wall', + 'electric_pole', + 'inserter', + 'lamp', + 'combinator_input', + 'combinator_output', + 'offshore_pump', + 'pump' + } + }, + command = { + fields = { + 'attack', + 'go_to_location', + 'compound', + 'group', + 'attack_area', + 'wander', + 'flee', + 'stop', + 'build_base' + } + }, + compound_command = { + fields = { + 'logical_and', + 'logical_or', + 'return_last' + } + }, + control_behavior = { + fields = { + inserter = { + fields = { + circuit_mode_of_operation = { + fields = { + 'enable_disable', + 'set_filters', + 'read_hand_contents', + 'set_stack_size' + } + }, + hand_read_mode = { + fields = { + 'hold', + 'pulse' + } + } + } + }, + lamp = { + fields = { + circuit_mode_of_operation = { + fields = { + 'use_colors' + } + } + } + }, + logistic_container = { + fields = { + circuit_mode_of_operation = { + fields = { + 'send_contents', + 'set_requests' + } + } + } + }, + mining_drill = { + fields = { + resource_read_mode = { + fields = { + 'this_miner', + 'entire_patch' + } + } + } + }, + roboport = { + fields = { + circuit_mode_of_operation = { + fields = { + 'read_logistics', + 'read_robot_stats' + } + } + } + }, + train_stop = { + fields = { + circuit_mode_of_operation = { + fields = { + 'enable_disable', + 'send_to_train', + 'read_from_train', + 'read_stopped_train' + } + } + } + }, + transport_belt = { + fields = { + content_read_mode = { + fields = { + 'pulse', + 'hold' + } + } + } + }, + type = { + fields = { + 'container', + 'generic_on_off', + 'inserter', + 'lamp', + 'logistic_container', + 'roboport', + 'storage_tank', + 'train_stop', + 'decider_combinator', + 'arithmetic_combinator', + 'constant_combinator', + 'transport_belt', + 'accumulator', + 'rail_signal', + 'rail_chain_signal', + 'wall', + 'mining_drill', + 'programmable_speaker' + } + } + } + }, + controllers = { + fields = { + 'ghost', + 'character', + 'god', + 'editor', + 'cutscene', + 'spectator' + } + }, + deconstruction_item = { + fields = { + entity_filter_mode = { + fields = { + 'whitelist', + 'blacklist' + } + }, + tile_filter_mode = { + fields = { + 'whitelist', + 'blacklist' + } + }, + tile_selection_mode = { + fields = { + 'normal', + 'always', + 'never', + 'only' + } + } + } + }, + difficulty = { + fields = { + 'easy', + 'normal', + 'hard' + } + }, + difficulty_settings = { + fields = { + recipe_difficulty = { + fields = { + 'normal', + 'expensive' + } + }, + technology_difficulty = { + fields = { + 'normal', + 'expensive' + } + } + } + }, + direction = { + fields = { + 'north', + 'northeast', + 'east', + 'southeast', + 'south', + 'southwest', + 'west', + 'northwest' + } + }, + distraction = { + fields = { + 'by_enemy', + 'by_anything', + 'by_damage' + } + }, + entity_status = { + fields = { + 'working', + 'no_power', + 'no_fuel', + 'no_recipe', + 'no_input_fluid', + 'no_research_in_progress', + 'no_minable_resources', + 'low_input_fluid', + 'low_power', + 'disabled_by_control_behavior', + 'disabled_by_script', + 'fluid_ingredient_shortage', + 'fluid_production_overload', + 'item_ingredient_shortage', + 'item_production_overload', + 'marked_for_deconstruction', + 'missing_required_fluid', + 'missing_science_packs', + 'waiting_for_source_items', + 'waiting_for_space_in_destination', + 'waiting_to_launch_rocket' + } + }, + events = { + fields = { + 'on_tick', + 'on_gui_click', + 'on_gui_confirmed', + 'on_gui_text_changed', + 'on_gui_checked_state_changed', + 'on_entity_died', + 'on_post_entity_died', + 'on_entity_damaged', + 'on_picked_up_item', + 'on_built_entity', + 'on_sector_scanned', + 'on_player_mined_item', + 'on_put_item', + 'on_rocket_launched', + 'on_pre_player_mined_item', + 'on_chunk_generated', + 'on_player_crafted_item', + 'on_robot_built_entity', + 'on_robot_pre_mined', + 'on_robot_mined', + 'on_research_started', + 'on_research_finished', + 'on_player_rotated_entity', + 'on_player_set_quickbar_slot', + 'on_marked_for_deconstruction', + 'on_cancelled_deconstruction', + 'on_trigger_created_entity', + 'on_trigger_fired_artillery', + 'on_train_changed_state', + 'on_player_created', + 'on_resource_depleted', + 'on_player_driving_changed_state', + 'on_force_created', + 'on_forces_merging', + 'on_player_cursor_stack_changed', + 'on_pre_entity_settings_pasted', + 'on_entity_settings_pasted', + 'on_player_main_inventory_changed', + 'on_player_armor_inventory_changed', + 'on_player_ammo_inventory_changed', + 'on_player_gun_inventory_changed', + 'on_player_placed_equipment', + 'on_player_removed_equipment', + 'on_pre_player_died', + 'on_player_died', + 'on_player_respawned', + 'on_player_joined_game', + 'on_player_left_game', + 'on_player_built_tile', + 'on_player_mined_tile', + 'on_robot_built_tile', + 'on_robot_mined_tile', + 'on_player_selected_area', + 'on_player_alt_selected_area', + 'on_player_changed_surface', + 'on_selected_entity_changed', + 'on_market_item_purchased', + 'on_player_dropped_item', + 'on_biter_base_built', + 'on_player_changed_force', + 'on_entity_renamed', + 'on_gui_selection_state_changed', + 'on_runtime_mod_setting_changed', + 'on_difficulty_settings_changed', + 'on_surface_created', + 'on_surface_deleted', + 'on_pre_surface_deleted', + 'on_player_mined_entity', + 'on_robot_mined_entity', + 'on_train_created', + 'on_gui_elem_changed', + 'on_player_setup_blueprint', + 'on_player_deconstructed_area', + 'on_player_configured_blueprint', + 'on_console_chat', + 'on_console_command', + 'on_player_removed', + 'on_pre_player_removed', + 'on_player_used_capsule', + 'script_raised_built', + 'script_raised_destroy', + 'script_raised_revive', + 'on_player_promoted', + 'on_player_demoted', + 'on_combat_robot_expired', + 'on_player_changed_position', + 'on_mod_item_opened', + 'on_gui_opened', + 'on_gui_closed', + 'on_gui_value_changed', + 'on_player_muted', + 'on_player_unmuted', + 'on_player_cheat_mode_enabled', + 'on_player_cheat_mode_disabled', + 'on_character_corpse_expired', + 'on_pre_ghost_deconstructed', + 'on_player_pipette', + 'on_player_display_resolution_changed', + 'on_player_display_scale_changed', + 'on_pre_player_crafted_item', + 'on_player_cancelled_crafting', + 'on_chunk_charted', + 'on_technology_effects_reset', + 'on_land_mine_armed', + 'on_forces_merged', + 'on_player_trash_inventory_changed', + 'on_pre_player_left_game', + 'on_pre_surface_cleared', + 'on_surface_cleared', + 'on_chunk_deleted', + 'on_pre_chunk_deleted', + 'on_train_schedule_changed', + 'on_player_banned', + 'on_player_kicked', + 'on_player_unbanned', + 'on_rocket_launch_ordered', + 'on_script_path_request_finished', + 'on_ai_command_completed', + 'on_marked_for_upgrade', + 'on_cancelled_upgrade', + 'on_player_toggled_map_editor', + 'on_entity_cloned', + 'on_area_cloned', + 'on_brush_cloned', + 'on_game_created_from_scenario', + 'on_surface_imported', + 'on_surface_renamed', + 'on_player_toggled_alt_mode', + 'on_player_repaired_entity', + 'on_player_fast_transferred', + 'on_pre_robot_exploded_cliff', + 'on_robot_exploded_cliff', + 'on_entity_spawned', + 'on_cutscene_waypoint_reached', + 'on_unit_group_created', + 'on_unit_added_to_group', + 'on_unit_removed_from_group', + 'on_unit_group_finished_gathering', + 'on_build_base_arrived', + 'on_chart_tag_added', + 'on_chart_tag_modified', + 'on_chart_tag_removed', + 'on_lua_shortcut', + 'on_gui_location_changed', + 'on_gui_selected_tab_changed', + 'on_gui_switch_state_changed', + 'on_force_cease_fire_changed', + 'on_force_friends_changed', + 'on_string_translated', + 'on_script_trigger_effect' + } + }, + flow_precision_index = { + fields = { + 'one_second', + 'one_minute', + 'ten_minutes', + 'one_hour', + 'ten_hours', + 'fifty_hours', + 'two_hundred_fifty_hours', + 'one_thousand_hours' + } + }, + group_state = { + fields = { + 'gathering', + 'moving', + 'attacking_distraction', + 'attacking_target', + 'finished', + 'pathfinding', + 'wander_in_group' + } + }, + gui_type = { + fields = { + 'entity', + 'research', + 'controller', + 'production', + 'item', + 'bonus', + 'trains', + 'achievement', + 'blueprint_library', + 'equipment', + 'logistic', + 'other_player', + 'kills', + 'permissions', + 'tutorials', + 'custom', + 'server_management', + 'player_management', + 'tile' + } + }, + input_action = { + fields = { + 'activate_copy', + 'activate_cut', + 'activate_paste', + 'add_permission_group', + 'add_train_station', + 'admin_action', + 'alt_select_area', + 'alt_select_blueprint_entities', + 'alternative_copy', + 'begin_mining', + 'begin_mining_terrain', + 'build_item', + 'build_rail', + 'build_terrain', + 'cancel_craft', + 'cancel_deconstruct', + 'cancel_new_blueprint', + 'cancel_research', + 'cancel_upgrade', + 'change_active_item_group_for_crafting', + 'change_active_item_group_for_filters', + 'change_active_quick_bar', + 'change_arithmetic_combinator_parameters', + 'change_blueprint_book_record_label', + 'change_decider_combinator_parameters', + 'change_item_label', + 'change_multiplayer_config', + 'change_picking_state', + 'change_programmable_speaker_alert_parameters', + 'change_programmable_speaker_circuit_parameters', + 'change_programmable_speaker_parameters', + 'change_riding_state', + 'change_shooting_state', + 'change_single_blueprint_record_label', + 'change_train_stop_station', + 'change_train_wait_condition', + 'change_train_wait_condition_data', + 'clean_cursor_stack', + 'clear_selected_blueprint', + 'clear_selected_deconstruction_item', + 'clear_selected_upgrade_item', + 'connect_rolling_stock', + 'copy', + 'copy_entity_settings', + 'craft', + 'create_blueprint_like', + 'cursor_split', + 'cursor_transfer', + 'custom_input', + 'cycle_blueprint_book_backwards', + 'cycle_blueprint_book_forwards', + 'deconstruct', + 'delete_blueprint_library', + 'delete_blueprint_record', + 'delete_custom_tag', + 'delete_permission_group', + 'destroy_opened_item', + 'disconnect_rolling_stock', + 'drag_train_schedule', + 'drag_train_wait_condition', + 'drop_blueprint_record', + 'drop_item', + 'drop_to_blueprint_book', + 'edit_custom_tag', + 'edit_permission_group', + 'export_blueprint', + 'fast_entity_split', + 'fast_entity_transfer', + 'go_to_train_station', + 'grab_blueprint_record', + 'gui_checked_state_changed', + 'gui_click', + 'gui_confirmed', + 'gui_elem_changed', + 'gui_location_changed', + 'gui_selected_tab_changed', + 'gui_selection_state_changed', + 'gui_switch_state_changed', + 'gui_text_changed', + 'gui_value_changed', + 'import_blueprint', + 'import_blueprint_string', + 'import_permissions_string', + 'inventory_split', + 'inventory_transfer', + 'launch_rocket', + 'lua_shortcut', + 'map_editor_action', + 'market_offer', + 'mod_settings_changed', + 'open_achievements_gui', + 'open_blueprint_library_gui', + 'open_blueprint_record', + 'open_bonus_gui', + 'open_character_gui', + 'open_equipment', + 'open_gui', + 'open_item', + 'open_kills_gui', + 'open_logistic_gui', + 'open_mod_item', + 'open_production_gui', + 'open_technology_gui', + 'open_train_gui', + 'open_train_station_gui', + 'open_trains_gui', + 'open_tutorials_gui', + 'paste_entity_settings', + 'place_equipment', + 'quick_bar_pick_slot', + 'quick_bar_set_selected_page', + 'quick_bar_set_slot', + 'remove_cables', + 'remove_train_station', + 'reset_assembling_machine', + 'rotate_entity', + 'select_area', + 'select_blueprint_entities', + 'select_entity_slot', + 'select_item', + 'select_mapper_slot', + 'select_next_valid_gun', + 'select_tile_slot', + 'set_auto_launch_rocket', + 'set_autosort_inventory', + 'set_behavior_mode', + 'set_car_weapons_control', + 'set_circuit_condition', + 'set_circuit_mode_of_operation', + 'set_deconstruction_item_tile_selection_mode', + 'set_deconstruction_item_trees_and_rocks_only', + 'set_entity_color', + 'set_entity_energy_property', + 'set_filter', + 'set_heat_interface_mode', + 'set_heat_interface_temperature', + 'set_infinity_container_filter_item', + 'set_infinity_container_remove_unfiltered_items', + 'set_infinity_pipe_filter', + 'set_inserter_max_stack_size', + 'set_inventory_bar', + 'set_logistic_filter_item', + 'set_logistic_filter_signal', + 'set_logistic_trash_filter_item', + 'set_request_from_buffers', + 'set_research_finished_stops_game', + 'set_signal', + 'set_single_blueprint_record_icon', + 'set_splitter_priority', + 'set_train_stopped', + 'setup_assembling_machine', + 'setup_blueprint', + 'setup_single_blueprint_record', + 'smart_pipette', + 'stack_split', + 'stack_transfer', + 'start_repair', + 'start_research', + 'start_walking', + 'stop_building_by_moving', + 'switch_connect_to_logistic_network', + 'switch_constant_combinator_state', + 'switch_inserter_filter_mode_state', + 'switch_power_switch_state', + 'switch_to_rename_stop_gui', + 'take_equipment', + 'toggle_deconstruction_item_entity_filter_mode', + 'toggle_deconstruction_item_tile_filter_mode', + 'toggle_driving', + 'toggle_enable_vehicle_logistics_while_moving', + 'toggle_equipment_movement_bonus', + 'toggle_map_editor', + 'toggle_personal_roboport', + 'toggle_show_entity_info', + 'translate_string', + 'undo', + 'upgrade', + 'upgrade_opened_blueprint', + 'use_artillery_remote', + 'use_item', + 'wire_dragging', + 'write_to_console' + } + }, + inventory = { + fields = { + 'fuel', + 'burnt_result', + 'chest', + 'furnace_source', + 'furnace_result', + 'furnace_modules', + 'character_main', + 'character_guns', + 'character_ammo', + 'character_armor', + 'character_vehicle', + 'character_trash', + 'god_main', + 'editor_main', + 'editor_guns', + 'editor_ammo', + 'editor_armor', + 'roboport_robot', + 'roboport_material', + 'robot_cargo', + 'robot_repair', + 'assembling_machine_input', + 'assembling_machine_output', + 'assembling_machine_modules', + 'lab_input', + 'lab_modules', + 'mining_drill_modules', + 'item_main', + 'rocket_silo_rocket', + 'rocket_silo_result', + 'rocket', + 'car_trunk', + 'car_ammo', + 'cargo_wagon', + 'turret_ammo', + 'beacon_modules', + 'character_corpse', + 'artillery_turret_ammo', + 'artillery_wagon_ammo' + } + }, + logistic_member_index = { + fields = { + 'logistic_container', + 'vehicle_storage', + 'character_requester', + 'character_storage', + 'character_provider', + 'generic_on_off_behavior' + } + }, + logistic_mode = { + fields = { + 'active_provider', + 'storage', + 'requester', + 'passive_provider', + 'buffer' + } + }, + mouse_button_type = { + fields = { + 'left', + 'right', + 'middle' + } + }, + rail_connection_direction = { + fields = { + 'left', + 'straight', + 'right' + } + }, + rail_direction = { + fields = { + 'front', + 'back' + } + }, + render_mode = { + fields = { + 'game', + 'chart', + 'chart_zoomed_in' + } + }, + rich_text_setting = { + fields = { + 'enabled', + 'disabled', + 'highlight' + } + }, + riding = { + fields = { + acceleration = { + fields = { + 'nothing', + 'accelerating', + 'braking', + 'reversing' + } + }, + direction = { + fields = { + 'left', + 'straight', + 'right' + } + } + } + }, + shooting = { + fields = { + 'not_shooting', + 'shooting_enemies', + 'shooting_selected' + } + }, + signal_state = { + fields = { + 'open', + 'closed', + 'reserved', + 'reserved_by_circuit_network' + } + }, + train_state = { + fields = { + 'on_the_path', + 'path_lost', + 'no_schedule', + 'no_path', + 'arrive_signal', + 'wait_signal', + 'arrive_station', + 'wait_station', + 'manual_control_stop', + 'manual_control' + } + }, + transport_line = { + fields = { + 'left_line', + 'right_line', + 'left_underground_line', + 'right_underground_line', + 'secondary_left_line', + 'secondary_right_line', + 'left_split_line', + 'right_split_line', + 'secondary_left_split_line', + 'secondary_right_split_line' + } + }, + wire_connection_id = { + fields = { + 'electric_pole', + 'power_switch_left', + 'power_switch_right' + } + }, + wire_type = { + fields = { + 'red', + 'green', + 'copper' + } + }, + -- Defines additional modules + color = { + other_fields = true + }, + anticolor = { + other_fields = true + }, + lightcolor = { + other_fields = true + }, + time = { + fields = { + 'second', + 'minute', + 'hour', + 'day', + 'week', + 'month', + 'year' + } + } + } + } + } + } +end + +--[[ Options "ignore", "std", "globals", "unused_args", "self", "compat", "global", "unused", "redefined", "unused_secondaries", "allow_defined", "allow_defined_top", "module", "read_globals", "new_globals", "new_read_globals", "enable", "only", "not_globals", @@ -949,54 +1643,55 @@ stds.factorio_defines = { "max_cyclomatic_complexity" --]] --- Warnings list --- 011 A syntax error. --- 021 An invalid inline option. --- 022 An unpaired inline push directive. --- 023 An unpaired inline pop directive. --- 111 Setting an undefined global variable. --- 112 Mutating an undefined global variable. --- 113 Accessing an undefined global variable. --- 121 Setting a read-only global variable. --- 122 Setting a read-only field of a global variable. --- 131 Unused implicitly defined global variable. --- 142 Setting an undefined field of a global variable. --- 143 Accessing an undefined field of a global variable. --- 211 Unused local variable. --- 212 Unused argument. --- 213 Unused loop variable. --- 221 Local variable is accessed but never set. --- 231 Local variable is set but never accessed. --- 232 An argument is set but never accessed. --- 233 Loop variable is set but never accessed. --- 241 Local variable is mutated but never accessed. --- 311 Value assigned to a local variable is unused. --- 312 Value of an argument is unused. --- 313 Value of a loop variable is unused. --- 314 Value of a field in a table literal is unused. --- 321 Accessing uninitialized local variable. --- 331 Value assigned to a local variable is mutated but never accessed. --- 341 Mutating uninitialized local variable. --- 411 Redefining a local variable. --- 412 Redefining an argument. --- 413 Redefining a loop variable. --- 421 Shadowing a local variable. --- 422 Shadowing an argument. --- 423 Shadowing a loop variable. --- 431 Shadowing an upvalue. --- 432 Shadowing an upvalue argument. --- 433 Shadowing an upvalue loop variable. --- 511 Unreachable code. --- 512 Loop can be executed at most once. --- 521 Unused label. --- 531 Left-hand side of an assignment is too short. --- 532 Left-hand side of an assignment is too long. --- 541 An empty do end block. --- 542 An empty if branch. --- 551 An empty statement. --- 611 A line consists of nothing but whitespace. --- 612 A line contains trailing whitespace. --- 613 Trailing whitespace in a string. --- 614 Trailing whitespace in a comment. --- 621 Inconsistent indentation (SPACE followed by TAB). --- 631 Line is too long. +--[[ Warnings list + -- 011 A syntax error. + -- 021 An invalid inline option. + -- 022 An unpaired inline push directive. + -- 023 An unpaired inline pop directive. + -- 111 Setting an undefined global variable. + -- 112 Mutating an undefined global variable. + -- 113 Accessing an undefined global variable. + -- 121 Setting a read-only global variable. + -- 122 Setting a read-only field of a global variable. + -- 131 Unused implicitly defined global variable. + -- 142 Setting an undefined field of a global variable. + -- 143 Accessing an undefined field of a global variable. + -- 211 Unused local variable. + -- 212 Unused argument. + -- 213 Unused loop variable. + -- 221 Local variable is accessed but never set. + -- 231 Local variable is set but never accessed. + -- 232 An argument is set but never accessed. + -- 233 Loop variable is set but never accessed. + -- 241 Local variable is mutated but never accessed. + -- 311 Value assigned to a local variable is unused. + -- 312 Value of an argument is unused. + -- 313 Value of a loop variable is unused. + -- 314 Value of a field in a table literal is unused. + -- 321 Accessing uninitialized local variable. + -- 331 Value assigned to a local variable is mutated but never accessed. + -- 341 Mutating uninitialized local variable. + -- 411 Redefining a local variable. + -- 412 Redefining an argument. + -- 413 Redefining a loop variable. + -- 421 Shadowing a local variable. + -- 422 Shadowing an argument. + -- 423 Shadowing a loop variable. + -- 431 Shadowing an upvalue. + -- 432 Shadowing an upvalue argument. + -- 433 Shadowing an upvalue loop variable. + -- 511 Unreachable code. + -- 512 Loop can be executed at most once. + -- 521 Unused label. + -- 531 Left-hand side of an assignment is too short. + -- 532 Left-hand side of an assignment is too long. + -- 541 An empty do end block. + -- 542 An empty if branch. + -- 551 An empty statement. + -- 611 A line consists of nothing but whitespace. + -- 612 A line contains trailing whitespace. + -- 613 Trailing whitespace in a string. + -- 614 Trailing whitespace in a comment. + -- 621 Inconsistent indentation (SPACE followed by TAB). + -- 631 Line is too long. +--]] diff --git a/README.md b/README.md index affbc44a..851be090 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ 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]. All our docs can be found [here][docs]. 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]. To find out what we already have please read our [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, this can be done through a pull request. @@ -58,6 +58,7 @@ All are welcome to make pull requests and issues for this scenario, if you are i | Scenario Version* | Version Name | Factorio Version** | |---|---|---| +| [v6.0][s6.0] | Gui / 0.18 Overhaul | [v0.18.17][f0.18.17] | | [v5.10][s5.10] | Data Store Rewrite | [v0.17.71][f0.17.71] | | [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] | @@ -79,6 +80,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. +[s6.0]: https://github.com/explosivegaming/scenario/releases/tag/6.0.0 [s5.10]: https://github.com/explosivegaming/scenario/releases/tag/5.10.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 @@ -96,6 +98,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.18.17]: https://wiki.factorio.com/Version_history/0.18.0#0.18.17 [f0.17.71]: https://wiki.factorio.com/Version_history/0.17.0#0.17.71 [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 diff --git a/config/_file_loader.lua b/config/_file_loader.lua index c4a5bba6..c78f6bde 100644 --- a/config/_file_loader.lua +++ b/config/_file_loader.lua @@ -13,6 +13,7 @@ return { 'modules.commands.tag', 'modules.commands.teleport', 'modules.commands.cheat-mode', + 'modules.commands.ratio', 'modules.commands.interface', 'modules.commands.help', 'modules.commands.roles', @@ -27,6 +28,8 @@ return { 'modules.commands.bonus', 'modules.commands.home', -- QoL Addons + 'modules.addons.station-auto-name', + 'modules.addons.greetings', 'modules.addons.chat-popups', 'modules.addons.damage-popups', 'modules.addons.death-logger', @@ -38,18 +41,20 @@ return { 'modules.addons.random-player-colours', 'modules.addons.discord-alerts', 'modules.addons.chat-reply', + 'modules.addons.tree-decon', -- GUI + 'modules.gui.readme', 'modules.gui.rocket-info', 'modules.gui.science-info', 'modules.gui.warp-list', 'modules.gui.task-list', 'modules.gui.player-list', + 'modules.gui.server-ups', 'modules.commands.debug', -- Config Files - 'config.expcore-commands.auth_admin', -- commands tagged with admin_only are blocked for non admins - 'config.expcore-commands.auth_roles', -- commands must be allowed via the role config - 'config.expcore-commands.auth_runtime_disable', -- allows commands to be enabled and disabled during runtime - 'config.permission_groups', -- loads some predefined permission groups - 'config.roles', -- loads some predefined roles - 'expcore.gui.test' -- loads multiple gui defines to test the gui system + 'config.expcore.command_auth_admin', -- commands tagged with admin_only are blocked for non admins + 'config.expcore.command_auth_roles', -- commands must be allowed via the role config + 'config.expcore.command_runtime_disable', -- allows commands to be enabled and disabled during runtime + 'config.expcore.permission_groups', -- loads some predefined permission groups + 'config.expcore.roles', -- loads some predefined roles } \ No newline at end of file diff --git a/config/chat_reply.lua b/config/chat_reply.lua index fc8dee5c..2f653569 100644 --- a/config/chat_reply.lua +++ b/config/chat_reply.lua @@ -1,7 +1,12 @@ --- This file defines the different triggers for the chat bot -- @config Chat-Reply -local format_time = ext_require('expcore.common','format_time') --- @dep expcore.common +local Async = require 'expcore.async' +local format_time = _C.format_time --- @dep expcore.common + +local async_message = Async.register(function(player, message) + player.print(message) +end) return { allow_command_prefix_for_messages = true, --- @setting allow_command_prefix_for_messages when true any message trigger will print to all player when prefixed @@ -12,12 +17,13 @@ return { ['wiki']={'info.wiki'}, ['status']={'info.status'}, ['github']={'info.github'}, + ['patreon']={'info.patreon'}, + ['donate']={'info.patreon'}, ['command']={'info.custom-commands'}, ['commands']={'info.custom-commands'}, ['softmod']={'info.softmod'}, ['script']={'info.softmod'}, ['loop']={'chat-bot.loops'}, - ['loops']={'chat-bot.loops'}, ['rhd']={'info.lhd'}, ['lhd']={'info.lhd'}, ['roundabout']={'chat-bot.loops'}, @@ -38,8 +44,8 @@ return { ['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})} + ['r!verify']=function(player) + return {'chat-bot.verify',player.name} end, }, command_admin_only = false, --- @setting command_admin_only when true will only allow chat commands for admins @@ -65,5 +71,48 @@ return { ['evolution']=function() return {'chat-bot.current-evolution',string.format('%.2f',game.forces['enemy'].evolution_factor)} end, + ['makepopcorn']=function(player) + local timeout = math.floor(180*(math.random()+0.5)) + Async(async_message,player,{'chat-bot.reply',{'chat-bot.get-popcorn-1'}}) + Async.wait(timeout,async_message,player,{'chat-bot.reply',{'chat-bot.get-popcorn-2',player.name}}) + end, + ['passsomesnaps']=function(player) + local timeout = math.floor(180*(math.random()+0.5)) + Async(async_message,player,{'chat-bot.reply',{'chat-bot.get-snaps-1'}}) + Async.wait(timeout,async_message,player,{'chat-bot.reply',{'chat-bot.get-snaps-2',player.name}}) + Async.wait(timeout*(math.random()+0.5),async_message,player,{'chat-bot.reply',{'chat-bot.get-snaps-3',player.name}}) + end, + ['makecocktail']=function(player) + local timeout = math.floor(180*(math.random()+0.5)) + Async(async_message,player,{'chat-bot.reply',{'chat-bot.get-cocktail-1'}}) + Async.wait(timeout,async_message,player,{'chat-bot.reply',{'chat-bot.get-cocktail-2',player.name}}) + Async.wait(timeout*(math.random()+0.5),async_message,player,{'chat-bot.reply',{'chat-bot.get-cocktail-3',player.name}}) + end, + ['makecoffee']=function(player) + local timeout = math.floor(180*(math.random()+0.5)) + Async(async_message,player,{'chat-bot.reply',{'chat-bot.make-coffee-1'}}) + Async.wait(timeout,async_message,player,{'chat-bot.reply',{'chat-bot.make-coffee-2',player.name}}) + end, + ['orderpizza']=function(player) + local timeout = math.floor(180*(math.random()+0.5)) + Async(async_message,player,{'chat-bot.reply',{'chat-bot.order-pizza-1'}}) + Async.wait(timeout,async_message,player,{'chat-bot.reply',{'chat-bot.order-pizza-2',player.name}}) + Async.wait(timeout*(math.random()+0.5),async_message,player,{'chat-bot.reply',{'chat-bot.order-pizza-3',player.name}}) + end, + ['maketea']=function(player) + local timeout = math.floor(180*(math.random()+0.5)) + Async(async_message,player,{'chat-bot.reply',{'chat-bot.make-tea-1'}}) + Async.wait(timeout,async_message,player,{'chat-bot.reply',{'chat-bot.make-tea-2',player.name}}) + end, + ['meadplease']=function(player) + local timeout = math.floor(180*(math.random()+0.5)) + Async(async_message,player,{'chat-bot.reply',{'chat-bot.get-mead-1'}}) + Async.wait(timeout,async_message,player,{'chat-bot.reply',{'chat-bot.get-mead-2',player.name}}) + end, + ['passabeer']=function(player) + local timeout = math.floor(180*(math.random()+0.5)) + Async(async_message,player,{'chat-bot.reply',{'chat-bot.get-beer-1'}}) + Async.wait(timeout,async_message,player,{'chat-bot.reply',{'chat-bot.get-beer-2',player.name}}) + end } } diff --git a/config/compilatron.lua b/config/compilatron.lua index 6b69601d..00c9ddcf 100644 --- a/config/compilatron.lua +++ b/config/compilatron.lua @@ -19,6 +19,7 @@ return { {'info.status'}, {'info.lhd'}, {'info.github'}, + {'info.patreon'}, } } } \ No newline at end of file diff --git a/config/discord_alerts.lua b/config/discord_alerts.lua index 1d2c58d0..dc9c48c4 100644 --- a/config/discord_alerts.lua +++ b/config/discord_alerts.lua @@ -8,10 +8,12 @@ return { player_mutes=true, player_kicks=true, player_promotes=false, - config=true, - purge=true, - c=true, - command=true, + player_jail=true, + player_temp_ban=true, + ['config']=true, + ['purge']=true, + ['c']=true, + ['command']=true, ['silent-command']=true, ['measured-command']=true, ['banlist']=true, diff --git a/config/expcore-commands/auth_admin.lua b/config/expcore/command_auth_admin.lua similarity index 100% rename from config/expcore-commands/auth_admin.lua rename to config/expcore/command_auth_admin.lua diff --git a/config/expcore-commands/auth_roles.lua b/config/expcore/command_auth_roles.lua similarity index 100% rename from config/expcore-commands/auth_roles.lua rename to config/expcore/command_auth_roles.lua diff --git a/config/expcore-commands/parse_general.lua b/config/expcore/command_general_parse.lua similarity index 100% rename from config/expcore-commands/parse_general.lua rename to config/expcore/command_general_parse.lua diff --git a/config/expcore-commands/parse_roles.lua b/config/expcore/command_role_parse.lua similarity index 92% rename from config/expcore-commands/parse_roles.lua rename to config/expcore/command_role_parse.lua index 20b0d51f..12e76bbc 100644 --- a/config/expcore-commands/parse_roles.lua +++ b/config/expcore/command_role_parse.lua @@ -9,8 +9,8 @@ local Commands = require 'expcore.commands' --- @dep expcore.commands local Roles = require 'expcore.roles' --- @dep expcore.roles -local auto_complete = ext_require('expcore.common','auto_complete') --- @dep expcore.common -require 'config.expcore-commands.parse_general' +local auto_complete = _C.auto_complete --- @dep expcore.common +require 'config.expcore.command_general_parse' Commands.add_parse('role',function(input,player,reject) if not input then return end diff --git a/config/expcore-commands/auth_runtime_disable.lua b/config/expcore/command_runtime_disable.lua similarity index 100% rename from config/expcore-commands/auth_runtime_disable.lua rename to config/expcore/command_runtime_disable.lua diff --git a/config/permission_groups.lua b/config/expcore/permission_groups.lua similarity index 97% rename from config/permission_groups.lua rename to config/expcore/permission_groups.lua index 74fc894b..236268b4 100644 --- a/config/permission_groups.lua +++ b/config/expcore/permission_groups.lua @@ -13,7 +13,7 @@ Permission_Groups.new_group('Admin') :disallow{ 'add_permission_group', -- admin 'delete_permission_group', - --'edit_permission_group', -- removed for admin till role script added + 'edit_permission_group', 'import_permissions_string', 'map_editor_action', 'toggle_map_editor', @@ -85,7 +85,7 @@ Permission_Groups.new_group('Guest') 'set_auto_launch_rocket', 'change_programmable_speaker_parameters', -- guest 'change_train_stop_station', - 'deconstruct', + --'deconstruct', 'remove_cables', 'remove_train_station', 'reset_assembling_machine', diff --git a/config/roles.lua b/config/expcore/roles.lua similarity index 64% rename from config/roles.lua rename to config/expcore/roles.lua index d46d08fe..763fd132 100644 --- a/config/roles.lua +++ b/config/expcore/roles.lua @@ -3,20 +3,6 @@ local Roles = require 'expcore.roles' --- @dep expcore.roles --- Use these to adjust for ticks ie game.tick < 5*minutes -local seconds, minutes, hours = 60, 3600, 216000 - ---[[ - -- cant use a factory as it has up values ;-; - local function playtime(time_required) - return function(player) - if player.online_time > time_required then - return true - end - end - end -]] - --- Role flags that will run when a player changes roles Roles.define_flag_trigger('is_admin',function(player,state) player.admin = state @@ -61,7 +47,8 @@ Roles.new_role('Administrator','Admin') :set_flag('instance-respawn') :set_parent('Moderator') :allow{ - 'gui/warp-list/no-limit', + 'gui/warp-list/bypass-cooldown', + 'gui/warp-list/bypass-proximity', } Roles.new_role('Moderator','Mod') @@ -90,6 +77,7 @@ Roles.new_role('Moderator','Mod') 'command/return', 'gui/rocket-info/toggle-active', 'gui/rocket-info/remote_launch', + 'fast-tree-decon', } Roles.new_role('Trainee','TrMod') @@ -98,7 +86,7 @@ Roles.new_role('Trainee','TrMod') :set_flag('is_admin') :set_flag('is_spectator') :set_flag('report-immune') -:set_parent('Donator') +:set_parent('Veteran') :allow{ 'command/admin-chat', 'command/teleport', @@ -108,28 +96,42 @@ Roles.new_role('Trainee','TrMod') 'command/give-warning', 'command/get-warnings', 'command/get-reports', + 'command/jail', + 'command/unjail', 'command/kick', 'command/ban', } --- Trusted Roles -Roles.new_role('Sponsor','Spon') +Roles.new_role('Board Member','Board') :set_permission_group('Trusted') :set_custom_color{r=247,g=246,b=54} :set_flag('is_spectator') :set_flag('report-immune') :set_flag('instance-respawn') -:set_parent('Pay to Win') +:set_parent('Sponsor') :allow{ + 'command/goto', + 'command/repair', } -Roles.new_role('Pay to Win','P2W') +Roles.new_role('Senior Backer','Backer') :set_permission_group('Trusted') :set_custom_color{r=238,g=172,b=44} :set_flag('is_spectator') :set_flag('report-immune') :set_flag('instance-respawn') -:set_parent('Donator') +:set_parent('Sponsor') +:allow{ +} + +Roles.new_role('Sponsor','Spon') +:set_permission_group('Trusted') +:set_custom_color{r=238,g=172,b=44} +:set_flag('is_spectator') +:set_flag('report-immune') +:set_flag('instance-respawn') +:set_parent('Supporter') :allow{ 'gui/rocket-info/toggle-active', 'gui/rocket-info/remote_launch', @@ -138,9 +140,10 @@ Roles.new_role('Pay to Win','P2W') 'command/home-set', 'command/home-get', 'command/return', + 'fast-tree-decon', } -Roles.new_role('Donator','Don') +Roles.new_role('Supporter','Sup') :set_permission_group('Trusted') :set_custom_color{r=230,g=99,b=34} :set_flag('is_spectator') @@ -167,7 +170,7 @@ Roles.new_role('Veteran','Vet') :allow{ 'command/chat-bot', } -:set_auto_promote_condition(function(player) +:set_auto_assign_condition(function(player) if player.online_time > 10*216000 then return true end @@ -179,7 +182,9 @@ Roles.new_role('Member','Mem') :set_custom_color{r=24,g=172,b=188} :set_parent('Regular') :allow{ + 'gui/task-list/add', 'gui/task-list/edit', + 'gui/warp-list/add', 'gui/warp-list/edit' } @@ -192,8 +197,9 @@ Roles.new_role('Regular','Reg') 'command/rainbow', 'command/go-to-spawn', 'command/me', + 'standard-decon' } -:set_auto_promote_condition(function(player) +:set_auto_assign_condition(function(player) if player.online_time > 3*216000 then return true end @@ -206,15 +212,18 @@ local default = Roles.new_role('Guest','') :allow{ 'command/tag', 'command/tag-clear', - 'command/chelp', + 'command/search-help', 'command/list-roles', 'command/find-on-map', 'command/report', + 'command/ratio', + 'command/server-ups', 'gui/player-list', 'gui/rocket-info', 'gui/science-info', 'gui/task-list', 'gui/warp-list', + 'gui/readme' } --- Jail role @@ -234,9 +243,10 @@ Roles.define_role_order{ 'Administrator', 'Moderator', 'Trainee', + 'Board Member', + 'Senior Backer', 'Sponsor', - 'Pay to Win', - 'Donator', + 'Supporter', 'Partner', 'Veteran', 'Member', @@ -246,43 +256,44 @@ Roles.define_role_order{ } Roles.override_player_roles{ - Cooldude2606={'Senior Administrator','Administrator','Moderator','Member'}, - arty714={'Senior Administrator','Administrator','Moderator','Member'}, - mark9064={'Administrator','Moderator','Member'}, - Drahc_pro={'Administrator','Moderator','Member'}, - aldldl={'Sponsor','Administrator','Moderator','Member'}, - LoicB={'Sponsor','Trainee','Member'}, - ookl={'Sponsor','Moderator','Member'}, - cydes={'Pay to Win','Moderator','Member'}, - darklich14={'Pay to Win','Moderator','Member'}, - porelos={'Pay to Win','Moderator','Member'}, - SilentLog={'Pay to Win','Moderator','Member'}, - UUBlueFire={'Pay to Win','Moderator','Member'}, - XenoCyber={'Pay to Win','Moderator','Member'}, - Chromaddict={'Donator','Moderator','Member'}, - eissturm={'Donator','Moderator','Member'}, - freek18={'Donator','Moderator','Member'}, - M74132={'Donator','Moderator','Member'}, - thadius856={'Donator','Moderator','Member'}, - ['7h3w1z4rd']={'Moderator','Member'}, - AssemblyStorm={'Moderator','Member'}, - bombershark={'Moderator','Member'}, - CmonMate497={'Moderator','Member'}, - facere={'Moderator','Member'}, - FlipHalfling90={'Moderator','Member'}, - Gizan={'Pay to Win','Moderator','Member'}, - Hobbitkicker={'Moderator','Member'}, - jessi_gaming={'Trainee','Member'}, - Koroto={'Moderator','Member'}, - mafisch3={'Moderator','Member'}, - maplesyrup01={'Moderator','Member'}, - NextIdea={'Moderator','Member'}, - Phoenix27833={'Moderator','Member'}, - Rezz={'Moderator','Member'}, - Ruuyji={'Moderator','Member'}, - samy115={'Moderator','Member'}, - scarbvis={'Moderator','Member'}, - Tcheko={'Moderator','Member'}, - WhomstThouAmMe={'Moderator','Member'}, - Windbomb={'Moderator','Member'}, + ["Cooldude2606"]={"Senior Administrator","Moderator","Senior Backer","Supporter"}, + ["arty714"]={"Senior Administrator","Senior Backer","Supporter"}, + ["Drahc_pro"]={"Administrator","Moderator","Veteran","Member"}, + ["mark9064"]={"Administrator","Moderator","Member"}, + ["aldldl"]={"Administrator","Moderator","Senior Backer","Sponsor","Supporter","Member"}, + + ["ookl"]={"Moderator","Senior Backer","Sponsor","Supporter","Partner","Member"}, + ["hamsterbryan"]={"Moderator","Senior Backer","Supporter","Member"}, + ["M74132"]={"Moderator","Senior Backer","Sponsor","Supporter","Member"}, + ["LoicB"]={"Moderator","Senior Backer","Supporter","Veteran","Member"}, + ["UUBlueFire"]={"Moderator","Senior Backer","Supporter","Member"}, + + ["thadius856"]={"Moderator","Supporter","Member"}, + ["XenoCyber"]={"Moderator","Supporter","Partner","Member"}, + ["cydes"]={"Moderator","Supporter","Member"}, + ["darklich14"]={"Moderator","Supporter","Member"}, + ["SilentLog"]={"Moderator","Supporter","Member"}, + ["freek18"]={"Moderator","Supporter","Member"}, + ["porelos"]={"Moderator","Supporter","Member"}, + + ["7h3w1z4rd"]={"Moderator","Member"}, + ["Windbomb"]={"Moderator","Member"}, + ["Phoenix27833"]={"Moderator","Member"}, + ["banakeg"]={"Moderator","Member"}, + ["maplesyrup01"]={"Moderator","Member"}, + ["FlipHalfling90"]={"Moderator","Member"}, + ["Ruuyji"]={"Moderator","Member"}, + ["Gizan"]={"Moderator"}, + ["samy115"]={"Moderator","Member"}, + ["Hobbitkicker"]={"Moderator","Member"}, + ["facere"]={"Moderator","Member"}, + ["whoami32"]={"Moderator","Member"}, + ["NextIdea"]={"Moderator","Member"}, + ["mafisch3"]={"Moderator","Member"}, + ["Tcheko"]={"Moderator","Member"}, + ["AssemblyStorm"]={"Moderator","Veteran","Member"}, + ["connormkii"]={"Moderator","Veteran","Member"}, + ["Koroto"]={"Moderator","Veteran","Member"}, + ["scarbvis"]={"Moderator","Member"}, + ["CmonMate497"]={"Moderator","Member"} } diff --git a/config/action_buttons.lua b/config/gui/player_list_actions.lua similarity index 81% rename from config/action_buttons.lua rename to config/gui/player_list_actions.lua index 2ce10565..1bd19bbf 100644 --- a/config/action_buttons.lua +++ b/config/gui/player_list_actions.lua @@ -12,8 +12,8 @@ local Game = require 'utils.game' --- @dep utils.game local Reports = require 'modules.control.reports' --- @dep modules.control.reports local Warnings = require 'modules.control.warnings' --- @dep modules.control.warnings local Jail = require 'modules.control.jail' --- @dep modules.control.jail -local Colors = require 'resources.color_presets' --- @dep resources.color_presets -local format_chat_player_name = ext_require('expcore.common','format_chat_player_name') --- @dep expcore.common +local Colors = require 'utils.color_presets' --- @dep utils.color_presets +local format_chat_player_name = _C.format_chat_player_name --- @dep expcore.common local selected_player_store = '' local selected_action_store = '' @@ -22,13 +22,6 @@ local function set_store_uids(player,action) selected_action_store = action end --- common style used by all action buttons -local function tool_button_style(style) - Gui.set_padding_style(style,-1,-1,-1,-1) - style.height = 28 - style.width = 28 -end - -- auth that will only allow when on player's of lower roles local function auth_lower_role(player,selected_player_name) local player_highest = Roles.get_player_highest_role(player) @@ -56,14 +49,23 @@ local function teleport(from_player,to_player) return true end +local function new_button(sprite,tooltip) + return Gui.element{ + type = 'sprite-button', + style = 'tool_button', + sprite = sprite, + tooltip = tooltip + }:style{ + padding = -1, + height = 28, + width = 28 + } +end + --- Teleports the user to the action player -- @element goto_player -local goto_player = -Gui.new_button() -:set_sprites('utility/export') -:set_tooltip{'player-list.goto-player'} -:set_style('tool_button',tool_button_style) -:on_click(function(player,element) +local goto_player = new_button('utility/export',{'player-list.goto-player'}) +:on_click(function(player) local selected_player_name = get_action_player_name(player) local selected_player = Game.get_player_from_any(selected_player_name) if not player.character or not selected_player.character then @@ -75,12 +77,8 @@ end) --- Teleports the action player to the user -- @element bring_player -local bring_player = -Gui.new_button() -:set_sprites('utility/import') -:set_tooltip{'player-list.bring-player'} -:set_style('tool_button',tool_button_style) -:on_click(function(player,element) +local bring_player = new_button('utility/import',{'player-list.bring-player'}) +:on_click(function(player) local selected_player_name = get_action_player_name(player) local selected_player = Game.get_player_from_any(selected_player_name) if not player.character or not selected_player.character then @@ -92,12 +90,8 @@ end) --- Kills the action player, if there are alive -- @element kill_player -local kill_player = -Gui.new_button() -:set_sprites('utility/too_far') -:set_tooltip{'player-list.kill-player'} -:set_style('tool_button',tool_button_style) -:on_click(function(player,element) +local kill_player = new_button('utility/too_far',{'player-list.kill-player'}) +:on_click(function(player) local selected_player_name = get_action_player_name(player) local selected_player = Game.get_player_from_any(selected_player_name) if selected_player.character then @@ -109,12 +103,8 @@ end) --- Reports the action player, requires a reason to be given -- @element report_player -local report_player = -Gui.new_button() -:set_sprites('utility/spawn_flag') -:set_tooltip{'player-list.report-player'} -:set_style('tool_button',tool_button_style) -:on_click(function(player,element) +local report_player = new_button('utility/spawn_flag',{'player-list.report-player'}) +:on_click(function(player) local selected_player_name = get_action_player_name(player) if Reports.is_reported(selected_player_name,player.name) then player.print({'expcom-report.already-reported'},Colors.orange_red) @@ -133,12 +123,8 @@ end --- Gives the action player a warning, requires a reason -- @element warn_player -local warn_player = -Gui.new_button() -:set_sprites('utility/spawn_flag') -:set_tooltip{'player-list.warn-player'} -:set_style('tool_button',tool_button_style) -:on_click(function(player,element) +local warn_player = new_button('utility/spawn_flag',{'player-list.warn-player'}) +:on_click(function(player) Store.set(selected_action_store,player,'command/give-warning') end) @@ -151,12 +137,8 @@ end --- Jails the action player, requires a reason -- @element jail_player -local jail_player = -Gui.new_button() -:set_sprites('utility/item_editor_icon') -:set_tooltip{'player-list.jail-player'} -:set_style('tool_button',tool_button_style) -:on_click(function(player,element) +local jail_player = new_button('utility/multiplayer_waiting_icon',{'player-list.jail-player'}) +:on_click(function(player) local selected_player_name, selected_player_color = get_action_player_name(player) if Jail.is_jailed(selected_player_name) then player.print({'expcom-jail.already-jailed', selected_player_color},Colors.orange_red) @@ -174,12 +156,8 @@ end --- Temp bans the action player, requires a reason -- @element temp_ban_player -local temp_ban_player = -Gui.new_button() -:set_sprites('utility/clock') -:set_tooltip{'player-list.temp-ban-player'} -:set_style('tool_button',tool_button_style) -:on_click(function(player,element) +local temp_ban_player = new_button('utility/warning_white',{'player-list.temp-ban-player'}) +:on_click(function(player) local selected_player_name, selected_player_color = get_action_player_name(player) if Jail.is_jailed(selected_player_name) then player.print({'expcom-jail.already-banned', selected_player_color},Colors.orange_red) @@ -197,12 +175,8 @@ end --- Kicks the action player, requires a reason -- @element kick_player -local kick_player = -Gui.new_button() -:set_sprites('utility/warning_icon') -:set_tooltip{'player-list.kick-player'} -:set_style('tool_button',tool_button_style) -:on_click(function(player,element) +local kick_player = new_button('utility/warning_icon',{'player-list.kick-player'}) +:on_click(function(player) Store.set(selected_action_store,player,'command/kick') end) @@ -213,12 +187,8 @@ end --- Bans the action player, requires a reason -- @element ban_player -local ban_player = -Gui.new_button() -:set_sprites('utility/danger_icon') -:set_tooltip{'player-list.ban-player'} -:set_style('tool_button',tool_button_style) -:on_click(function(player,element) +local ban_player = new_button('utility/danger_icon',{'player-list.ban-player'}) +:on_click(function(player) Store.set(selected_action_store,player,'command/ban') end) diff --git a/config/rockets.lua b/config/gui/rockets.lua similarity index 100% rename from config/rockets.lua rename to config/gui/rockets.lua diff --git a/config/science.lua b/config/gui/science.lua similarity index 100% rename from config/science.lua rename to config/gui/science.lua diff --git a/config/gui/tasks.lua b/config/gui/tasks.lua new file mode 100644 index 00000000..f7968e8e --- /dev/null +++ b/config/gui/tasks.lua @@ -0,0 +1,13 @@ +--- Config file for the tasks gui +-- @config Tasks + +return { + -- Adding tasks + allow_add_task = 'all', --- @setting allow_add_task dictates who is allowed to add new tasks; values: all, admin, expcore.roles, none + expcore_roles_allow_add_task = 'gui/task-list/add', --- @setting expcore_roles_allow_add_task if expcore.roles is used then this is the required permission + + -- Editing tasks + allow_edit_task = 'expcore.roles', --- @setting allow_edit_task dictates who is allowed to edit existing tasks; values: all, admin, expcore.roles, none + expcore_roles_allow_edit_task = 'gui/task-list/edit', --- @setting expcore_roles_allow_edit_task if expcore.roles is used then this is the required permission + user_can_edit_own_tasks = true --- @settings if true then the user who made the task can edit it regardless of the allow_edit_task setting +} \ No newline at end of file diff --git a/config/gui/warps.lua b/config/gui/warps.lua new file mode 100644 index 00000000..d1710ba8 --- /dev/null +++ b/config/gui/warps.lua @@ -0,0 +1,41 @@ +--- This file contains all the different settings for the warp system and gui +-- @config Warps + +return { + -- General config + update_smoothing = 10, --- @setting update_smoothing the amount of smoothing applied to updates to the cooldown timer, higher is better, max is 60 + minimum_distance = 100, --- @setting minimum_distance the minimum distance that is allowed between warps on the same force + default_icon = 'discharge-defense-equipment', --- @setting default_icon the default icon that will be used for warps + + -- Warp cooldowns + bypass_warp_cooldown = 'expcore.roles', --- @setting bypass_warp_cooldown dictates who the warp cooldown is applied to; values: all, admin, expcore.roles, none + expcore_roles_bypass_warp_cooldown = 'gui/warp-list/bypass-cooldown', --- @setting expcore_roles_bypass_warp_cooldown if expcore.roles is used then this is the required permission + cooldown_duraction = 60, --- @setting cooldown_duraction the duration of the warp cooldown in seconds + + -- Warp proximity + bypass_warp_proximity = 'expcore.roles', --- @setting bypass_warp_proximity dictates who the warp proximity is applied to; values: all, admin, expcore.roles, none + expcore_roles_bypass_warp_proximity = 'gui/warp-list/bypass-proximity', --- @setting expcore_roles_bypass_warp_proximity if expcore.roles is used then this is the required permission + standard_proximity_radius = 4, --- @setting standard_proximity_radius the minimum distance a player is allowed to be to a warp in order to use it + spawn_proximity_radius = 20, --- @setting spawn_proximity_radius the minimum distance a player is allowed to be from they spawn point to use warps + + -- Adding warps + allow_add_warp = 'expcore.roles', --- @setting allow_add_warp dictates who is allowed to add warps; values: all, admin, expcore.roles, none + expcore_roles_allow_add_warp = 'gui/warp-list/add', --- @setting expcore_roles_allow_add_warp if expcore.roles is used then this is the required permission + + -- Editing warps + allow_edit_warp = 'expcore.roles', --- @setting allow_edit_warp dictates who is allowed to edit warps; values: all, admin, expcore.roles, none + expcore_roles_allow_edit_warp = 'gui/warp-list/edit', --- @setting expcore_roles_allow_edit_warp if expcore.roles is used then this is the required permission + user_can_edit_own_warps = false, --- @settings user_can_edit_own_warps if true then the user who made the warp can edit it regardless of the allow_edit_warp setting + + -- Warp area generation + entities = { --- @setting entities The entities which are created for warp areas + {'small-lamp',-3,-2},{'small-lamp',-3,2},{'small-lamp',3,-2},{'small-lamp',3,2}, + {'small-lamp',-2,-3},{'small-lamp',2,-3},{'small-lamp',-2,3},{'small-lamp',2,3}, + {'small-electric-pole',-3,-3},{'small-electric-pole',3,3},{'small-electric-pole',-3,3},{'small-electric-pole',3,-3} + }, + base_tile = 'tutorial-grid', --- @setting base_tile The tile which is used for the warp areas + tiles = { --- @setting tiles The tiles which are created for warp areas + {-3,-2},{-3,-1},{-3,0},{-3,1},{-3,2},{3,-2},{3,-1},{3,0},{3,1},{3,2}, + {-2,-3},{-1,-3},{0,-3},{1,-3},{2,-3},{-2,3},{-1,3},{0,3},{1,3},{2,3} + } +} \ No newline at end of file diff --git a/config/join_messages.lua b/config/join_messages.lua new file mode 100644 index 00000000..b0226a28 --- /dev/null +++ b/config/join_messages.lua @@ -0,0 +1,8 @@ +return { + Cooldude2606 = 'Lua lets you set metatables on numbers, did you know that? Cooldude2606 knows this.', + samy115 = 'Tremble in fear as the banhammer is now here, its owner: samy115', + XenoCyber = '"Fire Fire Fire" oops wrong game, have no fear XenoCyber is here', + HunterOfGames = 'Unable to support HunterOfGames. You must construct additional miners.', + ookl = 'ookl says: "Pineapples are amazing, hello everyone!"', + arty714 = 'Arty\'s Potato made it!' +} \ No newline at end of file diff --git a/config/preset_player_colours.lua b/config/preset_player_colours.lua index d186fa01..b7e0bde7 100644 --- a/config/preset_player_colours.lua +++ b/config/preset_player_colours.lua @@ -16,7 +16,10 @@ return { UUBlueFire={r=0,g=204,b=255}, CmonMate497={r=103,g=224,b=194}, s4sh={r=255,g=120,b=0}, - ArPiiX={r=0,g=255,b=0} + ArPiiX={r=0,g=255,b=0}, + NextIdea={r=255,g=255,b=255}, + hamsterbryan={r=0,g=255,b=0}, + XenoCyber={r=0,g=128,b=255} }, disallow = { --- @setting disallow colours which will not given to players; the value does not matter it is only the key which is checked black = {r = 0, g = 0, b = 0}, diff --git a/config/tasks.lua b/config/tasks.lua deleted file mode 100644 index 95165ee0..00000000 --- a/config/tasks.lua +++ /dev/null @@ -1,9 +0,0 @@ ---- Config file for the tasks gui --- @config Tasks - -return { - any_user_can_add_new_task = true, --- @setting any_user_can_add_new_task when false only people with edit permission can make new reports - user_can_edit_own_tasks = true, --- @setting user_can_edit_own_tasks when false only people with edit permission can edit reports - only_admins_can_edit = false, --- @setting only_admins_can_edit true will hide the edit and delete buttons from non (game) admins - edit_tasks_role_permission = 'gui/task-list/edit' --- @setting edit_tasks_role_permission value used with custom permission system -} \ No newline at end of file diff --git a/config/warps.lua b/config/warps.lua deleted file mode 100644 index fb620108..00000000 --- a/config/warps.lua +++ /dev/null @@ -1,26 +0,0 @@ ---- This file contains all the different settings for the warp system and gui --- @config Warps - -return { - recharge_time = 60, --- @setting recharge_time The amount of time in seconds that the player must wait between warps, acts as a balance - update_smoothing = 10, --- @setting update_smoothing Higher is better, the amount of smoothing applied to recharge timer and other gui updates, max is 60 - minimum_distance = 100, --- @setting minimum_distance The minimum distance that must be between warp points, creating new ones is blocked when too close - activation_range = 4, --- @setting activation_range The distance the player must be to a warp in order to use the warp gui, gui can still be viewed but not used - spawn_activation_range = 20, --- @setting spawn_activation_range A second activation range which is used for the forces spawn point - default_icon = 'discharge-defense-equipment', --- @setting default_icon The default icon which is used by warps; must be an item name - user_can_edit_own_warps = false, --- @setting user_can_edit_own_warps When true the user can always edit warps which they created regardless of other settings - any_user_can_add_new_warp = false, --- @setting any_user_can_add_new_warp When true any user is able to create new warps, however editing may still be restricted - only_admins_can_edit = false, --- @setting only_admins_can_edit When true only admins can edit warps - edit_warps_role_permission = 'gui/warp-list/edit', --- @setting edit_warps_role_permission Role permission used by the role system to allow editing warps - bypass_warp_limits_permission = 'gui/warp-list/no-limit', --- @setting bypass_warp_limits_permission Role permission used by the role system to allow bypassing the time and distance restrictions - entities = { --- @setting entities The entities which are created for warps - {'small-lamp',-3,-2},{'small-lamp',-3,2},{'small-lamp',3,-2},{'small-lamp',3,2}, - {'small-lamp',-2,-3},{'small-lamp',2,-3},{'small-lamp',-2,3},{'small-lamp',2,3}, - {'small-electric-pole',-3,-3},{'small-electric-pole',3,3},{'small-electric-pole',-3,3},{'small-electric-pole',3,-3} - }, - base_tile = 'tutorial-grid', --- @setting base_tile The tile which is used for the warps - tiles = { --- @setting tiles The tiles which are created for warps - {-3,-2},{-3,-1},{-3,0},{-3,1},{-3,2},{3,-2},{3,-1},{3,0},{3,1},{3,2}, - {-2,-3},{-1,-3},{0,-3},{1,-3},{2,-3},{-2,3},{-1,3},{0,3},{1,3},{2,3} - } -} \ No newline at end of file diff --git a/control.lua b/control.lua index 82237d76..5658ba42 100644 --- a/control.lua +++ b/control.lua @@ -5,24 +5,17 @@ -- this file is the landing point for all scenarios please DO NOT edit directly, further comments are to aid development log('[START] -----| Explosive Gaming Scenario Loader |-----') - --- Info on the data lifecycle and how we use it: https://github.com/Refactorio/RedMew/wiki/The-data-lifecycle log('[INFO] Setting up lua environment') -require 'resources.data_stages' -_LIFECYCLE = _STAGE.control -- Control stage --- Overrides the _G.print function -require 'utils.print_override' - --- Omitting the math library is a very bad idea -require 'utils.math' - --- Global Debug and make sure our version file is registered -Debug = require 'utils.debug' --- @dep utils.debug -require 'resources.version' - --- Global require function used to extract parts of a module, because simply being in common is not good enough -ext_require = require('expcore.common').ext_require --- @dep expcore.common.ext_require +-- Require the global overrides +require 'overrides.stages' -- Data stages used in factorio, often used to test for runtime +require 'overrides.print' -- Overrides the _G.print function +require 'overrides.math' -- Omitting the math library is a very bad idea +require 'overrides.table' -- Adds alot more functions to the table module +inspect = require 'overrides.inspect' -- Used to covert any value into human readable string +Debug = require 'overrides.debug' -- Global Debug module +_C = require('expcore.common') -- _C is used to store lots of common functions expected to be used +global.expgaming_version = '6.0.0' -- The current version for exp gaming scenario -- Please go to config/file_loader.lua to edit the files that are loaded log('[INFO] Getting file loader config') @@ -52,7 +45,7 @@ end -- Override the default require; require can no longer load new scripts log('[INFO] Require Overright! No more requires can be made!') -require 'utils.require_override' +require 'overrides.require' -- Logs all errors again to make it make it easy to find log('[INFO] All files loaded with '..#errors..' errors:') diff --git a/docs/addons/Advanced-Start.html b/docs/addons/Advanced-Start.html index 8fc6a44a..1d717318 100644 --- a/docs/addons/Advanced-Start.html +++ b/docs/addons/Advanced-Start.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -56,10 +56,12 @@ + + @@ -67,13 +69,13 @@ @@ -96,8 +98,10 @@

Guis

@@ -135,7 +139,6 @@

Configs

@@ -168,18 +172,13 @@

Modules

@@ -348,7 +347,7 @@ generated by LDoc diff --git a/docs/addons/Chat-Popups.html b/docs/addons/Chat-Popups.html index c9ea0f82..7f17c3a9 100644 --- a/docs/addons/Chat-Popups.html +++ b/docs/addons/Chat-Popups.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -56,10 +56,12 @@ + + @@ -67,13 +69,13 @@ @@ -96,8 +98,10 @@

Guis

@@ -135,7 +139,6 @@

Configs

@@ -168,18 +172,13 @@

Modules

@@ -349,7 +348,7 @@ generated by LDoc diff --git a/docs/addons/Chat-Reply.html b/docs/addons/Chat-Reply.html index d6eda160..d7927bc8 100644 --- a/docs/addons/Chat-Reply.html +++ b/docs/addons/Chat-Reply.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -56,10 +56,12 @@ + + @@ -67,13 +69,13 @@ @@ -96,8 +98,10 @@

Guis

@@ -135,7 +139,6 @@

Configs

@@ -168,18 +172,13 @@

Modules

@@ -376,7 +375,7 @@ generated by LDoc diff --git a/docs/addons/Compilatron.html b/docs/addons/Compilatron.html index 4fafcaa9..5b569aae 100644 --- a/docs/addons/Compilatron.html +++ b/docs/addons/Compilatron.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -57,10 +57,12 @@ + + @@ -68,13 +70,13 @@ @@ -97,8 +99,10 @@

Guis

@@ -136,7 +140,6 @@

Configs

@@ -169,18 +173,13 @@

Modules

@@ -585,7 +584,7 @@ generated by LDoc diff --git a/docs/addons/Damage-Popups.html b/docs/addons/Damage-Popups.html index a445fe5a..48df3a68 100644 --- a/docs/addons/Damage-Popups.html +++ b/docs/addons/Damage-Popups.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -56,10 +56,12 @@ + + @@ -67,13 +69,13 @@ @@ -96,8 +98,10 @@

Guis

@@ -135,7 +139,6 @@

Configs

@@ -168,18 +172,13 @@

Modules

@@ -349,7 +348,7 @@ generated by LDoc diff --git a/docs/addons/Death-Logger.html b/docs/addons/Death-Logger.html index faadc765..a7b1b937 100644 --- a/docs/addons/Death-Logger.html +++ b/docs/addons/Death-Logger.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -56,10 +56,12 @@ + + @@ -67,13 +69,13 @@ @@ -96,8 +98,10 @@

Guis

@@ -135,7 +139,6 @@

Configs

@@ -168,18 +172,13 @@

Modules

@@ -404,7 +403,7 @@ generated by LDoc diff --git a/docs/addons/Discord-Alerts.html b/docs/addons/Discord-Alerts.html index e0ecba4b..78f0bcd6 100644 --- a/docs/addons/Discord-Alerts.html +++ b/docs/addons/Discord-Alerts.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -56,10 +56,12 @@ + + @@ -67,13 +69,13 @@ @@ -96,8 +98,10 @@

Guis

@@ -135,7 +139,6 @@

Configs

@@ -168,18 +172,13 @@

Modules

@@ -247,7 +246,7 @@ utils.game - resources.color_presets + utils.color_presets expcore.common @@ -323,8 +322,8 @@
- # - resources.color_presets + # + utils.color_presets
@@ -460,7 +459,7 @@ generated by LDoc diff --git a/docs/addons/Player-Colours.html b/docs/addons/Player-Colours.html index 8a60609c..a9b88d40 100644 --- a/docs/addons/Player-Colours.html +++ b/docs/addons/Player-Colours.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -56,10 +56,12 @@ + + @@ -67,13 +69,13 @@ @@ -96,8 +98,10 @@

Guis

@@ -135,7 +139,6 @@

Configs

@@ -168,18 +172,13 @@

Modules

@@ -241,7 +240,7 @@ - resources.color_presets + utils.color_presets utils.game @@ -267,8 +266,8 @@
- # - resources.color_presets + # + utils.color_presets
@@ -404,7 +403,7 @@ generated by LDoc diff --git a/docs/addons/Pollution-Grading.html b/docs/addons/Pollution-Grading.html index 46baddb7..d7166cc9 100644 --- a/docs/addons/Pollution-Grading.html +++ b/docs/addons/Pollution-Grading.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -56,10 +56,12 @@ + + @@ -67,13 +69,13 @@ @@ -96,8 +98,10 @@

Guis

@@ -135,7 +139,6 @@

Configs

@@ -168,18 +172,13 @@

Modules

@@ -320,7 +319,7 @@ generated by LDoc diff --git a/docs/addons/Scorched-Earth.html b/docs/addons/Scorched-Earth.html index c4f4487d..464c0bf3 100644 --- a/docs/addons/Scorched-Earth.html +++ b/docs/addons/Scorched-Earth.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -56,10 +56,12 @@ + + @@ -67,13 +69,13 @@ @@ -96,8 +98,10 @@

Guis

@@ -135,7 +139,6 @@

Configs

@@ -168,18 +172,13 @@

Modules

@@ -404,7 +403,7 @@ generated by LDoc diff --git a/docs/addons/Spawn-Area.html b/docs/addons/Spawn-Area.html index 6b3002a3..27174f1c 100644 --- a/docs/addons/Spawn-Area.html +++ b/docs/addons/Spawn-Area.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -56,10 +56,12 @@ + + @@ -67,13 +69,13 @@ @@ -96,8 +98,10 @@

Guis

@@ -135,7 +139,6 @@

Configs

@@ -168,18 +172,13 @@

Modules

@@ -376,7 +375,7 @@ generated by LDoc diff --git a/docs/addons/Tree-Decon.html b/docs/addons/Tree-Decon.html new file mode 100644 index 00000000..1ae7cd94 --- /dev/null +++ b/docs/addons/Tree-Decon.html @@ -0,0 +1,383 @@ + + + + + + + + Tree-Decon addon + + + + + + + +
+
+ + + + + + + +
+ + + + + + + + +

Tree-Decon addon

+

Makes trees which are marked for decon "decay" quickly to allow faster building

+

+ + + + + + + + + + + + + +

Dependencies

+ + + + + + + + + + + + + + + + +
utils.event
utils.game
utils.global
expcore.roles
+ + +
+ + +

Dependencies

+
+
+
+
+ # + utils.event +
+
+
+
+ + + + + + + + + + + + + + + +
+
+
+
+ # + utils.game +
+
+
+
+ + + + + + + + + + + + + + + +
+
+
+
+ # + utils.global +
+
+
+
+ + + + + + + + + + + + + + + +
+
+
+
+ # + expcore.roles +
+
+
+
+ + + + + + + + + + + + + + + +
+
+ + + +
+
+
+ + + + diff --git a/docs/addons/greetings.html b/docs/addons/greetings.html new file mode 100644 index 00000000..88bcabfb --- /dev/null +++ b/docs/addons/greetings.html @@ -0,0 +1,383 @@ + + + + + + + + greetings addon + + + + + + + +
+
+ + + + + + + +
+ + + + + + + + +

greetings addon

+

Greets players on join

+

+ + + + + + + + + + + + + +

Dependencies

+ + + + + + + + + + + + + + + + +
utils.event
utils.event
config.join_messages
utils.global
+ + +
+ + +

Dependencies

+
+
+
+
+ # + utils.event +
+
+
+
+ + + + + + + + + + + + + + + +
+
+
+
+ # + utils.event +
+
+
+
+ + + + + + + + + + + + + + + +
+
+
+
+ # + config.join_messages +
+
+
+
+ + + + + + + + + + + + + + + +
+
+
+
+ # + utils.global +
+
+
+
+ + + + + + + + + + + + + + + +
+
+ + + +
+
+
+ + + + diff --git a/docs/commands/Admin-Chat.html b/docs/commands/Admin-Chat.html index 04b6b9fe..e2928b14 100644 --- a/docs/commands/Admin-Chat.html +++ b/docs/commands/Admin-Chat.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -77,13 +77,13 @@ @@ -112,10 +112,12 @@ + + @@ -124,8 +126,10 @@

Guis

@@ -136,7 +140,6 @@

Configs

@@ -169,18 +173,13 @@

Modules

@@ -388,7 +387,7 @@ generated by LDoc diff --git a/docs/commands/Bonus.html b/docs/commands/Bonus.html index 3786a596..b4acd3f8 100644 --- a/docs/commands/Bonus.html +++ b/docs/commands/Bonus.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -77,13 +77,13 @@ @@ -112,10 +112,12 @@ + + @@ -124,8 +126,10 @@

Guis

@@ -136,7 +140,6 @@

Configs

@@ -169,18 +173,13 @@

Modules

@@ -500,7 +499,7 @@ generated by LDoc diff --git a/docs/commands/Cheat-Mode.html b/docs/commands/Cheat-Mode.html index 81523c11..bd44f024 100644 --- a/docs/commands/Cheat-Mode.html +++ b/docs/commands/Cheat-Mode.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -77,13 +77,13 @@ @@ -112,10 +112,12 @@ + + @@ -124,8 +126,10 @@

Guis

@@ -136,7 +140,6 @@

Configs

@@ -169,18 +173,13 @@

Modules

@@ -361,7 +360,7 @@ generated by LDoc diff --git a/docs/commands/Clear-Inventory.html b/docs/commands/Clear-Inventory.html index a250f390..8c73ddea 100644 --- a/docs/commands/Clear-Inventory.html +++ b/docs/commands/Clear-Inventory.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -77,13 +77,13 @@ @@ -112,10 +112,12 @@ + + @@ -124,8 +126,10 @@

Guis

@@ -136,7 +140,6 @@

Configs

@@ -169,18 +173,13 @@

Modules

@@ -388,7 +387,7 @@ generated by LDoc diff --git a/docs/commands/Debug.html b/docs/commands/Debug.html index 0af8bb1c..dc8bd630 100644 --- a/docs/commands/Debug.html +++ b/docs/commands/Debug.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -77,13 +77,13 @@ @@ -112,10 +112,12 @@ + + @@ -124,8 +126,10 @@

Guis

@@ -136,7 +140,6 @@

Configs

@@ -169,18 +173,13 @@

Modules

@@ -365,7 +364,7 @@ generated by LDoc diff --git a/docs/commands/Find.html b/docs/commands/Find.html index 0f1ae48d..fa39eb7d 100644 --- a/docs/commands/Find.html +++ b/docs/commands/Find.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -77,13 +77,13 @@ @@ -112,10 +112,12 @@ + + @@ -124,8 +126,10 @@

Guis

@@ -136,7 +140,6 @@

Configs

@@ -169,18 +173,13 @@

Modules

@@ -360,7 +359,7 @@ generated by LDoc diff --git a/docs/commands/Help.html b/docs/commands/Help.html index 024c376f..8d75f6db 100644 --- a/docs/commands/Help.html +++ b/docs/commands/Help.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -77,13 +77,13 @@ @@ -112,10 +112,12 @@ + + @@ -124,8 +126,10 @@

Guis

@@ -136,7 +140,6 @@

Configs

@@ -169,18 +173,13 @@

Modules

@@ -404,7 +403,7 @@ generated by LDoc diff --git a/docs/commands/Home.html b/docs/commands/Home.html index d4881527..512a2ee6 100644 --- a/docs/commands/Home.html +++ b/docs/commands/Home.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -77,13 +77,13 @@ @@ -112,10 +112,12 @@ + + @@ -124,8 +126,10 @@

Guis

@@ -136,7 +140,6 @@

Configs

@@ -169,18 +173,13 @@

Modules

@@ -458,7 +457,7 @@ generated by LDoc diff --git a/docs/commands/Interface.html b/docs/commands/Interface.html index eeaf7d3d..2f43cbd6 100644 --- a/docs/commands/Interface.html +++ b/docs/commands/Interface.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -77,13 +77,13 @@ @@ -112,10 +112,12 @@ + + @@ -124,8 +126,10 @@

Guis

@@ -136,7 +140,6 @@

Configs

@@ -169,18 +173,13 @@

Modules

@@ -416,7 +415,7 @@ generated by LDoc diff --git a/docs/commands/Jail.html b/docs/commands/Jail.html index 67d43bef..f7cdeb46 100644 --- a/docs/commands/Jail.html +++ b/docs/commands/Jail.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -77,13 +77,13 @@ @@ -112,10 +112,12 @@ + + @@ -124,8 +126,10 @@

Guis

@@ -136,7 +140,6 @@

Configs

@@ -169,18 +173,13 @@

Modules

@@ -611,7 +610,7 @@ generated by LDoc diff --git a/docs/commands/Kill.html b/docs/commands/Kill.html index 967cb7e1..085d3e43 100644 --- a/docs/commands/Kill.html +++ b/docs/commands/Kill.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -77,13 +77,13 @@ @@ -112,10 +112,12 @@ + + @@ -124,8 +126,10 @@

Guis

@@ -136,7 +140,6 @@

Configs

@@ -169,18 +173,13 @@

Modules

@@ -389,7 +388,7 @@ generated by LDoc diff --git a/docs/commands/Me.html b/docs/commands/Me.html index fbba050f..c8286186 100644 --- a/docs/commands/Me.html +++ b/docs/commands/Me.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -77,13 +77,13 @@ @@ -112,10 +112,12 @@ + + @@ -124,8 +126,10 @@

Guis

@@ -136,7 +140,6 @@

Configs

@@ -169,18 +173,13 @@

Modules

@@ -360,7 +359,7 @@ generated by LDoc diff --git a/docs/commands/Rainbow.html b/docs/commands/Rainbow.html index f30d335d..38c038a6 100644 --- a/docs/commands/Rainbow.html +++ b/docs/commands/Rainbow.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -77,13 +77,13 @@ @@ -112,10 +112,12 @@ + + @@ -124,8 +126,10 @@

Guis

@@ -136,7 +140,6 @@

Configs

@@ -169,18 +173,13 @@

Modules

@@ -388,7 +387,7 @@ generated by LDoc diff --git a/docs/commands/Repair.html b/docs/commands/Repair.html index 361a22d7..0a156f7b 100644 --- a/docs/commands/Repair.html +++ b/docs/commands/Repair.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -76,13 +76,13 @@ @@ -111,10 +111,12 @@ + + @@ -123,8 +125,10 @@

Guis

@@ -135,7 +139,6 @@

Configs

@@ -168,18 +172,13 @@

Modules

@@ -321,7 +320,7 @@ generated by LDoc diff --git a/docs/commands/Reports.html b/docs/commands/Reports.html index f94af164..88e9d0d0 100644 --- a/docs/commands/Reports.html +++ b/docs/commands/Reports.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -77,13 +77,13 @@ @@ -112,10 +112,12 @@ + + @@ -124,8 +126,10 @@

Guis

@@ -136,7 +140,6 @@

Configs

@@ -169,18 +173,13 @@

Modules

@@ -585,7 +584,7 @@ generated by LDoc diff --git a/docs/commands/Roles.html b/docs/commands/Roles.html index 3bc1f04d..9ca693d6 100644 --- a/docs/commands/Roles.html +++ b/docs/commands/Roles.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -77,13 +77,13 @@ @@ -112,10 +112,12 @@ + + @@ -124,8 +126,10 @@

Guis

@@ -136,7 +140,6 @@

Configs

@@ -169,18 +173,13 @@

Modules

@@ -250,7 +249,7 @@ expcore.roles - resources.color_presets + utils.color_presets @@ -334,8 +333,8 @@
- # - resources.color_presets + # + utils.color_presets
@@ -557,7 +556,7 @@ generated by LDoc diff --git a/docs/commands/Spawn.html b/docs/commands/Spawn.html index 257da669..479f2750 100644 --- a/docs/commands/Spawn.html +++ b/docs/commands/Spawn.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -77,13 +77,13 @@ @@ -112,10 +112,12 @@ + + @@ -124,8 +126,10 @@

Guis

@@ -136,7 +140,6 @@

Configs

@@ -169,18 +173,13 @@

Modules

@@ -389,7 +388,7 @@ generated by LDoc diff --git a/docs/commands/Tag.html b/docs/commands/Tag.html index 63606adc..c21383cd 100644 --- a/docs/commands/Tag.html +++ b/docs/commands/Tag.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -77,13 +77,13 @@ @@ -112,10 +112,12 @@ + + @@ -124,8 +126,10 @@

Guis

@@ -136,7 +140,6 @@

Configs

@@ -169,18 +173,13 @@

Modules

@@ -443,7 +442,7 @@ generated by LDoc diff --git a/docs/commands/Teleport.html b/docs/commands/Teleport.html index 472651ba..b343424b 100644 --- a/docs/commands/Teleport.html +++ b/docs/commands/Teleport.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -77,13 +77,13 @@ @@ -112,10 +112,12 @@ + + @@ -124,8 +126,10 @@

Guis

@@ -136,7 +140,6 @@

Configs

@@ -169,18 +173,13 @@

Modules

@@ -484,7 +483,7 @@ generated by LDoc diff --git a/docs/commands/Warnings.html b/docs/commands/Warnings.html index a62c9b8e..ab2e9aed 100644 --- a/docs/commands/Warnings.html +++ b/docs/commands/Warnings.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -77,13 +77,13 @@ @@ -112,10 +112,12 @@ + + @@ -124,8 +126,10 @@

Guis

@@ -136,7 +140,6 @@

Configs

@@ -169,18 +173,13 @@

Modules

@@ -569,7 +568,7 @@ generated by LDoc diff --git a/docs/config.ld b/docs/config.ld index 01c7486c..43e5bfdc 100644 --- a/docs/config.ld +++ b/docs/config.ld @@ -2,7 +2,7 @@ file = '../' dir = '../docs' project = 'ExpGaming Scenario' title = 'ExpGaming Scenario' -description = 'Explosive Gaming\'s server scenario for 0.17' +description = 'Explosive Gaming\'s server scenario for 0.18' convert_opt = true sort = false diff --git a/docs/configs/Advanced-Start.html b/docs/configs/Advanced-Start.html index 02b2965a..bb433438 100644 --- a/docs/configs/Advanced-Start.html +++ b/docs/configs/Advanced-Start.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -50,7 +50,6 @@

Configs

@@ -82,13 +82,13 @@ @@ -117,10 +117,12 @@ + + @@ -129,8 +131,10 @@

Guis

@@ -168,18 +172,13 @@

Modules

@@ -506,7 +505,7 @@ generated by LDoc diff --git a/docs/configs/Bonuses.html b/docs/configs/Bonuses.html index 2e3966d2..ed9c3bd1 100644 --- a/docs/configs/Bonuses.html +++ b/docs/configs/Bonuses.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -42,7 +42,6 @@

Configs

@@ -74,13 +74,13 @@ @@ -109,10 +109,12 @@ + + @@ -121,8 +123,10 @@

Guis

@@ -160,18 +164,13 @@

Modules

@@ -237,7 +236,7 @@ generated by LDoc diff --git a/docs/configs/Chat-Reply.html b/docs/configs/Chat-Reply.html index 727827bc..f7c4bca2 100644 --- a/docs/configs/Chat-Reply.html +++ b/docs/configs/Chat-Reply.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -51,7 +51,6 @@

Configs

@@ -83,13 +83,13 @@ @@ -118,10 +118,12 @@ + + @@ -130,8 +132,10 @@

Guis

@@ -169,18 +173,13 @@

Modules

@@ -485,7 +484,7 @@ generated by LDoc diff --git a/docs/configs/Commands-Auth-Admin.html b/docs/configs/Commands-Auth-Admin.html index fd824730..9da0f411 100644 --- a/docs/configs/Commands-Auth-Admin.html +++ b/docs/configs/Commands-Auth-Admin.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -50,7 +50,6 @@

Configs

@@ -82,13 +82,13 @@ @@ -117,10 +117,12 @@ + + @@ -129,8 +131,10 @@

Guis

@@ -168,18 +172,13 @@

Modules

@@ -294,7 +293,7 @@ generated by LDoc diff --git a/docs/configs/Commands-Auth-Roles.html b/docs/configs/Commands-Auth-Roles.html index 4f49a827..477cb804 100644 --- a/docs/configs/Commands-Auth-Roles.html +++ b/docs/configs/Commands-Auth-Roles.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -50,7 +50,6 @@

Configs

@@ -82,13 +82,13 @@ @@ -117,10 +117,12 @@ + + @@ -129,8 +131,10 @@

Guis

@@ -168,18 +172,13 @@

Modules

@@ -320,7 +319,7 @@ generated by LDoc diff --git a/docs/configs/Commands-Auth-Runtime-Disable.html b/docs/configs/Commands-Auth-Runtime-Disable.html index 9aacac5f..1636ab35 100644 --- a/docs/configs/Commands-Auth-Runtime-Disable.html +++ b/docs/configs/Commands-Auth-Runtime-Disable.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -51,7 +51,6 @@

Configs

@@ -83,13 +83,13 @@ @@ -118,10 +118,12 @@ + + @@ -130,8 +132,10 @@

Guis

@@ -169,18 +173,13 @@

Modules

@@ -442,7 +441,7 @@ generated by LDoc diff --git a/docs/configs/Commands-Parse-Roles.html b/docs/configs/Commands-Parse-Roles.html index 64d71e20..9d4292ca 100644 --- a/docs/configs/Commands-Parse-Roles.html +++ b/docs/configs/Commands-Parse-Roles.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -50,7 +50,6 @@

Configs

@@ -82,13 +82,13 @@ @@ -117,10 +117,12 @@ + + @@ -129,8 +131,10 @@

Guis

@@ -168,18 +172,13 @@

Modules

@@ -354,7 +353,7 @@ generated by LDoc diff --git a/docs/configs/Commands-Parse.html b/docs/configs/Commands-Parse.html index 574f8aa4..234392ad 100644 --- a/docs/configs/Commands-Parse.html +++ b/docs/configs/Commands-Parse.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -50,7 +50,6 @@

Configs

@@ -82,13 +82,13 @@ @@ -117,10 +117,12 @@ + + @@ -129,8 +131,10 @@

Guis

@@ -168,18 +172,13 @@

Modules

@@ -338,7 +337,7 @@ see ./expcore/commands.lua for more details

generated by LDoc diff --git a/docs/configs/Compilatron.html b/docs/configs/Compilatron.html index 98043b31..dec0e529 100644 --- a/docs/configs/Compilatron.html +++ b/docs/configs/Compilatron.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -50,7 +50,6 @@

Configs

@@ -82,13 +82,13 @@ @@ -117,10 +117,12 @@ + + @@ -129,8 +131,10 @@

Guis

@@ -168,18 +172,13 @@

Modules

@@ -354,7 +353,7 @@ generated by LDoc diff --git a/docs/configs/Death-Logger.html b/docs/configs/Death-Logger.html index 859cf7d9..67857dec 100644 --- a/docs/configs/Death-Logger.html +++ b/docs/configs/Death-Logger.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -50,7 +50,6 @@

Configs

@@ -82,13 +82,13 @@ @@ -117,10 +117,12 @@ + + @@ -129,8 +131,10 @@

Guis

@@ -168,18 +172,13 @@

Modules

@@ -416,7 +415,7 @@ generated by LDoc diff --git a/docs/configs/Discord-Alerts.html b/docs/configs/Discord-Alerts.html index 4139d6e6..5ea02120 100644 --- a/docs/configs/Discord-Alerts.html +++ b/docs/configs/Discord-Alerts.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -42,7 +42,6 @@

Configs

@@ -74,13 +74,13 @@ @@ -109,10 +109,12 @@ + + @@ -121,8 +123,10 @@

Guis

@@ -160,18 +164,13 @@

Modules

@@ -237,7 +236,7 @@ generated by LDoc diff --git a/docs/configs/File-Loader.html b/docs/configs/File-Loader.html index 8aa4661f..3a9716cf 100644 --- a/docs/configs/File-Loader.html +++ b/docs/configs/File-Loader.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -42,7 +42,6 @@

Configs

@@ -74,13 +74,13 @@ @@ -109,10 +109,12 @@ + + @@ -121,8 +123,10 @@

Guis

@@ -160,18 +164,13 @@

Modules

@@ -240,7 +239,7 @@ generated by LDoc diff --git a/docs/configs/Permission-Groups.html b/docs/configs/Permission-Groups.html index 305e744d..3abffdaa 100644 --- a/docs/configs/Permission-Groups.html +++ b/docs/configs/Permission-Groups.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -50,7 +50,6 @@

Configs

@@ -82,13 +82,13 @@ @@ -117,10 +117,12 @@ + + @@ -129,8 +131,10 @@

Guis

@@ -168,18 +172,13 @@

Modules

@@ -295,7 +294,7 @@ generated by LDoc diff --git a/docs/configs/Player-List.html b/docs/configs/Player-List.html index 2c9fc83f..cfda4261 100644 --- a/docs/configs/Player-List.html +++ b/docs/configs/Player-List.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -51,7 +51,6 @@

Configs

@@ -83,13 +83,13 @@ @@ -118,10 +118,12 @@ + + @@ -130,8 +132,10 @@

Guis

@@ -169,18 +173,13 @@

Modules

@@ -268,7 +267,7 @@ modules.control.jail - resources.color_presets + utils.color_presets expcore.common @@ -504,8 +503,8 @@
- # - resources.color_presets + # + utils.color_presets
@@ -812,7 +811,7 @@ generated by LDoc diff --git a/docs/configs/Pollution-Grading.html b/docs/configs/Pollution-Grading.html index 64d7f6f0..6be165c4 100644 --- a/docs/configs/Pollution-Grading.html +++ b/docs/configs/Pollution-Grading.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -50,7 +50,6 @@

Configs

@@ -82,13 +82,13 @@ @@ -117,10 +117,12 @@ + + @@ -129,8 +131,10 @@

Guis

@@ -168,18 +172,13 @@

Modules

@@ -384,7 +383,7 @@ generated by LDoc diff --git a/docs/configs/Popup-Messages.html b/docs/configs/Popup-Messages.html index 114b8348..4f9f85b0 100644 --- a/docs/configs/Popup-Messages.html +++ b/docs/configs/Popup-Messages.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -50,7 +50,6 @@

Configs

@@ -82,13 +82,13 @@ @@ -117,10 +117,12 @@ + + @@ -129,8 +131,10 @@

Guis

@@ -168,18 +172,13 @@

Modules

@@ -414,7 +413,7 @@ generated by LDoc diff --git a/docs/configs/Preset-Player-Colours.html b/docs/configs/Preset-Player-Colours.html index 824291f5..723391f4 100644 --- a/docs/configs/Preset-Player-Colours.html +++ b/docs/configs/Preset-Player-Colours.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -50,7 +50,6 @@

Configs

@@ -82,13 +82,13 @@ @@ -117,10 +117,12 @@ + + @@ -129,8 +131,10 @@

Guis

@@ -168,18 +172,13 @@

Modules

@@ -324,7 +323,7 @@ generated by LDoc diff --git a/docs/configs/Repair.html b/docs/configs/Repair.html index e61920c5..e8582c36 100644 --- a/docs/configs/Repair.html +++ b/docs/configs/Repair.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -50,7 +50,6 @@

Configs

@@ -82,13 +82,13 @@ @@ -117,10 +117,12 @@ + + @@ -129,8 +131,10 @@

Guis

@@ -168,18 +172,13 @@

Modules

@@ -414,7 +413,7 @@ generated by LDoc diff --git a/docs/configs/Rockets.html b/docs/configs/Rockets.html index 929fbf4c..0db5696a 100644 --- a/docs/configs/Rockets.html +++ b/docs/configs/Rockets.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -50,7 +50,6 @@

Configs

@@ -82,13 +82,13 @@ @@ -117,10 +117,12 @@ + + @@ -129,8 +131,10 @@

Guis

@@ -168,18 +172,13 @@

Modules

@@ -834,7 +833,7 @@ generated by LDoc diff --git a/docs/configs/Roles.html b/docs/configs/Roles.html index 5c7aabf3..a6816311 100644 --- a/docs/configs/Roles.html +++ b/docs/configs/Roles.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -50,7 +50,6 @@

Configs

@@ -82,13 +82,13 @@ @@ -117,10 +117,12 @@ + + @@ -129,8 +131,10 @@

Guis

@@ -168,18 +172,13 @@

Modules

@@ -292,7 +291,7 @@ generated by LDoc diff --git a/docs/configs/Science.html b/docs/configs/Science.html index c9c7fd1c..332659e6 100644 --- a/docs/configs/Science.html +++ b/docs/configs/Science.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -50,7 +50,6 @@

Configs

@@ -82,13 +82,13 @@ @@ -117,10 +117,12 @@ + + @@ -129,8 +131,10 @@

Guis

@@ -168,18 +172,13 @@

Modules

@@ -354,7 +353,7 @@ generated by LDoc diff --git a/docs/configs/Scorched-Earth.html b/docs/configs/Scorched-Earth.html index 3c038550..a55e5c6b 100644 --- a/docs/configs/Scorched-Earth.html +++ b/docs/configs/Scorched-Earth.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -50,7 +50,6 @@

Configs

@@ -82,13 +82,13 @@ @@ -117,10 +117,12 @@ + + @@ -129,8 +131,10 @@

Guis

@@ -168,18 +172,13 @@

Modules

@@ -388,7 +387,7 @@ generated by LDoc diff --git a/docs/configs/Spawn-Area.html b/docs/configs/Spawn-Area.html index 4395fc07..66357213 100644 --- a/docs/configs/Spawn-Area.html +++ b/docs/configs/Spawn-Area.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -50,7 +50,6 @@

Configs

@@ -82,13 +82,13 @@ @@ -117,10 +117,12 @@ + + @@ -129,8 +131,10 @@

Guis

@@ -168,18 +172,13 @@

Modules

@@ -744,7 +743,7 @@ generated by LDoc diff --git a/docs/configs/Tasks.html b/docs/configs/Tasks.html index 1bd48171..f3bf9416 100644 --- a/docs/configs/Tasks.html +++ b/docs/configs/Tasks.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -50,7 +50,6 @@

Configs

@@ -82,13 +82,13 @@ @@ -117,10 +117,12 @@ + + @@ -129,8 +131,10 @@

Guis

@@ -168,18 +172,13 @@

Modules

@@ -241,16 +240,16 @@ - any_user_can_add_new_task + allow_add_task - user_can_edit_own_tasks + expcore_roles_allow_add_task - only_admins_can_edit + allow_edit_task - edit_tasks_role_permission + expcore_roles_allow_edit_task @@ -264,15 +263,15 @@
- # - any_user_can_add_new_task + # + allow_add_task

-

when false only people with edit permission can make new reports

+

dictates who is allowed to add new tasks; values: all, admin, expcore.roles, none

@@ -291,15 +290,15 @@
- # - user_can_edit_own_tasks + # + expcore_roles_allow_add_task

-

when false only people with edit permission can edit reports

+

if expcore.roles is used then this is the required permission

@@ -318,15 +317,15 @@
- # - only_admins_can_edit + # + allow_edit_task

-

true will hide the edit and delete buttons from non (game) admins

+

dictates who is allowed to edit existing tasks; values: all, admin, expcore.roles, none

@@ -345,15 +344,15 @@
- # - edit_tasks_role_permission + # + expcore_roles_allow_edit_task

-

value used with custom permission system

+

if expcore.roles is used then this is the required permission

@@ -384,7 +383,7 @@ generated by LDoc
diff --git a/docs/configs/Warnings.html b/docs/configs/Warnings.html index 78291b18..77d8481e 100644 --- a/docs/configs/Warnings.html +++ b/docs/configs/Warnings.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -50,7 +50,6 @@

Configs

@@ -82,13 +82,13 @@ @@ -117,10 +117,12 @@ + + @@ -129,8 +131,10 @@

Guis

@@ -168,18 +172,13 @@

Modules

@@ -355,7 +354,7 @@ generated by LDoc diff --git a/docs/configs/Warps.html b/docs/configs/Warps.html index c8a87917..81f0ffec 100644 --- a/docs/configs/Warps.html +++ b/docs/configs/Warps.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -50,7 +50,6 @@

Configs

@@ -82,13 +82,13 @@ @@ -117,10 +117,12 @@ + + @@ -129,8 +131,10 @@

Guis

@@ -168,18 +172,13 @@

Modules

@@ -241,37 +240,46 @@ - recharge_time - - update_smoothing minimum_distance - activation_range - - - spawn_activation_range - - default_icon - user_can_edit_own_warps + bypass_warp_cooldown - any_user_can_add_new_warp + expcore_roles_bypass_warp_cooldown - only_admins_can_edit + cooldown_duraction - edit_warps_role_permission + bypass_warp_proximity - bypass_warp_limits_permission + expcore_roles_bypass_warp_proximity + + + standard_proximity_radius + + + spawn_proximity_radius + + + allow_add_warp + + + expcore_roles_allow_add_warp + + + allow_edit_warp + + + expcore_roles_allow_edit_warp entities @@ -294,33 +302,6 @@
- # - recharge_time -
-
-
-
- -

-

The amount of time in seconds that the player must wait between warps, acts as a balance

- - - - - - - - - - - - - - -
-
-
-
# update_smoothing
@@ -329,7 +310,7 @@

-

Higher is better, the amount of smoothing applied to recharge timer and other gui updates, max is 60

+

the amount of smoothing applied to updates to the cooldown timer, higher is better, max is 60

@@ -356,61 +337,7 @@

-

The minimum distance that must be between warp points, creating new ones is blocked when too close

- - - - - - - - - - - - - - - -
-
-
- # - activation_range -
-
-
-
- -

-

The distance the player must be to a warp in order to use the warp gui, gui can still be viewed but not used

- - - - - - - - - - - - - - -
-
-
-
- # - spawn_activation_range -
-
-
-
- -

-

A second activation range which is used for the forces spawn point

+

the minimum distance that is allowed between warps on the same force

@@ -437,7 +364,7 @@

-

The default icon which is used by warps; must be an item name

+

the default icon that will be used for warps

@@ -456,15 +383,15 @@
- # - user_can_edit_own_warps + # + bypass_warp_cooldown

-

When true the user can always edit warps which they created regardless of other settings

+

dictates who the warp cooldown is applied to; values: all, admin, expcore.roles, none

@@ -483,15 +410,15 @@
- # - any_user_can_add_new_warp + # + expcore_roles_bypass_warp_cooldown

-

When true any user is able to create new warps, however editing may still be restricted

+

if expcore.roles is used then this is the required permission

@@ -510,15 +437,15 @@
- # - only_admins_can_edit + # + cooldown_duraction

-

When true only admins can edit warps

+

the duration of the warp cooldown in seconds

@@ -537,15 +464,15 @@
- # - edit_warps_role_permission + # + bypass_warp_proximity

-

Role permission used by the role system to allow editing warps

+

dictates who the warp proximity is applied to; values: all, admin, expcore.roles, none

@@ -564,15 +491,177 @@
- # - bypass_warp_limits_permission + # + expcore_roles_bypass_warp_proximity

-

Role permission used by the role system to allow bypassing the time and distance restrictions

+

if expcore.roles is used then this is the required permission

+ + + + + + + + + + + + + + +
+
+
+
+ # + standard_proximity_radius +
+
+
+
+ +

+

the minimum distance a player is allowed to be to a warp in order to use it

+ + + + + + + + + + + + + + +
+
+
+
+ # + spawn_proximity_radius +
+
+
+
+ +

+

the minimum distance a player is allowed to be from they spawn point to use warps

+ + + + + + + + + + + + + + +
+
+
+
+ # + allow_add_warp +
+
+
+
+ +

+

dictates who is allowed to add warps; values: all, admin, expcore.roles, none

+ + + + + + + + + + + + + + +
+
+
+
+ # + expcore_roles_allow_add_warp +
+
+
+
+ +

+

if expcore.roles is used then this is the required permission

+ + + + + + + + + + + + + + +
+
+
+
+ # + allow_edit_warp +
+
+
+
+ +

+

dictates who is allowed to edit warps; values: all, admin, expcore.roles, none

+ + + + + + + + + + + + + + +
+
+
+
+ # + expcore_roles_allow_edit_warp +
+
+
+
+ +

+

if expcore.roles is used then this is the required permission

@@ -599,7 +688,7 @@

-

The entities which are created for warps

+

The entities which are created for warp areas

@@ -626,7 +715,7 @@

-

The tile which is used for the warps

+

The tile which is used for the warp areas

@@ -653,7 +742,7 @@

-

The tiles which are created for warps

+

The tiles which are created for warp areas

@@ -684,7 +773,7 @@ generated by LDoc
diff --git a/docs/control/Jail.html b/docs/control/Jail.html index 46633de1..f66c2789 100644 --- a/docs/control/Jail.html +++ b/docs/control/Jail.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -66,13 +66,13 @@ @@ -87,10 +87,12 @@ + + @@ -99,8 +101,10 @@

Guis

@@ -138,7 +142,6 @@

Configs

@@ -171,18 +175,13 @@

Modules

@@ -1208,7 +1207,7 @@ generated by LDoc diff --git a/docs/control/Production.html b/docs/control/Production.html index ea5291cb..66ab08bb 100644 --- a/docs/control/Production.html +++ b/docs/control/Production.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -42,9 +42,9 @@

Sections

@@ -66,13 +66,13 @@ @@ -87,10 +87,12 @@ + + @@ -99,8 +101,10 @@

Guis

@@ -138,7 +142,6 @@

Configs

@@ -171,18 +175,13 @@

Modules

@@ -205,9 +204,9 @@

Jump to Section

@@ -275,7 +274,7 @@ - resources.color_presets + utils.color_presets util @@ -284,6 +283,22 @@ +

Formating

+ + + + + + + + + + + + +
get_color(clamp, active_value, passive_value)Returns a color value bassed on the value that was given
format_number(value)Returns three parts used to format a number
+ +

Precision

@@ -334,22 +349,6 @@
- - -

Formating

- - - - - - - - - - - - -
get_color(clamp, active_value, passive_value)Returns a color value bassed on the value that was given
format_number(value)Returns three parts used to format a number

@@ -360,8 +359,8 @@
- # - resources.color_presets + # + utils.color_presets
@@ -400,6 +399,159 @@ + + + + + + +
+ +

Formating

+
+
+
+
+ # + get_color(clamp, active_value, passive_value) +
+
+
+
+ +

Returns a color value bassed on the value that was given

+

+ + + Parameters: + +
    + + + + + +
  • + + clamp + + : + + (number) + + value which seperates the different colours + +
  • + + + + + +
  • + + active_value + + : + + (number) + + first value tested, tested against clamp + +
  • + + + + + +
  • + + passive_value + + : + + (number) + + second value tested, tested against 0 + +
  • + + +
+ + + + + Returns: +
    +
  • + (table) + contains r,g,b keys +
  • +
+ + + + + + + + + +
+
+
+
+ # + format_number(value) +
+
+
+
+ +

Returns three parts used to format a number

+

+ + + Parameters: + +
    + + + + + +
  • + + value + + : + + (number) + + the value to format + +
  • + + +
+ + + + + Returns: +
    +
  • + (string) + the sign for the number +
  • +
  • + (string) + the surfix for any unit used +
  • +
+ + + @@ -1154,159 +1306,6 @@ - - - - - - -
-
-

Formating

-
-
-
-
- # - get_color(clamp, active_value, passive_value) -
-
-
-
- -

Returns a color value bassed on the value that was given

-

- - - Parameters: - -
    - - - - - -
  • - - clamp - - : - - (number) - - value which seperates the different colours - -
  • - - - - - -
  • - - active_value - - : - - (number) - - first value tested, tested against clamp - -
  • - - - - - -
  • - - passive_value - - : - - (number) - - second value tested, tested against 0 - -
  • - - -
- - - - - Returns: -
    -
  • - (table) - contains r,g,b keys -
  • -
- - - - - - - - - -
-
-
-
- # - format_number(value) -
-
-
-
- -

Returns three parts used to format a number

-

- - - Parameters: - -
    - - - - - -
  • - - value - - : - - (number) - - the value to format - -
  • - - -
- - - - - Returns: -
    -
  • - (string) - the sign for the number -
  • -
  • - (string) - the surfix for any unit used -
  • -
- - - @@ -1329,7 +1328,7 @@ generated by LDoc
diff --git a/docs/control/Reports.html b/docs/control/Reports.html index 4470dca7..09e64549 100644 --- a/docs/control/Reports.html +++ b/docs/control/Reports.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -66,13 +66,13 @@ @@ -87,10 +87,12 @@ + + @@ -99,8 +101,10 @@

Guis

@@ -138,7 +142,6 @@

Configs

@@ -171,18 +175,13 @@

Modules

@@ -1110,7 +1109,7 @@ generated by LDoc diff --git a/docs/control/Rockets.html b/docs/control/Rockets.html index ea2c7aae..d1bcf823 100644 --- a/docs/control/Rockets.html +++ b/docs/control/Rockets.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -65,13 +65,13 @@ @@ -86,10 +86,12 @@ + + @@ -98,8 +100,10 @@

Guis

@@ -137,7 +141,6 @@

Configs

@@ -170,18 +174,13 @@

Modules

@@ -984,7 +983,7 @@ generated by LDoc diff --git a/docs/control/Tasks.html b/docs/control/Tasks.html index 41068882..d8fe98bf 100644 --- a/docs/control/Tasks.html +++ b/docs/control/Tasks.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -65,13 +65,13 @@ @@ -86,10 +86,12 @@ + + @@ -98,8 +100,10 @@

Guis

@@ -137,7 +141,6 @@

Configs

@@ -170,18 +174,13 @@

Modules

@@ -998,7 +997,7 @@ Tasks.update_task(task_id,'We need more iron!',game. generated by LDoc diff --git a/docs/control/Warnings.html b/docs/control/Warnings.html index abec17b0..7465e015 100644 --- a/docs/control/Warnings.html +++ b/docs/control/Warnings.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -65,13 +65,13 @@ @@ -86,10 +86,12 @@ + + @@ -98,8 +100,10 @@

Guis

@@ -137,7 +141,6 @@

Configs

@@ -170,18 +174,13 @@

Modules

@@ -1465,7 +1464,7 @@ generated by LDoc diff --git a/docs/control/Warps.html b/docs/control/Warps.html index ebb0dfb5..f3a3b9f2 100644 --- a/docs/control/Warps.html +++ b/docs/control/Warps.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -66,13 +66,13 @@ @@ -87,10 +87,12 @@ + + @@ -99,8 +101,10 @@

Guis

@@ -138,7 +142,6 @@

Configs

@@ -171,18 +175,13 @@

Modules

@@ -274,9 +273,6 @@ Warps.make_warp_tag(warp_id) config.warps - - expcore.common - @@ -463,31 +459,6 @@ Warps.make_warp_tag(warp_id) - - - - - - - -
-
-
- # - expcore.common -
-
-
-
- - - - - - - - - @@ -1563,7 +1534,7 @@ Warps.make_warp_tag(warp_id) generated by LDoc
diff --git a/docs/core/Async.html b/docs/core/Async.html new file mode 100644 index 00000000..6a6a6a2d --- /dev/null +++ b/docs/core/Async.html @@ -0,0 +1,605 @@ + + + + + + + + Async core + + + + + + + +
+
+ + + + + + + +
+ + + + + + + + +

Async core

+

Core Module - Async +- An extention of task and token to allow a single require to register and run async functions.

+

+ + + + + + +

Usage

+

+-- To use Async you must register the allowed functions when the file is loaded, often this will just be giving access to
+-- some functions within a module if you expect that at part may be blocked by in game permissions or a custom system you have made
+-- you may also want to register functions that you want to have a time delay, such as waiting 2 seconds before printing a message
+
+-- When player.admin is called (either command or gui element event) by a player who isnt admin then it will error
+-- here we register the function to promote the player so that it will run async and outside the player scope
+local promote_player =
+Async.register(function(player)
+    player.admin = true
+end)
+
+-- This will allow us to bypass the error by running one tick later outside of any player scope
+Async(promote_player,game.player)
+
+-- Here we make an sync function that we want to have a delay, note the delay is not defined here
+local print_message =
+Async.register(function(player,message)
+    player.print(message)
+end)
+
+-- We can then call the async function with a delay using the wait function
+Async.wait(60, print_message, game.player, 'One second has passed!')
+ + + + + +
+ +

Dependencies

+ + + + + + + + + + +
utils.task
utils.token
+ + +

Functions

+ + + + + + + + + + + + + + + + +
register(callback)Register a new async function, must called when the file is loaded
run(token[, ...])Runs an async function, you may supply any number of arguments as required by that function
wait(ticks, token[, ...])Runs an async function after the given number of ticks, you may supply any number of arguments as required by that function
+ + +
+ + +

Dependencies

+
+
+
+
+ # + utils.task +
+
+
+
+ + + + + + + + + + + + + + + +
+
+
+
+ # + utils.token +
+
+
+
+ + + + + + + + + + + + + + + +
+
+

Functions

+
+
+
+
+ # + register(callback) +
+
+
+
+ +

Register a new async function, must called when the file is loaded

+

+ + + Parameters: + +
    + + + + + +
  • + + callback + + : + + (function) + + the function that can be called as an async function + +
  • + + +
+ + + + + Returns: +
    +
  • + (string) + the uid of the async function which can be passed to Async.run and Async.wait +
  • +
+ + + + + + + + Usage: +
-- Registering a function to set the admin state of a player
+local set_admin =
+Async.register(function(player, state)
+    if player.valid then
+        player.admin = state
+    end
+end)
+
-- Registering a function to print to a player
+local print_to_player =
+Async.register(function(player, message)
+    if player.valid then
+        player.print(message)
+    end
+end)
+ + +
+
+
+
+ # + run(token[, ...]) +
+
+
+
+ +

Runs an async function, you may supply any number of arguments as required by that function

+

+ + + Parameters: + +
    + + + + + +
  • + + token + + : + + (string) + + the token of the async function you want to run + +
  • + + + + + +
  • + + ... + + : + + (any) + + the other params that you want to pass to your function + + (optional) +
  • + + +
+ + + + + + + + + + + + Usage: +
-- Make a player admin regardless of if you are admin
+Async.run(set_admin, player, true)
+ + +
+
+
+
+ # + wait(ticks, token[, ...]) +
+
+
+
+ +

Runs an async function after the given number of ticks, you may supply any number of arguments as required by that function

+

+ + + Parameters: + +
    + + + + + +
  • + + ticks + + : + + (number) + + the number of ticks that you want the function to run after + +
  • + + + + + +
  • + + token + + : + + (string) + + the token of the async function you want to run + +
  • + + + + + +
  • + + ... + + : + + (any) + + the other params that you want to pass to your function + + (optional) +
  • + + +
+ + + + + + + + + + + + Usage: +
-- Print a message to a player after 5 seconds
+Async.wait(300, print_to_player, 'Hello, World!')
+ + +
+
+ + + + + + + + + + diff --git a/docs/core/Commands.html b/docs/core/Commands.html index 07dfce01..512c965a 100644 --- a/docs/core/Commands.html +++ b/docs/core/Commands.html @@ -29,7 +29,7 @@

ExpGaming Scenario

-

Explosive Gaming's server scenario for 0.17

+

Explosive Gaming's server scenario for 0.18

@@ -42,6 +42,8 @@

Sections

@@ -89,10 +91,12 @@ + + @@ -101,8 +105,10 @@

Guis

@@ -140,7 +146,6 @@

Configs

@@ -173,18 +179,13 @@

Modules

@@ -207,6 +208,8 @@

Jump to Section

+
+

Tables

+
+
+
+
+ # + defines +
+
+
+
+ +

Values returned by the signal functions to cause the command system to react

+

+ + + Fields: + +
    + + + + + +
  • + + error + + + + + +
  • + + + + + +
  • + + unauthorized + + + + + +
  • + + + + + +
  • + + success + + + + + +
  • + + +
+ + + + + + + + + + + + + +
+
+
+
+ # + commands +
+
+
+
+ +

Custom command data will be stored here

+

+ + + + + + + + + + + + + + +
+
+
+
+ # + authorization +
+
+
+
+ +

Custom function are stored here which control who can use what commands

+

+ + + + + + + + + + + + + + +
+
+
+
+ # + parse_functions +
+
+
+
+ +

Used to store default functions which are common parse function such as player or number in range

+

+ + + + + + + + + + + + + + +
+
+
+
+ # + _prototype +
+
+
+
+ +

Used to store functions which gets added to new custom commands

+

+ + + + + + + + + + + + + + +
+
+

Fields

+
+
+
+
+ # + authorization_fail_on_error +
+
+
+
+ +

Set true to have authorize fail if a callback fails to run, more secure

+

+ + + + + + + + @@ -662,10 +921,6 @@ (function) the callback you want to register as an authenticator - callback param - player: LuaPlayer - the player who is trying to use the command - callback param - command: string - the name of the command which is being used - callback param - flags: table - any flags which have been set for the command - callback param - reject: function(error_message?: string) - call to fail authorize with optional error message @@ -689,6 +944,16 @@ + Usage: +
-- Test if a command is admin only and if the player is admin
+local admin_authenticator =
+Commands.add_authenticator(function(player, command, flags, reject)
+    if flags.admin_only then
+        return player.admin or reject('This command is for admins only!')
+    else
+        return true
+    end
+end)
@@ -736,7 +1001,7 @@
  • (boolean) - was the callback found and removed + if the callback found and removed successfuly
@@ -746,6 +1011,9 @@ + Usage: +
-- Removing the admin authenticator, can not be done dueing runtime
+Commands.remove_authenticator(admin_authenticator)
@@ -834,6 +1102,9 @@ + Usage: +
-- Test if a player can use "repeat-name"
+local authorized, status = Commands.authorize(game.player, 'repeat-name')
@@ -850,7 +1121,7 @@
-

Gets all commands that a player is allowed to use, game commands not included

+

Gets all commands that a player is allowed to use, game commands are not included

@@ -895,6 +1166,11 @@ + Usage: +
-- Get the command you are allowed to use
+local commands = Commands.get(game.player)
+
-- Get all commands that are registered
+local commands = Commands.get()
@@ -902,13 +1178,13 @@
# - search(keyword[, allowed_player]) + search(keyword[, player])
-

Searches command names and help messages to find possible commands, game commands included

+

Searches command names and help messages to find possible commands, game commands are included

@@ -928,7 +1204,7 @@ (string) - the word which you are trying to find + the word which you are trying to find in your search @@ -938,7 +1214,7 @@
  • - allowed_player + player : @@ -969,6 +1245,11 @@ + Usage: +
    -- Get all commands which "repeat"
    +local commands = Commands.search('repeat')
    +
    -- Get all commands which "repeat" and you are allowed to use
    +local commands = Commands.search('repeat', game.player)
  • @@ -985,8 +1266,8 @@
    -

    Adds a parse function which can be called by name rather than callback (used in add_param) - nb: this is not needed as you can use the callback directly this just allows it to be called by name

    +

    Adds a parse function which can be called by name (used in add_param) +nb: this is not required as you can use the callback directly this just allows it to be called by name

    @@ -1023,10 +1304,6 @@ (function) the callback that is ran to parse the input - parse param - input: string - the input given by the user for this param - parse param - player: LuaPlayer - the player who is using the command - parse param - reject: function(error_message) - use this function to send a error to the user and fail running - parse return - the value that will be passed to the command callback, must not be nil and if reject then command is not run @@ -1050,6 +1327,18 @@ + Usage: +
    -- Adding a parse to validate ints in a given range
    +Commands.add_parse('number-range-int', function(input, player, reject, range_min, range_max)
    +    local rtn = tonumber(input) and math.floor(tonumber(input)) or nil -- converts input to number
    +    if not rtn or rtn < range_min or rtn > range_max then
    +        -- the input is either not a number or is outside the range
    +        return reject('Number entered is not in range: '..range_min..', '..range_max)
    +    else
    +        -- returns the input as a number rather than a string, thus the param is now the correct type
    +        return rtn
    +    end
    +end)
    @@ -1100,6 +1389,9 @@ + Usage: +
    -- Removing a parse
    +Commands.remove_parse('number-range-int')
    @@ -1133,7 +1425,7 @@ (string) - the name of the parse to call, must be registered and cant be a function + the name of the parse to call, must be registered parse @@ -1149,7 +1441,7 @@ (string) - string the input to pass to the parse, will always be a but might not be the original input + string the input to pass to the parse, must be a string but not necessarily the original input @@ -1165,7 +1457,7 @@ (LuaPlayer) - the player that is calling using the command + the player that is using the command @@ -1205,6 +1497,10 @@ + Usage: +
    -- Parsing a int in a given range
    +local parsed_input = Commands.parse('number-range-int', '7', player, reject, 1, 10) -- valid range 1 to 10
    +
    @@ -1221,7 +1517,7 @@
    -

    Creates a new command object to added details to, note this does not register the command to the game

    +

    Creates a new command object to added details to, note this does not register the command to the game api

    @@ -1281,6 +1577,10 @@ + Usage: +
    -- Define a new command
    +local command =
    +Commands.new_command('repeat-name', 'Will repeat you name a number of times in chat.')
    @@ -1364,10 +1664,6 @@ extra args you want to pass to the parse function; for example if the parse is general use - parse param - input: string - the input given by the user for this param - parse param - player: LuaPlayer - the player who is using the command - parse param - reject: function(error_message) - use this function to send a error to the user and fail running - parse return - the value that will be passed to the command callback, must not be nil and if reject then command is not run (optional) @@ -1392,6 +1688,14 @@ + Usage: +
    -- Adding a param which has an parse defined
    +command:add_param('repeat-count', false, 'number-range-int', 1, 5)
    +
    -- Adding a param which has a custom parse, see Commands.add_parse for details
    +command:add_param('smiley', true, function(input, player, reject)
    +    if not input then return end
    +    return input:lower() == 'true' or input:lower() == 'yes' or false
    +end)
    @@ -1405,7 +1709,7 @@
    -

    Adds default values to params only matters if the param is optional, if default value is a function it is called with param player

    +

    Add default values to params, only as an effect if the param is optional, if default value is a function it is called with acting player

    @@ -1425,8 +1729,7 @@ (table) - table a keyed by the name of the param with the value as the default value {paramName=defaultValue} - callback param - player: LuaPlayer - the player using the command, default value does not need to be a function callback + table which is keyed by the name of the param and the value is the default value @@ -1450,6 +1753,15 @@ + Usage: +
    -- Adding default values
    +command:set_defaults{
    +    smiley = false,
    +    -- not in example just used to show arguments given
    +    player_name = function(player)
    +        return player.name
    +    end
    +}
    @@ -1457,7 +1769,7 @@
    # - Commands._prototype:set_flag(name, value) + Commands._prototype:set_flag(name[, value=true])
    @@ -1483,7 +1795,7 @@ (string) - the name of the tag to be added; used to keep flags separate + the name of the tag to be added, set to true if no value is given @@ -1500,8 +1812,8 @@ (any) the tag that you want can be anything that the authenticators are expecting - nb: if value is nil then name will be assumed as the value and added at a numbered index + (default: true) @@ -1524,6 +1836,11 @@ + Usage: +
    -- Setting a custom flag
    +command:set_flag('admin_only', true)
    +
    -- When value is true it does not need to be given
    +command:set_flag('admin_only')
    @@ -1537,7 +1854,7 @@
    -

    Adds an alias or multiple that will also be registered with the same callback, eg /teleport can be /tp with both working

    +

    Adds an alias, or multiple, that will also be registered with the same callback, eg /teleport can be used as /tp

    @@ -1582,7 +1899,8 @@ Usage: -
    command:add_alias('aliasOne','aliasTwo','etc')
    +
    -- Added multiple aliases to a command
    +command:add_alias('name', 'rname')
    @@ -1597,8 +1915,8 @@

    Enables auto concatenation of any params on the end so quotes are not needed for last param - nb: this will disable max param checking as they will be concatenated onto the end of that last param - this can be useful for reasons or longs text, can only have one per command

    +nb: this will disable max param checking as they will be concatenated onto the end of that last param +this can be useful for reasons or longs text, can only have one per command

    @@ -1619,6 +1937,9 @@ + Usage: +
    -- Enable auto concat for a command
    +command:enable_auto_concat()
    @@ -1632,8 +1953,8 @@
    -

    Adds the callback to the command and registers all aliases, params and help message with the game - nb: this must be the last function ran on the command and must be done for the command to work

    +

    Adds the callback to the command and registers all aliases, params and help message with the game api +nb: this must be the last function ran on the command and must be done for the command to work

    @@ -1654,9 +1975,6 @@ (function) the callback for the command, will receive the player running command, and params added with add_param - callback param - player: LuaPlayer - the player who used the command - callback param - ... - any params which were registered with add_param in the order they where registered - callback param - raw: string - the raw input from the user, comes after every param added with add_param @@ -1673,6 +1991,16 @@ + Usage: +
    -- Registering your command to the game api
    +command:register(function(player, repeat_count, smiley, _)
    +    local msg = ') '..player.name
    +    if smiley then msg = ':'..msg end
    +
    +    for 1 = 1,repeat_count do
    +        Command.print(1..msg)
    +    end
    +end)
    @@ -1683,15 +2011,14 @@
    # - error([error_message][, play_sound]) + error([error_message=''][, play_sound=utility/wire_pickup])
    -

    Sends an error message to the player and returns a constant to return to command handler to exit execution - nb: this is for non fatal errors meaning there is no log of this event - nb: if reject is giving as a param to the callback use that instead

    +

    Sends an error message to the player and when returned will stop exicution of the command +nb: this is for non fatal errors meaning there is no log of this event, use during register callback

    @@ -1713,7 +2040,7 @@ an optional error message that can be sent to the user - (optional) + (default: '') @@ -1730,7 +2057,7 @@ the sound to play for the error - (optional) + (default: utility/wire_pickup) @@ -1754,7 +2081,8 @@ Usage: -
    return Commands.error()
    +
    -- Send an error message to the player, and stops further code running
    +return Commands.error('The player you selected is offline')
    @@ -1769,7 +2097,7 @@

    Sends an error to the player and logs the error, used with pcall within command handler please avoid direct use - nb: use error(error_message) within your callback to trigger do not trigger directly as the handler may still continue

    +nb: use error(error_message) within your callback to trigger do not trigger directly as code exictuion may still continue

    @@ -1845,6 +2173,12 @@ + Usage: +
    -- Used in the command system to log handler errors
    +local success, err = pcall(command_data.callback, player, unpack(params))
    +if Commands.internal_error(success, command_data.name, err) then
    +    return command_log(player, command_data, 'Internal Error: Command Callback Fail', raw_params, command_event.parameter, err)
    +end
    @@ -1859,7 +2193,7 @@

    Sends a value to the player, followed by a command complete message - nb: either return a value from your callback to trigger or return the return of this to prevent two messages

    +nb: returning any value from your callback will trigger this function, return this function to prevent duplicate messages

    @@ -1904,6 +2238,80 @@ + Usage: +
    -- Print a custom success message
    +return Commands.success('Your message has been printed')
    +
    -- Returning the value has the same result
    +return 'Your message has been printed'
    + + + +
    +
    +
    + # + print(value, colour) +
    +
    +
    +
    + +

    Sends a value to the player, different to success as this does not signal the end of your command

    +

    + + + Parameters: + +
      + + + + + +
    • + + value + + : + + (any) + + the value that you want to return to the player + +
    • + + + + + +
    • + + colour + + : + + (table) + + the colour of the message that the player sees + +
    • + + +
    + + + + + + + + + + + + Usage: +
    -- Output a message to the player
    +Commands.print('Your command is in progress')
    @@ -1954,6 +2362,8 @@ + Usage: +
    Commands.run_command(event)
    @@ -1972,7 +2382,7 @@ generated by LDoc
    diff --git a/docs/core/Common-Library.html b/docs/core/Common-Library.html index 4206d114..8b86b626 100644 --- a/docs/core/Common-Library.html +++ b/docs/core/Common-Library.html @@ -42,7 +42,10 @@

    Sections

    @@ -50,13 +53,13 @@ @@ -85,10 +88,12 @@ + + @@ -97,8 +102,10 @@

    Guis

    @@ -136,7 +143,6 @@

    Configs

    @@ -169,18 +176,13 @@

    Modules

    @@ -203,7 +205,10 @@

    Jump to Section

    @@ -244,7 +249,7 @@ - resources.color_presets + utils.color_presets utils.game @@ -256,25 +261,77 @@ -

    Functions

    +

    Type Checking

    - + - + - + + + + + + + + + - - + + + + + + + + + + + + +
    type_check(value[, test_type=nil])Compare types faster for faster validation of paramsAsserts the argument is of type test_type
    type_check_error(value, test_type, error_message, level)type_error(value, test_type, error_message, level) Raises an error if the value is of the wrong type
    param_check(value, test_type, param_name, param_number)multi_type_check(value, test_types)Asserts the argument is one of type test_types
    multi_type_error(value, test_types, error_message, level)Raises an error if the value is of the wrong type
    validate_argument_type(value, test_type, param_name, param_number) Raises an error when the value is the incorrect type, uses a consistent error message format
    player_return(value[, colour=defines.colour.white][, player=game.player])Will return a value of any type to the player/server console, allows colour for in-game playersvalidate_argument_multi_type(value, test_types, param_name, param_number)Raises an error when the value is the incorrect type, uses a consistent error message format
    error_if_runtime()Will raise an error if called during runtime
    error_if_runetime_closure(func)Will raise an error if the function is a closure
    + + +

    Value Returns

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -285,8 +342,40 @@ - - + + + + + + + + + + + + +
    string_contains(s, contains)Tests if a string contains a given substring.
    resolve_value(value)Used to resolve a value that could also be a function returning that value
    get_actor()Returns a valid string with the name of the actor of a command.
    cast_bool(var)Converts a varible into its boolean value, nil and false return false
    ternary(c, t, f)Returns either the second or third argument based on the first argument
    comma_value(n)Returns a string for a number with comma seperators
    set_and_return(tbl, key, value)Sets a table element to value while also returning value.
    write_json(path, tbl)Calls a require that will not error if the file is not found
    ext_require(path, ...)Calls a require and returns only the keys given, file must return a tableget_file_path([offset=0])Returns a desync safe file path for the current file
    enum(tbl)Converts a table to an enum
    auto_complete(options, input[, use_key=false][, rtn_key=false])Returns the closest match to the input
    + + +

    Formating

    + + + + + + + + + + + + + + + + + + @@ -296,6 +385,14 @@ string will return a string not a locale string when a denomination is false it will overflow into the next one + +
    format_chat_colour(message, color)Returns a message with valid chat tags to change its colour
    format_chat_colour_localized(message, color)Returns a message with valid chat tags to change its colour, using localization
    format_chat_player_name(player[, raw_string=false])Returns the players name in the players color
    player_return(value[, colour=defines.colour.white][, player=game.player])Will return a value of any type to the player/server console, allows colour for in-game players
    format_time(ticks, options)
    + + +

    Factorio

    + + + @@ -313,66 +410,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    move_items(items[, surface=navies][, position={0][, radius=32][, chest_type=iron-chest]) Moves items to the position and stores them in the closest entity of the type givenclear_flying_text(surface) Clears all flying text entities on a surface
    string_contains(s, contains)Tests if a string contains a given substring.
    extract_keys(tbl, ...)Extracts certain keys from a table
    enum(tbl)Converts a table to an enum
    auto_complete(options, input[, use_key=false][, rtn_key=false])Returns the closest match to the input
    table_values(tbl[, sorted][, as_string])Returns a copy of all of the values in the table.
    table_keys(tbl[, sorted][, as_string])Returns a copy of all of the keys in the table.
    table_alphanumsort(tbl)Returns the list is a sorted way that would be expected by people (this is by key)
    table_keysort(tbl)Returns the list is a sorted way that would be expected by people (this is by key) (faster alternative than above)
    format_chat_colour(message, color)Returns a message with valid chat tags to change its colour
    format_chat_colour_localized(message, color)Returns a message with valid chat tags to change its colour, using localization
    format_chat_player_name(player[, raw_string=false])Returns the players name in the players color
    get_file_path([offset=0])Returns a desync safe file path for the current file
    array_insert(tbl[, start_index], values)Much faster method for inserting items into an array
    table_insert(tbl[, start_index], tbl2)Much faster method for inserting keys into a table
    resolve_value(value)Used to resolve a value that could also be a function returning that value
    @@ -385,8 +422,8 @@
    - # - resources.color_presets + # + utils.color_presets
    @@ -458,7 +495,7 @@
    -

    Functions

    +

    Type Checking

    @@ -470,7 +507,7 @@
    -

    Compare types faster for faster validation of params

    +

    Asserts the argument is of type test_type

    @@ -540,8 +577,8 @@
    - # - type_check_error(value, test_type, error_message, level) + # + type_error(value, test_type, error_message, level)
    @@ -640,15 +677,193 @@ Usage: -
    type_check_error('foo','number','Value must be a number') -- will raise error "Value must be a number"
    +
    type_error('foo','number','Value must be a number') -- will raise error "Value must be a number"
    - # - param_check(value, test_type, param_name, param_number) + # + multi_type_check(value, test_types) +
    +
    +
    +
    + +

    Asserts the argument is one of type test_types

    +

    + + + Parameters: + +
      + + + + + +
    • + + value + + : + + + the variable to check + +
    • + + + + + +
    • + + test_types + + : + + + the type as a table of strings + +
    • + + +
    + + + + + Returns: +
      +
    • + (boolean) + true if value is one of test_types +
    • +
    + + + + + + + + + +
    +
    +
    +
    + # + multi_type_error(value, test_types, error_message, level) +
    +
    +
    +
    + +

    Raises an error if the value is of the wrong type

    +

    + + + Parameters: + +
      + + + + + +
    • + + value + + : + + (any) + + the value that you want to test the type of + +
    • + + + + + +
    • + + test_types + + : + + (table) + + the type as a table of strings + +
    • + + + + + +
    • + + error_message + + : + + (string) + + the error message that is returned + +
    • + + + + + +
    • + + level + + : + + (number) + + the level to call the error on (level = 1 means the caller) + +
    • + + +
    + + + + + Returns: +
      +
    • + (boolean) + true if no error was called +
    • +
    + + + + + + + + Usage: +
    multi_type_error('foo',{'string','table'},'Value must be a string or table') -- will raise error "Value must be a string or table"
    + + +
    +
    +
    +
    + # + validate_argument_type(value, test_type, param_name, param_number)
    @@ -747,21 +962,21 @@ Usage: -
    param_check('foo','number','repeat_count',2) -- will raise error "Invalid param #02 given to <anon>; repeat_count is not of type number"
    +
    validate_argument_type('foo','number','repeat_count',2) -- will raise error "Bad argument #02 to "<anon>"; "repeat_count" is of type string expected number"
    - # - player_return(value[, colour=defines.colour.white][, player=game.player]) + # + validate_argument_multi_type(value, test_types, param_name, param_number)
    -

    Will return a value of any type to the player/server console, allows colour for in-game players

    +

    Raises an error when the value is the incorrect type, uses a consistent error message format

    @@ -779,8 +994,9 @@ : + (any) - any value of any type that will be returned to the player or console + the value that you want to test the type of @@ -790,15 +1006,14 @@
  • - colour + test_types : - (defines.color or string) + (string) - the colour of the text for the player, ignored when printing to console + the types that the value should be - (default: defines.colour.white)
  • @@ -807,15 +1022,116 @@
  • - player + param_name : - (LuaPlayer) + (string) + + the name of the param + +
  • + + + + + +
  • + + param_number + + : + + (number) + + the number param it is + +
  • + + + + + + + + Returns: +
      +
    • + (boolean) + true if no error was raised +
    • +
    + + + + + + + + Usage: +
    validate_argument_type('foo',{'string','table'},'repeat_count',2) -- will raise error "Bad argument #02 to "<anon>"; "repeat_count" is of type string expected string or table"
    + + +
    +
    +
    +
    + # + error_if_runtime() +
    +
    +
    +
    + +

    Will raise an error if called during runtime

    +

    + + + + + + + + + + + + + Usage: +
    error_if_runtime()
    + + +
    +
    +
    +
    + # + error_if_runetime_closure(func) +
    +
    +
    +
    + +

    Will raise an error if the function is a closure

    +

    + + + Parameters: + +
      + + + + + +
    • + + func + + + - the player that return will go to, if no game.player then returns to server - (default: game.player)
    • @@ -832,9 +1148,445 @@ Usage: -
      player_return('Hello, World!') -- returns 'Hello, World!' to game.player or server console
      -
      player_return('Hello, World!','green') -- returns 'Hello, World!' to game.player with colour green or server console
      -
      player_return('Hello, World!',nil,player) -- returns 'Hello, World!' to the given player
      +
      error_if_runetime_closure(func)
      + + +
    +
    +

    Value Returns

    +
    +
    +
    +
    + # + string_contains(s, contains) +
    +
    +
    +
    + +

    Tests if a string contains a given substring.

    +

    + + + Parameters: + +
      + + + + + +
    • + + s + + : + + (string) + + the string to check for the substring + +
    • + + + + + +
    • + + contains + + : + + (string) + + the substring to test for + +
    • + + +
    + + + + + Returns: +
      +
    • + (boolean) + true if the substring was found in the string +
    • +
    + + + + + + + + + +
    +
    +
    +
    + # + resolve_value(value) +
    +
    +
    +
    + +

    Used to resolve a value that could also be a function returning that value

    +

    + + + Parameters: + +
      + + + + + +
    • + + value + + : + + (any) + + the value which you want to test is not nil and if it is a function then call the function + +
    • + + +
    + + + + + Returns: +
      +
    • + (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)
    + + +
    +
    +
    +
    + # + get_actor() +
    +
    +
    +
    + +

    Returns a valid string with the name of the actor of a command.

    +

    + + + + + + Returns: +
      +
    • + (string) + the name of the current actor +
    • +
    + + + + + + + + + +
    +
    +
    +
    + # + cast_bool(var) +
    +
    +
    +
    + +

    Converts a varible into its boolean value, nil and false return false

    +

    + + + Parameters: + +
      + + + + + +
    • + + var + + + + + +
    • + + +
    + + + + + Returns: +
      +
    • + (boolean) + the boolean form of the varible +
    • +
    + + + + + + + + + +
    +
    +
    +
    + # + ternary(c, t, f) +
    +
    +
    +
    + +

    Returns either the second or third argument based on the first argument

    +

    + + + Parameters: + +
      + + + + + +
    • + + c + + + + + +
    • + + + + + +
    • + + t + + + + + +
    • + + + + + +
    • + + f + + + + + +
    • + + +
    + + + + + + + + + + + + + +
    +
    +
    +
    + # + comma_value(n) +
    +
    +
    +
    + +

    Returns a string for a number with comma seperators

    +

    + + + Parameters: + +
      + + + + + +
    • + + n + + : + + (credit http) + + //richard.warburton.it + +
    • + + +
    + + + + + + + + + + + + + +
    +
    +
    +
    + # + set_and_return(tbl, key, value) +
    +
    +
    +
    + +

    Sets a table element to value while also returning value.

    +

    + + + Parameters: + +
      + + + + + +
    • + + tbl + + : + + + table to change the element of + +
    • + + + + + +
    • + + key + + : + + + string + +
    • + + + + + +
    • + + value + + : + + + nil|boolean|number|string|table to set the element to + +
    • + + +
    + + + + + Returns: +
      +
    • + value +
    • +
    + + + + + + +
    @@ -965,14 +1717,14 @@
    - # - ext_require(path, ...) + # + get_file_path([offset=0])
    -

    Calls a require and returns only the keys given, file must return a table

    +

    Returns a desync safe file path for the current file

    @@ -986,29 +1738,71 @@
  • - path + offset : - (string) + (number) - the path that you want to require + the offset in the stack to get, 0 is current file + (default: 0)
  • + + + + + + Returns: +
      +
    • + (string) + the file path +
    • +
    + + + + + + + + + +
    +
    +
    +
    + # + enum(tbl) +
    +
    +
    +
    + +

    Converts a table to an enum

    +

    + + + Parameters: + +
      + +
    • - ... + tbl : - (string) + (table) - the name of the keys that you want returned + table the that will be converted
    • @@ -1021,18 +1815,433 @@ Returns:
      • - the keys in the order given + (table) + the new table that acts like an enum
      + + + + + + +
    +
    +
    +
    + # + auto_complete(options, input[, use_key=false][, rtn_key=false]) +
    +
    +
    +
    + +

    Returns the closest match to the input

    +

    + + + Parameters: + +
      + + + + + +
    • + + options + + : + + (table) + + table a of options for the auto complete + +
    • + + + + + +
    • + + input + + : + + (string) + + string the input that will be completed + +
    • + + + + + +
    • + + use_key + + : + + (boolean) + + when true the keys of options will be used as the options + + (default: false) +
    • + + + + + +
    • + + rtn_key + + : + + (boolean) + + when true the the key will be returned rather than the value + + (default: false) +
    • + + +
    + + + + + Returns: +
      +
    • + the list item found that matches the input +
    • +
    + + + + + + + + + +
    +
    +

    Formating

    +
    +
    +
    +
    + # + format_chat_colour(message, color) +
    +
    +
    +
    + +

    Returns a message with valid chat tags to change its colour

    +

    + + + Parameters: + +
      + + + + + +
    • + + message + + : + + (string) + + the message that will be in the output + +
    • + + + + + +
    • + + color + + : + + (table) + + a color which contains r,g,b as its keys + +
    • + + +
    + + + + + Returns: +
      +
    • + (string) + the message with the color tags included +
    • +
    + + + + + + + + + +
    +
    +
    +
    + # + format_chat_colour_localized(message, color) +
    +
    +
    +
    + +

    Returns a message with valid chat tags to change its colour, using localization

    +

    + + + Parameters: + +
      + + + + + +
    • + + message + + : + + (string or table) + + the message that will be in the output + +
    • + + + + + +
    • + + color + + : + + (table) + + a color which contains r,g,b as its keys + +
    • + + +
    + + + + + Returns: +
      +
    • + (table) + the message with the color tags included +
    • +
    + + + + + + + + + +
    +
    +
    +
    + # + format_chat_player_name(player[, raw_string=false]) +
    +
    +
    +
    + +

    Returns the players name in the players color

    +

    + + + Parameters: + +
      + + + + + +
    • + + player + + : + + (LuaPlayer) + + the player to use the name and color of + +
    • + + + + + +
    • + + raw_string + + : + + (boolean) + + when true a is returned rather than a localized string + + (default: false) +
    • + + +
    + + + + + Returns: +
      +
    • + (table) + the players name with tags for the players color +
    • +
    + + + + + + + + + +
    +
    +
    +
    + # + player_return(value[, colour=defines.colour.white][, player=game.player]) +
    +
    +
    +
    + +

    Will return a value of any type to the player/server console, allows colour for in-game players

    +

    + + + Parameters: + +
      + + + + + +
    • + + value + + : + + + any value of any type that will be returned to the player or console + +
    • + + + + + +
    • + + colour + + : + + (defines.color or string) + + the colour of the text for the player, ignored when printing to console + + (default: defines.colour.white) +
    • + + + + + +
    • + + player + + : + + (LuaPlayer) + + the player that return will go to, if no game.player then returns to server + + (default: game.player) +
    • + + +
    + + + + + + + Usage: -
    local extract, param_check = ext_require('expcore.common','extract','param_check') --- @dep expcore.common
    +
    player_return('Hello, World!') -- returns 'Hello, World!' to game.player or server console
    +
    player_return('Hello, World!','green') -- returns 'Hello, World!' to game.player with colour green or server console
    +
    player_return('Hello, World!',nil,player) -- returns 'Hello, World!' to the given player
    @@ -1113,6 +2322,9 @@ +
    +

    Factorio

    +
    @@ -1592,1144 +2804,6 @@ - -
    -
    -
    - # - string_contains(s, contains) -
    -
    -
    -
    - -

    Tests if a string contains a given substring.

    -

    - - - Parameters: - -
      - - - - - -
    • - - s - - : - - (string) - - the string to check for the substring - -
    • - - - - - -
    • - - contains - - : - - (string) - - the substring to test for - -
    • - - -
    - - - - - Returns: -
      -
    • - (boolean) - true if the substring was found in the string -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - extract_keys(tbl, ...) -
    -
    -
    -
    - -

    Extracts certain keys from a table

    -

    - - - Parameters: - -
      - - - - - -
    • - - tbl - - : - - (table) - - table the which contains the keys - -
    • - - - - - -
    • - - ... - - : - - (string) - - the names of the keys you want extracted - -
    • - - -
    - - - - - Returns: -
      -
    • - the keys in the order given -
    • -
    - - - - - - - - Usage: -
    local key_three, key_one = extract({key_one='foo',key_two='bar',key_three=true},'key_three','key_one')
    - - -
    -
    -
    -
    - # - enum(tbl) -
    -
    -
    -
    - -

    Converts a table to an enum

    -

    - - - Parameters: - -
      - - - - - -
    • - - tbl - - : - - (table) - - table the that will be converted - -
    • - - -
    - - - - - Returns: -
      -
    • - (table) - the new table that acts like an enum -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - auto_complete(options, input[, use_key=false][, rtn_key=false]) -
    -
    -
    -
    - -

    Returns the closest match to the input

    -

    - - - Parameters: - -
      - - - - - -
    • - - options - - : - - (table) - - table a of options for the auto complete - -
    • - - - - - -
    • - - input - - : - - (string) - - string the input that will be completed - -
    • - - - - - -
    • - - use_key - - : - - (boolean) - - when true the keys of options will be used as the options - - (default: false) -
    • - - - - - -
    • - - rtn_key - - : - - (boolean) - - when true the the key will be returned rather than the value - - (default: false) -
    • - - -
    - - - - - Returns: -
      -
    • - the list item found that matches the input -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - table_values(tbl[, sorted][, as_string]) -
    -
    -
    -
    - -

    Returns a copy of all of the values in the table.

    -

    - - - Parameters: - -
      - - - - - -
    • - - tbl - - : - - (table) - - the to copy the keys from, or an empty table if tbl is nil - -
    • - - - - - -
    • - - sorted - - : - - (boolean) - - whether to sort the keys (slower) or keep the random order from pairs() - - (optional) -
    • - - - - - -
    • - - as_string - - : - - (boolean) - - whether to try and parse the values as strings, or leave them as their existing type - - (optional) -
    • - - -
    - - - - - Returns: -
      -
    • - (array) - an array with a copy of all the values in the table -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - table_keys(tbl[, sorted][, as_string]) -
    -
    -
    -
    - -

    Returns a copy of all of the keys in the table.

    -

    - - - Parameters: - -
      - - - - - -
    • - - tbl - - : - - (table) - - the to copy the keys from, or an empty table if tbl is nil - -
    • - - - - - -
    • - - sorted - - : - - (boolean) - - whether to sort the keys (slower) or keep the random order from pairs() - - (optional) -
    • - - - - - -
    • - - as_string - - : - - (boolean) - - whether to try and parse the keys as strings, or leave them as their existing type - - (optional) -
    • - - -
    - - - - - Returns: -
      -
    • - (array) - an array with a copy of all the keys in the table -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - table_alphanumsort(tbl) -
    -
    -
    -
    - -

    Returns the list is a sorted way that would be expected by people (this is by key)

    -

    - - - Parameters: - -
      - - - - - -
    • - - tbl - - : - - (table) - - the table to be sorted - -
    • - - -
    - - - - - Returns: -
      -
    • - (table) - the sorted table -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - table_keysort(tbl) -
    -
    -
    -
    - -

    Returns the list is a sorted way that would be expected by people (this is by key) (faster alternative than above)

    -

    - - - Parameters: - -
      - - - - - -
    • - - tbl - - : - - (table) - - the table to be sorted - -
    • - - -
    - - - - - Returns: -
      -
    • - (table) - the sorted table -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - format_chat_colour(message, color) -
    -
    -
    -
    - -

    Returns a message with valid chat tags to change its colour

    -

    - - - Parameters: - -
      - - - - - -
    • - - message - - : - - (string) - - the message that will be in the output - -
    • - - - - - -
    • - - color - - : - - (table) - - a color which contains r,g,b as its keys - -
    • - - -
    - - - - - Returns: -
      -
    • - (string) - the message with the color tags included -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - format_chat_colour_localized(message, color) -
    -
    -
    -
    - -

    Returns a message with valid chat tags to change its colour, using localization

    -

    - - - Parameters: - -
      - - - - - -
    • - - message - - : - - (string or table) - - the message that will be in the output - -
    • - - - - - -
    • - - color - - : - - (table) - - a color which contains r,g,b as its keys - -
    • - - -
    - - - - - Returns: -
      -
    • - (table) - the message with the color tags included -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - format_chat_player_name(player[, raw_string=false]) -
    -
    -
    -
    - -

    Returns the players name in the players color

    -

    - - - Parameters: - -
      - - - - - -
    • - - player - - : - - (LuaPlayer) - - the player to use the name and color of - -
    • - - - - - -
    • - - raw_string - - : - - (boolean) - - when true a is returned rather than a localized string - - (default: false) -
    • - - -
    - - - - - Returns: -
      -
    • - (table) - the players name with tags for the players color -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - get_file_path([offset=0]) -
    -
    -
    -
    - -

    Returns a desync safe file path for the current file

    -

    - - - Parameters: - -
      - - - - - -
    • - - offset - - : - - (number) - - the offset in the stack to get, 0 is current file - - (default: 0) -
    • - - -
    - - - - - Returns: -
      -
    • - (string) - the file path -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - array_insert(tbl[, start_index], values) -
    -
    -
    -
    - -

    Much faster method for inserting items into an array

    -

    - - - Parameters: - -
      - - - - - -
    • - - tbl - - : - - (table) - - the table that will have the values added to it - -
    • - - - - - -
    • - - start_index - - : - - (number) - - the index at which values will be added, nil means end of the array - - (optional) -
    • - - - - - -
    • - - values - - : - - (table) - - the new values that will be added to the table - -
    • - - -
    - - - - - Returns: -
      -
    • - (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
    - - -
    -
    -
    -
    - # - table_insert(tbl[, start_index], tbl2) -
    -
    -
    -
    - -

    Much faster method for inserting keys into a table

    -

    - - - Parameters: - -
      - - - - - -
    • - - tbl - - : - - (table) - - the table that will have keys added to it - -
    • - - - - - -
    • - - start_index - - : - - (number) - - the index at which values will be added, nil means end of the array, numbered indexs only - - (optional) -
    • - - - - - -
    • - - tbl2 - - : - - (table) - - the table that may contain both string and numbered keys - -
    • - - -
    - - - - - Returns: -
      -
    • - (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)
    - - -
    -
    -
    -
    - # - resolve_value(value) -
    -
    -
    -
    - -

    Used to resolve a value that could also be a function returning that value

    -

    - - - Parameters: - -
      - - - - - -
    • - - value - - : - - (any) - - the value which you want to test is not nil and if it is a function then call the function - -
    • - - -
    - - - - - Returns: -
      -
    • - (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)
    - -
    @@ -2746,7 +2820,7 @@ Common.table_insert(tbl,50,tbl2) generated by LDoc diff --git a/docs/core/Common.html b/docs/core/Common.html new file mode 100644 index 00000000..2adc2dbf --- /dev/null +++ b/docs/core/Common.html @@ -0,0 +1,2759 @@ + + + + + + + + Common core + + + + + + + +
    +
    + + + + + + + +
    + + + + + + + + +

    Common core

    +

    Core Module - Common +- Adds some commonly used functions used in many modules

    +

    + + + + + + + + + + + + + +

    Dependencies

    + + + + + + + + + + + + + +
    utils.color_presets
    utils.game
    util
    + + +

    Type Checking

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    type_check(value[, test_type=nil])Asserts the argument is of type test_type
    type_error(value, test_type, error_message, level)Raises an error if the value is of the wrong type
    multi_type_check(value, test_types)Asserts the argument is one of type test_types
    multi_type_error(value, test_types, error_message, level)Raises an error if the value is of the wrong type
    validate_argument_type(value, test_type, param_number[, param_name])Raises an error when the value is the incorrect type, uses a consistent error message format
    validate_argument_multi_type(value, test_types, param_number[, param_name])Raises an error when the value is the incorrect type, uses a consistent error message format
    error_if_runtime()Will raise an error if called during runtime
    error_if_runetime_closure(func)Will raise an error if the function is a closure
    + + +

    Value Returns

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    string_contains(s, contains)Tests if a string contains a given substring.
    resolve_value(value)Used to resolve a value that could also be a function returning that value
    cast_bool(var)Converts a varible into its boolean value, nil and false return false
    ternary(c, t, f)Returns either the second or third argument based on the first argument
    comma_value(n)Returns a string for a number with comma seperators
    set_and_return(tbl, key, value)Sets a table element to value while also returning value.
    write_json(path, tbl)Writes a table object to a file in json format
    opt_require(path)Calls a require that will not error if the file is not found
    get_file_path([offset=0])Returns a desync safe file path for the current file
    enum(tbl)Converts a table to an enum
    auto_complete(options, input[, use_key=false][, rtn_key=false])Returns the closest match to the input
    + + +

    Formating

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    get_actor(player_name)Returns a valid string with the name of the actor of a command.
    format_chat_colour(message, color)Returns a message with valid chat tags to change its colour
    format_chat_colour_localized(message, color)Returns a message with valid chat tags to change its colour, using localization
    format_chat_player_name(player[, raw_string=false])Returns the players name in the players color
    player_return(value[, colour=defines.colour.white][, player=game.player])Will return a value of any type to the player/server console, allows colour for in-game players
    format_time(ticks, options)Formats tick into a clean format, denominations from highest to lowest +-- time will use : separates +-- when a denomination is false it will overflow into the next one
    + + +

    Factorio

    + + + + + + + + + + + + + + + + +
    move_items(items[, surface=navies][, position={0][, radius=32][, chest_type=iron-chest])Moves items to the position and stores them in the closest entity of the type given
    print_grid_value(value, surface, position[, scale=1][, offset=0][, immutable=false])Prints a colored value on a location, color is based on the value.
    clear_flying_text(surface)Clears all flying text entities on a surface
    + + +
    + + +

    Dependencies

    +
    +
    +
    +
    + # + utils.color_presets +
    +
    +
    +
    + + + + + + + + + + + + + + + +
    +
    +
    +
    + # + utils.game +
    +
    +
    +
    + + + + + + + + + + + + + + + +
    +
    +
    +
    + # + util +
    +
    +
    +
    + + + + + + + + + + + + + + + +
    +
    +

    Type Checking

    +
    +
    +
    +
    + # + type_check(value[, test_type=nil]) +
    +
    +
    +
    + +

    Asserts the argument is of type test_type

    +

    + + + Parameters: + +
      + + + + + +
    • + + value + + : + + (any) + + the value to be tested + +
    • + + + + + +
    • + + test_type + + : + + (string) + + the type to test for if not given then it tests for nil + + (default: nil) +
    • + + +
    + + + + + Returns: +
      +
    • + (boolean) + is v of type test_type +
    • +
    + + + + + + + + Usage: +
    -- Check for a string value
    +local is_string = type_check(value, 'string')
    +
    -- Check for a nil value
    +local is_nil = type_check(value)
    + + +
    +
    +
    +
    + # + type_error(value, test_type, error_message, level) +
    +
    +
    +
    + +

    Raises an error if the value is of the wrong type

    +

    + + + Parameters: + +
      + + + + + +
    • + + value + + : + + (any) + + the value that you want to test the type of + +
    • + + + + + +
    • + + test_type + + : + + (string) + + the type that the value should be + +
    • + + + + + +
    • + + error_message + + : + + (string) + + the error message that is returned + +
    • + + + + + +
    • + + level + + : + + (number) + + the level to call the error on (level = 1 is the caller) + +
    • + + +
    + + + + + Returns: +
      +
    • + (boolean) + true if no error was called +
    • +
    + + + + + + + + Usage: +
    -- Raise error if value is not a number
    +type_error(value, 'number', 'Value must be a number')
    + + +
    +
    +
    +
    + # + multi_type_check(value, test_types) +
    +
    +
    +
    + +

    Asserts the argument is one of type test_types

    +

    + + + Parameters: + +
      + + + + + +
    • + + value + + : + + + the variable to check + +
    • + + + + + +
    • + + test_types + + : + + + the type as a table of strings + +
    • + + +
    + + + + + Returns: +
      +
    • + (boolean) + true if value is one of test_types +
    • +
    + + + + + + + + Usage: +
    -- Check for a string or table
    +local is_string_or_table = multi_type_check(value, {'string','table'})
    + + +
    +
    +
    +
    + # + multi_type_error(value, test_types, error_message, level) +
    +
    +
    +
    + +

    Raises an error if the value is of the wrong type

    +

    + + + Parameters: + +
      + + + + + +
    • + + value + + : + + (any) + + the value that you want to test the type of + +
    • + + + + + +
    • + + test_types + + : + + (table) + + the type as a table of strings + +
    • + + + + + +
    • + + error_message + + : + + (string) + + the error message that is returned + +
    • + + + + + +
    • + + level + + : + + (number) + + the level to call the error on (level = 1 is the caller) + +
    • + + +
    + + + + + Returns: +
      +
    • + (boolean) + true if no error was called +
    • +
    + + + + + + + + Usage: +
    -- Raise error if value is not a string or table
    +multi_type_error('foo', {'string','table'}, 'Value must be a string or table')
    + + +
    +
    +
    +
    + # + validate_argument_type(value, test_type, param_number[, param_name]) +
    +
    +
    +
    + +

    Raises an error when the value is the incorrect type, uses a consistent error message format

    +

    + + + Parameters: + +
      + + + + + +
    • + + value + + : + + (any) + + the value that you want to test the type of + +
    • + + + + + +
    • + + test_type + + : + + (string) + + the type that the value should be + +
    • + + + + + +
    • + + param_number + + : + + (number) + + the number param it is + +
    • + + + + + +
    • + + param_name + + : + + (string) + + the name of the param + + (optional) +
    • + + +
    + + + + + Returns: +
      +
    • + (boolean) + true if no error was raised +
    • +
    + + + + + + + + Usage: +
    -- Output: "Bad argument #2 to "<anon>"; argument is of type string expected number"
    +validate_argument_type(value, 'number', 2)
    +
    -- Output: "Bad argument #2 to "<anon>"; "repeat_count" is of type string expected number"
    +validate_argument_type(value, 'number', 2, 'repeat_count')
    + + +
    +
    +
    +
    + # + validate_argument_multi_type(value, test_types, param_number[, param_name]) +
    +
    +
    +
    + +

    Raises an error when the value is the incorrect type, uses a consistent error message format

    +

    + + + Parameters: + +
      + + + + + +
    • + + value + + : + + (any) + + the value that you want to test the type of + +
    • + + + + + +
    • + + test_types + + : + + (string) + + the types that the value should be + +
    • + + + + + +
    • + + param_number + + : + + (number) + + the number param it is + +
    • + + + + + +
    • + + param_name + + : + + (string) + + the name of the param + + (optional) +
    • + + +
    + + + + + Returns: +
      +
    • + (boolean) + true if no error was raised +
    • +
    + + + + + + + + Usage: +
    -- Output: "Bad argument #2 to "<anon>"; argument is of type number expected string or table"
    +validate_argument_type(value, {'string','table'}, 2)
    +
    -- Output: "Bad argument #2 to "<anon>"; "player" is of type number expected string or table"
    +validate_argument_type(value, {'string','table'}, 2, 'player')
    + + +
    +
    +
    +
    + # + error_if_runtime() +
    +
    +
    +
    + +

    Will raise an error if called during runtime

    +

    + + + + + + + + + + + + + Usage: +
    error_if_runtime()
    + + +
    +
    +
    +
    + # + error_if_runetime_closure(func) +
    +
    +
    +
    + +

    Will raise an error if the function is a closure

    +

    + + + Parameters: + +
      + + + + + +
    • + + func + + + + + +
    • + + +
    + + + + + + + + + + + + Usage: +
    error_if_runetime_closure(func)
    + + +
    +
    +

    Value Returns

    +
    +
    +
    +
    + # + string_contains(s, contains) +
    +
    +
    +
    + +

    Tests if a string contains a given substring.

    +

    + + + Parameters: + +
      + + + + + +
    • + + s + + : + + (string) + + the string to check for the substring + +
    • + + + + + +
    • + + contains + + : + + (string) + + the substring to test for + +
    • + + +
    + + + + + Returns: +
      +
    • + (boolean) + true if the substring was found in the string +
    • +
    + + + + + + + + Usage: +
    -- Test if a string contains a sub string
    +local found = string_contains(str, 'foo')
    + + +
    +
    +
    +
    + # + resolve_value(value) +
    +
    +
    +
    + +

    Used to resolve a value that could also be a function returning that value

    +

    + + + Parameters: + +
      + + + + + +
    • + + value + + : + + (any) + + the value which you want to test is not nil and if it is a function then call the function + +
    • + + +
    + + + + + Returns: +
      +
    • + (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 default value is a function then it is called with the first argument being self
    +local value = Common.resolve_value(self.defaut_value, self)
    + + +
    +
    +
    +
    + # + cast_bool(var) +
    +
    +
    +
    + +

    Converts a varible into its boolean value, nil and false return false

    +

    + + + Parameters: + +
      + + + + + +
    • + + var + + + + + +
    • + + +
    + + + + + Returns: +
      +
    • + (boolean) + the boolean form of the varible +
    • +
    + + + + + + + + Usage: +
    local bool = cast_bool(var)
    + + +
    +
    +
    +
    + # + ternary(c, t, f) +
    +
    +
    +
    + +

    Returns either the second or third argument based on the first argument

    +

    + + + Parameters: + +
      + + + + + +
    • + + c + + + + + +
    • + + + + + +
    • + + t + + + + + +
    • + + + + + +
    • + + f + + + + + +
    • + + +
    + + + + + + + + + + + + Usage: +
    ternary(input_string == 'test', 'Input is test', 'Input is not test')
    + + +
    +
    +
    +
    + # + comma_value(n) +
    +
    +
    +
    + +

    Returns a string for a number with comma seperators

    +

    + + + Parameters: + +
      + + + + + +
    • + + n + + : + + (credit http) + + //richard.warburton.it + +
    • + + +
    + + + + + + + + + + + + Usage: +
    comma_value(input_number)
    + + +
    +
    +
    +
    + # + set_and_return(tbl, key, value) +
    +
    +
    +
    + +

    Sets a table element to value while also returning value.

    +

    + + + Parameters: + +
      + + + + + +
    • + + tbl + + : + + (table) + + to change the element of + +
    • + + + + + +
    • + + key + + : + + (string) + + the key to set the value of + +
    • + + + + + +
    • + + value + + : + + (any) + + the value to set the key as + +
    • + + +
    + + + + + Returns: +
      +
    • + (any) + the value that was set +
    • +
    + + + + + + + + Usage: +
    -- Set and return value
    +local value = set_and_return(players, player.name, player.online_time)
    + + +
    +
    +
    +
    + # + write_json(path, tbl) +
    +
    +
    +
    + +

    Writes a table object to a file in json format

    +

    + + + Parameters: + +
      + + + + + +
    • + + path + + : + + (string) + + the path of the file to write include / to use dir + +
    • + + + + + +
    • + + tbl + + : + + (table) + + the table that will be converted to a json string and wrote to file + +
    • + + +
    + + + + + + + + + + + + Usage: +
    -- Write a lua table as a json to script-outpt/dump
    +write_json('dump', tbl)
    + + +
    +
    +
    +
    + # + opt_require(path) +
    +
    +
    +
    + +

    Calls a require that will not error if the file is not found

    +

    + + + Parameters: + +
      + + + + + +
    • + + path + + : + + (string) + + the path that you want to require + +
    • + + +
    + + + + + Returns: +
      +
    • + the returns from that file or nil, error if not loaded +
    • +
    + + + + + + + + Usage: +
    local file = opt_require('file.not.present') -- will not cause any error
    +
    -- Require a file without causing errors, for when a file might not exist
    +local Module = opt_require 'expcore.common'
    + + +
    +
    +
    +
    + # + get_file_path([offset=0]) +
    +
    +
    +
    + +

    Returns a desync safe file path for the current file

    +

    + + + Parameters: + +
      + + + + + +
    • + + offset + + : + + (number) + + the offset in the stack to get, 0 is current file + + (default: 0) +
    • + + +
    + + + + + Returns: +
      +
    • + (string) + the file path +
    • +
    + + + + + + + + Usage: +
    -- Get the current file path
    +local file_path = get_file_path()
    + + +
    +
    +
    +
    + # + enum(tbl) +
    +
    +
    +
    + +

    Converts a table to an enum

    +

    + + + Parameters: + +
      + + + + + +
    • + + tbl + + : + + (table) + + table the that will be converted + +
    • + + +
    + + + + + Returns: +
      +
    • + (table) + the new table that acts like an enum +
    • +
    + + + + + + + + Usage: +
    -- Make an enum
    +local colors = enum{
    +    'red',
    +    'green',
    +    'blue'
    +}
    + + +
    +
    +
    +
    + # + auto_complete(options, input[, use_key=false][, rtn_key=false]) +
    +
    +
    +
    + +

    Returns the closest match to the input

    +

    + + + Parameters: + +
      + + + + + +
    • + + options + + : + + (table) + + table a of options for the auto complete + +
    • + + + + + +
    • + + input + + : + + (string) + + string the input that will be completed + +
    • + + + + + +
    • + + use_key + + : + + (boolean) + + when true the keys of options will be used as the options + + (default: false) +
    • + + + + + +
    • + + rtn_key + + : + + (boolean) + + when true the the key will be returned rather than the value + + (default: false) +
    • + + +
    + + + + + Returns: +
      +
    • + the list item found that matches the input +
    • +
    + + + + + + + + Usage: +
    -- Get the element that includes "foo"
    +local value = auto_complete(tbl, "foo")
    +
    -- Get the element with a key that includes "foo"
    +local value = auto_complete(tbl, "foo", true)
    +
    -- Get the key with that includes "foo"
    +local key = auto_complete(tbl, "foo", true, true)
    + + +
    +
    +

    Formating

    +
    +
    +
    +
    + # + get_actor(player_name) +
    +
    +
    +
    + +

    Returns a valid string with the name of the actor of a command.

    +

    + + + Parameters: + +
      + + + + + +
    • + + player_name + + : + + (string) + + the name of the player to use rather than server, used only if game.player is nil + +
    • + + +
    + + + + + Returns: +
      +
    • + (string) + the name of the current actor +
    • +
    + + + + + + + + Usage: +
    -- Get the current actor
    +local player_name = get_actor()
    + + +
    +
    +
    +
    + # + format_chat_colour(message, color) +
    +
    +
    +
    + +

    Returns a message with valid chat tags to change its colour

    +

    + + + Parameters: + +
      + + + + + +
    • + + message + + : + + (string) + + the message that will be in the output + +
    • + + + + + +
    • + + color + + : + + (table) + + a color which contains r,g,b as its keys + +
    • + + +
    + + + + + Returns: +
      +
    • + (string) + the message with the color tags included +
    • +
    + + + + + + + + Usage: +
    -- Use factorio tags to color a chat message
    +local message = format_chat_colour('Hello, World!', { r=355, g=100, b=100 })
    + + +
    +
    +
    +
    + # + format_chat_colour_localized(message, color) +
    +
    +
    +
    + +

    Returns a message with valid chat tags to change its colour, using localization

    +

    + + + Parameters: + +
      + + + + + +
    • + + message + + : + + (string or table) + + the message that will be in the output + +
    • + + + + + +
    • + + color + + : + + (table) + + a color which contains r,g,b as its keys + +
    • + + +
    + + + + + Returns: +
      +
    • + (table) + the message with the color tags included +
    • +
    + + + + + + + + Usage: +
    -- Use factorio tags and locale strings to color a chat message
    +local message = format_chat_colour_localized('Hello, World!', { r=355, g=100, b=100 })
    + + +
    +
    +
    +
    + # + format_chat_player_name(player[, raw_string=false]) +
    +
    +
    +
    + +

    Returns the players name in the players color

    +

    + + + Parameters: + +
      + + + + + +
    • + + player + + : + + (LuaPlayer) + + the player to use the name and color of + +
    • + + + + + +
    • + + raw_string + + : + + (boolean) + + when true a string is returned rather than a localized string + + (default: false) +
    • + + +
    + + + + + Returns: +
      +
    • + (table) + the players name with tags for the players color +
    • +
    + + + + + + + + Usage: +
    -- Format a players name using the players color as a string
    +local message = format_chat_player_name(game.player, true)
    + + +
    +
    +
    +
    + # + player_return(value[, colour=defines.colour.white][, player=game.player]) +
    +
    +
    +
    + +

    Will return a value of any type to the player/server console, allows colour for in-game players

    +

    + + + Parameters: + +
      + + + + + +
    • + + value + + : + + (any) + + a value of any type that will be returned to the player or console + +
    • + + + + + +
    • + + colour + + : + + (defines.color or string) + + the colour of the text for the player, ignored when printing to console + + (default: defines.colour.white) +
    • + + + + + +
    • + + player + + : + + (LuaPlayer) + + the player that return will go to, if no game.player then returns to server + + (default: game.player) +
    • + + +
    + + + + + + + + + + + + Usage: +
    -- Return a value to the current actor, rcon included
    +player_return('Hello, World!')
    +
    -- Return a value to the current actor, with color
    +player_return('Hello, World!', 'green')
    +
    -- Return to a player other than the current
    +player_return('Hello, World!', nil, player)
    + + +
    +
    +
    +
    + # + format_time(ticks, options) +
    +
    +
    +
    + +

    Formats tick into a clean format, denominations from highest to lowest +-- time will use : separates +-- when a denomination is false it will overflow into the next one

    +

    + + + Parameters: + +
      + + + + + +
    • + + ticks + + : + + (number) + + the number of ticks that represents a time + +
    • + + + + + +
    • + + options + + : + + (table) + + table a of options to use for the format + +
    • + + +
    + + + + + Returns: +
      +
    • + (string) + a locale string that can be used +
    • +
    + + + + + + + + Usage: +
    -- Output: "0h 5m"
    +local time = format_time(18000, { hours=true, minutes=true, string=true })
    +
    -- Output: "0 hours and 5 minutes"
    +local time = format_time(18000, { hours=true, minutes=true, string=true, long=true })
    +
    -- Output: "00:05:00"
    +local time = format_time(18000, { hours=true, minutes=true, seconds=true, string=true })
    +
    -- Output: "--:--:--"
    +local time = format_time(18000, { hours=true, minutes=true, seconds=true, string=true, null=true })
    + + +
    +
    +

    Factorio

    +
    +
    +
    +
    + # + move_items(items[, surface=navies][, position={0][, radius=32][, chest_type=iron-chest]) +
    +
    +
    +
    + +

    Moves items to the position and stores them in the closest entity of the type given

    +

    + + + Parameters: + +
      + + + + + +
    • + + items + + : + + (table) + + items which are to be added to the chests, ['name']=count + +
    • + + + + + +
    • + + surface + + : + + (LuaSurface) + + the surface that the items will be moved to + + (default: navies) +
    • + + + + + +
    • + + position + + : + + (table) + + the position that the items will be moved to {x=100,y=100} + + (default: {0) +
    • + + + + + +
    • + + radius + + : + + (number) + + the radius in which the items are allowed to be placed + + (default: 32) +
    • + + + + + +
    • + + chest_type + + : + + (string) + + the chest type that the items should be moved into + + (default: iron-chest) +
    • + + +
    + + + + + Returns: +
      +
    • + (LuaEntity) + the last chest that had items inserted into it +
    • +
    + + + + + + + + Usage: +
    -- Copy all the items in a players inventory and place them in chests at {0,0}
    +move_items(game.player.get_main_inventory().get_contents())
    + + +
    +
    +
    +
    + # + print_grid_value(value, surface, position[, scale=1][, offset=0][, immutable=false]) +
    +
    +
    +
    + +

    Prints a colored value on a location, color is based on the value.

    +

    +nb: src is below but the gradent has been edited +https://github.com/Refactorio/RedMew/blob/9184b2940f311d8c9c891e83429fc57ec7e0c4a2/map_gen/maps/diggy/debug.lua#L31

    + + + Parameters: + +
      + + + + + +
    • + + value + + : + + (number) + + the value to show must be between -1 and 1, scale can be used to achive this + +
    • + + + + + +
    • + + surface + + : + + (LuaSurface) + + the surface to palce the value on + +
    • + + + + + +
    • + + position + + : + + (table) + + {x, y} the possition to palce the value at + +
    • + + + + + +
    • + + scale + + : + + (number) + + how much to scale the colours by + + (default: 1) +
    • + + + + + +
    • + + offset + + : + + (number) + + the offset in the +x +y direction + + (default: 0) +
    • + + + + + +
    • + + immutable + + : + + (boolean) + + if immutable, only set, never do a surface lookup, values never change + + (default: false) +
    • + + +
    + + + + + + + + + + + + Usage: +
    -- Place a 0 at {0,0}
    +print_grid_value(0, game.player.surface, { x=0, y=0 })
    + + +
    +
    +
    +
    + # + clear_flying_text(surface) +
    +
    +
    +
    + +

    Clears all flying text entities on a surface

    +

    + + + Parameters: + +
      + + + + + +
    • + + surface + + : + + (LuaSurface) + + the surface to clear + +
    • + + +
    + + + + + + + + + + + + Usage: +
    -- Remove all flying text on the surface
    +clear_flying_text(game.player.surface)
    + + +
    +
    + + + +
    +
    +
    + + + + diff --git a/docs/core/Groups.html b/docs/core/Groups.html new file mode 100644 index 00000000..fcf6fcc9 --- /dev/null +++ b/docs/core/Groups.html @@ -0,0 +1,1435 @@ + + + + + + + + Groups core + + + + + + + +
    +
    + + + + + + + +
    + + + + + + + + +

    Groups core

    +

    Core Module - Permission Groups +- Permission group making for factorio so you never have to make one by hand again

    +

    + + + + + + +

    Usage

    +
    --- Example Group (Allow All)
    +-- here we will create an admin group however we do not want them to use the map editor or mess with the permission groups
    +Permission_Groups.new_group('Admin') -- this defines a new group called "Admin"
    +:allow_all() -- this makes the default to allow any input action unless set other wise
    +:disallow{ -- here we disallow the input action we don't want them to use
    +    'add_permission_group',
    +    'delete_permission_group',
    +    'import_permissions_string',
    +    'map_editor_action',
    +    'toggle_map_editor'
    +}
    +
    --- Example Group (Disallow All)
    +-- here we will create a group that cant do anything but talk in chat
    +Permission_Groups.new_group('Restricted') -- this defines a new group called "Restricted"
    +:disallow_all() -- this makes the default to disallow any input action unless set other wise
    +:allow('write_to_console') -- here we allow them to chat, {} can be used here if we had more than one action
    +
    + + + + + + + +

    Dependencies

    + + + + + + + + + + + + + +
    utils.game
    utils.event
    expcore.async
    + + +

    Getters

    + + + + + + + + + + + + + + + + +
    new_group(name)Defines a new permission group that can have it actions set in the config
    get_group_by_name(name)Returns the group with the given name, case sensitive
    get_group_from_player(player)Returns the group that a player is in
    + + +

    Setters

    + + + + + + + + + + + + +
    reload_permissions()Reloads/creates all permission groups and sets them to they configured state
    set_player_group(player, group)Sets a player's group to the one given, a player can only have one group at a time
    + + +

    Actions

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Permissions_Groups._prototype:set_action(action, state)Sets the allow state of an action for this group, used internally but is safe to use else where
    Permissions_Groups._prototype:allow(actions)Sets an action or actions to be allowed for this group even with disallow_all triggered, Do not use in runtime
    Permissions_Groups._prototype:disallow(actions)Sets an action or actions to be disallowed for this group even with allow_all triggered, Do not use in runtime
    Permissions_Groups._prototype:allow_all()Sets the default state for any actions not given to be allowed, useful with :disallow
    Permissions_Groups._prototype:disallow_all()Sets the default state for any action not given to be disallowed, useful with :allow
    Permissions_Groups._prototype:is_allowed(action)Returns if an input action is allowed for this group
    + + +

    Players

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Permissions_Groups._prototype:create()Creates or updates the permission group with the configured actions, used internally
    Permissions_Groups._prototype:get_raw()Returns the LuaPermissionGroup that was created with this group object, used internally
    Permissions_Groups._prototype:add_player(player)Adds a player to this group
    Permissions_Groups._prototype:remove_player(player)Removes a player from this group
    Permissions_Groups._prototype:get_players([online])Returns all player that are in this group with the option to filter to online/offline only
    Permissions_Groups._prototype:print(message)Prints a message to every player in this group
    + + +
    + + +

    Dependencies

    +
    +
    +
    +
    + # + utils.game +
    +
    +
    +
    + + + + + + + + + + + + + + + +
    +
    +
    +
    + # + utils.event +
    +
    +
    +
    + + + + + + + + + + + + + + + +
    +
    +
    +
    + # + expcore.async +
    +
    +
    +
    + + + + + + + + + + + + + + + +
    +
    +

    Getters

    +
    +
    +
    +
    + # + new_group(name) +
    +
    +
    +
    + +

    Defines a new permission group that can have it actions set in the config

    +

    + + + Parameters: + +
      + + + + + +
    • + + name + + : + + (string) + + the name of the new group + +
    • + + +
    + + + + + Returns: +
      +
    • + (Permissions_Groups._prototype) + the new group made with function to allow and disallow actions +
    • +
    + + + + + + + + Usage: +
    -- Defining a new permission group
    +Groups.new_group('Admin')
    + + +
    +
    +
    +
    + # + get_group_by_name(name) +
    +
    +
    +
    + +

    Returns the group with the given name, case sensitive

    +

    + + + Parameters: + +
      + + + + + +
    • + + name + + : + + (string) + + the name of the group to get + +
    • + + +
    + + + + + Returns: +
      +
    • + (Permissions_Groups._prototype or nil) + the group with that name or nil if non found +
    • +
    + + + + + + + + Usage: +
    -- Getting a permision group
    +local admin_group = Groups.get_group_by_name('Admin')
    + + +
    +
    +
    +
    + # + get_group_from_player(player) +
    +
    +
    +
    + +

    Returns the group that a player is in

    +

    + + + Parameters: + +
      + + + + + +
    • + + player + + : + + (LuaPlayer) + + the player to get the group of can be name index etc + +
    • + + +
    + + + + + Returns: +
      +
    • + (Permissions_Groups._prototype or nil) + the group with that player or nil if non found +
    • +
    + + + + + + + + Usage: +
    -- Get your permission group
    +local group = Groups.get_group_from_player(game.player)
    + + +
    +
    +

    Setters

    +
    +
    +
    +
    + # + reload_permissions() +
    +
    +
    +
    + +

    Reloads/creates all permission groups and sets them to they configured state

    +

    + + + + + + + + + + + + + Usage: +
    -- Reload the permission groups, used internally
    +Groups.reload_permissions()
    + + +
    +
    +
    +
    + # + set_player_group(player, group) +
    +
    +
    +
    + +

    Sets a player's group to the one given, a player can only have one group at a time

    +

    + + + Parameters: + +
      + + + + + +
    • + + player + + : + + (LuaPlayer) + + the player to effect can be name index etc + +
    • + + + + + +
    • + + group + + : + + (string) + + the name of the group to give to the player + +
    • + + +
    + + + + + Returns: +
      +
    • + (boolean) + true if the player was added successfully, false other wise +
    • +
    + + + + + + + + Usage: +
    -- Set your permission group
    +Groups.set_player_group(game.player, 'Admin')
    + + +
    +
    +

    Actions

    +
    +
    +
    +
    + # + Permissions_Groups._prototype:set_action(action, state) +
    +
    +
    +
    + +

    Sets the allow state of an action for this group, used internally but is safe to use else where

    +

    + + + Parameters: + +
      + + + + + +
    • + + action + + : + + (string or defines.input_action) + + the action that you want to set the state of + +
    • + + + + + +
    • + + state + + : + + (boolean) + + the state that you want to set it to, true = allow, false = disallow + +
    • + + +
    + + + + + Returns: +
      +
    • + (Permissions_Groups._prototype) + returns self so function can be chained +
    • +
    + + + + + + + + Usage: +
    -- Set an action to be disalowed
    +group:set_action('toggle_map_editor', false)
    + + +
    +
    +
    +
    + # + Permissions_Groups._prototype:allow(actions) +
    +
    +
    +
    + +

    Sets an action or actions to be allowed for this group even with disallow_all triggered, Do not use in runtime

    +

    + + + Parameters: + +
      + + + + + +
    • + + actions + + : + + (string or Array) + + the action or actions that you want to allow for this group + +
    • + + +
    + + + + + Returns: +
      +
    • + (Permissions_Groups._prototype) + returns self so function can be chained +
    • +
    + + + + + + + + Usage: +
    -- Allow some actions
    +group:allow{
    +    'write_to_console'
    +}
    + + +
    +
    +
    +
    + # + Permissions_Groups._prototype:disallow(actions) +
    +
    +
    +
    + +

    Sets an action or actions to be disallowed for this group even with allow_all triggered, Do not use in runtime

    +

    + + + Parameters: + +
      + + + + + +
    • + + actions + + : + + (string or Array) + + the action or actions that you want to disallow for this group + +
    • + + +
    + + + + + Returns: +
      +
    • + (Permissions_Groups._prototype) + returns self so function can be chained +
    • +
    + + + + + + + + Usage: +
    -- Disalow some actions
    +group:disallow{
    +    'add_permission_group',
    +    'delete_permission_group',
    +    'import_permissions_string',
    +    'map_editor_action',
    +    'toggle_map_editor'
    +}
    + + +
    +
    +
    +
    + # + Permissions_Groups._prototype:allow_all() +
    +
    +
    +
    + +

    Sets the default state for any actions not given to be allowed, useful with :disallow

    +

    + + + + + + Returns: +
      +
    • + (Permissions_Groups._prototype) + returns self so function can be chained +
    • +
    + + + + + + + + Usage: +
    -- Allow all actions unless given by disallow
    +group:allow_all()
    + + +
    +
    +
    +
    + # + Permissions_Groups._prototype:disallow_all() +
    +
    +
    +
    + +

    Sets the default state for any action not given to be disallowed, useful with :allow

    +

    + + + + + + Returns: +
      +
    • + (Permissions_Groups._prototype) + returns self so function can be chained +
    • +
    + + + + + + + + Usage: +
    -- Disallow all actions unless given by allow
    +group:disallow_all()
    + + +
    +
    +
    +
    + # + Permissions_Groups._prototype:is_allowed(action) +
    +
    +
    +
    + +

    Returns if an input action is allowed for this group

    +

    + + + Parameters: + + + + + + + Returns: +
      +
    • + (boolean) + true if the group is allowed the action, false other wise +
    • +
    + + + + + + + + Usage: +
    -- Test if a group is allowed an action
    +local allowed = group:is_allowed('write_to_console')
    + + +
    +
    +

    Players

    +
    +
    +
    +
    + # + Permissions_Groups._prototype:create() +
    +
    +
    +
    + +

    Creates or updates the permission group with the configured actions, used internally

    +

    + + + + + + Returns: + + + + + + + + + Usage: +
    -- Create the permission group so players can be added, used internally
    +group:create()
    + + +
    +
    +
    +
    + # + Permissions_Groups._prototype:get_raw() +
    +
    +
    +
    + +

    Returns the LuaPermissionGroup that was created with this group object, used internally

    +

    + + + + + + Returns: + + + + + + + + + Usage: +
    -- Get the factorio api permision group, used internally
    +local permission_group = group:get_raw()
    + + +
    +
    +
    +
    + # + Permissions_Groups._prototype:add_player(player) +
    +
    +
    +
    + +

    Adds a player to this group

    +

    + + + Parameters: + +
      + + + + + +
    • + + player + + : + + (LuaPlayer) + + LuaPlayer the player you want to add to this group can be name or index etc + +
    • + + +
    + + + + + Returns: +
      +
    • + (boolean) + true if the player was added successfully, false other wise +
    • +
    + + + + + + + + Usage: +
    -- Add a player to this permission group
    +group:add_player(game.player)
    + + +
    +
    +
    +
    + # + Permissions_Groups._prototype:remove_player(player) +
    +
    +
    +
    + +

    Removes a player from this group

    +

    + + + Parameters: + +
      + + + + + +
    • + + player + + : + + (LuaPlayer) + + LuaPlayer the player you want to remove from this group can be name or index etc + +
    • + + +
    + + + + + Returns: +
      +
    • + (boolean) + true if the player was removed successfully, false other wise +
    • +
    + + + + + + + + Usage: +
    -- Remove a player from this permission group
    +group:remove_player(game.player)
    + + +
    +
    +
    +
    + # + Permissions_Groups._prototype:get_players([online]) +
    +
    +
    +
    + +

    Returns all player that are in this group with the option to filter to online/offline only

    +

    + + + Parameters: + +
      + + + + + +
    • + + online + + : + + (boolean) + + if nil returns all players, if true online players only, if false returns online players only + + (optional) +
    • + + +
    + + + + + Returns: +
      +
    • + (table) + a table of players that are in this group; filtered if online param is given +
    • +
    + + + + + + + + Usage: +
    -- Get all players in this group
    +local online_players = group:get_players()
    +
    -- Get all online players in this group
    +local online_players = group:get_players(true)
    + + +
    +
    +
    +
    + # + Permissions_Groups._prototype:print(message) +
    +
    +
    +
    + +

    Prints a message to every player in this group

    +

    + + + Parameters: + +
      + + + + + +
    • + + message + + : + + (string) + + the message that you want to send to the players + +
    • + + +
    + + + + + Returns: +
      +
    • + (number) + the number of players that received the message +
    • +
    + + + + + + + + Usage: +
    -- Print a message to all players in thie group
    +group:print('Hello, World!')
    + + +
    +
    + + + +
    +
    +
    + + + + diff --git a/docs/core/Gui.html b/docs/core/Gui.html index 09dee1fe..e9480d3c 100644 --- a/docs/core/Gui.html +++ b/docs/core/Gui.html @@ -29,7 +29,7 @@

    ExpGaming Scenario

    -

    Explosive Gaming's server scenario for 0.17

    +

    Explosive Gaming's server scenario for 0.18

    @@ -42,21 +42,15 @@

    Sections

    @@ -64,13 +58,13 @@ @@ -99,10 +93,12 @@ + + @@ -111,8 +107,10 @@

    Guis

    @@ -150,7 +148,6 @@

    Configs

    @@ -183,18 +181,13 @@

    Modules

    @@ -217,21 +210,15 @@

    Jump to Section

    @@ -252,10 +239,7 @@

    Gui core

    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 - - please read the files for more documentation that cant be shown here - - please note there is a rework planned but not started

    +- Used to simplify gui creation using factory functions called element defines

    @@ -263,6 +247,115 @@ +

    Usage

    +
    -- To draw your element you only need to call the factory function
    +-- You are able to pass any other arguments that are used in your custom functions but the first is always the parent element
    +local example_button_element = example_button(parent_element)
    +
    -- Making a factory function for a button with the caption "Example Button"
    +-- This method has all the same features as LuaGuiElement.add
    +local example_button =
    +Gui.element{
    +    type = 'button',
    +    caption = 'Example Button'
    +}
    +
    -- Making a factory function for a button which is contained within a flow
    +-- This method is for when you still want to register event handlers but cant use the table method
    +local example_flow_with_button =
    +Gui.element(function(event_trigger,parent,...)
    +    -- ... shows that all other arguments from the factory call are passed to this function
    +    -- Here we are adding a flow which we will then later add a button to
    +    local flow =
    +    parent.add{ -- paraent is the element which is passed to the factory function
    +        name = 'example_flow',
    +        type = 'flow'
    +    }
    +
    +    -- Now we add the button to the flow that we created earlier
    +    local element =
    +    flow.add{
    +        name = event_trigger, -- event_trigger should be the name of any elements you want to trigger your event handlers
    +        type = 'button',
    +        caption = 'Example Button'
    +    }
    +
    +    -- You must return a new element, this is so styles can be applied and returned to the caller
    +    -- You may return any of your elements that you added, consider the context in which it will be used for which should be returned
    +    return element
    +end)
    +
    -- Styles can be added to any element define, simplest way mimics LuaGuiElement.style[key] = value
    +local example_button =
    +Gui.element{
    +    type = 'button',
    +    caption = 'Example Button',
    +    style = 'forward_button' -- factorio styles can be applied here
    +}
    +:style{
    +    height = 25, -- same as element.style.height = 25
    +    width = 100 -- same as element.style.width = 25
    +}
    +
    -- Styles can also have a custom function when the style is dynamic and depends on other factors
    +-- Use this method if your style is dynamic and depends on other factors
    +local example_button =
    +Gui.element{
    +    type = 'button',
    +    caption = 'Example Button',
    +    style = 'forward_button' -- factorio styles can be applied here
    +}
    +:style(function(style,element,...)
    +    -- style is the current style object for the elemenent
    +    -- element is the element that is being changed
    +    -- ... shows that all other arguments from the factory call are passed to this function
    +    local player = game.players[element.player_index]
    +    style.height = 25
    +    style.width = 100
    +    style.font_color = player.color
    +end)
    +
    -- You are able to register event handlers to your elements, these can be factorio events or custom ones
    +-- All events are checked to be valid before raising any handlers, this means element.valid = true and player.valid = true
    +Gui.element{
    +    type = 'button',
    +    caption = 'Example Button'
    +}
    +:on_click(function(player,element,event)
    +    -- player is the player who interacted with the element to cause the event
    +    -- element is a refrence to the element which caused the event
    +    -- event is a raw refrence to the event data if player and element are not enough
    +    player.print('Clicked: '..element.name)
    +end)
    +
    -- Example from core_defines, Gui.core_defines.hide_left_flow, called like: hide_left_flow(parent_element)
    +--- Button which hides the elements in the left flow, shows inside the left flow when frames are visible
    +-- @element hide_left_flow
    +local hide_left_flow =
    +Gui.element{
    +    type = 'sprite-button',
    +    sprite = 'utility/close_black',
    +    style = 'tool_button',
    +    tooltip = {'expcore-gui.left-button-tooltip'}
    +}
    +:style{
    +    padding = -3,
    +    width = 18,
    +    height = 20
    +}
    +:on_click(function(player,_,_)
    +    Gui.hide_left_flow(player)
    +end)
    +
    -- Eample from defines, Gui.alignment, called like: Gui.alignment(parent, name, horizontal_align, vertical_align)
    +-- Notice how _ are used to blank arguments that are not needed in that context and how they line up with above
    +Gui.alignment =
    +Gui.element(function(_,parent,name,_,_)
    +    return parent.add{
    +        name = name or 'alignment',
    +        type = 'flow',
    +    }
    +end)
    +:style(function(style,_,_,horizontal_align,vertical_align)
    +    style.padding = {1,2}
    +    style.vertical_align = vertical_align or 'center'
    +    style.horizontal_align = horizontal_align or 'right'
    +    style.vertically_stretchable  = style.vertical_align ~= 'center'
    +    style.horizontally_stretchable = style.horizontal_align ~= 'center'
    +end)
    @@ -275,840 +368,318 @@ - 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 - - - - - -

    Center Guis

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    expcore.gui.core
    expcore.gui.prototype
    expcore.gui.concepts.toolbar
    utils.game
    CenterFrames.get_flow(player)Gets the center flow for a player
    CenterFrames.clear_flow(player)Clears the center flow for a player
    CenterFrames.draw_frame(player, name)Draws the center frame for a player, if already open then will do nothing
    CenterFrames.redraw_frame(player, name)Draws the center frame for a player, if already open then will destroy it and redraw
    CenterFrames.toggle_frame(player, name[, state])Toggles if the frame is currently open or not, will open if closed and close if open
    CenterFrames.new_frame(permission_name)Creates a new center frame define
    CenterFrames._prototype:set_auto_focus([state=true])Sets the frame to be the current active gui when opened and closes all other frames
    CenterFrames._prototype:draw_frame(player)Draws this frame to the player, if already open does nothing (will call on_draw to draw to the frame)
    CenterFrames._prototype:redraw_frame(player)Draws this frame to the player, if already open it will remove it and redraw it (will call on_draw to draw to the frame)
    CenterFrames._prototype:toggle_frame(player)Toggles if the frame is open, if open it will close it and if closed it will open it
    CenterFrames._prototype:event_handler([action=update])Creates an event handler that will trigger one of its functions, use with Event.add
    - - -

    Left Guis

    - - - - - - - - - - - - - - + + +
    expcore.gui.core
    expcore.gui.prototype
    expcore.gui.concepts.toolbar
    expcore.gui.elements.buttonsutils.event
    mod-gui
    + + +

    Tables

    + + + - + + - + + - - + + - - + + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +
    utils.gameeventsString indexed table used to avoid conflict with custom event names, similar to how defines.events works
    utils.eventdefinesUid indexed array that stores all the factory functions that were defined, no new values will be added during runtime
    LeftFrames.get_flow(player)Gets the left frame flow for a playercore_definesAn string indexed table of all the defines which are used by the core of the gui system, used for internal refrence
    LeftFrames.get_frame(name, player)Gets one frame from the left flow by its namefile_pathsUsed to store the file names where elements were defined, this can be useful to find the uid of an element, mostly for debuging
    LeftFrames.get_open(player)Gets all open frames for a player, if non are open it will remove the close all buttondebug_infoUsed to store extra infomation about elements as they get defined such as the params used and event handlers registered to them
    LeftFrames.toggle_frame(name, player[, state])Toggles the visibility of a left frame, or sets its visibility state_prototype_elementThe prototype used to store the functions of an element define
    LeftFrames.new_frame(permission_name)Creates a new left frame define
    LeftFrames._prototype:set_open_by_default([state=true])Sets if the frame is visible when a player joins, can also be a function to return a boolean
    LeftFrames._prototype:set_direction(direction)Sets the direction of the frame, either vertical or horizontal
    LeftFrames._prototype:_internal_draw(player)Creates the gui for the first time, used internally
    LeftFrames._prototype:get_frame(player)Gets the frame for this define from the left frame flow
    LeftFrames._prototype:is_open(player)Returns if the player currently has this define visible
    LeftFrames._prototype:toggle(player)Toggles the visibility of the left frame
    LeftFrames._prototype:update(player)Updates the contents of the left frame, first tries update callback, other wise will clear and redraw
    LeftFrames._prototype:update_all([update_offline=false])Updates the frame for all players, see update
    LeftFrames._prototype:redraw(player)Redraws the frame by calling on_draw, will always clear the frame
    LeftFrames._prototype:redraw_all([update_offline=false])Redraws the frame for all players, see redraw
    LeftFrames._prototype:event_handler([action=update])Creates an event handler that will trigger one of its functions, use with Event.add_mt_elementThe prototype metatable applied to new element defines
    -

    Popups

    +

    Fields

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +
    expcore.gui.core
    expcore.gui.prototype
    utils.game
    utils.event
    expcore.gui.elements.progress-bar
    expcore.gui.elements.buttons
    mod-gui
    resources.color_presets
    utils.global
    PopupFrames.get_flow(player)Gets the left flow that contains the popup frames
    PopupFrames.open(define_name, player[, open_time], ...)Opens a popup for the player, can give the amount of time it is open as well as params for the draw function
    PopupFrames.close_progressProgress bar which when depleted will close the popup frame
    PopupFrames.close_buttonA button which can be used to close the gui before the timer runs out
    PopupFrames.new_popup([name])Creates a new popup frame define
    PopupFrames._prototype:set_default_open_time(amount)Sets the default open time for the popup, will be used if non is provided with open
    PopupFrames._prototype:open(player[, open_time], ...)Opens this define for a player, can be given open time and any other params for the draw functionuidThe current highest uid that is being used by a define, will not increase during runtime
    -

    Toolbar

    +

    Core Defines

    - + + - + + - - - - - - - - - - - - - - - - - - - - - - + +
    expcore.gui.corehide_top_flowButton which toggles the top flow elements, version which shows inside the top flow when top flow is visible
    expcore.gui.elements.buttonsshow_top_flowButton which toggles the top flow elements, version which shows inside the left flow when top flow is hidden
    expcore.roles
    utils.event
    utils.game
    mod-gui
    Toolbar.new_button([name])Adds a new button to the toolbar
    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 returnhide_left_flowButton which hides the elements in the left flow, shows inside the left flow when frames are visible
    -

    Core

    +

    Defines

    - + + - + + - - + + - - + + - - + + - - + + - - + + - - + + + + +
    utils.guialignmentDraw a flow used to align its child elements, default is right align
    utils.gamescroll_tableDraw a scroll pane that has a table inside of it
    new_define(prototype[, debug_name])Used to create new element defines from a class prototype, please use the own given by the classheaderUsed to add a frame with the header style, has the option for a right alignment flow for buttons
    get_define(name[, internal])Gets an element define give the uid, debug name or a copy of the element definefooterUsed to add a frame with the footer style, has the option for a right alignment flow for buttons
    categorize_by_player(element)A categorize function to be used with add_store, each player has their own valuecontainerUsed for left frames to give them a nice boarder
    categorize_by_force(element)A categorize function to be used with add_store, each force has its own valuebarUsed to make a solid white bar in a gui
    categorize_by_surface(element)A categorize function to be used with add_store, each surface has its own valuecentered_labelUsed to make a label which is centered and of a certian size
    draw(name, element)Draws a copy of the element define to the parent element, see draw_totitle_labelUsed to make a title which has two bars on either side
    + + +

    Helper Functions

    + + + + + + - - + + - - - - - - - - - - - - - - + + - + - - - - - - + +
    get_player_from_element(element)Get the player that owns a gui element
    toggle_enabled(element)Will toggle the enabled state of an elementtoggle_enabled_state(element[, state])Will toggle the enabled state of an element or set it to the one given
    toggle_visible(element)Will toggle the visiblity of an element
    set_padding(element[, up=0][, down=0][, left=0][, right=0])Sets the padding for a gui element
    set_padding_style(style[, up=0][, down=0][, left=0][, right=0])Sets the padding for a gui style
    create_alignment(element[, name][, horizontal_align='right'][, vertical_align='center'])Allows the creation of an alignment flow to place elements intotoggle_visible_state(element[, state])Will toggle the visible state of an element or set it to the one given
    destroy_if_valid(element)Destroies an element but tests for it being present and valid firstDestory a gui element without causing any errors, often because the element was already removed
    create_scroll_table(element, table_size, maximal_height[, name='scroll'])Creates a scroll area with a table inside, table can be any size
    create_header(element, caption[, tooltip][, right_align][, name='header'])Creates a header section with a label and button areasprite_style(size[, padding=-2][, style])Returns a table to be used as the style for a sprite buttons, produces a sqaure button
    -

    Buttons

    +

    Left Flow

    - + + - + + - + + - - + + - - + + - - + + - - + + + + + + + + + +
    mod-guileft_elementsContains the uids of the elements that will shown on the left flow and their join functions
    expcore.gui.coreget_left_flow(player)Gets the flow refered to as the left flow, each player has one left flow
    expcore.gui.prototypeGui._prototype_element:add_to_left_flow([open_on_join])Sets an element define to be drawn to the left flow when a player joins, includes optional check
    Button.new_button([name])Creates a new button element defineleft_toolbar_button(sprite, tooltip, element_define[, authenticator])Creates a button on the top flow which will toggle the given element define, the define must exist in the left flow
    Button._prototype:set_sprites(sprite[, hovered_sprite][, clicked_sprite])Adds sprites to a button making it a sprite buttondraw_left_flow(player)Draw all the left elements onto the left flow, internal use only with on join
    Button._prototype:set_click_filter(filter[, ...])Adds a click / mouse button filter to the buttonupdate_left_flow(player)Update the visible state of the hide button, can be used to check if any frames are visible
    Button._prototype:set_key_filter(filter[, ...])Adds a control key filter to the buttonhide_left_flow(player)Hides all left elements for a player
    get_left_element(player, element_define)Get the element define that is in the left flow, use in events without an element refrence
    toggle_left_element(player, element_define[, state])Toggles the visible state of a left element for a given player, can be used to set the visible state
    -

    Checkboxs

    +

    Element Define

    - + + - + + - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +
    expcore.gui.coreelement(element_define)Used to define new elements for your gui, can be used like LuaGuiElement.add or a custom function
    expcore.gui.prototypeGui._prototype_element:style(style_define)Used to extent your element define with a style factory, this style will be applied to your element when created, can also be a custom function
    expcore.storeGui._prototype_element:on_custom_event(event_name, handler)Set the handler which will be called for a custom event, only one handler can be used per event per element
    utils.game
    Checkbox.new_checkbox([name])Creates a new checkbox element define
    Checkbox.new_radiobutton([name])Creates a new radiobutton element define, has all functions checkbox has
    Checkbox._prototype_radiobutton:add_as_option(option_set, option_name)Adds this radiobutton to be an option in the given option set (only one can be true at a time)
    Checkbox._prototype_radiobutton:get_store(category, internal)Gets the stored value of the radiobutton or the option set if present
    Checkbox._prototype_radiobutton:set_store(category, value, internal)Sets the stored value of the radiobutton or the option set if present
    Checkbox.new_option_set(callback, categorize)Registers a new option set that can be linked to radiobuttons (only one can be true at a time)
    Checkbox.draw_option_set(name, element)Draws all radiobuttons that are part of an option set at once (Gui.draw will not work)
    Checkbox.reset_radiobuttons(element[, exclude][, recursive=false])Sets all radiobutton in a element to false (unless excluded) and can act recursivelyGui._prototype_element:raise_custom_event(event)Raise the handler which is attached to an event; external use should be limited to custom events
    -

    Dropdowns

    +

    Element Events

    - + + - + + - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + + + + + + + +
    expcore.gui.coreGui._prototype_element.on_openCalled when the player opens a GUI.
    expcore.gui.prototypeGui._prototype_element.on_closeCalled when the player closes the GUI they have open.
    utils.gameGui._prototype_element.on_clickCalled when LuaGuiElement is clicked.
    Dropdown.new_dropdown([name])Creates a new dropdown element defineGui._prototype_element.on_confirmedCalled when a LuaGuiElement is confirmed, for example by pressing Enter in a textfield.
    Dropdown.new_list_box([name])Creates a new list box element defineGui._prototype_element.on_checked_changedCalled when LuaGuiElement checked state is changed (related to checkboxes and radio buttons).
    Dropdown._prototype:new_static_options(options[, ...], the)Adds new static options to the dropdown which will trigger the general callbackGui._prototype_element.on_elem_changedCalled when LuaGuiElement element value is changed (related to choose element buttons).
    Dropdown._prototype:new_dynamic_options(callback)Adds a callback which should return a table of values to be added as options for the dropdown (appended after static options)Gui._prototype_element.on_location_changedCalled when LuaGuiElement element location is changed (related to frames in player.gui.screen).
    Dropdown._prototype:add_option_callback(option, callback)Adds a case specific callback which will only run when that option is selected (general case still triggered)Gui._prototype_element.on_tab_changedCalled when LuaGuiElement selected tab is changed (related to tabbed-panes).
    Dropdown.select_value(element, value)Selects the option from a dropdown or list box given the value rather than keyGui._prototype_element.on_selection_changedCalled when LuaGuiElement selection state is changed (related to drop-downs and listboxes).
    Dropdown.get_selected_value(element)Returns the currently selected value rather than indexGui._prototype_element.on_switch_changedCalled when LuaGuiElement switch state is changed (related to switches).
    Gui._prototype_element.on_text_changedCalled when LuaGuiElement text is changed by the player.
    Gui._prototype_element.on_value_changedCalled when LuaGuiElement slider value is changed (related to the slider element).
    -

    Elem Buttons

    +

    Top Flow

    - + + - + + - + + - - + + - - + + - - + + - -
    expcore.gui.coretop_elementsContains the uids of the elements that will shown on the top flow and their auth functions
    expcore.gui.prototypetop_flow_button_styleThe style that should be used for buttons on the top flow
    utils.gametop_flow_button_visible_styleThe style that should be used for buttons on the top flow when their flow is visible
    ElemButton.new_elem_button([name])Creates a new elem button element defineget_top_flow(player)Gets the flow refered to as the top flow, each player has one top flow
    ElemButton._prototype.set_typeSets the type of the elem button, the type is required so this must be called at least onceGui._prototype_element:add_to_top_flow([authenticator])Sets an element define to be drawn to the top flow when a player joins, includes optional authenticator
    ElemButton._prototype:set_default(value)Sets the default value for the elem button, this may be a function or a stringupdate_top_flow(player)Updates the visible state of all the elements on the players top flow, uses authenticator
    - - -

    Progress Bars

    - - - - + + - + + - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    expcore.gui.coretoggle_top_flow(player[, state])Toggles the visible state of all the elements on a players top flow, effects all elements
    expcore.gui.prototypeget_top_element(player, element_define)Get the element define that is in the top flow, use in events without an element refrence
    utils.globaltoolbar_button(sprite, tooltip[, authenticator])Creates a button on the top flow with consistent styling
    utils.game
    ProgressBar.set_maximum(element, amount)Sets the maximum value that represents the end value of the progress bar
    ProgressBar.increment(element[, amount=1])Increases the value of the progressbar, if a define is given all of its instances have incremented
    ProgressBar.decrement(element[, amount=1])Decreases the value of the progressbar, if a define is given all of its instances have decremented
    ProgressBar.new_progressbar([name])Creates a new progressbar element define
    ProgressBar._prototype:set_default_maximum(amount)Sets the maximum value that represents the end value of the progress bar
    ProgressBar._prototype:use_count_down([state=true])Will set the progress bar to start at 1 and trigger when it hits 0
    ProgressBar._prototype:increment([amount=1][, category])Increases the value of the progressbar
    ProgressBar._prototype:increment_filtered([amount=1], filter)Increases the value of the progressbar, if the filter condition is met, does not work with store
    ProgressBar._prototype:decrement([amount=1][, category])Decreases the value of the progressbar
    ProgressBar._prototype:decrement_filtered([amount=1], filter)Decreases the value of the progressbar, if the filter condition is met, does not work with store
    ProgressBar._prototype:add_element(element[, maximum])Adds an element into the list of instances that will are waiting to complete, does not work with store - note use store if you want persistent data, this only stores the elements not the values which they have
    ProgressBar._prototype:reset_element(element)Resets an element, or its store, to be back at the start, either 1 or 0
    ProgressBar._prototype:event_counter([filter])Event handler factory that counts up by 1 every time the event triggers, can filter which elements have incremented
    ProgressBar._prototype:event_countdown([filter])Event handler factory that counts down by 1 every time the event triggers, can filter which elements have decremented
    - - -

    Sliders

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    expcore.gui.core
    expcore.gui.prototype
    expcore.gui.instances
    utils.game
    Slider.new_slider([name])Creates a new slider element define
    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=true])Enables auto draw of the label, the label will share the same parent element as the slider
    - - -

    Text

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    expcore.gui.core
    expcore.gui.prototype
    utils.game
    Text.new_text_field([name])Creates a new text field element define
    Text.new_text_box([name])Creates a new text box element define
    Text._prototype_box:set_selectable([state=true])Sets the text box to be selectable
    Text._prototype_box:set_word_wrap([state=true])Sets the text box to have word wrap
    Text._prototype_box:set_read_only([state=true])Sets the text box to be read only
    - - -

    Instances

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    utils.global
    Instances.has_categories(name)Returns if a instance group has a serializer function; must be registered
    Instances.is_registered(name)Returns if the given name is a registered instance group
    Instances.register(name[, serializer])Registers the name of an instance group to allow for storing element instances
    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
    - - -

    Prototype

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    utils.game
    expcore.store
    expcore.gui.instances
    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(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_nameSets a debug alias for the define
    Prototype.set_captionSets the caption for the element define
    Prototype.set_tooltipSets the tooltip for the element define
    Prototype.set_pre_authenticatorSets an authenticator that blocks the draw function if check fails
    Prototype.set_post_authenticatorSets an authenticator that disables the element if check fails
    Prototype.on_drawRegisters a callback to the on_draw event
    Prototype.on_style_updateRegisters a callback to the on_style_update event
    Prototype:set_style(style[, callback])Sets the style for the element define
    Prototype:set_embedded_flow(state)Sets the element to be drawn inside a nameless flow, can be given a name using a function
    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 - what is drawn is based on the data in draw_data which is set using other functions
    Prototype:get_store(category)Gets the value in this elements store, category needed if serializer function used
    Prototype:set_store(category, value)Sets the value in this elements store, category needed if serializer function used
    Prototype:clear_store([category])Sets the value in this elements store to nil, category needed if serializer function used
    - - -

    Test

    - - - - - - - - - - - - - - - - - + +
    expcore.gui
    expcore.common
    resources.color_presets
    utils.event
    expcore.storetoolbar_button_style(button, state)Styles a top flow button depending on the state given
    @@ -1122,1187 +693,8 @@
    - # - 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 -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    - -

    Center Guis

    -
    -
    -
    -
    - # - expcore.gui.core -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - expcore.gui.prototype -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - expcore.gui.concepts.toolbar -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - utils.game -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - CenterFrames.get_flow(player) -
    -
    -
    -
    - -

    Gets the center flow for a player

    -

    - - - Parameters: - -
      - - - - - -
    • - - player - - : - - (LuaPlayer) - - the player to get the flow for - -
    • - - -
    - - - - - Returns: - - - - - - - - - - -
    -
    -
    -
    - # - CenterFrames.clear_flow(player) -
    -
    -
    -
    - -

    Clears the center flow for a player

    -

    - - - Parameters: - -
      - - - - - -
    • - - player - - : - - (LuaPlayer) - - the player to clear the flow for - -
    • - - -
    - - - - - - - - - - - - - -
    -
    -
    -
    - # - CenterFrames.draw_frame(player, name) -
    -
    -
    -
    - -

    Draws the center frame for a player, if already open then will do nothing

    -

    - - - Parameters: - -
      - - - - - -
    • - - player - - : - - (LuaPlayer) - - the player that will have the frame drawn - -
    • - - - - - -
    • - - name - - : - - (string) - - the name of the hui that will drawn - -
    • - - -
    - - - - - Returns: - - - - - - - - - - -
    -
    -
    -
    - # - CenterFrames.redraw_frame(player, name) -
    -
    -
    -
    - -

    Draws the center frame for a player, if already open then will destroy it and redraw

    -

    - - - Parameters: - -
      - - - - - -
    • - - player - - : - - (LuaPlayer) - - the player that will have the frame drawn - -
    • - - - - - -
    • - - name - - : - - (string) - - the name of the hui that will drawn - -
    • - - -
    - - - - - Returns: - - - - - - - - - - -
    -
    -
    -
    - # - CenterFrames.toggle_frame(player, name[, state]) -
    -
    -
    -
    - -

    Toggles if the frame is currently open or not, will open if closed and close if open

    -

    - - - Parameters: - -
      - - - - - -
    • - - player - - : - - (LuaPlayer) - - the player that will have the frame toggled - -
    • - - - - - -
    • - - name - - : - - (string) - - the name of the hui that will be toggled - -
    • - - - - - -
    • - - state - - : - - (boolean) - - when set will force a state for the frame - - (optional) -
    • - - -
    - - - - - Returns: -
      -
    • - (boolean) - if the frame if no open or closed -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - CenterFrames.new_frame(permission_name) -
    -
    -
    -
    - -

    Creates a new center frame define

    -

    - - - Parameters: - -
      - - - - - -
    • - - permission_name - - : - - (string) - - the name that can be used with the permission system - -
    • - - -
    - - - - - Returns: -
      -
    • - (table) - the new center frame define -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - CenterFrames._prototype:set_auto_focus([state=true]) -
    -
    -
    -
    - -

    Sets the frame to be the current active gui when opened and closes all other frames

    -

    - - - Parameters: - -
      - - - - - -
    • - - state - - : - - (boolean) - - when true will auto close other frames and set this frame as player.opened - - (default: true) -
    • - - -
    - - - - - - - - - - - - - -
    -
    -
    -
    - # - CenterFrames._prototype:draw_frame(player) -
    -
    -
    -
    - -

    Draws this frame to the player, if already open does nothing (will call on_draw to draw to the frame)

    -

    - - - Parameters: - -
      - - - - - -
    • - - player - - : - - (LuaPlayer) - - the player to draw the frame for - -
    • - - -
    - - - - - Returns: - - - - - - - - - - -
    -
    -
    -
    - # - CenterFrames._prototype:redraw_frame(player) -
    -
    -
    -
    - -

    Draws this frame to the player, if already open it will remove it and redraw it (will call on_draw to draw to the frame)

    -

    - - - Parameters: - -
      - - - - - -
    • - - player - - : - - (LuaPlayer) - - the player to draw the frame for - -
    • - - -
    - - - - - Returns: - - - - - - - - - - -
    -
    -
    -
    - # - CenterFrames._prototype:toggle_frame(player) -
    -
    -
    -
    - -

    Toggles if the frame is open, if open it will close it and if closed it will open it

    -

    - - - Parameters: - -
      - - - - - -
    • - - player - - : - - (LuaPlayer) - - the player to draw the frame for - -
    • - - -
    - - - - - Returns: -
      -
    • - (boolean) - with the gui frame is now open -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - CenterFrames._prototype:event_handler([action=update]) -
    -
    -
    -
    - -

    Creates an event handler that will trigger one of its functions, use with Event.add

    -

    - - - Parameters: - -
      - - - - - -
    • - - action - - : - - (string) - - the action to take on this event - - (default: update) -
    • - - -
    - - - - - - - - - - - - - -
    -
    -

    Left Guis

    -
    -
    -
    -
    - # - expcore.gui.core -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - expcore.gui.prototype -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - expcore.gui.concepts.toolbar -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - expcore.gui.elements.buttons + # + utils.event
    @@ -2341,975 +733,6 @@ - - - - - - -
    -
    -
    -
    - # - utils.game -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - utils.event -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - LeftFrames.get_flow(player) -
    -
    -
    -
    - -

    Gets the left frame flow for a player

    -

    - - - Parameters: - -
      - - - - - -
    • - - player - - : - - (LuaPlayer) - - the player to get the flow of - -
    • - - -
    - - - - - Returns: - - - - - - - - - - -
    -
    -
    -
    - # - LeftFrames.get_frame(name, player) -
    -
    -
    -
    - -

    Gets one frame from the left flow by its name

    -

    - - - Parameters: - -
      - - - - - -
    • - - name - - : - - (string) - - the name of the gui frame to get - -
    • - - - - - -
    • - - player - - : - - (LuaPlayer) - - the player to get the frame of - -
    • - - -
    - - - - - Returns: -
      -
    • - (LuaGuiElement) - the frame in the left frame flow with that name -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - LeftFrames.get_open(player) -
    -
    -
    -
    - -

    Gets all open frames for a player, if non are open it will remove the close all button

    -

    - - - Parameters: - -
      - - - - - -
    • - - player - - : - - (LuaPlayer) - - the player to get the flow of - -
    • - - -
    - - - - - Returns: -
      -
    • - (table) - contains all the open (and registered) frames for the player -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - LeftFrames.toggle_frame(name, player[, state]) -
    -
    -
    -
    - -

    Toggles the visibility of a left frame, or sets its visibility state

    -

    - - - Parameters: - -
      - - - - - -
    • - - name - - : - - (string) - - the name of the gui frame to toggle - -
    • - - - - - -
    • - - player - - : - - (LuaPlayer) - - the player to get the frame of - -
    • - - - - - -
    • - - state - - : - - (boolean) - - when given will be the state that the visibility is set to - - (optional) -
    • - - -
    - - - - - Returns: -
      -
    • - (boolean) - the new state of the visibility -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - LeftFrames.new_frame(permission_name) -
    -
    -
    -
    - -

    Creates a new left frame define

    -

    - - - Parameters: - -
      - - - - - -
    • - - permission_name - - : - - (string) - - the name that can be used with the permission system - -
    • - - -
    - - - - - Returns: -
      -
    • - (table) - the new left frame define -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - LeftFrames._prototype:set_open_by_default([state=true]) -
    -
    -
    -
    - -

    Sets if the frame is visible when a player joins, can also be a function to return a boolean

    -

    - - - Parameters: - -
      - - - - - -
    • - - state - - : - - (boolean or function) - - the default state of the visibility, can be a function - state param - player LuaPlayer - the player that has joined the game - state param - define_name string - the define name for the frame - state return - boolean - false will hide the frame - - (default: true) -
    • - - -
    - - - - - - - - - - - - - -
    -
    -
    -
    - # - LeftFrames._prototype:set_direction(direction) -
    -
    -
    -
    - -

    Sets the direction of the frame, either vertical or horizontal

    -

    - - - Parameters: - -
      - - - - - -
    • - - direction - - : - - (string) - - the direction to have the elements be added to the frame - -
    • - - -
    - - - - - - - - - - - - - -
    -
    -
    -
    - # - LeftFrames._prototype:_internal_draw(player) -
    -
    -
    -
    - -

    Creates the gui for the first time, used internally

    -

    - - - Parameters: - -
      - - - - - -
    • - - player - - : - - (LuaPlayer) - - the player to draw the frame to - -
    • - - -
    - - - - - Returns: - - - - - - - - - - -
    -
    -
    -
    - # - LeftFrames._prototype:get_frame(player) -
    -
    -
    -
    - -

    Gets the frame for this define from the left frame flow

    -

    - - - Parameters: - -
      - - - - - -
    • - - player - - : - - (LuaPlayer) - - the player to get the frame of - -
    • - - -
    - - - - - Returns: -
      -
    • - (LuaGuiElement) - the frame in the left frame flow for this define -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - LeftFrames._prototype:is_open(player) -
    -
    -
    -
    - -

    Returns if the player currently has this define visible

    -

    - - - Parameters: - -
      - - - - - -
    • - - player - - : - - (LuaPlayer) - - the player to get the frame of - -
    • - - -
    - - - - - Returns: -
      -
    • - (boolean) - true if it is open/visible -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - LeftFrames._prototype:toggle(player) -
    -
    -
    -
    - -

    Toggles the visibility of the left frame

    -

    - - - Parameters: - -
      - - - - - -
    • - - player - - : - - (LuaPlayer) - - the player to toggle the frame of - -
    • - - -
    - - - - - Returns: -
      -
    • - (boolean) - the new state of the visibility -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - LeftFrames._prototype:update(player) -
    -
    -
    -
    - -

    Updates the contents of the left frame, first tries update callback, other wise will clear and redraw

    -

    - - - Parameters: - -
      - - - - - -
    • - - player - - : - - (LuaPlayer) - - the player to update the frame of - -
    • - - -
    - - - - - - - - - - - - - -
    -
    -
    -
    - # - LeftFrames._prototype:update_all([update_offline=false]) -
    -
    -
    -
    - -

    Updates the frame for all players, see update

    -

    - - - Parameters: - -
      - - - - - -
    • - - update_offline - - : - - (boolean) - - when true will update the frame for offline players - - (default: false) -
    • - - -
    - - - - - - - - - - - - - -
    -
    -
    -
    - # - LeftFrames._prototype:redraw(player) -
    -
    -
    -
    - -

    Redraws the frame by calling on_draw, will always clear the frame

    -

    - - - Parameters: - -
      - - - - - -
    • - - player - - : - - (LuaPlayer) - - the player to update the frame of - -
    • - - -
    - - - - - - - - - - - - - -
    -
    -
    -
    - # - LeftFrames._prototype:redraw_all([update_offline=false]) -
    -
    -
    -
    - -

    Redraws the frame for all players, see redraw

    -

    - - - Parameters: - -
      - - - - - -
    • - - update_offline - - : - - (boolean) - - when true will update the frame for offline players - - (default: false) -
    • - - -
    - - - - - - - - - - - - - -
    -
    -
    -
    - # - LeftFrames._prototype:event_handler([action=update]) -
    -
    -
    -
    - -

    Creates an event handler that will trigger one of its functions, use with Event.add

    -

    - - - Parameters: - -
      - - - - - -
    • - - action - - : - - (string) - - the action to take on this event - - (default: update) -
    • - - -
    - - - - - - - @@ -3318,407 +741,19 @@
    -

    Popups

    +

    Tables

    - # - expcore.gui.core + # + events
    - - - - - - - - - - - - - - -
    -
    -
    -
    - # - expcore.gui.prototype -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - utils.game -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - utils.event -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - expcore.gui.elements.progress-bar -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - expcore.gui.elements.buttons -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - mod-gui -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - resources.color_presets -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - utils.global -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - PopupFrames.get_flow(player) -
    -
    -
    -
    - -

    Gets the left flow that contains the popup frames

    -

    - - - Parameters: - -
      - - - - - -
    • - - player - - : - - (LuaPlayer) - - the player to get the flow for - -
    • - - -
    - - - - - Returns: -
      -
    • - (LuaGuiElement) - the left flow that contains the popup frames -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - PopupFrames.open(define_name, player[, open_time], ...) -
    -
    -
    -
    - -

    Opens a popup for the player, can give the amount of time it is open as well as params for the draw function

    -

    - - - Parameters: - -
      - - - - - -
    • - - define_name - - : - - (string) - - the name of the define that you want to open for the player - -
    • - - - - - -
    • - - player - - : - - (LuaPlayer) - - the player to open the popup for - -
    • - - - - - -
    • - - open_time - - : - - (number) - - the minimum number of ticks you want the popup open for, 0 means no limit, nil will take default - - (optional) -
    • - - - - - -
    • - - ... - - : - - (any) - - the other params that you want to pass to your on_draw event - -
    • - - -
    - - - - - Returns: -
      -
    • - (LuaGuiElement) - the frame that was drawn, the inner gui flow which contains the content -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - PopupFrames.close_progress -
    -
    -
    -
    - -

    Progress bar which when depleted will close the popup frame

    +

    String indexed table used to avoid conflict with custom event names, similar to how defines.events works

    @@ -3738,14 +773,14 @@
    - # - PopupFrames.close_button + # + defines
    -

    A button which can be used to close the gui before the timer runs out

    +

    Uid indexed array that stores all the factory functions that were defined, no new values will be added during runtime

    @@ -3765,51 +800,20 @@
    - # - PopupFrames.new_popup([name]) + # + core_defines
    -

    Creates a new popup frame define

    +

    An string indexed table of all the defines which are used by the core of the gui system, used for internal refrence

    - Parameters: - -
      - - - - - -
    • - - name - - : - - (string) - - the optional debug name that can be added - - (optional) -
    • - - -
    - - Returns: -
      -
    • - (table) - the new popup frame define -
    • -
    @@ -3823,50 +827,20 @@
    - # - PopupFrames._prototype:set_default_open_time(amount) + # + file_paths
    -

    Sets the default open time for the popup, will be used if non is provided with open

    +

    Used to store the file names where elements were defined, this can be useful to find the uid of an element, mostly for debuging

    - Parameters: - -
      - - - - - -
    • - - amount - - : - - (number) - - the number of ticks, by default, the popup will be open for - -
    • - - -
    - - Returns: -
      -
    • - (table) - the define to allow for chaining -
    • -
    @@ -3880,107 +854,16 @@
    - # - PopupFrames._prototype:open(player[, open_time], ...) + # + debug_info
    -

    Opens this define for a player, can be given open time and any other params for the draw function

    +

    Used to store extra infomation about elements as they get defined such as the params used and event handlers registered to them

    - - Parameters: - -
      - - - - - -
    • - - player - - : - - (LuaPlayer) - - the player to open the popup for - -
    • - - - - - -
    • - - open_time - - : - - (number) - - the minimum number of ticks you want the popup open for, 0 means no limit, nil will take default - - (optional) -
    • - - - - - -
    • - - ... - - : - - (any) - - the other params that you want to pass to your on_draw event - -
    • - - -
    - - - - - Returns: -
      -
    • - (LuaGuiElement) - the frame that was drawn, the inner gui flow which contains the content -
    • -
    - - - - - - - - - -
    -
    -

    Toolbar

    -
    -
    -
    -
    - # - expcore.gui.core -
    -
    -
    -
    - - @@ -3998,223 +881,17 @@
    - # - expcore.gui.elements.buttons + # + _prototype_element
    - - - - - - - - - - - - - - -
    -
    -
    -
    - # - expcore.roles -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - utils.event -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - utils.game -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - mod-gui -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - Toolbar.new_button([name]) -
    -
    -
    -
    - -

    Adds a new button to the toolbar

    +

    The prototype used to store the functions of an element define

    - Parameters: - -
      - - - - - -
    • - - name - - : - - (string) - - when given allows an alias to the button for the permission system - - (optional) -
    • - - -
    - - - - - Returns: -
      -
    • - (table) - the button define -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - Toolbar.add_button(button) -
    -
    -
    -
    - -

    Adds an existing buttton to the toolbar

    -

    - - - Parameters: - -
      - - - - - -
    • - - button - - : - - (table) - - the button define for the button to be added - -
    • - - -
    - @@ -4231,18 +908,18 @@
    - # - Toolbar.update(player) + # + _mt_element
    -

    Updates the player's toolbar with an new buttons or expected change in auth return

    +

    The prototype metatable applied to new element defines

    - Parameters: + Fields:
      @@ -4252,13 +929,11 @@
    • - player + __call + - : - (LuaPlayer) - the player to update the toolbar for
    • @@ -4279,122 +954,55 @@
    -

    Core

    +

    Fields

    - # - utils.gui + # + uid
    - - - - - - - - - - - - - - -
    -
    -
    -
    - # - utils.game -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - new_define(prototype[, debug_name]) -
    -
    -
    -
    - -

    Used to create new element defines from a class prototype, please use the own given by the class

    +

    The current highest uid that is being used by a define, will not increase during runtime

    +

    + + + + + + + + + + + + + + +
    +
    +

    Core Defines

    +
    +
    +
    +
    + # + hide_top_flow +
    +
    +
    +
    + +

    Button which toggles the top flow elements, version which shows inside the top flow when top flow is visible

    - Parameters: - -
      - - - - - -
    • - - prototype - - : - - (table) - - the class prototype that will be used for the element define - -
    • - - - - - -
    • - - debug_name - - : - - (string) - - the name that you want to see while debuging - - (optional) -
    • - - -
    - - Returns: -
      -
    • - (table) - the new element define with all functions accessed via __index metamethod -
    • -
    @@ -4408,67 +1016,20 @@
    - # - get_define(name[, internal]) + # + show_top_flow
    -

    Gets an element define give the uid, debug name or a copy of the element define

    +

    Button which toggles the top flow elements, version which shows inside the left flow when top flow is hidden

    - Parameters: - -
      - - - - - -
    • - - name - - : - - (string or table) - - the uid, debug name or define for the element define to get - -
    • - - - - - -
    • - - internal - - : - - (boolean) - - when true the error trace is one level higher (used internally) - - (optional) -
    • - - -
    - - Returns: -
      -
    • - (table) - the element define that was found or an error -
    • -
    @@ -4482,18 +1043,48 @@
    - # - categorize_by_player(element) + # + hide_left_flow
    -

    A categorize function to be used with add_store, each player has their own value

    +

    Button which hides the elements in the left flow, shows inside the left flow when frames are visible

    - Parameters: + + + + + + + + + + + + +
    +
    +

    Defines

    +
    +
    +
    +
    + # + alignment +
    +
    +
    +
    + +

    Draw a flow used to align its child elements, default is right align

    +

    + + + Properties / Events:
      @@ -4503,607 +1094,13 @@
    • - element + parent : (LuaGuiElement) - the element that will be converted to a string - -
    • - - -
    - - - - - Returns: -
      -
    • - (string) - the player's name who owns this element -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - categorize_by_force(element) -
    -
    -
    -
    - -

    A categorize function to be used with add_store, each force has its own value

    -

    - - - Parameters: - -
      - - - - - -
    • - - element - - : - - (LuaGuiElement) - - the element that will be converted to a string - -
    • - - -
    - - - - - Returns: -
      -
    • - (string) - the player's force name who owns this element -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - categorize_by_surface(element) -
    -
    -
    -
    - -

    A categorize function to be used with add_store, each surface has its own value

    -

    - - - Parameters: - -
      - - - - - -
    • - - element - - : - - (LuaGuiElement) - - the element that will be converted to a string - -
    • - - -
    - - - - - Returns: -
      -
    • - (string) - the player's surface name who owns this element -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - draw(name, element) -
    -
    -
    -
    - -

    Draws a copy of the element define to the parent element, see draw_to

    -

    - - - Parameters: - -
      - - - - - -
    • - - name - - : - - (string or table) - - the uid, debug name or define for the element define to draw - -
    • - - - - - -
    • - - element - - : - - (LuaGuiEelement) - - the parent element that it the define will be drawn to - -
    • - - -
    - - - - - Returns: - - - - - - - - - - -
    -
    -
    -
    - # - toggle_enabled(element) -
    -
    -
    -
    - -

    Will toggle the enabled state of an element

    -

    - - - Parameters: - -
      - - - - - -
    • - - element - - : - - (LuaGuiElement) - - the gui element to toggle - -
    • - - -
    - - - - - Returns: -
      -
    • - (boolean) - the new state that the element has -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - toggle_visible(element) -
    -
    -
    -
    - -

    Will toggle the visiblity of an element

    -

    - - - Parameters: - -
      - - - - - -
    • - - element - - : - - (LuaGuiElement) - - the gui element to toggle - -
    • - - -
    - - - - - Returns: -
      -
    • - (boolean) - the new state that the element has -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - set_padding(element[, up=0][, down=0][, left=0][, right=0]) -
    -
    -
    -
    - -

    Sets the padding for a gui element

    -

    - - - Parameters: - -
      - - - - - -
    • - - element - - : - - (LuaGuiElement) - - the element to set the padding for - -
    • - - - - - -
    • - - up - - : - - (number) - - the amount of padding on the top - - (default: 0) -
    • - - - - - -
    • - - down - - : - - (number) - - the amount of padding on the bottom - - (default: 0) -
    • - - - - - -
    • - - left - - : - - (number) - - the amount of padding on the left - - (default: 0) -
    • - - - - - -
    • - - right - - : - - (number) - - the amount of padding on the right - - (default: 0) -
    • - - -
    - - - - - - - - - - - - - -
    -
    -
    -
    - # - set_padding_style(style[, up=0][, down=0][, left=0][, right=0]) -
    -
    -
    -
    - -

    Sets the padding for a gui style

    -

    - - - Parameters: - -
      - - - - - -
    • - - style - - : - - (LuaStyle) - - the element to set the padding for - -
    • - - - - - -
    • - - up - - : - - (number) - - the amount of padding on the top - - (default: 0) -
    • - - - - - -
    • - - down - - : - - (number) - - the amount of padding on the bottom - - (default: 0) -
    • - - - - - -
    • - - left - - : - - (number) - - the amount of padding on the left - - (default: 0) -
    • - - - - - -
    • - - right - - : - - (number) - - the amount of padding on the right - - (default: 0) -
    • - - -
    - - - - - - - - - - - - - -
    -
    -
    -
    - # - create_alignment(element[, name][, horizontal_align='right'][, vertical_align='center']) -
    -
    -
    -
    - -

    Allows the creation of an alignment flow to place elements into

    -

    - - - Parameters: - -
      - - - - - -
    • - - element - - : - - (LuaGuiElement) - - the element to add this alignment into + the parent element to which the alignment will be added
    • @@ -5119,9 +1116,9 @@ (string) - the name to use for the alignment + the name of the alignment flow which is added - (optional) + (default: 'alignment') @@ -5136,7 +1133,7 @@ (string) - the horizontal alignment of the elements in this flow + the horizontal alignment of the elements in the flow (default: 'right') @@ -5153,7 +1150,7 @@ (string) - the vertical alignment of the elements in this flow + the vertical alignment of the elements in the flow (default: 'center') @@ -5164,13 +1161,6 @@ - Returns: - @@ -5178,24 +1168,29 @@ + Usage: +
      -- Adding a right align flow
      +local alignment = Gui.alignment(element,'example_right_alignment')
      +
      -- Adding a horizontal center and top align flow
      +local alignment = Gui.alignment(element,'example_center_top_alignment','center','top')
    - # - destroy_if_valid(element) + # + scroll_table
    -

    Destroies an element but tests for it being present and valid first

    +

    Draw a scroll pane that has a table inside of it

    - Parameters: + Properties / Events:
      @@ -5205,70 +1200,13 @@
    • - element + parent : (LuaGuiElement) - the element to be destroied - -
    • - - -
    - - - - - Returns: -
      -
    • - (boolean) - true if it was destoried -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - create_scroll_table(element, table_size, maximal_height[, name='scroll']) -
    -
    -
    -
    - -

    Creates a scroll area with a table inside, table can be any size

    -

    - - - Parameters: - -
      - - - - - -
    • - - element - - : - - (LuaGuiElement) - - the element to add this scroll into + the parent element to which the scroll table will be added
    • @@ -5278,13 +1216,13 @@
    • - table_size + height : (number) - the number of columns in the table + the maximum height for the scroll pane
    • @@ -5294,13 +1232,13 @@
    • - maximal_height + column_count : (number) - the max hieght of the scroll + the number of columns that the table will have
    • @@ -5316,7 +1254,7 @@ (string) - the name of the scoll element + the name of the scroll pane that is added, the table is always called "table" (default: 'scroll') @@ -5327,13 +1265,6 @@ - Returns: - @@ -5341,24 +1272,27 @@ + Usage: +
      -- Adding a scroll table with max height of 200 and column count of 3
      +local scroll_table = Gui.scroll_table(element,200,3)
    - # - create_header(element, caption[, tooltip][, right_align][, name='header']) + # + header
    -

    Creates a header section with a label and button area

    +

    Used to add a frame with the header style, has the option for a right alignment flow for buttons

    - Parameters: + Properties / Events:
      @@ -5368,13 +1302,13 @@
    • - element + parent : (LuaGuiElement) - the element to add this header into + the parent element to which the header will be added
    • @@ -5388,9 +1322,9 @@ : - (localeString) + (string or LocalizedString) - the caption that is used as the title + the caption that will be shown on the header @@ -5404,9 +1338,9 @@ : - (localeString) + (string or LocalizedString) - the tooltip that is shown on the caption + the tooltip that will be shown on the header (optional) @@ -5417,15 +1351,15 @@
    • - right_align + add_alignment : (boolean) - when true will include the right align area + when true an alignment flow will be added to the header - (optional) + (default: false)
    • @@ -5440,7 +1374,7 @@ (string) - the name of the header area + the name of the header that is being added, the alignment is always called "alignment" (default: 'header') @@ -5451,13 +1385,6 @@ - Returns: -
        -
      • - (LuaGuiElement) - the header that was made, or the align area if that was created -
      • -
      @@ -5465,98 +1392,512 @@ + Usage: +
      -- Adding a custom header with a label
      +local header = Gui.header(
      +    element,
      +    'Example Caption',
      +    'Example Tooltip'
      +)
      + + +
    +
    +
    +
    + # + footer +
    +
    +
    +
    + +

    Used to add a frame with the footer style, has the option for a right alignment flow for buttons

    +

    + + + Properties / Events: + +
      + + + + + +
    • + + parent + + : + + (LuaGuiElement) + + the parent element to which the footer will be added + +
    • + + + + + +
    • + + caption + + : + + (string or LocalizedString) + + the caption that will be shown on the footer + +
    • + + + + + +
    • + + tooltip + + : + + (string or LocalizedString) + + the tooltip that will be shown on the footer + + (optional) +
    • + + + + + +
    • + + add_alignment + + : + + (boolean) + + when true an alignment flow will be added to the footer + + (default: false) +
    • + + + + + +
    • + + name + + : + + (string) + + the name of the footer that is being added, the alignment is always called "alignment" + + (default: 'footer') +
    • + + +
    + + + + + + + + + + + + Usage: +
    -- Adding a custom footer with a label
    +local footer = Gui.footer(
    +    element,
    +    'Example Caption',
    +    'Example Tooltip'
    +)
    + + +
    +
    +
    +
    + # + container +
    +
    +
    +
    + +

    Used for left frames to give them a nice boarder

    +

    + + + Properties / Events: + +
      + + + + + +
    • + + parent + + : + + (LuaGuiElement) + + the parent element to which the container will be added + +
    • + + + + + +
    • + + name + + : + + (string) + + the name that you want to give to the outer frame, often just event_trigger + +
    • + + + + + +
    • + + width + + : + + (number) + + the minimal width that the frame will have + +
    • + + +
    + + + + + + + + + + + + Usage: +
    -- Adding a container as a base
    +local container = Gui.container(parent,'my_container',200)
    + + +
    +
    +
    +
    + # + bar +
    +
    +
    +
    + +

    Used to make a solid white bar in a gui

    +

    + + + Properties / Events: + +
      + + + + + +
    • + + parent + + : + + (LuaGuiElement) + + the parent element to which the bar will be added + +
    • + + + + + +
    • + + width + + : + + (number) + + the width of the bar that will be made, if not given bar will strech to fill the parent + +
    • + + +
    + + + + + + + + + + + + Usage: +
    -- Adding a bar to a gui
    +local bar = Gui.bar(parent, 100)
    + + +
    +
    +
    +
    + # + centered_label +
    +
    +
    +
    + +

    Used to make a label which is centered and of a certian size

    +

    + + + Properties / Events: + +
      + + + + + +
    • + + parent + + : + + (LuaGuiElement) + + the parent element to which the label will be added + +
    • + + + + + +
    • + + width + + : + + (number) + + the width of the label, must be given in order to center the caption + +
    • + + + + + +
    • + + caption + + : + + (string or LocalizedString) + + the caption that will be shown on the label + +
    • + + + + + +
    • + + tooltip + + : + + (string or LocalizedString) + + the tooltip that will be shown on the label + + (optional) +
    • + + +
    + + + + + + + + + + + + Usage: +
    -- Adding a centered label
    +local label = Gui.centered_label(parent, 100, 'This is centered')
    + + +
    +
    +
    +
    + # + title_label +
    +
    +
    +
    + +

    Used to make a title which has two bars on either side

    +

    + + + Properties / Events: + +
      + + + + + +
    • + + parent + + : + + (LuaGuiElement) + + the parent element to which the label will be added + +
    • + + + + + +
    • + + width + + : + + (number) + + the width of the first bar, this can be used to position the label + +
    • + + + + + +
    • + + caption + + : + + (string or LocalizedString) + + the caption that will be shown on the label + +
    • + + + + + +
    • + + tooltip + + : + + (string or LocalizedString) + + the tooltip that will be shown on the label + + (optional) +
    • + + +
    + + + + + + + + + + + + Usage: +
    -- Adding a centered label
    +local label = Gui.centered_label(parent, 100, 'This is centered')
    -

    Buttons

    +

    Helper Functions

    - # - mod-gui + # + get_player_from_element(element)
    - - - - - - - - - - - - - - -
    -
    -
    -
    - # - expcore.gui.core -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - expcore.gui.prototype -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - Button.new_button([name]) -
    -
    -
    -
    - -

    Creates a new button element define

    +

    Get the player that owns a gui element

    @@ -5570,13 +1911,320 @@
  • - name + element : - (string) + (LuaGuiElement) - the optional debug name that can be added + the element to get the owner of + +
  • + + + + + + + + Returns: +
      +
    • + (LuaPlayer) + the player that owns this element +
    • +
    + + + + + + + + Usage: +
    -- Geting the owner of an element
    +local player = Gui.get_player_from_element(element)
    + + +
    +
    +
    +
    + # + toggle_enabled_state(element[, state]) +
    +
    +
    +
    + +

    Will toggle the enabled state of an element or set it to the one given

    +

    + + + Parameters: + +
      + + + + + +
    • + + element + + : + + (LuaGuiElement) + + the element to toggle/set the enabled state of + +
    • + + + + + +
    • + + state + + : + + (boolean) + + with given will set the state, else state will be toggled + + (optional) +
    • + + +
    + + + + + Returns: +
      +
    • + (boolean) + the new enabled state that the element has +
    • +
    + + + + + + + + Usage: +
    -- Toggling the the enabled state
    +local new_enabled_state = Gui.toggle_enabled_state(element)
    + + +
    +
    +
    +
    + # + toggle_visible_state(element[, state]) +
    +
    +
    +
    + +

    Will toggle the visible state of an element or set it to the one given

    +

    + + + Parameters: + +
      + + + + + +
    • + + element + + : + + (LuaGuiElement) + + the element to toggle/set the visible state of + +
    • + + + + + +
    • + + state + + : + + (boolean) + + with given will set the state, else state will be toggled + + (optional) +
    • + + +
    + + + + + Returns: +
      +
    • + (boolean) + the new visible state that the element has +
    • +
    + + + + + + + + Usage: +
    -- Toggling the the visible state
    +local new_visible_state = Gui.toggle_visible_state(element)
    + + +
    +
    +
    +
    + # + destroy_if_valid(element) +
    +
    +
    +
    + +

    Destory a gui element without causing any errors, often because the element was already removed

    +

    + + + Parameters: + +
      + + + + + +
    • + + element + + : + + (LuaGuiElement) + + the element that you want to remove + +
    • + + +
    + + + + + Returns: +
      +
    • + (boolean) + true if the element was valid and has been removed +
    • +
    + + + + + + + + Usage: +
    -- Remove a child element if it exists
    +Gui.destroy_if_valid(element[child_name])
    + + +
    +
    +
    +
    + # + sprite_style(size[, padding=-2][, style]) +
    +
    +
    +
    + +

    Returns a table to be used as the style for a sprite buttons, produces a sqaure button

    +

    + + + Parameters: + +
      + + + + + +
    • + + size + + : + + (number) + + the size that you want the button to be + +
    • + + + + + +
    • + + padding + + : + + (number) + + the padding that you want on the sprite + + (default: -2) +
    • + + + + + +
    • + + style + + : + + (table) + + any extra style settings that you want to have (optional)
    • @@ -5591,12 +2239,50 @@
      • (table) - the new button element define + the style table to be used with element_define:style()
      + + + + + Usage: +
      -- Adding a sprite button with size 20
      +local button =
      +Gui.element{
      +    type = 'sprite-button',
      +    sprite = 'entity/inserter'
      +}
      +:style(Gui.sprite_style(20))
      + + +
    +
    +

    Left Flow

    +
    +
    +
    +
    + # + left_elements +
    +
    +
    +
    + +

    Contains the uids of the elements that will shown on the left flow and their join functions

    +

    + + + + + + + + @@ -5607,14 +2293,135 @@
    - # - Button._prototype:set_sprites(sprite[, hovered_sprite][, clicked_sprite]) + # + get_left_flow(player)
    -

    Adds sprites to a button making it a sprite button

    +

    Gets the flow refered to as the left flow, each player has one left flow

    +

    (player)

    + + + Parameters: + +
      + + + + + +
    • + + player + + : + + (LuaPlayer) + + the player that you want to get the left flow for + +
    • + + +
    + + + + + Returns: + + + + + + + + + Usage: +
    -- Geting your left flow
    +local left_flow = Gui.get_left_flow(game.player)
    + + +
    +
    +
    +
    + # + Gui._prototype_element:add_to_left_flow([open_on_join]) +
    +
    +
    +
    + +

    Sets an element define to be drawn to the left flow when a player joins, includes optional check

    +

    + + + Parameters: + +
      + + + + + +
    • + + open_on_join + + : + + (boolean or function) + + called during first darw to decide if the element should be visible + + (optional) +
    • + + +
    + + + + + Returns: +
      +
    • + (table) + the new element define that is used to register events to this element +
    • +
    + + + + + + + + Usage: +
    -- Adding the example button
    +example_flow_with_button:add_to_left_flow(true)
    + + +
    +
    +
    +
    + # + left_toolbar_button(sprite, tooltip, element_define[, authenticator]) +
    +
    +
    +
    + +

    Creates a button on the top flow which will toggle the given element define, the define must exist in the left flow

    @@ -5632,4306 +2439,9 @@ : - (SpritePath) - - the sprite path for the default sprite for the button - - - - - - - -
  • - - hovered_sprite - - : - - (SpritePath) - - the sprite path for the sprite when the player hovers over the button - - (optional) -
  • - - - - - -
  • - - clicked_sprite - - : - - (SpritePath) - - the sprite path for the sprite when the player clicks the button - - (optional) -
  • - - - - - - - - Returns: -
      -
    • - (self) - returns the button define to allow chaining -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - Button._prototype:set_click_filter(filter[, ...]) -
    -
    -
    -
    - -

    Adds a click / mouse button filter to the button

    -

    - - - Parameters: - -
      - - - - - -
    • - - filter - - : - - (table) - - ?string|table either a of mouse buttons or the first mouse button to filter, with a table true means allowed - -
    • - - - - - -
    • - - ... - - : - - (table) - - when filter is not a you can add the mouse buttons one after each other - - (optional) -
    • - - -
    - - - - - Returns: -
      -
    • - (self) - returns the button define to allow chaining -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - Button._prototype:set_key_filter(filter[, ...]) -
    -
    -
    -
    - -

    Adds a control key filter to the button

    -

    - - - Parameters: - -
      - - - - - -
    • - - filter - - : - - (table) - - ?string|table either a of control keys or the first control keys to filter, with a table true means allowed - -
    • - - - - - -
    • - - ... - - : - - (table) - - when filter is not a you can add the control keys one after each other - - (optional) -
    • - - -
    - - - - - Returns: -
      -
    • - (self) - returns the button define to allow chaining -
    • -
    - - - - - - - - - -
    -
    -

    Checkboxs

    -
    -
    -
    -
    - # - expcore.gui.core -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - expcore.gui.prototype -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - expcore.store -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - utils.game -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - Checkbox.new_checkbox([name]) -
    -
    -
    -
    - -

    Creates a new checkbox element define

    -

    - - - Parameters: - -
      - - - - - -
    • - - name - - : - (string) - the optional debug name that can be added - - (optional) -
    • - - -
    - - - - - Returns: -
      -
    • - (table) - the new checkbox element define -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - Checkbox.new_radiobutton([name]) -
    -
    -
    -
    - -

    Creates a new radiobutton element define, has all functions checkbox has

    -

    - - - Parameters: - -
      - - - - - -
    • - - name - - : - - (string) - - the optional debug name that can be added - - (optional) -
    • - - -
    - - - - - Returns: -
      -
    • - (table) - the new button element define -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - Checkbox._prototype_radiobutton:add_as_option(option_set, option_name) -
    -
    -
    -
    - -

    Adds this radiobutton to be an option in the given option set (only one can be true at a time)

    -

    - - - Parameters: - -
      - - - - - -
    • - - option_set - - : - - (string) - - the name of the option set to add this element to - -
    • - - - - - -
    • - - option_name - - : - - (string) - - the name of this option that will be used to identify it - -
    • - - -
    - - - - - Returns: -
      -
    • - (self) - the define to allow chaining -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - Checkbox._prototype_radiobutton:get_store(category, internal) -
    -
    -
    -
    - -

    Gets the stored value of the radiobutton or the option set if present

    -

    - - - Parameters: - -
      - - - - - -
    • - - category - - : - - (string) - - [opt] the category to get such as player name or force name - -
    • - - - - - -
    • - - internal - - : - - (boolean) - - used to prevent stackover flow - -
    • - - -
    - - - - - Returns: -
      -
    • - (any) - the value that is stored for this define -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - Checkbox._prototype_radiobutton:set_store(category, value, internal) -
    -
    -
    -
    - -

    Sets the stored value of the radiobutton or the option set if present

    -

    - - - Parameters: - -
      - - - - - -
    • - - category - - : - - (string) - - [opt] the category to get such as player name or force name - -
    • - - - - - -
    • - - value - - : - - (boolean) - - the value to set for this define, must be valid for its type ie for checkbox etc - -
    • - - - - - -
    • - - internal - - : - - (boolean) - - used to prevent stackover flow - -
    • - - -
    - - - - - Returns: -
      -
    • - (boolean) - true if the value was set -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - Checkbox.new_option_set(callback, categorize) -
    -
    -
    -
    - -

    Registers a new option set that can be linked to radiobuttons (only one can be true at a time)

    -

    - - - Parameters: - -
      - - - - - -
    • - - callback - - : - - (function) - - the update callback when the value of the option set changes - callback param - value string - the new selected option for this option set - callback param - category string - the category that updated if categorize was used - -
    • - - - - - -
    • - - categorize - - : - - (function) - - the function used to convert an element into a string - -
    • - - -
    - - - - - Returns: -
      -
    • - (string) - the name of this option set to be passed to add_as_option -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - Checkbox.draw_option_set(name, element) -
    -
    -
    -
    - -

    Draws all radiobuttons that are part of an option set at once (Gui.draw will not work)

    -

    - - - Parameters: - -
      - - - - - -
    • - - name - - : - - (string) - - the name of the option set to draw the radiobuttons of - -
    • - - - - - -
    • - - element - - : - - (LuaGuiElement) - - the parent element that the radiobuttons will be drawn to - -
    • - - -
    - - - - - - - - - - - - - -
    -
    -
    -
    - # - Checkbox.reset_radiobuttons(element[, exclude][, recursive=false]) -
    -
    -
    -
    - -

    Sets all radiobutton in a element to false (unless excluded) and can act recursively

    -

    - - - Parameters: - -
      - - - - - -
    • - - element - - : - - (LuaGuiElement) - - the root gui element to start setting radio buttons from - -
    • - - - - - -
    • - - exclude - - : - - (table) - - ?string|table the name of the radiobutton to exclude or a of radiobuttons where true will set the state true - - (optional) -
    • - - - - - -
    • - - recursive - - : - - (number or boolean) - - if true will recur as much as possible, if a will recur that number of times - - (default: false) -
    • - - -
    - - - - - Returns: -
      -
    • - (boolean) - true if successful -
    • -
    - - - - - - - - - -
    -
    -

    Dropdowns

    -
    -
    -
    -
    - # - expcore.gui.core -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - expcore.gui.prototype -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - utils.game -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - Dropdown.new_dropdown([name]) -
    -
    -
    -
    - -

    Creates a new dropdown element define

    -

    - - - Parameters: - -
      - - - - - -
    • - - name - - : - - (string) - - the optional debug name that can be added - - (optional) -
    • - - -
    - - - - - Returns: -
      -
    • - (table) - the new dropdown element define -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - Dropdown.new_list_box([name]) -
    -
    -
    -
    - -

    Creates a new list box element define

    -

    - - - Parameters: - -
      - - - - - -
    • - - name - - : - - (string) - - the optional debug name that can be added - - (optional) -
    • - - -
    - - - - - Returns: -
      -
    • - (table) - the new list box element define -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - Dropdown._prototype:new_static_options(options[, ...], the) -
    -
    -
    -
    - -

    Adds new static options to the dropdown which will trigger the general callback

    -

    - - - Parameters: - -
      - - - - - -
    • - - options - - : - - (table) - - ?string|table either a of option strings or the first option string, with a table values are the options - -
    • - - - - - -
    • - - ... - - : - - (table) - - when options is not a you can add the options one after each other - - (optional) -
    • - - - - - -
    • - - the - - : - - (self) - - define to allow chaining - -
    • - - -
    - - - - - - - - - - - - - -
    -
    -
    -
    - # - Dropdown._prototype:new_dynamic_options(callback) -
    -
    -
    -
    - -

    Adds a callback which should return a table of values to be added as options for the dropdown (appended after static options)

    -

    - - - Parameters: - -
      - - - - - -
    • - - callback - - : - - (function) - - the function that will run to get the options for the dropdown - callback param - player LuaPlayer - the player that the element is being drawn to - callback param - element LuaGuiElement - the element that is being drawn - callback return - table - the values of this table will be appended to the static options of the dropdown - -
    • - - -
    - - - - - Returns: -
      -
    • - (self) - the define to allow chaining -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - Dropdown._prototype:add_option_callback(option, callback) -
    -
    -
    -
    - -

    Adds a case specific callback which will only run when that option is selected (general case still triggered)

    -

    - - - Parameters: - -
      - - - - - -
    • - - option - - : - - (string) - - the name of the option to trigger the callback on; if not already added then will be added as an option - -
    • - - - - - -
    • - - callback - - : - - (function) - - the function that will be called when that option is selected - callback param - player LuaPlayer - the player who owns the gui element - callback param - element LuaGuiElement - the element which is being effected - callback param - value string - the new option that has been selected - -
    • - - -
    - - - - - Returns: -
      -
    • - (self) - the define to allow chaining -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - Dropdown.select_value(element, value) -
    -
    -
    -
    - -

    Selects the option from a dropdown or list box given the value rather than key

    -

    - - - Parameters: - -
      - - - - - -
    • - - element - - : - - (LuaGuiElement) - - the element that contains the option - -
    • - - - - - -
    • - - value - - : - - (string) - - the option to select from the dropdown - -
    • - - -
    - - - - - Returns: -
      -
    • - (number) - the key where the value was -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - Dropdown.get_selected_value(element) -
    -
    -
    -
    - -

    Returns the currently selected value rather than index

    -

    - - - Parameters: - -
      - - - - - -
    • - - element - - : - - (LuaGuiElement) - - the gui element that you want to get the value of - -
    • - - -
    - - - - - Returns: -
      -
    • - (string) - the value that is currently selected -
    • -
    - - - - - - - - - -
    -
    -

    Elem Buttons

    -
    -
    -
    -
    - # - expcore.gui.core -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - expcore.gui.prototype -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - utils.game -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - ElemButton.new_elem_button([name]) -
    -
    -
    -
    - -

    Creates a new elem button element define

    -

    - - - Parameters: - -
      - - - - - -
    • - - name - - : - - (string) - - the optional debug name that can be added - - (optional) -
    • - - -
    - - - - - Returns: -
      -
    • - (table) - the new elem button element define -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - ElemButton._prototype.set_type -
    -
    -
    -
    - -

    Sets the type of the elem button, the type is required so this must be called at least once

    -

    - - - -
      - - - - - -
    • - - type - - : - - (string) - - the type that this elem button is see factorio api - -
    • - - -
    - - - - - - - - - - - - - -
    -
    -
    -
    - # - ElemButton._prototype:set_default(value) -
    -
    -
    -
    - -

    Sets the default value for the elem button, this may be a function or a string

    -

    - - - Parameters: - -
      - - - - - -
    • - - value - - : - - (string or function) - - string a will be a static default and a function will be called when drawn to get the default - -
    • - - -
    - - - - - Returns: -
      -
    • - (the) - element define to allow for chaining -
    • -
    - - - - - - - - - -
    -
    -

    Progress Bars

    -
    -
    -
    -
    - # - expcore.gui.core -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - expcore.gui.prototype -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - utils.global -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - utils.game -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - ProgressBar.set_maximum(element, amount) -
    -
    -
    -
    - -

    Sets the maximum value that represents the end value of the progress bar

    -

    - - - Parameters: - -
      - - - - - -
    • - - element - - : - - (LuaGuiElement or string) - - either a gui element or a registered define - -
    • - - - - - -
    • - - amount - - : - - (number) - - the amount to have set as the maximum - -
    • - - -
    - - - - - - - - - - - - - -
    -
    -
    -
    - # - ProgressBar.increment(element[, amount=1]) -
    -
    -
    -
    - -

    Increases the value of the progressbar, if a define is given all of its instances have incremented

    -

    - - - Parameters: - -
      - - - - - -
    • - - element - - : - - (LuaGuiElement or string) - - either a gui element or a registered define - -
    • - - - - - -
    • - - amount - - : - - (number) - - the amount to increase the progressbar by - - (default: 1) -
    • - - -
    - - - - - - - - - - - - - -
    -
    -
    -
    - # - ProgressBar.decrement(element[, amount=1]) -
    -
    -
    -
    - -

    Decreases the value of the progressbar, if a define is given all of its instances have decremented

    -

    - - - Parameters: - -
      - - - - - -
    • - - element - - : - - (LuaGuiElement or string) - - either a gui element or a registered define - -
    • - - - - - -
    • - - amount - - : - - (number) - - the amount to decrease the progressbar by - - (default: 1) -
    • - - -
    - - - - - - - - - - - - - -
    -
    -
    -
    - # - ProgressBar.new_progressbar([name]) -
    -
    -
    -
    - -

    Creates a new progressbar element define

    -

    - - - Parameters: - -
      - - - - - -
    • - - name - - : - - (string) - - the optional debug name that can be added - - (optional) -
    • - - -
    - - - - - Returns: -
      -
    • - (table) - the new progressbar element define -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - ProgressBar._prototype:set_default_maximum(amount) -
    -
    -
    -
    - -

    Sets the maximum value that represents the end value of the progress bar

    -

    - - - Parameters: - -
      - - - - - -
    • - - amount - - : - - (number) - - the amount to have set as the maximum - -
    • - - -
    - - - - - Returns: -
      -
    • - (table) - the define to allow chaining -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - ProgressBar._prototype:use_count_down([state=true]) -
    -
    -
    -
    - -

    Will set the progress bar to start at 1 and trigger when it hits 0

    -

    - - - Parameters: - -
      - - - - - -
    • - - state - - : - - (boolean) - - when true the bar will start filled, to be used with decrease - - (default: true) -
    • - - -
    - - - - - Returns: -
      -
    • - (table) - the define to allow chaining -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - ProgressBar._prototype:increment([amount=1][, category]) -
    -
    -
    -
    - -

    Increases the value of the progressbar

    -

    - - - Parameters: - -
      - - - - - -
    • - - amount - - : - - (number) - - the amount to increase the progressbar by - - (default: 1) -
    • - - - - - -
    • - - category - - : - - (string) - - the category that is used with a store - - (optional) -
    • - - -
    - - - - - - - - - - - - - -
    -
    -
    -
    - # - ProgressBar._prototype:increment_filtered([amount=1], filter) -
    -
    -
    -
    - -

    Increases the value of the progressbar, if the filter condition is met, does not work with store

    -

    - - - Parameters: - -
      - - - - - -
    • - - amount - - : - - (number) - - the amount to increase the progressbar by - - (default: 1) -
    • - - - - - -
    • - - filter - - : - - (function) - - the filter to be used - -
    • - - -
    - - - - - - - - - - - - - -
    -
    -
    -
    - # - ProgressBar._prototype:decrement([amount=1][, category]) -
    -
    -
    -
    - -

    Decreases the value of the progressbar

    -

    - - - Parameters: - -
      - - - - - -
    • - - amount - - : - - (number) - - the amount to decrease the progressbar by - - (default: 1) -
    • - - - - - -
    • - - category - - : - - (string) - - the category that is used with a store - - (optional) -
    • - - -
    - - - - - - - - - - - - - -
    -
    -
    -
    - # - ProgressBar._prototype:decrement_filtered([amount=1], filter) -
    -
    -
    -
    - -

    Decreases the value of the progressbar, if the filter condition is met, does not work with store

    -

    - - - Parameters: - -
      - - - - - -
    • - - amount - - : - - (number) - - the amount to decrease the progressbar by - - (default: 1) -
    • - - - - - -
    • - - filter - - : - - (function) - - the filter to be used - -
    • - - -
    - - - - - - - - - - - - - -
    -
    -
    -
    - # - ProgressBar._prototype:add_element(element[, maximum]) -
    -
    -
    -
    - -

    Adds an element into the list of instances that will are waiting to complete, does not work with store - note use store if you want persistent data, this only stores the elements not the values which they have

    -

    - - - Parameters: - -
      - - - - - -
    • - - element - - : - - (LuaGuiElement) - - the element that you want to add into the waiting to complete list - -
    • - - - - - -
    • - - maximum - - : - - (number) - - the maximum for this element if not given the default for this define is used - - (optional) -
    • - - -
    - - - - - - - - - - - - - -
    -
    -
    -
    - # - ProgressBar._prototype:reset_element(element) -
    -
    -
    -
    - -

    Resets an element, or its store, to be back at the start, either 1 or 0

    -

    - - - Parameters: - -
      - - - - - -
    • - - element - - : - - (LuaGuiElement) - - the element that you want to reset the progress of - -
    • - - -
    - - - - - - - - - - - - - -
    -
    -
    -
    - # - ProgressBar._prototype:event_counter([filter]) -
    -
    -
    -
    - -

    Event handler factory that counts up by 1 every time the event triggers, can filter which elements have incremented

    -

    - - - Parameters: - -
      - - - - - -
    • - - filter - - : - - (function) - - when given will use filtered increment - - (optional) -
    • - - -
    - - - - - Returns: -
      -
    • - (function) - the event handler -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - ProgressBar._prototype:event_countdown([filter]) -
    -
    -
    -
    - -

    Event handler factory that counts down by 1 every time the event triggers, can filter which elements have decremented

    -

    - - - Parameters: - -
      - - - - - -
    • - - filter - - : - - (function) - - when given will use filtered decrement - - (optional) -
    • - - -
    - - - - - Returns: -
      -
    • - (function) - the event handler -
    • -
    - - - - - - - - - -
    -
    -

    Sliders

    -
    -
    -
    -
    - # - expcore.gui.core -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - expcore.gui.prototype -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - expcore.gui.instances -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - utils.game -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - Slider.new_slider([name]) -
    -
    -
    -
    - -

    Creates a new slider element define

    -

    - - - Parameters: - -
      - - - - - -
    • - - name - - : - - (string) - - the optional debug name that can be added - - (optional) -
    • - - -
    - - - - - Returns: -
      -
    • - (table) - the new slider element define -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - Slider._prototype:set_range([min][, max]) -
    -
    -
    -
    - -

    Sets the range of a slider, if not used will use default values for a slider

    -

    - - - Parameters: - -
      - - - - - -
    • - - min - - : - - (number) - - the minimum value that the slider can take - - (optional) -
    • - - - - - -
    • - - max - - : - - (number) - - the maximum value that the slider can take - - (optional) -
    • - - -
    - - - - - Returns: -
      -
    • - (self) - the define to allow chaining -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - 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

    -

    - - - Parameters: - -
      - - - - - -
    • - - element - - : - - (LuaGuiElement) - - the parent element that the label will be drawn to - -
    • - - -
    - - - - - Returns: -
      -
    • - (LuaGuiElement) - the new label element so that styles can be applied -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - Slider._prototype:enable_auto_draw_label([state=true]) -
    -
    -
    -
    - -

    Enables auto draw of the label, the label will share the same parent element as the slider

    -

    - - - Parameters: - -
      - - - - - -
    • - - state - - : - - (boolean) - - when false will disable the auto draw of the label - - (default: true) -
    • - - -
    - - - - - Returns: -
      -
    • - (self) - the define to allow chaining -
    • -
    - - - - - - - - - -
    -
    -

    Text

    -
    -
    -
    -
    - # - expcore.gui.core -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - expcore.gui.prototype -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - utils.game -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - Text.new_text_field([name]) -
    -
    -
    -
    - -

    Creates a new text field element define

    -

    - - - Parameters: - -
      - - - - - -
    • - - name - - : - - (string) - - the optional debug name that can be added - - (optional) -
    • - - -
    - - - - - Returns: -
      -
    • - (table) - the new text field element define -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - Text.new_text_box([name]) -
    -
    -
    -
    - -

    Creates a new text box element define

    -

    - - - Parameters: - -
      - - - - - -
    • - - name - - : - - (string) - - the optional debug name that can be added - - (optional) -
    • - - -
    - - - - - Returns: -
      -
    • - (table) - the new text box element define -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - Text._prototype_box:set_selectable([state=true]) -
    -
    -
    -
    - -

    Sets the text box to be selectable

    -

    - - - Parameters: - -
      - - - - - -
    • - - state - - : - - (boolean) - - when false will set the state to false - - (default: true) -
    • - - -
    - - - - - Returns: -
      -
    • - (self) - table the define to allow for chaining -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - Text._prototype_box:set_word_wrap([state=true]) -
    -
    -
    -
    - -

    Sets the text box to have word wrap

    -

    - - - Parameters: - -
      - - - - - -
    • - - state - - : - - (boolean) - - when false will set the state to false - - (default: true) -
    • - - -
    - - - - - Returns: -
      -
    • - (self) - table the define to allow for chaining -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - Text._prototype_box:set_read_only([state=true]) -
    -
    -
    -
    - -

    Sets the text box to be read only

    -

    - - - Parameters: - -
      - - - - - -
    • - - state - - : - - (boolean) - - when false will set the state to false - - (default: true) -
    • - - -
    - - - - - Returns: -
      -
    • - (self) - table the define to allow for chaining -
    • -
    - - - - - - - - - -
    -
    -

    Instances

    -
    -
    -
    -
    - # - utils.global -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - Instances.has_categories(name) -
    -
    -
    -
    - -

    Returns if a instance group has a serializer function; must be registered

    -

    - - - Parameters: - -
      - - - - - -
    • - - name - - : - - (string) - - the name of the instance group - -
    • - - -
    - - - - - Returns: -
      -
    • - (boolean) - true if there is a serializer function -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - Instances.is_registered(name) -
    -
    -
    -
    - -

    Returns if the given name is a registered instance group

    -

    - - - Parameters: - -
      - - - - - -
    • - - name - - : - - (string) - - the name of the instance group you are testing - -
    • - - -
    - - - - - Returns: -
      -
    • - (boolean) - true if the name is registered -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - Instances.register(name[, serializer]) -
    -
    -
    -
    - -

    Registers the name of an instance group to allow for storing element instances

    -

    - - - Parameters: - -
      - - - - - -
    • - - name - - : - - (string) - - the name of the instance group; must to unique - -
    • - - - - - -
    • - - serializer - - : - - (function) - - function used to turn the element into a string - serializer param - element LuaGuiElement - the gui element to be turned into a string - serializer return - string - the category that the element will be added to like the player's name or force's name - - (optional) -
    • - - -
    - - - - - Returns: -
      -
    • - (string) - the name that was added so it can be used as a variable -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - Instances.add_element(name, element) -
    -
    -
    -
    - -

    Adds an element to the instance group under the correct category; must be registered

    -

    - - - Parameters: - -
      - - - - - -
    • - - name - - : - - (string) - - the name of the instance group to add the element to - -
    • - - - - - -
    • - - element - - : - - (LuaGuiElement) - - the element to add the the instance group - -
    • - - -
    - - - - - - - - - - - - - -
    -
    -
    -
    - # - Instances.get_elements_raw(name[, category]) -
    -
    -
    -
    - -

    Gets all element instances without first removing any invalid ones; used internally and must be registered

    -

    - - - Parameters: - -
      - - - - - -
    • - - name - - : - - (string) - - the name of the instance group to get the instances of - -
    • - - - - - -
    • - - category - - : - - (string) - - the category to get the instance from, not needed when no serializer function - - (optional) -
    • - - -
    - - - - - Returns: -
      -
    • - (table) - the table of element instances of which some may be invalid -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - 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

    -

    - - - Parameters: - -
      - - - - - -
    • - - name - - : - - (string) - - the name of the instance group to get the instances of - -
    • - - - - - -
    • - - category - - : - - (string) - - the category to get the instances of, not needed when no serializer function - - (optional) -
    • - - - - - -
    • - - callback - - : - - (function) - - when given the callback will be ran on all valid elements - callback param - element LuaGuiElement - the current valid element - - (optional) -
    • - - -
    - - - - - Returns: -
      -
    • - (table) - the table of element instances with all invalid ones removed -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - Instances.unregistered_add_element(name, category, element) -
    -
    -
    -
    - -

    A version of add_element that does not require the group to be registered

    -

    - - - Parameters: - -
      - - - - - -
    • - - name - - : - - (string) - - the name of the instance group to add the element to - -
    • - - - - - -
    • - - category - - : - - (string or nil) - - the category to add the element to, can be nil but must still be given - -
    • - - - - - -
    • - - element - - : - - (LuaGuiElement) - - the element to add to the instance group - -
    • - - -
    - - - - - - - - - - - - - -
    -
    -
    -
    - # - Instances.unregistered_get_elements(name, category[, callback]) -
    -
    -
    -
    - -

    A version of get_elements that does not require the group to be registered

    -

    - - - Parameters: - -
      - - - - - -
    • - - name - - : - - (string) - - the name of the instance group to get the instances of - -
    • - - - - - -
    • - - category - - : - - (string or nil) - - the category to get the instances of, can be nil but must still be given - -
    • - - - - - -
    • - - callback - - : - - (function) - - when given will be called on all valid instances - callback param - element LuaGuiElement - the current valid element - - (optional) -
    • - - -
    - - - - - Returns: -
      -
    • - (table) - the table of element instances with all invalid ones removed -
    • -
    - - - - - - - - - -
    -
    -

    Prototype

    -
    -
    -
    -
    - # - utils.game -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - expcore.store -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - expcore.gui.instances -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - Constructor.event(event_name) -
    -
    -
    -
    - -

    Creates a new function to add functions to an event handler

    -

    - - - Parameters: - -
      - - - - - -
    • - - event_name - - : - - (string) - - the name of the event that callbacks will be added to - -
    • - - -
    - - - - - Returns: -
      -
    • - (function) - the function used to register handlers -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - Constructor.extend(new_prototype) -
    -
    -
    -
    - -

    Extents a prototype with the base functions of all gui prototypes, no metatables

    -

    - - - Parameters: - -
      - - - - - -
    • - - new_prototype - - : - - (table) - - the prototype that you want to add the functions to - -
    • - - -
    - - - - - Returns: -
      -
    • - (table) - the same prototype but with the new functions added -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - Constructor.store(callback) -
    -
    -
    -
    - -

    Creates a new function which adds a store to a gui define

    -

    - - - Parameters: - -
      - - - - - -
    • - - callback - - : - - (function) - - the function called when needing to update the value of an element - -
    • - - -
    - - - - - Returns: -
      -
    • - (function) - the function that will add a store for this define -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - Constructor.setter(value_type, key[, second_key]) -
    -
    -
    -
    - -

    Creates a setter function that checks the type when a value is set

    -

    - - - Parameters: - -
      - - - - - -
    • - - value_type - - : - - (string) - - the type that the value should be when it is set - -
    • - - - - - -
    • - - key - - : - - (string) - - the key of the define that will be set + the sprite that you want to use on the button
    • @@ -9941,255 +2451,47 @@
    • - second_key - - : - - (string) - - allows for setting of a key in a sub table - - (optional) -
    • - - -
    - - - - - Returns: -
      -
    • - (function) - the function that will check the type and set the value -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - Prototype:uid() -
    -
    -
    -
    - -

    Gets the uid for the element define

    -

    - - - - - - Returns: -
      -
    • - (string) - the uid of this element define -
    • -
    - - - - - - - - - -
    -
    -
    -
    - # - Prototype.debug_name -
    -
    -
    -
    - -

    Sets a debug alias for the define

    -

    - - - -
      - - - - - -
    • - - name - - : - - (string) - - the debug name for the element define that can be used to get this element define - -
    • - - -
    - - - - - - - - - - - - - -
    -
    -
    -
    - # - Prototype.set_caption -
    -
    -
    -
    - -

    Sets the caption for the element define

    -

    - - - -
      - - - - - -
    • - - caption - - : - - (string) - - the caption that will be drawn with the element - -
    • - - -
    - - - - - - - - - - - - - -
    -
    -
    -
    - # - Prototype.set_tooltip -
    -
    -
    -
    - -

    Sets the tooltip for the element define

    -

    - - - -
      - - - - - -
    • - tooltip : - (string) + (string or LocalizedString) - the tooltip that will be displayed for this element when drawn + the tooltip that you want the button to have
    • -
    - - - - - - - - - +
  • -
  • -
    -
    -
    - # - Prototype.set_pre_authenticator -
    -
    -
    -
    + element_define -

    Sets an authenticator that blocks the draw function if check fails

    -

    + : - + (table) -
      + the element define that you want to have toggled by this button, define must exist on the left flow + + -
    • +
    • - callback + authenticator : (function) - 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 + used to decide if the button should be visible to a player + (optional)
    • @@ -10205,174 +2507,26 @@ + Usage: +
      -- Add a button to toggle a left element
      +local toolbar_button =
      +Gui.left_toolbar_button('entity/inserter', 'Nothing to see here', example_flow_with_button, function(player)
      +    return player.admin
      +end)
    - # - Prototype.set_post_authenticator + # + draw_left_flow(player)
    -

    Sets an authenticator that disables the element if check fails

    -

    - - - -
      - - - - - -
    • - - callback - - : - - (function) - - 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 - -
    • - - -
    - - - - - - - - - - - - - -
    -
    -
    -
    - # - Prototype.on_draw -
    -
    -
    -
    - -

    Registers a callback to the on_draw event

    -

    - - - -
      - - - - - -
    • - - callback - - : - - (function) - - - 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_style_update -
    -
    -
    -
    - -

    Registers a callback to the on_style_update event

    -

    - - - -
      - - - - - -
    • - - callback - - : - - (function) - - - callback param - LuaStyle style - the style that was changed and/or needs changing - -
    • - - -
    - - - - - - - - - - - - - -
    -
    -
    -
    - # - Prototype:set_style(style[, callback]) -
    -
    -
    -
    - -

    Sets the style for the element define

    +

    Draw all the left elements onto the left flow, internal use only with on join

    @@ -10386,13 +2540,179 @@
  • - style + player : - (string) + (LuaPlayer) - the style that will be used for this element when drawn + the player that you want to draw the elements for + +
  • + + + + + + + + + + + + + + + Usage: +
    -- Draw all the left elements
    +Gui.draw_left_flow(player)
    + + +
    +
    +
    +
    + # + update_left_flow(player) +
    +
    +
    +
    + +

    Update the visible state of the hide button, can be used to check if any frames are visible

    +

    + + + Parameters: + +
      + + + + + +
    • + + player + + : + + (LuaPlayer) + + the player to update the left flow for + +
    • + + +
    + + + + + Returns: +
      +
    • + (boolean) + true if any left element is visible +
    • +
    + + + + + + + + Usage: +
    -- Check if any left elements are visible
    +local visible = Gui.update_left_flow(player)
    + + +
    +
    +
    +
    + # + hide_left_flow(player) +
    +
    +
    +
    + +

    Hides all left elements for a player

    +

    + + + Parameters: + +
      + + + + + +
    • + + player + + : + + (LuaPlayer) + + the player to hide the elements for + +
    • + + +
    + + + + + + + + + + + + Usage: +
    -- Hide your left elements
    +Gui.hide_left_flow(game.player)
    + + +
    +
    +
    +
    + # + get_left_element(player, element_define) +
    +
    +
    +
    + +

    Get the element define that is in the left flow, use in events without an element refrence

    +

    + + + Parameters: + +
      + + + + + +
    • + + player + + : + + (LuaPlayer) + + the player that you want to get the element for
    • @@ -10402,13 +2722,105 @@
    • - callback + element_define : - (function) + (table) - function is called when element is drawn to alter its style + the element that you want to get + +
    • + + +
    + + + + + Returns: +
      +
    • + (LuaGuiElement) + the gui element linked to this define for this player +
    • +
    + + + + + + + + Usage: +
    -- Get your left element
    +local frame = Gui.get_left_element(game.player, example_flow_with_button)
    + + +
    +
    +
    +
    + # + toggle_left_element(player, element_define[, state]) +
    +
    +
    +
    + +

    Toggles the visible state of a left element for a given player, can be used to set the visible state

    +

    + + + Parameters: + +
      + + + + + +
    • + + player + + : + + (LuaPlayer) + + the player that you want to toggle the element for + +
    • + + + + + +
    • + + element_define + + : + + (table) + + the element that you want to toggle + +
    • + + + + + +
    • + + state + + : + + (boolean) + + with given will set the state, else state will be toggled (optional)
    • @@ -10422,8 +2834,8 @@ Returns:
      • - (self) - the element define to allow chaining + (boolean) + the new visible state of the element
      @@ -10433,20 +2845,28 @@ + Usage: +
      -- Toggle your example button
      +Gui.toggle_top_flow(game.player, example_flow_with_button)
      +
      -- Show your example button
      +Gui.toggle_top_flow(game.player, example_flow_with_button, true)
    +
    +

    Element Define

    +
    - # - Prototype:set_embedded_flow(state) + # + element(element_define)
    -

    Sets the element to be drawn inside a nameless flow, can be given a name using a function

    +

    Used to define new elements for your gui, can be used like LuaGuiElement.add or a custom function

    @@ -10460,13 +2880,13 @@
  • - state + element_define : - (boolean or function) + (table or function) - when true a padless flow is created to contain the element + the define information for the gui element, same data as LuaGuiElement.add, or a custom function may be used
  • @@ -10479,8 +2899,8 @@ Returns:
    • - (self) - the element define to allow chaining + (table) + the new element define, this can be considered a factory for the element which can be called to draw the element to any other element
    @@ -10490,20 +2910,140 @@ + Usage: +
    -- Using element defines like LuaGuiElement.add
    +-- This returns a factory function to draw a button with the caption "Example Button"
    +local example_button =
    +Gui.element{
    +    type = 'button',
    +    caption = 'Example Button'
    +}
    +
    -- Using element defines with a custom factory function
    +-- This method can be used if you still want to be able register event handlers but it is too complex to be compatible with LuaGuiElement.add
    +local example_flow_with_button =
    +Gui.element(function(event_trigger,parent,...)
    +    -- ... shows that all other arguments from the factory call are passed to this function
    +    -- parent is the element which was passed to the factory function where you should add your new element
    +    -- here we are adding a flow which we will then later add a button to
    +    local flow =
    +    parent.add{
    +        name = 'example_flow',
    +        type = 'flow'
    +    }
    +
    +    -- event_trigger should be the name of any elements you want to trigger your event handlers, such as on_click or on_state_changed
    +    -- now we add the button to the flow that we created earlier
    +    local element =
    +    flow.add{
    +        name = event_trigger,
    +        type = 'button',
    +        caption = 'Example Button'
    +    }
    +
    +    -- you must return your new element, this is so styles can be applied and returned to the caller
    +    -- you may return any of your elements that you add, consider the context in which it will be used for what should be returned
    +    return element
    +end)
    - # - Prototype:raise_event(event_name, ...) + # + Gui._prototype_element:style(style_define)
    -

    Raises a custom event for this define, any number of params can be given

    +

    Used to extent your element define with a style factory, this style will be applied to your element when created, can also be a custom function

    +

    + + + Parameters: + +
      + + + + + +
    • + + style_define + + : + + (table or function) + + style table where each key and value pair is treated like LuaGuiElement.style[key] = value, a custom function can be used + +
    • + + +
    + + + + + Returns: +
      +
    • + (table) + the element define is returned to allow for event handlers to be registered +
    • +
    + + + + + + + + Usage: +
    -- Using the table method of setting the style
    +local example_button =
    +Gui.element{
    +    type = 'button',
    +    caption = 'Example Button',
    +    style = 'forward_button' -- factorio styles can be applied here
    +}
    +:style{
    +    height = 25, -- same as element.style.height = 25
    +    width = 100 -- same as element.style.width = 25
    +}
    +
    -- Using the function method to set the style
    +-- Use this method if your style is dynamic and depends on other factors
    +local example_button =
    +Gui.element{
    +    type = 'button',
    +    caption = 'Example Button',
    +    style = 'forward_button' -- factorio styles can be applied here
    +}
    +:style(function(style,element,...)
    +    -- style is the current style object for the elemenent
    +    -- element is the element that is being changed
    +    -- ... shows that all other arguments from the factory call are passed to this function
    +    local player = game.players[element.player_index]
    +    style.height = 25
    +    style.width = 100
    +    style.font_color = player.color
    +end)
    + + +
    +
    +
    +
    + # + Gui._prototype_element:on_custom_event(event_name, handler) +
    +
    +
    +
    + +

    Set the handler which will be called for a custom event, only one handler can be used per event per element

    @@ -10523,7 +3063,7 @@ (string) - the name of the event that you want to raise + the name of the event you want to handler to be called on, often from Gui.events @@ -10533,13 +3073,13 @@
  • - ... + handler : - (any) + (function) - any params that you want to pass to the event + the handler that you want to be called when the event is raised
  • @@ -10552,8 +3092,8 @@ Returns:
    • - (number) - the number of handlers that were registered + (table) + the element define so more handleres can be registered
    @@ -10563,21 +3103,25 @@ + Usage: +
    -- Register a handler to "my_custom_event" for this element
    +element_deinfe:on_custom_event('my_custom_event', function(event)
    +    event.player.print(player.name)
    +end)
    - # - Prototype:draw_to(element) + # + Gui._prototype_element:raise_custom_event(event)
    -

    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

    +

    Raise the handler which is attached to an event; external use should be limited to custom events

    @@ -10591,13 +3135,799 @@
  • - element + event : - (LuaGuiElement) + (table) - the element that the define will draw a instance of its self onto + the event table passed to the handler, must contain fields: name, element + +
  • + + + + + + + + Returns: +
      +
    • + (table) + the element define so more events can be raised +
    • +
    + + + + + + + + Usage: +
     Raising a custom event
    +element_define:raise_custom_event{
    +    name = 'my_custom_event',
    +    element = element
    +}
    + + +
    +
    +

    Element Events

    +
    +
    +
    +
    + # + Gui._prototype_element.on_open +
    +
    +
    +
    + +

    Called when the player opens a GUI.

    +

    + + + +
      + + + + + +
    • + + handler + + : + + (function) + + the event handler which will be called + +
    • + + +
    + + + + + + + + + + + + Usage: +
     element_define:on_open(function(event)
    +  event.player.print(table.inspect(event))
    +end)
    + + +
    +
    +
    +
    + # + Gui._prototype_element.on_close +
    +
    +
    +
    + +

    Called when the player closes the GUI they have open.

    +

    + + + +
      + + + + + +
    • + + handler + + : + + (function) + + the event handler which will be called + +
    • + + +
    + + + + + + + + + + + + Usage: +
     element_define:on_close(function(event)
    +  event.player.print(table.inspect(event))
    +end)
    + + +
    +
    +
    +
    + # + Gui._prototype_element.on_click +
    +
    +
    +
    + +

    Called when LuaGuiElement is clicked.

    +

    + + + +
      + + + + + +
    • + + handler + + : + + (function) + + the event handler which will be called + +
    • + + +
    + + + + + + + + + + + + Usage: +
     element_define:on_click(function(event)
    +  event.player.print(table.inspect(event))
    +end)
    + + +
    +
    +
    +
    + # + Gui._prototype_element.on_confirmed +
    +
    +
    +
    + +

    Called when a LuaGuiElement is confirmed, for example by pressing Enter in a textfield.

    +

    + + + +
      + + + + + +
    • + + handler + + : + + (function) + + the event handler which will be called + +
    • + + +
    + + + + + + + + + + + + Usage: +
     element_define:on_confirmed(function(event)
    +  event.player.print(table.inspect(event))
    +end)
    + + +
    +
    +
    +
    + # + Gui._prototype_element.on_checked_changed +
    +
    +
    +
    + +

    Called when LuaGuiElement checked state is changed (related to checkboxes and radio buttons).

    +

    + + + +
      + + + + + +
    • + + handler + + : + + (function) + + the event handler which will be called + +
    • + + +
    + + + + + + + + + + + + Usage: +
     element_define:on_checked_changed(function(event)
    +  event.player.print(table.inspect(event))
    +end)
    + + +
    +
    +
    +
    + # + Gui._prototype_element.on_elem_changed +
    +
    +
    +
    + +

    Called when LuaGuiElement element value is changed (related to choose element buttons).

    +

    + + + +
      + + + + + +
    • + + handler + + : + + (function) + + the event handler which will be called + +
    • + + +
    + + + + + + + + + + + + Usage: +
     element_define:on_elem_changed(function(event)
    +  event.player.print(table.inspect(event))
    +end)
    + + +
    +
    +
    +
    + # + Gui._prototype_element.on_location_changed +
    +
    +
    +
    + +

    Called when LuaGuiElement element location is changed (related to frames in player.gui.screen).

    +

    + + + +
      + + + + + +
    • + + handler + + : + + (function) + + the event handler which will be called + +
    • + + +
    + + + + + + + + + + + + Usage: +
     element_define:on_location_changed(function(event)
    +  event.player.print(table.inspect(event))
    +end)
    + + +
    +
    +
    +
    + # + Gui._prototype_element.on_tab_changed +
    +
    +
    +
    + +

    Called when LuaGuiElement selected tab is changed (related to tabbed-panes).

    +

    + + + +
      + + + + + +
    • + + handler + + : + + (function) + + the event handler which will be called + +
    • + + +
    + + + + + + + + + + + + Usage: +
     element_define:on_tab_changed(function(event)
    +  event.player.print(table.inspect(event))
    +end)
    + + +
    +
    +
    +
    + # + Gui._prototype_element.on_selection_changed +
    +
    +
    +
    + +

    Called when LuaGuiElement selection state is changed (related to drop-downs and listboxes).

    +

    + + + +
      + + + + + +
    • + + handler + + : + + (function) + + the event handler which will be called + +
    • + + +
    + + + + + + + + + + + + Usage: +
     element_define:on_selection_changed(function(event)
    +  event.player.print(table.inspect(event))
    +end)
    + + +
    +
    +
    +
    + # + Gui._prototype_element.on_switch_changed +
    +
    +
    +
    + +

    Called when LuaGuiElement switch state is changed (related to switches).

    +

    + + + +
      + + + + + +
    • + + handler + + : + + (function) + + the event handler which will be called + +
    • + + +
    + + + + + + + + + + + + Usage: +
     element_define:on_switch_changed(function(event)
    +  event.player.print(table.inspect(event))
    +end)
    + + +
    +
    +
    +
    + # + Gui._prototype_element.on_text_changed +
    +
    +
    +
    + +

    Called when LuaGuiElement text is changed by the player.

    +

    + + + +
      + + + + + +
    • + + handler + + : + + (function) + + the event handler which will be called + +
    • + + +
    + + + + + + + + + + + + Usage: +
     element_define:on_text_changed(function(event)
    +  event.player.print(table.inspect(event))
    +end)
    + + +
    +
    +
    +
    + # + Gui._prototype_element.on_value_changed +
    +
    +
    +
    + +

    Called when LuaGuiElement slider value is changed (related to the slider element).

    +

    + + + +
      + + + + + +
    • + + handler + + : + + (function) + + the event handler which will be called + +
    • + + +
    + + + + + + + + + + + + Usage: +
     element_define:on_value_changed(function(event)
    +  event.player.print(table.inspect(event))
    +end)
    + + +
    +
    +

    Top Flow

    +
    +
    +
    +
    + # + top_elements +
    +
    +
    +
    + +

    Contains the uids of the elements that will shown on the top flow and their auth functions

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + top_flow_button_style +
    +
    +
    +
    + +

    The style that should be used for buttons on the top flow

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + top_flow_button_visible_style +
    +
    +
    +
    + +

    The style that should be used for buttons on the top flow when their flow is visible

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + get_top_flow(player) +
    +
    +
    +
    + +

    Gets the flow refered to as the top flow, each player has one top flow

    +

    (player)

    + + + Parameters: + +
      + + + + + +
    • + + player + + : + + (LuaPlayer) + + the player that you want to get the flow for
    • @@ -10611,7 +3941,7 @@
      • (LuaGuiElement) - the new element that was drawn + the top element flow
      @@ -10621,20 +3951,23 @@ + Usage: +
      -- Geting your top flow
      +local top_flow = Gui.get_top_flow(game.player)
    - # - Prototype:get_store(category) + # + Gui._prototype_element:add_to_top_flow([authenticator])
    -

    Gets the value in this elements store, category needed if serializer function used

    +

    Sets an element define to be drawn to the top flow when a player joins, includes optional authenticator

    @@ -10648,14 +3981,15 @@
  • - category + authenticator : - (string) + (function) - [opt] the category to get such as player name or force name + called during toggle or update to decide weather the element should be visible + (optional)
  • @@ -10667,8 +4001,8 @@ Returns:
    • - (any) - the value that is stored for this define + (table) + the new element define to allow event handlers to be registered
    @@ -10678,20 +4012,27 @@ + Usage: +
    -- Adding an element to the top flow on join
    +example_button:add_to_top_flow(function(player)
    +    -- example button will only be shown if the player is an admin
    +    -- note button will not update its state when player.admin is changed Gui.update_top_flow must be called for this
    +    return player.admin
    +end)
    - # - Prototype:set_store(category, value) + # + update_top_flow(player)
    -

    Sets the value in this elements store, category needed if serializer function used

    +

    Updates the visible state of all the elements on the players top flow, uses authenticator

    @@ -10705,29 +4046,13 @@
  • - category + player : - (string) + (LuaPlayer) - [opt] the category to get such as player name or force name - -
  • - - - - - -
  • - - value - - : - - (any) - - the value to set for this define, must be valid for its type ie for checkbox etc + the player that you want to update the top flow for
  • @@ -10737,54 +4062,66 @@ - Returns: + + + + + + + + Usage: +
    -- Update your top flow
    +Gui.update_top_flow(game.player)
    + + +
    +
    +
    +
    + # + toggle_top_flow(player[, state]) +
    +
    +
    +
    + +

    Toggles the visible state of all the elements on a players top flow, effects all elements

    +

    + + + Parameters: +
      -
    • + + + + + +
    • + + player + + : + + (LuaPlayer) + + the player that you want to toggle the top flow for + +
    • + + + + + +
    • + + state + + : + (boolean) - true if the value was set -
    • -
    - - - - - - - - -
    -
    -
    -
    - # - Prototype:clear_store([category]) -
    -
    -
    -
    - -

    Sets the value in this elements store to nil, category needed if serializer function used

    -

    - - - Parameters: - -
      - - - - - -
    • - - category - - : - - (string) - - the category to get such as player name or force name + if given then the state will be set to this (optional)
    • @@ -10799,7 +4136,7 @@
      • (boolean) - true if the value was set + the new visible state of the top flow
      @@ -10809,24 +4146,160 @@ + Usage: +
      -- Toggle your flow
      +Gui.toggle_top_flow(game.player)
      +
      -- Open your top flow
      +Gui.toggle_top_flow(game.player,true)
    -
    -

    Test

    -
    - # - expcore.gui + # + get_top_element(player, element_define)
    +

    Get the element define that is in the top flow, use in events without an element refrence

    +

    + Parameters: + +
      + + + + + +
    • + + player + + : + + (LuaPlayer) + + the player that you want to get the element for + +
    • + + + + + +
    • + + element_define + + : + + (table) + + the element that you want to get + +
    • + + +
    + + + + + Returns: +
      +
    • + (LuaGuiElement) + the gui element linked to this define for this player +
    • +
    + + + + + + + + Usage: +
    -- Get your top element
    +local button = Gui.get_top_element(game.player, example_button)
    + + +
    +
    +
    +
    + # + toolbar_button(sprite, tooltip[, authenticator]) +
    +
    +
    +
    + +

    Creates a button on the top flow with consistent styling

    +

    + + + Parameters: + +
      + + + + + +
    • + + sprite + + : + + (string) + + the sprite that you want to use on the button + +
    • + + + + + +
    • + + tooltip + + : + + (string or LocalizedString) + + the tooltip that you want the button to have + +
    • + + + + + +
    • + + authenticator + + : + + (function) + + used to decide if the button should be visible to a player + + (optional) +
    • + + +
    + @@ -10837,96 +4310,68 @@ + Usage: +
    -- Add a button to the toolbar
    +local toolbar_button =
    +Gui.left_toolbar_button('entity/inserter', 'Nothing to see here', function(player)
    +    return player.admin
    +end)
    - # - expcore.common -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - resources.color_presets -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - utils.event -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - expcore.store + # + toolbar_button_style(button, state)
    +

    Styles a top flow button depending on the state given

    +

    + Parameters: + +
      + + + + + +
    • + + button + + : + + (LuaGuiElement) + + the button element to style + +
    • + + + + + +
    • + + state + + : + + (boolean) + + The state the button is in + +
    • + + +
    + @@ -10937,6 +4382,11 @@ + Usage: +
    -- Sets the button to the visible style
    +Gui.toolbar_button_style(button, true)
    +
    -- Sets the button to the hidden style
    +Gui.toolbar_button_style(button, false)
    @@ -10955,7 +4405,7 @@ generated by LDoc diff --git a/docs/core/Permissions-Groups.html b/docs/core/Permissions-Groups.html index 00b18e72..41fde465 100644 --- a/docs/core/Permissions-Groups.html +++ b/docs/core/Permissions-Groups.html @@ -53,13 +53,13 @@ @@ -88,10 +88,12 @@ + + @@ -100,8 +102,10 @@

    Guis

    @@ -139,7 +143,6 @@

    Configs

    @@ -172,18 +176,13 @@

    Modules

    @@ -230,7 +229,7 @@

    Permissions-Groups core

    Core Module - Permission Groups - - Permission group making for factorio so you never have to make one by hand again

    +- Permission group making for factorio so you never have to make one by hand again

    @@ -239,26 +238,22 @@

    Usage

    -
    
    ----- Example Group (Allow All)
    -
    -    -- here we will create an admin group however we do not want them to use the map editor or mess with the permission groups
    -    Permission_Groups.new_group('Admin') -- this defines a new group called "Admin"
    -    :allow_all() -- this makes the default to allow any input action unless set other wise
    -    :disallow{ -- here we disallow the input action we don't want them to use
    -        'add_permission_group',
    -        'delete_permission_group',
    -        'import_permissions_string',
    -        'map_editor_action',
    -        'toggle_map_editor'
    -    }
    -
    
    ----- Example Group (Disallow All)
    -
    -    -- here we will create a group that cant do anything but talk in chat
    -    Permission_Groups.new_group('Restricted') -- this defines a new group called "Restricted"
    -    :disallow_all() -- this makes the default to disallow any input action unless set other wise
    -    :allow('write_to_console') -- here we allow them to chat, {} can be used here if we had more than one action
    +    
    --- Example Group (Allow All)
    +-- here we will create an admin group however we do not want them to use the map editor or mess with the permission groups
    +Permission_Groups.new_group('Admin') -- this defines a new group called "Admin"
    +:allow_all() -- this makes the default to allow any input action unless set other wise
    +:disallow{ -- here we disallow the input action we don't want them to use
    +    'add_permission_group',
    +    'delete_permission_group',
    +    'import_permissions_string',
    +    'map_editor_action',
    +    'toggle_map_editor'
    +}
    +
    --- Example Group (Disallow All)
    +-- here we will create a group that cant do anything but talk in chat
    +Permission_Groups.new_group('Restricted') -- this defines a new group called "Restricted"
    +:disallow_all() -- this makes the default to disallow any input action unless set other wise
    +:allow('write_to_console') -- here we allow them to chat, {} can be used here if we had more than one action
     
    @@ -278,7 +273,7 @@ utils.event - expcore.sudo + expcore.async @@ -313,10 +308,6 @@ Reloads/creates all permission groups and sets them to they configured state - lockdown_permissions(exempt) - Removes all permissions from every permission group except for "Default" and any passed as exempt - - set_player_group(player, group) Sets a player's group to the one given, a player can only have one group at a time @@ -361,14 +352,14 @@ - Permissions_Groups._prototype:get_raw() - Returns the LuaPermissionGroup that was created with this group object, used internally - - Permissions_Groups._prototype:create() Creates or updates the permission group with the configured actions, used internally + Permissions_Groups._prototype:get_raw() + Returns the LuaPermissionGroup that was created with this group object, used internally + + Permissions_Groups._prototype:add_player(player) Adds a player to this group @@ -446,8 +437,8 @@
    - # - expcore.sudo + # + expcore.async
    @@ -525,6 +516,9 @@ + Usage: +
    -- Defining a new permission group
    +Groups.new_group('Admin')
    @@ -582,6 +576,9 @@ + Usage: +
    -- Getting a permision group
    +local admin_group = Groups.get_group_by_name('Admin')
    @@ -639,6 +636,9 @@ + Usage: +
    -- Get your permission group
    +local group = Groups.get_group_from_player(game.player)
    @@ -669,63 +669,9 @@ - - - -
    -
    -
    - # - lockdown_permissions(exempt) -
    -
    -
    -
    - -

    Removes all permissions from every permission group except for "Default" and any passed as exempt

    -

    - - - Parameters: - -
      - - - - - -
    • - - exempt - - : - - (string or Array) - - groups that you want to be except, "Default" is always exempt - -
    • - - -
    - - - - - Returns: -
      -
    • - (number) - the number of groups that had they permissions removed -
    • -
    - - - - - - - + Usage: +
    -- Reload the permission groups, used internally
    +Groups.reload_permissions()
    @@ -799,6 +745,9 @@ + Usage: +
    -- Set your permission group
    +Groups.set_player_group(game.player, 'Admin')
    @@ -875,6 +824,9 @@ + Usage: +
    -- Set an action to be disalowed
    +group:set_action('toggle_map_editor', false)
    @@ -932,6 +884,11 @@ + Usage: +
    -- Allow some actions
    +group:allow{
    +    'write_to_console'
    +}
    @@ -989,6 +946,15 @@ + Usage: +
    -- Disalow some actions
    +group:disallow{
    +    'add_permission_group',
    +    'delete_permission_group',
    +    'import_permissions_string',
    +    'map_editor_action',
    +    'toggle_map_editor'
    +}
    @@ -1023,6 +989,9 @@ + Usage: +
    -- Allow all actions unless given by disallow
    +group:allow_all()
    @@ -1057,6 +1026,9 @@ + Usage: +
    -- Disallow all actions unless given by allow
    +group:disallow_all()
    @@ -1114,6 +1086,9 @@ + Usage: +
    -- Test if a group is allowed an action
    +local allowed = group:is_allowed('write_to_console')
    @@ -1123,40 +1098,6 @@
    - # - Permissions_Groups._prototype:get_raw() -
    -
    -
    -
    - -

    Returns the LuaPermissionGroup that was created with this group object, used internally

    -

    - - - - - - Returns: - - - - - - - - - - -
    -
    -
    -
    # Permissions_Groups._prototype:create()
    @@ -1185,6 +1126,46 @@ + Usage: +
    -- Create the permission group so players can be added, used internally
    +group:create()
    + + + +
    +
    +
    + # + Permissions_Groups._prototype:get_raw() +
    +
    +
    +
    + +

    Returns the LuaPermissionGroup that was created with this group object, used internally

    +

    + + + + + + Returns: + + + + + + + + + Usage: +
    -- Get the factorio api permision group, used internally
    +local permission_group = group:get_raw()
    @@ -1242,6 +1223,9 @@ + Usage: +
    -- Add a player to this permission group
    +group:add_player(game.player)
    @@ -1299,6 +1283,9 @@ + Usage: +
    -- Remove a player from this permission group
    +group:remove_player(game.player)
    @@ -1357,6 +1344,11 @@ + Usage: +
    -- Get all players in this group
    +local online_players = group:get_players()
    +
    -- Get all online players in this group
    +local online_players = group:get_players(true)
    @@ -1414,6 +1406,9 @@ + Usage: +
    -- Print a message to all players in thie group
    +group:print('Hello, World!')
    @@ -1432,7 +1427,7 @@ generated by LDoc diff --git a/docs/core/Roles.html b/docs/core/Roles.html index 3f2be0c2..5a2def19 100644 --- a/docs/core/Roles.html +++ b/docs/core/Roles.html @@ -29,7 +29,7 @@

    ExpGaming Scenario

    -

    Explosive Gaming's server scenario for 0.17

    +

    Explosive Gaming's server scenario for 0.18

    @@ -57,13 +57,13 @@ @@ -92,10 +92,12 @@ + + @@ -104,8 +106,10 @@

    Guis

    @@ -143,7 +147,6 @@

    Configs

    @@ -176,18 +180,13 @@

    Modules

    @@ -238,7 +237,7 @@

    Roles core

    Core Module - Roles - - Factorio role system to manage custom permissions.

    +- Factorio role system to manage custom permissions.

    @@ -247,111 +246,107 @@

    Usage

    -
    
    ----- Using Role System (Frontend):
    -    When a map first starts you will want to define on mass all the players you expect to join and the roles to give them:
    -    Roles.override_player_roles{
    -        Cooldude2606 = {'Owner','Admin','Member'},
    -        NotCooldude2606 = {'Member'}
    -    }
    +    
    --- Using Role System (assignment):
    +--When a map first starts you will want to define on mass all the players you expect to join and the roles to give them:
    +Roles.override_player_roles{
    +    Cooldude2606 = {'Owner','Admin','Member'},
    +    NotCooldude2606 = {'Member'}
    +}
     
    -    Once the game is running you still want to be able to give role and remove them which is when you would use:
    -    Roles.assign_player(player,'Admin',by_player_name) -- this will give the "Admin" role to the player
    -    Roles.unassign_player(player,{'Admin','Moderator'},by_player_name) -- this will remove "Admin" and "Moderator" role in one go
    +--Once the game is running you still want to be able to give role and remove them which is when you would use:
    +Roles.assign_player(player,'Admin',by_player_name) -- this will give the "Admin" role to the player
    +Roles.unassign_player(player,{'Admin','Moderator'},by_player_name) -- this will remove "Admin" and "Moderator" role in one go
     
    -
    
    ----- Using Role System (Backend):
    -    To comparer two players you can comparer the index of they highest roles, can be used when you want to allow a "write" down type system:
    -    Roles.get_player_highest_role(playerOne).index < Roles.get_player_highest_role(playerTwo).index -- remember that less means a higher role
    +    
    --- Using Role System (role testing):
    +--To comparer two players you can comparer the index of they highest roles, can be used when you want to allow a "write" down type system:
    +Roles.get_player_highest_role(playerOne).index < Roles.get_player_highest_role(playerTwo).index -- remember that less means a higher role
     
    -    Listing all of a players roles can also be useful which is when you would want to use:
    -    Roles.get_player_roles(player) -- the return is an array that can be looped over however this is not in particular order
    +--Listing all of a players roles can also be useful which is when you would want to use:
    +Roles.get_player_roles(player) -- the return is an array that can be looped over however this is not in particular order
     
    -    Finally you may want to test if a player has a certain role, flag or action allowed which is when you would use:
    -    Roles.player_has_role(player,'Admin') -- you can provide a role name if you only want a name based system
    -    Roles.player_has_flag(player,'is_donator') -- your roles can be grouped together with flags such as is_donator
    -    Roles.player_allowed(player,'game modifiers') -- or you can have an action based system where each action is something the player can do
    +--Finally you may want to test if a player has a certain role, flag or action allowed which is when you would use:
    +Roles.player_has_role(player,'Admin') -- you can provide a role name if you only want a name based system
    +Roles.player_has_flag(player,'is_donator') -- your roles can be grouped together with flags such as is_donator
    +Roles.player_allowed(player,'game modifiers') -- or you can have an action based system where each action is something the player can do
     
    -
    
    ----- Example Flag Define:
    -    Flags can be used to group multiple roles and actions under one catch all, for example if you want a piece of code to only
    -    be active for your donators then you would add a "is_donator" flag to all your donator roles and then in the code test if
    -    a player has that tag present:
    +    
    --- Example Flag Define:
    +--Flags can be used to group multiple roles and actions under one catch all, for example if you want a piece of code to only
    +--be active for your donators then you would add a "is_donator" flag to all your donator roles and then in the code test if
    +--a player has that tag present:
    +
    +-- give you donators a speed boost when they join; these functions aren't required but can be useful
    +Roles.define_flag_trigger('is_donator',function(player,state)
    +    if state then
    +        player.character_running_speed_modifier = 1.5
    +    else
    +        player.character_running_speed_modifier = 1
    +    end
    +end)
     
    -    -- give you donators a speed boost when they join; these functions aren't required but can be useful
    -    Roles.define_flag_trigger('is_donator',function(player,state)
    -        if state then
    -            player.character_running_speed_modifier = 1.5
    -        else
    -            player.character_running_speed_modifier = 1
    -        end
    -    end)
    +-- then on all your donator roles you would add
    +Roles.new_role('Donator')
    +:set_flag('is_donator')
     
    -    -- then on all your donator roles you would add
    -    Roles.new_role('Donator')
    -    :set_flag('is_donator')
    +-- and in your code you would test for
    +if Roles.player_has_flag(player,'is_donator') then
    +    -- some donator only code
    +end
    +
    --- Example Role Define:
    +--You can't use a role system without any roles so first you must define your roles; each role has a minimum of a name with
    +--the option for a shorthand:
    +Roles.new_role('Administrator','Admin')
     
    -    -- and in your code you would test for
    -    if Roles.player_has_flag(player,'is_donator') then
    -        -- some donator only code
    -    end
    -
    
    ----- Example Role Define:
    -    You can't use a role system without any roles so first you must define your roles; each role has a minimum of a name with
    -    the option for a shorthand:
    -    Roles.new_role('Administrator','Admin')
    +--Next you will want to add any extras you want to have, such as a tag, colour, permission group or any custom flags:
    +Roles.new_role('Administrator','Admin')
    +:set_custom_tag('[Admin]')
    +:set_custom_color('red') -- this can be {r=0,g=0,b=0} or a predefined value
    +:set_permission_group('Staff') -- a second argument can be added if you have not used the custom permission group config
    +:set_flag('is_admin')
     
    -    Next you will want to add any extras you want to have, such as a tag, colour, permission group or any custom flags:
    -    Roles.new_role('Administrator','Admin')
    -    :set_custom_tag('[Admin]')
    -    :set_custom_color('red') -- this can be {r=0,g=0,b=0} or a predefined value
    -    :set_permission_group('Staff') -- a second argument can be added if you have not used the custom permission group config
    -    :set_flag('is_admin')
    +--You will then want to decide if you want to allow all actions, this should of course be used sparely:
    +Roles.new_role('Administrator','Admin')
    +...extras...
    +:set_allow_all()
     
    -    You will then want to decide if you want to allow all actions, this should of course be used sparely:
    -    Roles.new_role('Administrator','Admin')
    -    ...extras...
    -    :set_allow_all()
    +--If you don't do this want this as i would advise you do then you will want to define what the role can do; this comes with
    +--an optional inheritance system if you like those sort of things in which case disallow may also be of some use to you:
    +Roles.new_role('Administrator','Admin')
    +...extras...
    +:set_parent('Moderator') -- the admin can do anything that a moderator can do
    +:allow{ -- these actions can be anything just try to keep them without conflicts
    +    'command/kill',
    +    'gui/game settings'
    +}
     
    -    If you don't do this want this as i would advise you do then you will want to define what the role can do; this comes with
    -    an optional inheritance system if you like those sort of things in which case disallow may also be of some use to you:
    -    Roles.new_role('Administrator','Admin')
    -    ...extras...
    -    :set_parent('Moderator') -- the admin can do anything that a moderator can do
    -    :allow{ -- these actions can be anything just try to keep them without conflicts
    -        'command/kill',
    -        'gui/game settings'
    -    }
    +--Here is what the finished admin role would look like:
    +Roles.new_role('Administrator','Admin')
    +:set_custom_tag('[Admin]')
    +:set_custom_color('red')
    +:set_permission_group('Staff')
    +:set_flag('is_admin')
    +:set_parent('Moderator')
    +:allow{
    +    'command/kill',
    +    'gui/game settings'
    +}
    +
    --- Example System Define:
    +--Once all roles are defined these steps must be done to ensure the system is ready to use, this includes setting a default
    +--role, assigning a root (all permission) role that the server/system will use and the linear order that the roles fall into:
    +
    +Roles.set_default('Guest')
    +Roles.set_root('System')
     
    -    Here is what the finished admin role would look like:
    -    Roles.new_role('Administrator','Admin')
    -    :set_custom_tag('[Admin]')
    -    :set_custom_color('red')
    -    :set_permission_group('Staff')
    -    :set_flag('is_admin')
    -    :set_parent('Moderator')
    -    :allow{
    -        'command/kill',
    -        'gui/game settings'
    -    }
    -
    
    ----- Example System Define:
    -    Once all roles are defined these steps must be done to ensure the system is ready to use, this includes setting a default
    -    role, assigning a root (all permission) role that the server/system will use and the linear order that the roles fall into:
    +Roles.define_role_order{
    +    'System',
    +    'Administrator',
    +    'Moderator',
    +    'Donator',
    +    'Guest'
    +}
     
    -    Roles.set_default('Guest')
    -    Roles.set_root('System')
    -
    -    Roles.define_role_order{
    -        'System',
    -        'Administrator',
    -        'Moderator',
    -        'Donator',
    -        'Guest'
    -    }
    -
    -    Just remember that in this example all these roles have not been defined; so make sure all your roles that are used are defined
    -    before hand; a config file on load is useful for this to ensure that its loaded before the first player even joins.
    +--Just remember that in this example all these roles have not been defined; so make sure all your roles that are used are defined +--before hand; a config file on load is useful for this to ensure that its loaded before the first player even joins. +
    @@ -376,10 +371,10 @@ expcore.permission_groups - expcore.sudo + expcore.async - resources.color_presets + utils.color_presets expcore.common @@ -419,7 +414,7 @@ get_role_from_any(any) Gets a role from a name,index or role object (where it is just returned) - nb: this function is used for the input for most outward facing functions +nb: this function is used for the input for most outward facing functions get_player_roles(player) @@ -438,15 +433,15 @@ - assign_player(player, roles[, by_player_name=][, silent=false]) + assign_player(player, roles[, by_player_name=][, skip_checks=false][, silent=false]) Gives a player the given role(s) with an option to pass a by player name used in the log - unassign_player(player, roles[, by_player_name=][, silent=false]) + unassign_player(player, roles[, by_player_name=][, skip_checks=false][, silent=false]) Removes a player from the given role(s) with an option to pass a by player name used in the log - override_player_roles(roles) + override_player_roles([player_name], roles) Overrides all player roles with the given table of roles, useful to mass set roles on game start @@ -480,7 +475,7 @@ define_role_order(order) Used to set the role order, higher in the list is better, must be called at least once in config - nb: function also re links parents due to expected position in the config file +-- nb: function also re links parents due to expected position in the config file define_flag_trigger(name, callback) @@ -565,16 +560,16 @@ Roles._prototype:set_parent(role) Sets the parent for a role, any action not in allow or disallow will be looked for in its parents - nb: this is a recursive action, and changing the allows and disallows will effect all children roles +nb: this is a recursive action, and changing the allows and disallows will effect all children roles - Roles._prototype:set_auto_promote_condition(callback) - Sets an auto promote condition that is checked every 5 seconds, if true is returned then the player will receive the role - nb: this is one way, failing false after already gaining the role will not revoke the role + Roles._prototype:set_auto_assign_condition(callback) + Sets an auto assign condition that is checked every 60 seconds, if true is returned then the player will receive the role +nb: this is one way, failing false after already gaining the role will not revoke the role Roles._prototype:set_block_auto_promote([state=true]) - Sets the role to not allow players to have auto promote effect them, useful to keep people locked to a punishment + Sets the role to not allow players to have auto assign effect them, useful to keep people locked to a role @@ -712,8 +707,8 @@
    - # - expcore.sudo + # + expcore.async
    @@ -737,8 +732,8 @@
    - # - resources.color_presets + # + utils.color_presets
    @@ -818,6 +813,9 @@ + Usage: +
    -- Print the debug string
    +game.player.print(Roles.debug())
    @@ -884,6 +882,9 @@ + Usage: +
    -- Print a message to the given roles
    +Roles.print_to_roles({'Administrator','Moderator'}, 'Hello, World!')
    @@ -950,6 +951,9 @@ + Usage: +
    -- Print a message to the roles above this role, includes the given role
    +Roles.print_to_roles_higher('Moderator', 'Hello, World!')
    @@ -1016,6 +1020,9 @@ + Usage: +
    -- Print a message to the roles below this role, includes the given role
    +Roles.print_to_roles_higher('Moderator', 'Hello, World!')
    @@ -1073,6 +1080,9 @@ + Usage: +
    -- Get a role by its name
    +local role = Roles.get_role_by_name('Moderator')
    @@ -1130,6 +1140,9 @@ + Usage: +
    -- Get a role by its index in the order list
    +local role = Roles.get_role_by_name(2)
    @@ -1144,7 +1157,7 @@

    Gets a role from a name,index or role object (where it is just returned) - nb: this function is used for the input for most outward facing functions

    +nb: this function is used for the input for most outward facing functions

    @@ -1188,6 +1201,9 @@ + Usage: +
    -- Get a role by its name or order
    +local role = Roles.get_role_from_any('Moderator')
    @@ -1245,6 +1261,9 @@ + Usage: +
    -- Get the roles that a player has
    +local roles = Roles.get_player_roles(game.player)
    @@ -1302,6 +1321,9 @@ + Usage: +
    -- Get the highest role that a player has
    +local role = Roles.get_player_highest_role(game.player)
    @@ -1312,7 +1334,7 @@
    # - assign_player(player, roles[, by_player_name=][, silent=false]) + assign_player(player, roles[, by_player_name=][, skip_checks=false][, silent=false])
    @@ -1379,6 +1401,23 @@ +
  • + + skip_checks + + : + + (boolean) + + when true there will be no checks are done for if the player is valid + + (default: false) +
  • + + + + +
  • silent @@ -1405,6 +1444,11 @@ + Usage: +
    -- Assign a player to the Moderator role
    +Roles.assign_player(game.player,  'Moderator')
    +
    -- Assign a player to the Moderator role, even if the player has never been on the map
    +Roles.assign_player('Cooldude2606',  'Moderator', nil, true)
  • @@ -1412,7 +1456,7 @@
    # - unassign_player(player, roles[, by_player_name=][, silent=false]) + unassign_player(player, roles[, by_player_name=][, skip_checks=false][, silent=false])
    @@ -1479,6 +1523,23 @@ +
  • + + skip_checks + + : + + (boolean) + + when true there will be no checks are done for if the player is valid + + (default: false) +
  • + + + + +
  • silent @@ -1505,6 +1566,11 @@ + Usage: +
    -- Unassign a player from the Moderator role
    +Roles.unassign_player(game.player,  'Moderator')
    +
    -- Unassign a player from the Moderator role, even if the player has never been on the map
    +Roles.unassign_player('Cooldude2606',  'Moderator', nil, true)
  • @@ -1512,7 +1578,7 @@
    # - override_player_roles(roles) + override_player_roles([player_name], roles)
    @@ -1530,6 +1596,23 @@ +
  • + + player_name + + : + + (string) + + the player to set the roles for, if not given all roles are overriden + + (optional) +
  • + + + + +
  • roles @@ -1555,6 +1638,14 @@ + Usage: +
    -- Override the roles of a single player, other users are not effected
    +Roles.override_player_roles('Cooldude2606', {'Moderator'})
    +
    -- Override all existing roles, effects all users not just ones listed
    +Roles.override_player_roles{
    +    ['Cooldude2606'] = {'Administrator','Moderator'},
    +    ['arty714'] = {'Administrator','Moderator'},
    +}
  • @@ -1631,6 +1722,9 @@ + Usage: +
    -- Test if a player has a role
    +local has_role = Roles.player_has_role(game.player, 'Moderator')
    @@ -1704,6 +1798,9 @@ + Usage: +
    -- Test if a player has a role
    +local has_flag = Roles.player_has_flag(game.player, 'is_donator')
    @@ -1777,6 +1874,9 @@ + Usage: +
    -- Test if a player has a role
    +local has_flag = Roles.player_has_flag(game.player, 'is_donator')
    @@ -1794,7 +1894,7 @@

    Used to set the role order, higher in the list is better, must be called at least once in config - nb: function also re links parents due to expected position in the config file

    +-- nb: function also re links parents due to expected position in the config file

    @@ -1831,6 +1931,15 @@ + Usage: +
    -- Define which roles are higher than others
    +Roles.define_role_order{
    +    'System',
    +    'Administrator',
    +    'Moderator',
    +    'Donator',
    +    'Guest'
    +}
    @@ -1881,8 +1990,6 @@ (function) the function that is called when roles are assigned - flag param - player - the player that has had they roles changed - flag param - state - the state of the flag, aka if the flag is present @@ -1899,6 +2006,11 @@ + Usage: +
    -- Defineing a flag trigger
    +Roles.define_flag_trigger('is_donator', function(player, state)
    +    player.character_running_speed_modifier = state and 1.5 or 1
    +end)
    @@ -1949,6 +2061,9 @@ + Usage: +
    -- Setting the default role
    +Roles.set_default('Guest')
    @@ -1999,6 +2114,9 @@ + Usage: +
    -- Setting the root role
    +Roles.set_root('System')
    @@ -2073,6 +2191,9 @@ + Usage: +
    -- Defineing a new role
    +local role = Roles.new_role('Moderator', 'Mod')
    @@ -2134,6 +2255,9 @@ + Usage: +
    -- Allow all actions for this role, useful for root like roles
    +role:set_allow_all()
    @@ -2191,6 +2315,12 @@ + Usage: +
    -- Allow some actions for a role
    +role:allow{
    +    'command/kill',
    +    'gui/game settings'
    +}
    @@ -2248,6 +2378,12 @@ + Usage: +
    -- Disalow an action for a role, useful if inherit an action from a parent
    +role:disallow{
    +    'command/kill',
    +    'gui/game settings'
    +}
    @@ -2305,6 +2441,9 @@ + Usage: +
    -- Test if a role is allowed an action
    +local allowed = role:is_allowed('command/kill')
    @@ -2382,6 +2521,9 @@ + Usage: +
    -- Set a flag for a role
    +role:set_flag('is_admin')
    @@ -2416,6 +2558,9 @@ + Usage: +
    -- Remove all flags from a role
    +role:clear_flags()
    @@ -2473,6 +2618,9 @@ + Usage: +
    -- Test if a role has a flag
    +local has_flag = role:has_flag('is_admin')
    @@ -2533,6 +2681,9 @@ + Usage: +
    -- Set a custom tag for this role, other code is required to set the tag
    +role:set_custom_tag('Mod')
    @@ -2590,6 +2741,9 @@ + Usage: +
    -- Set a custom colour for this role, other code is required to use this value
    +role:set_custom_color{ r=255, g=100, b=100}
    @@ -2664,6 +2818,9 @@ + Usage: +
    -- Set the permission group for this role, see permission_groups.lua
    +role:set_permission_group('Admin')
    @@ -2678,7 +2835,7 @@

    Sets the parent for a role, any action not in allow or disallow will be looked for in its parents - nb: this is a recursive action, and changing the allows and disallows will effect all children roles

    +nb: this is a recursive action, and changing the allows and disallows will effect all children roles

    @@ -2722,21 +2879,24 @@ + Usage: +
    -- Set the parent for this role to inherit all actions allowed
    +role:set_parent('Guest')
    - # - Roles._prototype:set_auto_promote_condition(callback) + # + Roles._prototype:set_auto_assign_condition(callback)
    -

    Sets an auto promote condition that is checked every 5 seconds, if true is returned then the player will receive the role - nb: this is one way, failing false after already gaining the role will not revoke the role

    +

    Sets an auto assign condition that is checked every 60 seconds, if true is returned then the player will receive the role +nb: this is one way, failing false after already gaining the role will not revoke the role

    @@ -2780,6 +2940,11 @@ + Usage: +
    -- Give this role to a user if there are admin, ran every 60 seconds
    +role:set_auto_assign_condition(function(player)
    +    return player.admin
    +end)
    @@ -2793,7 +2958,7 @@
    -

    Sets the role to not allow players to have auto promote effect them, useful to keep people locked to a punishment

    +

    Sets the role to not allow players to have auto assign effect them, useful to keep people locked to a role

    @@ -2813,7 +2978,7 @@ (boolean) - when true the players with this role will not be auto promoted + when true the players with this role will not be auto assigned to other roles (default: true) @@ -2838,6 +3003,9 @@ + Usage: +
    -- Make a role stop players from being auto assigned to other roles
    +role:set_block_auto_promote()
    @@ -2930,6 +3098,9 @@ + Usage: +
    -- Assign a player to this role
    +role:add_player(game.player)
    @@ -3019,6 +3190,9 @@ + Usage: +
    -- Unassign a player from this role
    +role:remove_player(game.player)
    @@ -3077,6 +3251,11 @@ + Usage: +
    -- Get all the players with this role
    +local players = role:get_players()
    +
    -- Get all online players with this role
    +local players = role:get_players(true)
    @@ -3134,6 +3313,9 @@ + Usage: +
    -- Print a message to all players with this role
    +role:print('Hello, World!')
    @@ -3152,7 +3334,7 @@ generated by LDoc
    diff --git a/docs/core/Store.html b/docs/core/Store.html index 1d8ad527..51907502 100644 --- a/docs/core/Store.html +++ b/docs/core/Store.html @@ -29,7 +29,7 @@

    ExpGaming Scenario

    -

    Explosive Gaming's server scenario for 0.17

    +

    Explosive Gaming's server scenario for 0.18

    @@ -53,13 +53,13 @@ @@ -88,10 +88,12 @@ + + @@ -100,8 +102,10 @@

    Guis

    @@ -139,7 +143,6 @@

    Configs

    @@ -172,18 +176,13 @@

    Modules

    @@ -262,7 +261,7 @@ Store.set(scenario_diffculty,'hard') end) -- When any key in the store is changed this function will trigger -Store.watch(player_scores,function(value,key) +
    Store.watch(player_scores,function(value,key,old_value) game.print(key..' now has a score of '..value) end) @@ -370,7 +369,7 @@ Store.set(player_scores,game.player,10) Used to trigger watcher functions, this may be used to trigger them if you did not use Store.update or Store.set - raw_trigger(store[, key][, value]) + raw_trigger(store[, key][, value][, old_value]) Used to trigger watcher functions, the value and key are passed directly to the watchers regardless if the value is correct @@ -791,7 +790,7 @@ Store.set(player_scores,game.player,10) end) -- Register the watcher so that when we change the value the message is printed -Store.watch(player_scores,function(value,key) +Store.watch(player_scores,function(value,key,old_value) game.print(key..' now has a score of '..value) end) @@ -1361,7 +1360,7 @@ Store.set(player_scores,game.player,10)
    # - raw_trigger(store[, key][, value]) + raw_trigger(store[, key][, value][, old_value])
    @@ -1426,6 +1425,23 @@ Store.set(player_scores,game.player,10) + + + +
  • + + old_value + + : + + (any) + + the old value that was at this key or store often the same if value is a table, passed directly to the watcher + + (optional) +
  • + + @@ -1445,7 +1461,7 @@ Store.set(player_scores,game.player,10) -- Trigger the watchers with a fake change of diffculty -- This is mostly used internally but it can be useful in other cases -Store.raw_trigger(scenario_diffculty,nil,'normal')
    +Store.raw_trigger(scenario_diffculty,nil,'normal','normal')
    @@ -1464,7 +1480,7 @@ Store.set(player_scores,game.player,10) generated by LDoc diff --git a/docs/core/Sudo.html b/docs/core/Sudo.html index 23573d85..27c2542b 100644 --- a/docs/core/Sudo.html +++ b/docs/core/Sudo.html @@ -544,7 +544,7 @@ generated by LDoc diff --git a/docs/guis/Player-List.html b/docs/guis/Player-List.html index da3e4e7f..f6a07252 100644 --- a/docs/guis/Player-List.html +++ b/docs/guis/Player-List.html @@ -29,7 +29,7 @@

    ExpGaming Scenario

    -

    Explosive Gaming's server scenario for 0.17

    +

    Explosive Gaming's server scenario for 0.18

    @@ -51,8 +51,10 @@

    Guis

    @@ -62,13 +64,13 @@ @@ -97,10 +99,12 @@ + + @@ -136,7 +140,6 @@

    Configs

    @@ -169,18 +173,13 @@

    Modules

    @@ -224,7 +223,7 @@

    Player-List gui

    Gui Module - Player List - - Adds a player list to show names and play time; also includes action buttons which can apply to players

    + - Adds a player list to show names and play time; also includes action buttons which can preform actions to players

    @@ -259,14 +258,14 @@ utils.event + config.gui.player_list_actions + + + utils.color_presets + + expcore.common - - config.action_buttons - - - resources.color_presets - @@ -288,8 +287,20 @@ - - + + + + + + + + + + + + + +
    Button used to confirm a reason
    player_listRegisters the player listadd_player_baseSet of elements that are used to make up a row of the player table
    add_action_barAdds all the buttons and flows that make up the action bar
    player_list_containerMain player list container for the left flow
    toggle_left_elementButton on the top flow used to toggle the player list container
    @@ -418,6 +429,56 @@ + + + + + + + +
    +
    +
    + # + config.gui.player_list_actions +
    +
    +
    +
    + + + + + + + + + + + + + + + +
    +
    +
    +
    + # + utils.color_presets +
    +
    +
    +
    + + + + + + + + + @@ -443,56 +504,6 @@ - - - - - - -
    -
    -
    -
    - # - config.action_buttons -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - resources.color_presets -
    -
    -
    -
    - - - - - - - - - @@ -587,14 +598,95 @@
    - # - player_list + # + add_player_base
    -

    Registers the player list

    +

    Set of elements that are used to make up a row of the player table

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + add_action_bar +
    +
    +
    +
    + +

    Adds all the buttons and flows that make up the action bar

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + player_list_container +
    +
    +
    +
    + +

    Main player list container for the left flow

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + toggle_left_element +
    +
    +
    +
    + +

    Button on the top flow used to toggle the player list container

    @@ -626,7 +718,7 @@ generated by LDoc
    diff --git a/docs/guis/Readme.html b/docs/guis/Readme.html new file mode 100644 index 00000000..beecc8d1 --- /dev/null +++ b/docs/guis/Readme.html @@ -0,0 +1,735 @@ + + + + + + + + Readme gui + + + + + + + +
    +
    + + + + + + + +
    + + + + + + + + +

    Readme gui

    +

    Gui Module - Readme + - Adds a main gui that contains lots of important information about our server

    +

    + + + + + + + + + + + + + +

    Dependencies

    + + + + + + + + + + + + + + + + + + + +
    expcore.gui
    expcore.roles
    expcore.commands
    utils.event
    utils.game
    + + +

    Elements

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    sub_contentSub content area used within the content areas
    title_tableTable which has a title above it above it
    title_table_scrollScroll to be used with Gui.title_label tables
    welcome_contentContent area for the welcome tab
    rules_contentContent area for the rules tab
    commands_contentContent area for the commands tab
    servers_contentContent area for the servers tab
    backers_contentContent area for the servers tab
    readmeMain readme container for the center flow
    readme_toggleToggle button for the readme gui
    + + +
    + + +

    Dependencies

    +
    +
    +
    +
    + # + expcore.gui +
    +
    +
    +
    + + + + + + + + + + + + + + + +
    +
    +
    +
    + # + expcore.roles +
    +
    +
    +
    + + + + + + + + + + + + + + + +
    +
    +
    +
    + # + expcore.commands +
    +
    +
    +
    + + + + + + + + + + + + + + + +
    +
    +
    +
    + # + utils.event +
    +
    +
    +
    + + + + + + + + + + + + + + + +
    +
    +
    +
    + # + utils.game +
    +
    +
    +
    + + + + + + + + + + + + + + + +
    +
    +

    Elements

    +
    +
    +
    +
    + # + sub_content +
    +
    +
    +
    + +

    Sub content area used within the content areas

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + title_table +
    +
    +
    +
    + +

    Table which has a title above it above it

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + title_table_scroll +
    +
    +
    +
    + +

    Scroll to be used with Gui.title_label tables

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + welcome_content +
    +
    +
    +
    + +

    Content area for the welcome tab

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + rules_content +
    +
    +
    +
    + +

    Content area for the rules tab

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + commands_content +
    +
    +
    +
    + +

    Content area for the commands tab

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + servers_content +
    +
    +
    +
    + +

    Content area for the servers tab

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + backers_content +
    +
    +
    +
    + +

    Content area for the servers tab

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + readme +
    +
    +
    +
    + +

    Main readme container for the center flow

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + readme_toggle +
    +
    +
    +
    + +

    Toggle button for the readme gui

    +

    + + + + + + + + + + + + + + +
    +
    + + + +
    +
    +
    + + + + diff --git a/docs/guis/Rocket-Info.html b/docs/guis/Rocket-Info.html index cd01fbd5..b112fb6a 100644 --- a/docs/guis/Rocket-Info.html +++ b/docs/guis/Rocket-Info.html @@ -29,7 +29,7 @@

    ExpGaming Scenario

    -

    Explosive Gaming's server scenario for 0.17

    +

    Explosive Gaming's server scenario for 0.18

    @@ -51,8 +51,10 @@

    Guis

    @@ -62,13 +64,13 @@ @@ -97,10 +99,12 @@ + + @@ -136,7 +140,6 @@

    Configs

    @@ -169,18 +173,13 @@

    Modules

    @@ -253,17 +252,17 @@ utils.event - config.rockets + config.gui.rockets - expcore.common - - - resources.color_presets + utils.color_presets modules.control.rockets + + expcore.common + @@ -273,24 +272,32 @@ - - + + - + - - + + - - + + - - + + + + + + + + + +
    zoom_to_mapUsed on the name label to allow zoom to maptoggle_launchButton to toggle the auto launch on a rocket silo
    launch_rocketUsed to launch the rocket, when it is readyButton to remotely launch a rocket from a silo
    toggle_rocketUsed to toggle the auto launch on a rocketsilo_cordsXY cords that allow zoom to map when pressed
    toggle_sectionUsed to toggle the visibility of the different sectionsrocket_entryBase element for each rocket in the progress list
    rocket_infoRegisters the rocket infodata_labelData label which contains a name and a value label pair
    rocket_list_containerMain gui container for the left flow
    toggle_left_elementButton on the top flow used to toggle the container
    @@ -379,8 +386,8 @@
    - # - config.rockets + # + config.gui.rockets
    @@ -404,33 +411,8 @@
    - # - expcore.common -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - resources.color_presets + # + utils.color_presets
    @@ -469,6 +451,31 @@ + + + + + + +
    +
    +
    +
    + # + expcore.common +
    +
    +
    +
    + + + + + + + + + @@ -482,14 +489,14 @@
    - # - zoom_to_map + # + toggle_launch
    -

    Used on the name label to allow zoom to map

    +

    Button to toggle the auto launch on a rocket silo

    @@ -516,7 +523,7 @@
    -

    Used to launch the rocket, when it is ready

    +

    Button to remotely launch a rocket from a silo

    @@ -536,14 +543,14 @@
    - # - toggle_rocket + # + silo_cords
    -

    Used to toggle the auto launch on a rocket

    +

    XY cords that allow zoom to map when pressed

    @@ -563,14 +570,14 @@
    - # - toggle_section + # + rocket_entry
    -

    Used to toggle the visibility of the different sections

    +

    Base element for each rocket in the progress list

    @@ -590,14 +597,68 @@
    - # - rocket_info + # + data_label
    -

    Registers the rocket info

    +

    Data label which contains a name and a value label pair

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + rocket_list_container +
    +
    +
    +
    + +

    Main gui container for the left flow

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + toggle_left_element +
    +
    +
    +
    + +

    Button on the top flow used to toggle the container

    @@ -629,7 +690,7 @@ generated by LDoc
    diff --git a/docs/guis/Science-Info.html b/docs/guis/Science-Info.html index 7a48f8dc..3b409eb2 100644 --- a/docs/guis/Science-Info.html +++ b/docs/guis/Science-Info.html @@ -29,7 +29,7 @@

    ExpGaming Scenario

    -

    Explosive Gaming's server scenario for 0.17

    +

    Explosive Gaming's server scenario for 0.18

    @@ -51,8 +51,10 @@

    Guis

    @@ -62,13 +64,13 @@ @@ -97,10 +99,12 @@ + + @@ -136,7 +140,6 @@

    Configs

    @@ -169,18 +173,13 @@

    Modules

    @@ -247,17 +246,20 @@ expcore.gui + expcore.gui + + utils.event - expcore.common - - - config.science + config.gui.science modules.control.production + + expcore.common + @@ -267,8 +269,20 @@ - - + + + + + + + + + + + + + +
    science_infoRegisters the science infoproduction_labelData label that contains the value and the surfix
    science_pack_baseAdds 4 elements that show the data for a science pack
    task_list_containerMain task list container for the left flow
    toggle_left_elementButton on the top flow used to toggle the task list container
    @@ -297,6 +311,31 @@ + + + + + + +
    +
    +
    +
    + # + expcore.gui +
    +
    +
    +
    + + + + + + + + + @@ -332,33 +371,8 @@
    - # - expcore.common -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - config.science + # + config.gui.science
    @@ -397,6 +411,31 @@ + + + + + + +
    +
    +
    +
    + # + expcore.common +
    +
    +
    +
    + + + + + + + + + @@ -410,14 +449,95 @@
    - # - science_info + # + production_label
    -

    Registers the science info

    +

    Data label that contains the value and the surfix

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + science_pack_base +
    +
    +
    +
    + +

    Adds 4 elements that show the data for a science pack

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + task_list_container +
    +
    +
    +
    + +

    Main task list container for the left flow

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + toggle_left_element +
    +
    +
    +
    + +

    Button on the top flow used to toggle the task list container

    @@ -449,7 +569,7 @@ generated by LDoc
    diff --git a/docs/guis/Task-List.html b/docs/guis/Task-List.html index 44170d3b..c9d42c26 100644 --- a/docs/guis/Task-List.html +++ b/docs/guis/Task-List.html @@ -29,7 +29,7 @@

    ExpGaming Scenario

    -

    Explosive Gaming's server scenario for 0.17

    +

    Explosive Gaming's server scenario for 0.18

    @@ -51,8 +51,10 @@

    Guis

    @@ -62,13 +64,13 @@ @@ -97,10 +99,12 @@ + + @@ -136,7 +140,6 @@

    Configs

    @@ -169,18 +173,13 @@

    Modules

    @@ -224,7 +223,7 @@

    Task-List gui

    Gui Module - Task List - - Adds a task list to the game which players can add remove and edit items on

    + - Adds a task list to the game which players can add, remove and edit items on

    @@ -253,14 +252,14 @@ expcore.roles - config.tasks - - - expcore.common + config.gui.tasks modules.control.tasks + + expcore.common + @@ -271,27 +270,43 @@ - - - - - - - - - - - - - + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    add_new_taskButton in the header to add a new task
    confirm_editUsed to save changes to a task
    cancel_editUsed to cancel any changes you made to a task
    discard_taskRemoves the task from the listButton displayed in the ehader bar, used to add a new task
    edit_taskOpens edit mode for the taskButton displayed next to tasks which the user is can edit, used to start editing a task
    task_listRegisters the task listdiscard_taskButton displayed next to tasks which the user is can edit, used to delete a task from the list
    add_task_baseSet of three elements which make up each row of the task table
    confirm_editButton displayed next to tasks which the user is currently editing, used to save changes
    cancel_editButton displayed next to tasks which the user is currently editing, used to discard changes
    task_editingEditing state for a task, contrins a text field and the two edit buttons
    task_labelDefault state for a task, contains only a label with the task message
    task_list_containerMain task list container for the left flow
    toggle_left_elementButton on the top flow used to toggle the task list container
    @@ -380,33 +395,8 @@
    - # - config.tasks -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - expcore.common + # + config.gui.tasks
    @@ -445,6 +435,31 @@ + + + + + + +
    +
    +
    +
    + # + expcore.common +
    +
    +
    +
    + + + + + + + + + @@ -465,88 +480,7 @@
    -

    Button in the header to add a new task

    -

    - - - - - - - - - - - - - - -
    -
    -
    -
    - # - confirm_edit -
    -
    -
    -
    - -

    Used to save changes to a task

    -

    - - - - - - - - - - - - - - -
    -
    -
    -
    - # - cancel_edit -
    -
    -
    -
    - -

    Used to cancel any changes you made to a task

    -

    - - - - - - - - - - - - - - -
    -
    -
    -
    - # - discard_task -
    -
    -
    -
    - -

    Removes the task from the list

    +

    Button displayed in the ehader bar, used to add a new task

    @@ -573,7 +507,7 @@
    -

    Opens edit mode for the task

    +

    Button displayed next to tasks which the user is can edit, used to start editing a task

    @@ -593,14 +527,203 @@
    - # - task_list + # + discard_task
    -

    Registers the task list

    +

    Button displayed next to tasks which the user is can edit, used to delete a task from the list

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + add_task_base +
    +
    +
    +
    + +

    Set of three elements which make up each row of the task table

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + confirm_edit +
    +
    +
    +
    + +

    Button displayed next to tasks which the user is currently editing, used to save changes

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + cancel_edit +
    +
    +
    +
    + +

    Button displayed next to tasks which the user is currently editing, used to discard changes

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + task_editing +
    +
    +
    +
    + +

    Editing state for a task, contrins a text field and the two edit buttons

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + task_label +
    +
    +
    +
    + +

    Default state for a task, contains only a label with the task message

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + task_list_container +
    +
    +
    +
    + +

    Main task list container for the left flow

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + toggle_left_element +
    +
    +
    +
    + +

    Button on the top flow used to toggle the task list container

    @@ -632,7 +755,7 @@ generated by LDoc
    diff --git a/docs/guis/Warps-List.html b/docs/guis/Warps-List.html index 196ec539..0eaf7808 100644 --- a/docs/guis/Warps-List.html +++ b/docs/guis/Warps-List.html @@ -29,7 +29,7 @@

    ExpGaming Scenario

    -

    Explosive Gaming's server scenario for 0.17

    +

    Explosive Gaming's server scenario for 0.18

    @@ -51,8 +51,10 @@

    Guis

    @@ -62,13 +64,13 @@ @@ -97,10 +99,12 @@ + + @@ -136,7 +140,6 @@

    Configs

    @@ -169,18 +173,13 @@

    Modules

    @@ -262,17 +261,17 @@ expcore.roles - resources.color_presets + utils.color_presets - config.warps - - - expcore.common + config.gui.warps modules.control.warps + + expcore.common + @@ -282,30 +281,10 @@ - - - - - - - - - - - - - - - - - - - - @@ -314,8 +293,44 @@ - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    zoom_to_mapUsed on the name label to allow zoom to map
    warp_timerThis timer controls when a player is able to warp, eg every 60 seconds
    goto_warpWhen the button is clicked it will teleport the player
    add_new_warp Will add a new warp to the list, checks if the player is too close to an existing one
    confirm_editConfirms the edit to name or icon of the warp
    cancel_editCancels the editing changes of the selected warp name or icon
    discard_warp Removes a warp from the list, including the physical area and map tag
    Opens edit mode for the warp
    warp_listRegisters the warp listadd_warp_baseSet of three elements which make up each row of the warp table
    confirm_editConfirms the edit to name or icon of the warp
    cancel_editCancels the editing changes of the selected warp name or icon
    warp_editingEditing state for a warp, contrins a text field and the two edit buttons
    warp_labelDefault state for a warp, contains only a label with the warp name
    warp_icon_buttonDefault state for the warp icon, when pressed teleports the player
    warp_icon_editingEditing state for the warp icon, chose elem used to chosse icon
    warp_timerThis timer controls when a player is able to warp, eg every 60 seconds
    warp_list_containerMain warp list container for the left flow
    warp_list_toggleButton on the top flow used to toggle the warp list container
    @@ -479,8 +494,8 @@
    - # - resources.color_presets + # + utils.color_presets
    @@ -504,33 +519,8 @@
    - # - config.warps -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - expcore.common + # + config.gui.warps
    @@ -569,6 +559,31 @@ + + + + + + +
    +
    +
    +
    + # + expcore.common +
    +
    +
    +
    + + + + + + + + + @@ -582,87 +597,6 @@
    - # - zoom_to_map -
    -
    -
    -
    - -

    Used on the name label to allow zoom to map

    -

    - - - - - - - - - - - - - - -
    -
    -
    -
    - # - warp_timer -
    -
    -
    -
    - -

    This timer controls when a player is able to warp, eg every 60 seconds

    -

    - - - - - - - - - - - - - - -
    -
    -
    -
    - # - goto_warp -
    -
    -
    -
    - -

    When the button is clicked it will teleport the player

    -

    - - - - - - - - - - - - - - -
    -
    -
    -
    # add_new_warp
    @@ -680,60 +614,6 @@ - - - - - - - -
    -
    -
    - # - confirm_edit -
    -
    -
    -
    - -

    Confirms the edit to name or icon of the warp

    -

    - - - - - - - - - - - - - - -
    -
    -
    -
    - # - cancel_edit -
    -
    -
    -
    - -

    Cancels the editing changes of the selected warp name or icon

    -

    - - - - - - - - @@ -798,14 +678,257 @@
    - # - warp_list + # + add_warp_base
    -

    Registers the warp list

    +

    Set of three elements which make up each row of the warp table

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + confirm_edit +
    +
    +
    +
    + +

    Confirms the edit to name or icon of the warp

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + cancel_edit +
    +
    +
    +
    + +

    Cancels the editing changes of the selected warp name or icon

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + warp_editing +
    +
    +
    +
    + +

    Editing state for a warp, contrins a text field and the two edit buttons

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + warp_label +
    +
    +
    +
    + +

    Default state for a warp, contains only a label with the warp name

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + warp_icon_button +
    +
    +
    +
    + +

    Default state for the warp icon, when pressed teleports the player

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + warp_icon_editing +
    +
    +
    +
    + +

    Editing state for the warp icon, chose elem used to chosse icon

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + warp_timer +
    +
    +
    +
    + +

    This timer controls when a player is able to warp, eg every 60 seconds

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + warp_list_container +
    +
    +
    +
    + +

    Main warp list container for the left flow

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + warp_list_toggle +
    +
    +
    +
    + +

    Button on the top flow used to toggle the warp list container

    @@ -837,7 +960,7 @@ generated by LDoc
    diff --git a/docs/guis/server-ups.html b/docs/guis/server-ups.html new file mode 100644 index 00000000..3acdff7b --- /dev/null +++ b/docs/guis/server-ups.html @@ -0,0 +1,444 @@ + + + + + + + + server-ups gui + + + + + + + +
    +
    + + + + + + + +
    + + + + + + + + +

    server-ups gui

    +

    Gui Module - Server UPS + - Adds a server ups counter in the top right and a command to toggle is

    +

    + + + + + + + + + + + + + +

    Dependencies

    + + + + + + + + + + + + + +
    expcore.gui
    utils.event
    expcore.commands
    + + +

    Elements

    + + + + + + + + +
    server_upsLabel to show the server ups
    + + +

    Commands

    + + + + + + + + +
    server-upsToggles if the server ups is visbile
    + + +
    + + +

    Dependencies

    +
    +
    +
    +
    + # + expcore.gui +
    +
    +
    +
    + + + + + + + + + + + + + + + +
    +
    +
    +
    + # + utils.event +
    +
    +
    +
    + + + + + + + + + + + + + + + +
    +
    +
    +
    + # + expcore.commands +
    +
    +
    +
    + + + + + + + + + + + + + + + +
    +
    +

    Elements

    +
    +
    +
    +
    + # + server_ups +
    +
    +
    +
    + +

    Label to show the server ups

    +

    + + + + + + + + + + + + + + +
    +
    +

    Commands

    +
    +
    +
    +
    + # + server-ups +
    +
    +
    +
    + +

    Toggles if the server ups is visbile

    +

    + + + + + + + + + + + + + + +
    +
    + + + +
    +
    +
    + + + + diff --git a/docs/index.html b/docs/index.html index 4601a828..266d509e 100644 --- a/docs/index.html +++ b/docs/index.html @@ -29,7 +29,7 @@

    ExpGaming Scenario

    -

    Explosive Gaming's server scenario for 0.17

    +

    Explosive Gaming's server scenario for 0.18

    @@ -45,42 +45,39 @@

    Core

    - - + + - - + + + + + + +- Used to simplify gui creation using factory functions called element defines - + +- Permission group making for factorio so you never have to make one by hand again +- Factorio role system to manage custom permissions. - - - -
    CommandsCore Module - Commands - - Factorio command making module that makes commands with better parse and more modularityAsyncCore Module - Async +- An extention of task and token to allow a single require to register and run async functions.
    Common-LibraryCore Module - Common Library - - Adds some commonly used functions used in many modulesCommandsCore Module - Commands +- Factorio command making module that makes commands with better parse and more modularity
    CommonCore Module - Common +- Adds some commonly used functions used in many modules
    Gui 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 - - please read the files for more documentation that cant be shown here - - please note there is a rework planned but not started
    Permissions-GroupsGroups Core Module - Permission Groups - - Permission group making for factorio so you never have to make one by hand again
    Roles Core Module - Roles - - Factorio role system to manage custom permissions.
    Store Core Module - Store - Used to store and watch for updates for values in the global table
    SudoCore Module - Sudo - - An extention of task and token to allow a single require to register and run functions bypassing all permissions.

    Control

    @@ -154,6 +151,10 @@ Sends alert messages to our discord server when certain events are triggered + greetings + Greets players on join + + Pollution-Grading Makes polution look much nice of the map, ie not one big red mess @@ -169,13 +170,22 @@ Spawn-Area Adds a custom spawn area with chests and afk turrets + + Tree-Decon + Makes trees which are marked for decon "decay" quickly to allow faster building +

    Guis

    + - Adds a player list to show names and play time; also includes action buttons which can preform actions to players + + + + @@ -188,9 +198,14 @@ - Adds a science info gui that shows production usage and net for the different science packs as well as an eta + + + + + - Adds a task list to the game which players can add, remove and edit items on @@ -309,14 +324,6 @@ to stop a file from loading add "--" in front of it, remove the "--" to have the file be loaded; config files should be loaded after all modules are loaded; core files should be required by modules and not be present in this list; - - - - @@ -353,11 +360,6 @@ - - - - @@ -370,6 +372,11 @@ see ./expcore/commands.lua for more details + + + + @@ -377,6 +384,34 @@ see ./expcore/commands.lua for more details start with Permission_Groups.new_group('name'); then use either :allow_all() or :disallow_all() to set the default for non specified actions; then use :allow{} and :disallow{} to specify certain actions to allow/disallow + + + + + + + + + + + + + + + + + + + + + + + + @@ -395,18 +430,6 @@ see ./expcore/commands.lua for more details - - - - - - - - - - - - @@ -415,17 +438,9 @@ see ./expcore/commands.lua for more details - - - - - - - -
    Player-List Gui Module - Player List - - Adds a player list to show names and play time; also includes action buttons which can apply to players
    ReadmeGui Module - Readme + - Adds a main gui that contains lots of important information about our server
    Rocket-Info
    server-upsGui Module - Server UPS + - Adds a server ups counter in the top right and a command to toggle is
    Task-List Gui Module - Task List - - Adds a task list to the game which players can add remove and edit items on
    Warps-List
    Player-ListConfig for the different action buttons that show on the player list; - each button has the button define(s) given along side an auth function, and optional reason callback; - if a reason callback is used then Store.set(action_name_store,player.name,'BUTTON_NAME') should be called during on_click; - buttons can be removed from the gui by commenting them out of the config at the bottom of this file; - the key used for the name of the button is the permission name used by the role system;
    Advanced-Start
    Commands-Auth-Roles This will make commands only work if the role has been allowed it in the role config
    Commands-Auth-Runtime-DisableThis config for command auth allows commands to be globally enabled and disabled during runtime; - this config adds Commands.disable and Commands.enable to enable and disable commands for all users
    Commands-Parse
    Commands-Parse-Roles Adds some parse functions that can be used with the role system
    Commands-Auth-Runtime-DisableThis config for command auth allows commands to be globally enabled and disabled during runtime; + this config adds Commands.disable and Commands.enable to enable and disable commands for all users
    Permission-Groups
    RolesThis is the main config file for the role system; file includes defines for roles and role flags and default values
    Player-ListConfig for the different action buttons that show on the player list; + each button has the button define(s) given along side an auth function, and optional reason callback; + if a reason callback is used then Store.set(action_name_store,player.name,'BUTTON_NAME') should be called during on_click; + buttons can be removed from the gui by commenting them out of the config at the bottom of this file; + the key used for the name of the button is the permission name used by the role system;
    RocketsThis file controls what will show in each section of the rocket info gui
    ScienceConfig file for the science info gui
    TasksConfig file for the tasks gui
    WarpsThis file contains all the different settings for the warp system and gui
    Pollution-Grading Config file for the repair command
    RocketsThis file controls what will show in each section of the rocket info gui
    RolesThis is the main config file for the role system; file includes defines for roles and role flags and default values
    ScienceConfig file for the science info gui
    Scorched-Earth This file controls the placement/degrading of tiles as players build and walk
    Used to config the spawn generation settings yes there is alot here i know just ignore the long tables at the end (they were generated with a command)
    TasksConfig file for the tasks gui
    Warnings Config file for the warning system, this is very similar to reports but is for the use of moderators rather than normal users.
    WarpsThis file contains all the different settings for the warp system and gui

    Modules

    @@ -437,21 +452,20 @@ see ./expcore/commands.lua for more details this file is the landing point for all scenarios please DO NOT edit directly, further comments are to aid development - - + + - - + - + + - - + + @@ -462,30 +476,9 @@ see ./expcore/commands.lua for more details - - - - - - - - - - - - - - - - - - - -
    utils.alien_evolution_progressinfo - Original (javascript) version: https://hastebin.com/udakacavap.js - Can be tested against: https://wiki.factorio.com/Enemies#Spawn_chances_by_evolution_factormodules.addons.station-auto-nameLuaPlayerBuiltEntityEventFilters +Events.set_event_filter(defines.events.on_built_entity, {{filter = "name", name = "fast-inserter"}})
    utils.coreThis file contains core utilities used by the redmew scenario.overrides.debug
    utils.debugoverrides.mathTakes two points and calculates the slope of a line
    utils.dump_envA small debugging tool that writes the contents of _ENV to a file when the game loads.overrides.tableSearches a table to remove a specific element without an index
    utils.event Do not use this function, use Event.add instead as it has safety checks.
    utils.mathTakes two points and calculates the slope of a line
    utils.recipe_lockerA module to prevent recipes from being unlocked by research.
    utils.state_machineThis module provides a classical mealy/moore state machine.
    utils.tableSearches a table to remove a specific element without an index
    utils.task Threading simulation module Task.sleep()
    utils.timestampsource https://github.com/daurnimator/luatz/blob/master/luatz/timetable.lua - edited down to just what is needed.

    Topics

    @@ -514,7 +507,7 @@ see ./expcore/commands.lua for more details generated by LDoc diff --git a/docs/modules/Gui.html b/docs/modules/Gui.html index 7f2d9a40..4ff9023c 100644 --- a/docs/modules/Gui.html +++ b/docs/modules/Gui.html @@ -41,7 +41,16 @@ @@ -51,18 +60,13 @@ @@ -70,12 +74,26 @@ + + @@ -90,10 +108,26 @@ + + + + + + @@ -126,36 +160,9 @@ - - @@ -201,7 +209,16 @@ @@ -221,7 +238,8 @@

    Gui module

    -

    Core Module - Gui

    +

    Core Module - Gui +- Gui defines that are used internally by the gui system

    @@ -236,17 +254,329 @@ -

    Functions

    +

    Dependencies

    - - + - - + + + + + + + + + +
    on_custom_event(handler)Adds a custom event handler, replace with the name of the eventutils.event
    set_custom_property(value)Sets a new value for a property, triggers setter method if provided, replace with property namemod-gui
    utils.event
    mod-gui
    + + +

    Tables

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    eventsString indexed table used to avoid conflict with custom event names, similar to how defines.events works
    definesUid indexed array that stores all the factory functions that were defined, no new values will be added during runtime
    core_definesAn string indexed table of all the defines which are used by the core of the gui system, used for internal refrence
    file_pathsUsed to store the file names where elements were defined, this can be useful to find the uid of an element, mostly for debuging
    debug_infoUsed to store extra infomation about elements as they get defined such as the params used and event handlers registered to them
    _prototype_elementThe prototype used to store the functions of an element define
    _mt_elementThe prototype metatable applied to new element defines
    + + +

    Fields

    + + + + + + + + +
    uidThe current highest uid that is being used by a define, will not increase during runtime
    + + +

    Core Defines

    + + + + + + + + + + + + + + + + +
    hide_top_flowButton which toggles the top flow elements, version which shows inside the top flow when top flow is visible
    show_top_flowButton which toggles the top flow elements, version which shows inside the left flow when top flow is hidden
    hide_left_flowButton which hides the elements in the left flow, shows inside the left flow when frames are visible
    + + +

    Defines

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    alignmentDraw a flow used to align its child elements, default is right align
    scroll_tableDraw a scroll pane that has a table inside of it
    headerUsed to add a frame with the header style, has the option for a right alignment flow for buttons
    footerUsed to add a frame with the footer style, has the option for a right alignment flow for buttons
    containerUsed for left frames to give them a nice boarder
    barUsed to make a solid white bar in a gui
    centered_labelUsed to make a label which is centered and of a certian size
    title_labelUsed to make a title which has two bars on either side
    + + +

    Helper Functions

    + + + + + + + + + + + + + + + + + + + + + + + + +
    get_player_from_element(element)Get the player that owns a gui element
    toggle_enabled_state(element[, state])Will toggle the enabled state of an element or set it to the one given
    toggle_visible_state(element[, state])Will toggle the visible state of an element or set it to the one given
    destroy_if_valid(element)Destory a gui element without causing any errors, often because the element was already removed
    sprite_style(size[, padding=-2][, style])Returns a table to be used as the style for a sprite buttons, produces a sqaure button
    + + +

    Left Flow

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    left_elementsContains the uids of the elements that will shown on the left flow and their join functions
    get_left_flow(player)Gets the flow refered to as the left flow, each player has one left flow
    Gui._prototype_element:add_to_left_flow([open_on_join])Sets an element define to be drawn to the left flow when a player joins, includes optional check
    left_toolbar_button(sprite, tooltip, element_define[, authenticator])Creates a button on the top flow which will toggle the given element define, the define must exist in the left flow
    draw_left_flow(player)Draw all the left elements onto the left flow, internal use only with on join
    update_left_flow(player)Update the visible state of the hide button, can be used to check if any frames are visible
    hide_left_flow(player)Hides all left elements for a player
    get_left_element(player, element_define)Get the element define that is in the left flow, use in events without an element refrence
    toggle_left_element(player, element_define[, state])Toggles the visible state of a left element for a given player, can be used to set the visible state
    + + +

    Element Define

    + + + + + + + + + + + + + + + + + + + + +
    element(element_define)Used to define new elements for your gui, can be used like LuaGuiElement.add or a custom function
    Gui._prototype_element:style(style_define)Used to extent your element define with a style factory, this style will be applied to your element when created, can also be a custom function
    Gui._prototype_element:on_custom_event(event_name, handler)Set the handler which will be called for a custom event, only one handler can be used per event per element
    Gui._prototype_element:raise_custom_event(event)Raise the handler which is attached to an event; external use should be limited to custom events
    + + +

    Element Events

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Gui._prototype_element.on_openCalled when the player opens a GUI.
    Gui._prototype_element.on_closeCalled when the player closes the GUI they have open.
    Gui._prototype_element.on_clickCalled when LuaGuiElement is clicked.
    Gui._prototype_element.on_confirmedCalled when a LuaGuiElement is confirmed, for example by pressing Enter in a textfield.
    Gui._prototype_element.on_checked_changedCalled when LuaGuiElement checked state is changed (related to checkboxes and radio buttons).
    Gui._prototype_element.on_elem_changedCalled when LuaGuiElement element value is changed (related to choose element buttons).
    Gui._prototype_element.on_location_changedCalled when LuaGuiElement element location is changed (related to frames in player.gui.screen).
    Gui._prototype_element.on_tab_changedCalled when LuaGuiElement selected tab is changed (related to tabbed-panes).
    Gui._prototype_element.on_selection_changedCalled when LuaGuiElement selection state is changed (related to drop-downs and listboxes).
    Gui._prototype_element.on_switch_changedCalled when LuaGuiElement switch state is changed (related to switches).
    Gui._prototype_element.on_text_changedCalled when LuaGuiElement text is changed by the player.
    Gui._prototype_element.on_value_changedCalled when LuaGuiElement slider value is changed (related to the slider element).
    + + +

    Top Flow

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    top_elementsContains the uids of the elements that will shown on the top flow and their auth functions
    top_flow_button_styleThe style that should be used for buttons on the top flow
    top_flow_button_visible_styleThe style that should be used for buttons on the top flow when their flow is visible
    get_top_flow(player)Gets the flow refered to as the top flow, each player has one top flow
    Gui._prototype_element:add_to_top_flow([authenticator])Sets an element define to be drawn to the top flow when a player joins, includes optional authenticator
    update_top_flow(player)Updates the visible state of all the elements on the players top flow, uses authenticator
    toggle_top_flow(player[, state])Toggles the visible state of all the elements on a players top flow, effects all elements
    get_top_element(player, element_define)Get the element define that is in the top flow, use in events without an element refrence
    toolbar_button(sprite, tooltip[, authenticator])Creates a button on the top flow with consistent styling
    toolbar_button_style(button, state)Styles a top flow button depending on the state given
    @@ -255,56 +585,23 @@
    -

    Functions

    +

    Dependencies

    - # - on_custom_event(handler) + # + utils.event
    -

    Adds a custom event handler, replace with the name of the event

    -

    - Parameters: - -
      - - - - - -
    • - - handler - - : - - (function) - - the function which will recive the event - -
    • - - -
    - - Returns: -
      -
    • - (GuiConcept) - to allow chaing of functions -[[@usage -
    • -
    @@ -318,14 +615,1256 @@
    - # - set_custom_property(value) + # + mod-gui
    -

    Sets a new value for a property, triggers setter method if provided, replace with property name

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + utils.event +
    +
    +
    +
    + + + + + + + + + + + + + + + +
    +
    +
    +
    + # + mod-gui +
    +
    +
    +
    + + + + + + + + + + + + + + + +
    +
    +

    Tables

    +
    +
    +
    +
    + # + events +
    +
    +
    +
    + +

    String indexed table used to avoid conflict with custom event names, similar to how defines.events works

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + defines +
    +
    +
    +
    + +

    Uid indexed array that stores all the factory functions that were defined, no new values will be added during runtime

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + core_defines +
    +
    +
    +
    + +

    An string indexed table of all the defines which are used by the core of the gui system, used for internal refrence

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + file_paths +
    +
    +
    +
    + +

    Used to store the file names where elements were defined, this can be useful to find the uid of an element, mostly for debuging

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + debug_info +
    +
    +
    +
    + +

    Used to store extra infomation about elements as they get defined such as the params used and event handlers registered to them

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + _prototype_element +
    +
    +
    +
    + +

    The prototype used to store the functions of an element define

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + _mt_element +
    +
    +
    +
    + +

    The prototype metatable applied to new element defines

    +

    + + + Fields: + +
      + + + + + +
    • + + __call + + + + + +
    • + + +
    + + + + + + + + + + + + + +
    +
    +

    Fields

    +
    +
    +
    +
    + # + uid +
    +
    +
    +
    + +

    The current highest uid that is being used by a define, will not increase during runtime

    +

    + + + +
      + + + + + +
    • + + uid + + + + + +
    • + + +
    + + + + + + + + + + + + + +
    +
    +

    Core Defines

    +
    +
    +
    +
    + # + hide_top_flow +
    +
    +
    +
    + +

    Button which toggles the top flow elements, version which shows inside the top flow when top flow is visible

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + show_top_flow +
    +
    +
    +
    + +

    Button which toggles the top flow elements, version which shows inside the left flow when top flow is hidden

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + hide_left_flow +
    +
    +
    +
    + +

    Button which hides the elements in the left flow, shows inside the left flow when frames are visible

    +

    + + + + + + + + + + + + + + +
    +
    +

    Defines

    +
    +
    +
    +
    + # + alignment +
    +
    +
    +
    + +

    Draw a flow used to align its child elements, default is right align

    +

    + + + Properties / Events: + +
      + + + + + +
    • + + parent + + : + + (LuaGuiElement) + + the parent element to which the alignment will be added + +
    • + + + + + +
    • + + name + + : + + (string) + + the name of the alignment flow which is added + + (default: 'alignment') +
    • + + + + + +
    • + + horizontal_align + + : + + (string) + + the horizontal alignment of the elements in the flow + + (default: 'right') +
    • + + + + + +
    • + + vertical_align + + : + + (string) + + the vertical alignment of the elements in the flow + + (default: 'center') +
    • + + +
    + + + + + + + + + + + + Usage: +
    -- Adding a right align flow
    +local alignment = Gui.alignment(element,'example_right_alignment')
    +
    -- Adding a horizontal center and top align flow
    +local alignment = Gui.alignment(element,'example_center_top_alignment','center','top')
    + + +
    +
    +
    +
    + # + scroll_table +
    +
    +
    +
    + +

    Draw a scroll pane that has a table inside of it

    +

    + + + Properties / Events: + +
      + + + + + +
    • + + parent + + : + + (LuaGuiElement) + + the parent element to which the scroll table will be added + +
    • + + + + + +
    • + + height + + : + + (number) + + the maximum height for the scroll pane + +
    • + + + + + +
    • + + column_count + + : + + (number) + + the number of columns that the table will have + +
    • + + + + + +
    • + + name + + : + + (string) + + the name of the scroll pane that is added, the table is always called "table" + + (default: 'scroll') +
    • + + +
    + + + + + + + + + + + + Usage: +
    -- Adding a scroll table with max height of 200 and column count of 3
    +local scroll_table = Gui.scroll_table(element,200,3)
    + + +
    +
    +
    +
    + # + header +
    +
    +
    +
    + +

    Used to add a frame with the header style, has the option for a right alignment flow for buttons

    +

    + + + Properties / Events: + +
      + + + + + +
    • + + parent + + : + + (LuaGuiElement) + + the parent element to which the header will be added + +
    • + + + + + +
    • + + caption + + : + + (string or LocalizedString) + + the caption that will be shown on the header + +
    • + + + + + +
    • + + tooltip + + : + + (string or LocalizedString) + + the tooltip that will be shown on the header + + (optional) +
    • + + + + + +
    • + + add_alignment + + : + + (boolean) + + when true an alignment flow will be added to the header + + (default: false) +
    • + + + + + +
    • + + name + + : + + (string) + + the name of the header that is being added, the alignment is always called "alignment" + + (default: 'header') +
    • + + +
    + + + + + + + + + + + + Usage: +
    -- Adding a custom header with a label
    +local header = Gui.header(
    +    element,
    +    'Example Caption',
    +    'Example Tooltip'
    +)
    + + +
    +
    +
    +
    + # + footer +
    +
    +
    +
    + +

    Used to add a frame with the footer style, has the option for a right alignment flow for buttons

    +

    + + + Properties / Events: + +
      + + + + + +
    • + + parent + + : + + (LuaGuiElement) + + the parent element to which the footer will be added + +
    • + + + + + +
    • + + caption + + : + + (string or LocalizedString) + + the caption that will be shown on the footer + +
    • + + + + + +
    • + + tooltip + + : + + (string or LocalizedString) + + the tooltip that will be shown on the footer + + (optional) +
    • + + + + + +
    • + + add_alignment + + : + + (boolean) + + when true an alignment flow will be added to the footer + + (default: false) +
    • + + + + + +
    • + + name + + : + + (string) + + the name of the footer that is being added, the alignment is always called "alignment" + + (default: 'footer') +
    • + + +
    + + + + + + + + + + + + Usage: +
    -- Adding a custom footer with a label
    +local footer = Gui.footer(
    +    element,
    +    'Example Caption',
    +    'Example Tooltip'
    +)
    + + +
    +
    +
    +
    + # + container +
    +
    +
    +
    + +

    Used for left frames to give them a nice boarder

    +

    + + + Properties / Events: + +
      + + + + + +
    • + + parent + + : + + (LuaGuiElement) + + the parent element to which the container will be added + +
    • + + + + + +
    • + + name + + : + + (string) + + the name that you want to give to the outer frame, often just event_trigger + +
    • + + + + + +
    • + + width + + : + + (number) + + the minimal width that the frame will have + +
    • + + +
    + + + + + + + + + + + + Usage: +
    -- Adding a container as a base
    +local container = Gui.container(parent,'my_container',200)
    + + +
    +
    +
    +
    + # + bar +
    +
    +
    +
    + +

    Used to make a solid white bar in a gui

    +

    + + + Properties / Events: + +
      + + + + + +
    • + + parent + + : + + (LuaGuiElement) + + the parent element to which the bar will be added + +
    • + + + + + +
    • + + width + + : + + (number) + + the width of the bar that will be made, if not given bar will strech to fill the parent + +
    • + + +
    + + + + + + + + + + + + Usage: +
    -- Adding a bar to a gui
    +local bar = Gui.bar(parent, 100)
    + + +
    +
    +
    +
    + # + centered_label +
    +
    +
    +
    + +

    Used to make a label which is centered and of a certian size

    +

    + + + Properties / Events: + +
      + + + + + +
    • + + parent + + : + + (LuaGuiElement) + + the parent element to which the label will be added + +
    • + + + + + +
    • + + width + + : + + (number) + + the width of the label, must be given in order to center the caption + +
    • + + + + + +
    • + + caption + + : + + (string or LocalizedString) + + the caption that will be shown on the label + +
    • + + + + + +
    • + + tooltip + + : + + (string or LocalizedString) + + the tooltip that will be shown on the label + + (optional) +
    • + + +
    + + + + + + + + + + + + Usage: +
    -- Adding a centered label
    +local label = Gui.centered_label(parent, 100, 'This is centered')
    + + +
    +
    +
    +
    + # + title_label +
    +
    +
    +
    + +

    Used to make a title which has two bars on either side

    +

    + + + Properties / Events: + +
      + + + + + +
    • + + parent + + : + + (LuaGuiElement) + + the parent element to which the label will be added + +
    • + + + + + +
    • + + width + + : + + (number) + + the width of the first bar, this can be used to position the label + +
    • + + + + + +
    • + + caption + + : + + (string or LocalizedString) + + the caption that will be shown on the label + +
    • + + + + + +
    • + + tooltip + + : + + (string or LocalizedString) + + the tooltip that will be shown on the label + + (optional) +
    • + + +
    + + + + + + + + + + + + Usage: +
    -- Adding a centered label
    +local label = Gui.centered_label(parent, 100, 'This is centered')
    + + +
    +
    +

    Helper Functions

    +
    +
    +
    +
    + # + get_player_from_element(element) +
    +
    +
    +
    + +

    Get the player that owns a gui element

    @@ -339,13 +1878,13 @@
  • - value + element : - (any) + (LuaGuiElement) - the value that you want to set for this property + the element to get the owner of
  • @@ -358,9 +1897,8 @@ Returns:
    • - (GuiConcept) - to allow chaing of functions -[[@usage + (LuaPlayer) + the player that owns this element
    @@ -370,6 +1908,2404 @@ + Usage: +
    -- Geting the owner of an element
    +local player = Gui.get_player_from_element(element)
    + + +
    +
    +
    +
    + # + toggle_enabled_state(element[, state]) +
    +
    +
    +
    + +

    Will toggle the enabled state of an element or set it to the one given

    +

    + + + Parameters: + +
      + + + + + +
    • + + element + + : + + (LuaGuiElement) + + the element to toggle/set the enabled state of + +
    • + + + + + +
    • + + state + + : + + (boolean) + + with given will set the state, else state will be toggled + + (optional) +
    • + + +
    + + + + + Returns: +
      +
    • + (boolean) + the new enabled state that the element has +
    • +
    + + + + + + + + Usage: +
    -- Toggling the the enabled state
    +local new_enabled_state = Gui.toggle_enabled_state(element)
    + + +
    +
    +
    +
    + # + toggle_visible_state(element[, state]) +
    +
    +
    +
    + +

    Will toggle the visible state of an element or set it to the one given

    +

    + + + Parameters: + +
      + + + + + +
    • + + element + + : + + (LuaGuiElement) + + the element to toggle/set the visible state of + +
    • + + + + + +
    • + + state + + : + + (boolean) + + with given will set the state, else state will be toggled + + (optional) +
    • + + +
    + + + + + Returns: +
      +
    • + (boolean) + the new visible state that the element has +
    • +
    + + + + + + + + Usage: +
    -- Toggling the the visible state
    +local new_visible_state = Gui.toggle_visible_state(element)
    + + +
    +
    +
    +
    + # + destroy_if_valid(element) +
    +
    +
    +
    + +

    Destory a gui element without causing any errors, often because the element was already removed

    +

    + + + Parameters: + +
      + + + + + +
    • + + element + + : + + (LuaGuiElement) + + the element that you want to remove + +
    • + + +
    + + + + + Returns: +
      +
    • + (boolean) + true if the element was valid and has been removed +
    • +
    + + + + + + + + Usage: +
    -- Remove a child element if it exists
    +Gui.destroy_if_valid(element[child_name])
    + + +
    +
    +
    +
    + # + sprite_style(size[, padding=-2][, style]) +
    +
    +
    +
    + +

    Returns a table to be used as the style for a sprite buttons, produces a sqaure button

    +

    + + + Parameters: + +
      + + + + + +
    • + + size + + : + + (number) + + the size that you want the button to be + +
    • + + + + + +
    • + + padding + + : + + (number) + + the padding that you want on the sprite + + (default: -2) +
    • + + + + + +
    • + + style + + : + + (table) + + any extra style settings that you want to have + + (optional) +
    • + + +
    + + + + + Returns: +
      +
    • + (table) + the style table to be used with element_define:style() +
    • +
    + + + + + + + + Usage: +
    -- Adding a sprite button with size 20
    +local button =
    +Gui.element{
    +    type = 'sprite-button',
    +    sprite = 'entity/inserter'
    +}
    +:style(Gui.sprite_style(20))
    + + +
    +
    +

    Left Flow

    +
    +
    +
    +
    + # + left_elements +
    +
    +
    +
    + +

    Contains the uids of the elements that will shown on the left flow and their join functions

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + get_left_flow(player) +
    +
    +
    +
    + +

    Gets the flow refered to as the left flow, each player has one left flow

    +

    (player)

    + + + Parameters: + +
      + + + + + +
    • + + player + + : + + (LuaPlayer) + + the player that you want to get the left flow for + +
    • + + +
    + + + + + Returns: + + + + + + + + + Usage: +
    -- Geting your left flow
    +local left_flow = Gui.get_left_flow(game.player)
    + + +
    +
    +
    +
    + # + Gui._prototype_element:add_to_left_flow([open_on_join]) +
    +
    +
    +
    + +

    Sets an element define to be drawn to the left flow when a player joins, includes optional check

    +

    + + + Parameters: + +
      + + + + + +
    • + + open_on_join + + : + + (boolean or function) + + called during first darw to decide if the element should be visible + + (optional) +
    • + + +
    + + + + + Returns: +
      +
    • + (table) + the new element define that is used to register events to this element +
    • +
    + + + + + + + + Usage: +
    -- Adding the example button
    +example_flow_with_button:add_to_left_flow(true)
    + + +
    +
    +
    +
    + # + left_toolbar_button(sprite, tooltip, element_define[, authenticator]) +
    +
    +
    +
    + +

    Creates a button on the top flow which will toggle the given element define, the define must exist in the left flow

    +

    + + + Parameters: + +
      + + + + + +
    • + + sprite + + : + + (string) + + the sprite that you want to use on the button + +
    • + + + + + +
    • + + tooltip + + : + + (string or LocalizedString) + + the tooltip that you want the button to have + +
    • + + + + + +
    • + + element_define + + : + + (table) + + the element define that you want to have toggled by this button, define must exist on the left flow + +
    • + + + + + +
    • + + authenticator + + : + + (function) + + used to decide if the button should be visible to a player + + (optional) +
    • + + +
    + + + + + + + + + + + + Usage: +
    -- Add a button to toggle a left element
    +local toolbar_button =
    +Gui.left_toolbar_button('entity/inserter', 'Nothing to see here', example_flow_with_button, function(player)
    +    return player.admin
    +end)
    + + +
    +
    +
    +
    + # + draw_left_flow(player) +
    +
    +
    +
    + +

    Draw all the left elements onto the left flow, internal use only with on join

    +

    + + + Parameters: + +
      + + + + + +
    • + + player + + : + + (LuaPlayer) + + the player that you want to draw the elements for + +
    • + + +
    + + + + + + + + + + + + Usage: +
     Draw all the left elements
    +Gui.draw_left_flow(player)
    + + +
    +
    +
    +
    + # + update_left_flow(player) +
    +
    +
    +
    + +

    Update the visible state of the hide button, can be used to check if any frames are visible

    +

    + + + Parameters: + +
      + + + + + +
    • + + player + + : + + (LuaPlayer) + + the player to update the left flow for + +
    • + + +
    + + + + + Returns: +
      +
    • + (boolean) + true if any left element is visible +
    • +
    + + + + + + + + Usage: +
    -- Check if any left elements are visible
    +local visible = Gui.update_left_flow(player)
    + + +
    +
    +
    +
    + # + hide_left_flow(player) +
    +
    +
    +
    + +

    Hides all left elements for a player

    +

    + + + Parameters: + +
      + + + + + +
    • + + player + + : + + (LuaPlayer) + + the player to hide the elements for + +
    • + + +
    + + + + + + + + + + + + Usage: +
    -- Hide your left elements
    +Gui.hide_left_flow(game.player)
    + + +
    +
    +
    +
    + # + get_left_element(player, element_define) +
    +
    +
    +
    + +

    Get the element define that is in the left flow, use in events without an element refrence

    +

    + + + Parameters: + +
      + + + + + +
    • + + player + + : + + (LuaPlayer) + + the player that you want to get the element for + +
    • + + + + + +
    • + + element_define + + : + + (table) + + the element that you want to get + +
    • + + +
    + + + + + Returns: +
      +
    • + (LuaGuiElement) + the gui element linked to this define for this player +
    • +
    + + + + + + + + Usage: +
    -- Get your left element
    +local frame = Gui.get_left_element(game.player, example_flow_with_button)
    + + +
    +
    +
    +
    + # + toggle_left_element(player, element_define[, state]) +
    +
    +
    +
    + +

    Toggles the visible state of a left element for a given player, can be used to set the visible state

    +

    + + + Parameters: + +
      + + + + + +
    • + + player + + : + + (LuaPlayer) + + the player that you want to toggle the element for + +
    • + + + + + +
    • + + element_define + + : + + (table) + + the element that you want to toggle + +
    • + + + + + +
    • + + state + + : + + (boolean) + + with given will set the state, else state will be toggled + + (optional) +
    • + + +
    + + + + + Returns: +
      +
    • + (boolean) + the new visible state of the element +
    • +
    + + + + + + + + Usage: +
    -- Toggle your example button
    +Gui.toggle_top_flow(game.player, example_flow_with_button)
    +
    -- Show your example button
    +Gui.toggle_top_flow(game.player, example_flow_with_button, true)
    + + +
    +
    +

    Element Define

    +
    +
    +
    +
    + # + element(element_define) +
    +
    +
    +
    + +

    Used to define new elements for your gui, can be used like LuaGuiElement.add or a custom function

    +

    + + + Parameters: + +
      + + + + + +
    • + + element_define + + : + + (table or function) + + the define information for the gui element, same data as LuaGuiElement.add, or a custom function may be used + +
    • + + +
    + + + + + Returns: +
      +
    • + (table) + the new element define, this can be considered a factory for the element which can be called to draw the element to any other element +
    • +
    + + + + + + + + Usage: +
    -- Using element defines like LuaGuiElement.add
    +-- This returns a factory function to draw a button with the caption "Example Button"
    +local example_button =
    +Gui.element{
    +    type = 'button',
    +    caption = 'Example Button'
    +}
    +
    -- Using element defines with a custom factory function
    +-- This method can be used if you still want to be able register event handlers but it is too complex to be compatible with LuaGuiElement.add
    +local example_flow_with_button =
    +Gui.element(function(event_trigger,parent,...)
    +    -- ... shows that all other arguments from the factory call are passed to this function
    +    -- parent is the element which was passed to the factory function where you should add your new element
    +    -- here we are adding a flow which we will then later add a button to
    +    local flow =
    +    parent.add{
    +        name = 'example_flow',
    +        type = 'flow'
    +    }
    +
    +    -- event_trigger should be the name of any elements you want to trigger your event handlers, such as on_click or on_state_changed
    +    -- now we add the button to the flow that we created earlier
    +    local element =
    +    flow.add{
    +        name = event_trigger,
    +        type = 'button',
    +        caption = 'Example Button'
    +    }
    +
    +    -- you must return your new element, this is so styles can be applied and returned to the caller
    +    -- you may return any of your elements that you add, consider the context in which it will be used for what should be returned
    +    return element
    +end)
    + + +
    +
    +
    +
    + # + Gui._prototype_element:style(style_define) +
    +
    +
    +
    + +

    Used to extent your element define with a style factory, this style will be applied to your element when created, can also be a custom function

    +

    + + + Parameters: + +
      + + + + + +
    • + + style_define + + : + + (table or function) + + style table where each key and value pair is treated like LuaGuiElement.style[key] = value, a custom function can be used + +
    • + + +
    + + + + + Returns: +
      +
    • + (table) + the element define is returned to allow for event handlers to be registered +
    • +
    + + + + + + + + Usage: +
    -- Using the table method of setting the style
    +local example_button =
    +Gui.element{
    +    type = 'button',
    +    caption = 'Example Button',
    +    style = 'forward_button' -- factorio styles can be applied here
    +}
    +:style{
    +    height = 25, -- same as element.style.height = 25
    +    width = 100 -- same as element.style.width = 25
    +}
    +
    -- Using the function method to set the style
    +-- Use this method if your style is dynamic and depends on other factors
    +local example_button =
    +Gui.element{
    +    type = 'button',
    +    caption = 'Example Button',
    +    style = 'forward_button' -- factorio styles can be applied here
    +}
    +:style(function(style,element,...)
    +    -- style is the current style object for the elemenent
    +    -- element is the element that is being changed
    +    -- ... shows that all other arguments from the factory call are passed to this function
    +    local player = game.players[element.player_index]
    +    style.height = 25
    +    style.width = 100
    +    style.font_color = player.color
    +end)
    + + +
    +
    +
    +
    + # + Gui._prototype_element:on_custom_event(event_name, handler) +
    +
    +
    +
    + +

    Set the handler which will be called for a custom event, only one handler can be used per event per element

    +

    + + + Parameters: + +
      + + + + + +
    • + + event_name + + : + + (string) + + the name of the event you want to handler to be called on, often from Gui.events + +
    • + + + + + +
    • + + handler + + : + + (function) + + the handler that you want to be called when the event is raised + +
    • + + +
    + + + + + Returns: +
      +
    • + (table) + the element define so more handleres can be registered +
    • +
    + + + + + + + + Usage: +
    -- Register a handler to "my_custom_event" for this element
    +element_deinfe:on_custom_event('my_custom_event', function(event)
    +    event.player.print(player.name)
    +end)
    + + +
    +
    +
    +
    + # + Gui._prototype_element:raise_custom_event(event) +
    +
    +
    +
    + +

    Raise the handler which is attached to an event; external use should be limited to custom events

    +

    + + + Parameters: + +
      + + + + + +
    • + + event + + : + + (table) + + the event table passed to the handler, must contain fields: name, element + +
    • + + +
    + + + + + Returns: +
      +
    • + (table) + the element define so more events can be raised +
    • +
    + + + + + + + + Usage: +
     Raising a custom event
    +element_define:raise_custom_event{
    +    name = 'my_custom_event',
    +    element = element
    +}
    + + +
    +
    +

    Element Events

    +
    +
    +
    +
    + # + Gui._prototype_element.on_open +
    +
    +
    +
    + +

    Called when the player opens a GUI.

    +

    + + + +
      + + + + + +
    • + + handler + + : + + (function) + + the event handler which will be called + +
    • + + +
    + + + + + + + + + + + + + +
    +
    +
    +
    + # + Gui._prototype_element.on_close +
    +
    +
    +
    + +

    Called when the player closes the GUI they have open.

    +

    + + + +
      + + + + + +
    • + + handler + + : + + (function) + + the event handler which will be called + +
    • + + +
    + + + + + + + + + + + + + +
    +
    +
    +
    + # + Gui._prototype_element.on_click +
    +
    +
    +
    + +

    Called when LuaGuiElement is clicked.

    +

    + + + +
      + + + + + +
    • + + handler + + : + + (function) + + the event handler which will be called + +
    • + + +
    + + + + + + + + + + + + + +
    +
    +
    +
    + # + Gui._prototype_element.on_confirmed +
    +
    +
    +
    + +

    Called when a LuaGuiElement is confirmed, for example by pressing Enter in a textfield.

    +

    + + + +
      + + + + + +
    • + + handler + + : + + (function) + + the event handler which will be called + +
    • + + +
    + + + + + + + + + + + + + +
    +
    +
    +
    + # + Gui._prototype_element.on_checked_changed +
    +
    +
    +
    + +

    Called when LuaGuiElement checked state is changed (related to checkboxes and radio buttons).

    +

    + + + +
      + + + + + +
    • + + handler + + : + + (function) + + the event handler which will be called + +
    • + + +
    + + + + + + + + + + + + + +
    +
    +
    +
    + # + Gui._prototype_element.on_elem_changed +
    +
    +
    +
    + +

    Called when LuaGuiElement element value is changed (related to choose element buttons).

    +

    + + + +
      + + + + + +
    • + + handler + + : + + (function) + + the event handler which will be called + +
    • + + +
    + + + + + + + + + + + + + +
    +
    +
    +
    + # + Gui._prototype_element.on_location_changed +
    +
    +
    +
    + +

    Called when LuaGuiElement element location is changed (related to frames in player.gui.screen).

    +

    + + + +
      + + + + + +
    • + + handler + + : + + (function) + + the event handler which will be called + +
    • + + +
    + + + + + + + + + + + + + +
    +
    +
    +
    + # + Gui._prototype_element.on_tab_changed +
    +
    +
    +
    + +

    Called when LuaGuiElement selected tab is changed (related to tabbed-panes).

    +

    + + + +
      + + + + + +
    • + + handler + + : + + (function) + + the event handler which will be called + +
    • + + +
    + + + + + + + + + + + + + +
    +
    +
    +
    + # + Gui._prototype_element.on_selection_changed +
    +
    +
    +
    + +

    Called when LuaGuiElement selection state is changed (related to drop-downs and listboxes).

    +

    + + + +
      + + + + + +
    • + + handler + + : + + (function) + + the event handler which will be called + +
    • + + +
    + + + + + + + + + + + + + +
    +
    +
    +
    + # + Gui._prototype_element.on_switch_changed +
    +
    +
    +
    + +

    Called when LuaGuiElement switch state is changed (related to switches).

    +

    + + + +
      + + + + + +
    • + + handler + + : + + (function) + + the event handler which will be called + +
    • + + +
    + + + + + + + + + + + + + +
    +
    +
    +
    + # + Gui._prototype_element.on_text_changed +
    +
    +
    +
    + +

    Called when LuaGuiElement text is changed by the player.

    +

    + + + +
      + + + + + +
    • + + handler + + : + + (function) + + the event handler which will be called + +
    • + + +
    + + + + + + + + + + + + + +
    +
    +
    +
    + # + Gui._prototype_element.on_value_changed +
    +
    +
    +
    + +

    Called when LuaGuiElement slider value is changed (related to the slider element).

    +

    + + + +
      + + + + + +
    • + + handler + + : + + (function) + + the event handler which will be called + +
    • + + +
    + + + + + + + + + + + + + +
    +
    +

    Top Flow

    +
    +
    +
    +
    + # + top_elements +
    +
    +
    +
    + +

    Contains the uids of the elements that will shown on the top flow and their auth functions

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + top_flow_button_style +
    +
    +
    +
    + +

    The style that should be used for buttons on the top flow

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + top_flow_button_visible_style +
    +
    +
    +
    + +

    The style that should be used for buttons on the top flow when their flow is visible

    +

    + + + + + + + + + + + + + + +
    +
    +
    +
    + # + get_top_flow(player) +
    +
    +
    +
    + +

    Gets the flow refered to as the top flow, each player has one top flow

    +

    (player)

    + + + Parameters: + +
      + + + + + +
    • + + player + + : + + (LuaPlayer) + + the player that you want to get the flow for + +
    • + + +
    + + + + + Returns: + + + + + + + + + Usage: +
    -- Geting your top flow
    +local top_flow = Gui.get_top_flow(game.player)
    + + +
    +
    +
    +
    + # + Gui._prototype_element:add_to_top_flow([authenticator]) +
    +
    +
    +
    + +

    Sets an element define to be drawn to the top flow when a player joins, includes optional authenticator

    +

    + + + Parameters: + +
      + + + + + +
    • + + authenticator + + : + + (function) + + called during toggle or update to decide weather the element should be visible + + (optional) +
    • + + +
    + + + + + Returns: +
      +
    • + (table) + the new element define to allow event handlers to be registered +
    • +
    + + + + + + + + Usage: +
    -- Adding an element to the top flow on join
    +example_button:add_to_top_flow(function(player)
    +    -- example button will only be shown if the player is an admin
    +    -- note button will not update its state when player.admin is changed Gui.update_top_flow must be called for this
    +    return player.admin
    +end)
    + + +
    +
    +
    +
    + # + update_top_flow(player) +
    +
    +
    +
    + +

    Updates the visible state of all the elements on the players top flow, uses authenticator

    +

    + + + Parameters: + +
      + + + + + +
    • + + player + + : + + (LuaPlayer) + + the player that you want to update the top flow for + +
    • + + +
    + + + + + + + + + + + + Usage: +
    -- Update your top flow
    +Gui.update_top_flow(game.player)
    + + +
    +
    +
    +
    + # + toggle_top_flow(player[, state]) +
    +
    +
    +
    + +

    Toggles the visible state of all the elements on a players top flow, effects all elements

    +

    + + + Parameters: + +
      + + + + + +
    • + + player + + : + + (LuaPlayer) + + the player that you want to toggle the top flow for + +
    • + + + + + +
    • + + state + + : + + (boolean) + + if given then the state will be set to this + + (optional) +
    • + + +
    + + + + + Returns: +
      +
    • + (boolean) + the new visible state of the top flow +
    • +
    + + + + + + + + Usage: +
    -- Toggle your flow
    +Gui.toggle_top_flow(game.player)
    +
    -- Open your top flow
    +Gui.toggle_top_flow(game.player,true)
    + + +
    +
    +
    +
    + # + get_top_element(player, element_define) +
    +
    +
    +
    + +

    Get the element define that is in the top flow, use in events without an element refrence

    +

    + + + Parameters: + +
      + + + + + +
    • + + player + + : + + (LuaPlayer) + + the player that you want to get the element for + +
    • + + + + + +
    • + + element_define + + : + + (table) + + the element that you want to get + +
    • + + +
    + + + + + Returns: +
      +
    • + (LuaGuiElement) + the gui element linked to this define for this player +
    • +
    + + + + + + + + Usage: +
    -- Get your top element
    +local button = Gui.get_top_element(game.player, example_button)
    + + +
    +
    +
    +
    + # + toolbar_button(sprite, tooltip[, authenticator]) +
    +
    +
    +
    + +

    Creates a button on the top flow with consistent styling

    +

    + + + Parameters: + +
      + + + + + +
    • + + sprite + + : + + (string) + + the sprite that you want to use on the button + +
    • + + + + + +
    • + + tooltip + + : + + (string or LocalizedString) + + the tooltip that you want the button to have + +
    • + + + + + +
    • + + authenticator + + : + + (function) + + used to decide if the button should be visible to a player + + (optional) +
    • + + +
    + + + + + + + + + + + + Usage: +
    -- Add a button to the toolbar
    +local toolbar_button =
    +Gui.left_toolbar_button('entity/inserter', 'Nothing to see here', function(player)
    +    return player.admin
    +end)
    + + +
    +
    +
    +
    + # + toolbar_button_style(button, state) +
    +
    +
    +
    + +

    Styles a top flow button depending on the state given

    +

    + + + Parameters: + +
      + + + + + +
    • + + button + + : + + (LuaGuiElement) + + the button element to style + +
    • + + + + + +
    • + + state + + : + + (boolean) + + The state the button is in + +
    • + + +
    + + + + + + + + + + + + Usage: +
    -- Sets the button to the visible style
    +Gui.toolbar_button_style(button, true)
    +
    -- Sets the button to the hidden style
    +Gui.toolbar_button_style(button, false)
    @@ -388,7 +4324,7 @@ generated by LDoc diff --git a/docs/modules/control.html b/docs/modules/control.html index 75103f1b..3542b831 100644 --- a/docs/modules/control.html +++ b/docs/modules/control.html @@ -29,7 +29,7 @@

    ExpGaming Scenario

    -

    Explosive Gaming's server scenario for 0.17

    +

    Explosive Gaming's server scenario for 0.18

    @@ -50,18 +50,13 @@

    Modules

    @@ -69,13 +64,13 @@ @@ -104,10 +99,12 @@ + + @@ -116,8 +113,10 @@

    Guis

    @@ -155,7 +154,6 @@

    Configs

    @@ -244,12 +243,6 @@ - utils.debug - - - expcore.common.ext_require - - config._file_loader @@ -264,56 +257,6 @@
    - # - utils.debug -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    - # - expcore.common.ext_require -
    -
    -
    -
    - - - - - - - - - - - - - - - -
    -
    -
    -
    # config._file_loader
    @@ -351,7 +294,7 @@ generated by LDoc diff --git a/docs/modules/modules.addons.station-auto-name.html b/docs/modules/modules.addons.station-auto-name.html new file mode 100644 index 00000000..e5d0e142 --- /dev/null +++ b/docs/modules/modules.addons.station-auto-name.html @@ -0,0 +1,300 @@ + + + + + + + + modules.addons.station-auto-name module + + + + + + + +
    +
    + + + + + + + +
    + + + + + + + + +

    modules.addons.station-auto-name module

    +

    LuaPlayerBuiltEntityEventFilters +Events.set_event_filter(defines.events.on_built_entity, {{filter = "name", name = "fast-inserter"}})

    +

    + + + + + + + + + + + + + +

    Dependencies

    + + + + + + + +
    utils.event
    + + +
    + + +

    Dependencies

    +
    +
    +
    +
    + # + utils.event +
    +
    +
    +
    + + + + + + + + + + + + + + + +
    +
    + + + +
    +
    +
    + + + + diff --git a/docs/modules/overrides.debug.html b/docs/modules/overrides.debug.html new file mode 100644 index 00000000..3e5221fc --- /dev/null +++ b/docs/modules/overrides.debug.html @@ -0,0 +1,661 @@ + + + + + + + + overrides.debug module + + + + + + + +
    +
    + + + + + + + +
    + + + + + + + + +

    overrides.debug module

    +

    +

    + + + + + + + + + + + + + +

    Functions

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Debug.print(message, trace_levels)Shows the given message if debug is enabled.
    Debug.get_meta_value(object, key)Returns the value of the key inside the object + or 'InvalidLuaObject' if the LuaObject is invalid.
    Debug.object_type(object)Returns the Lua data type or the factorio LuaObject type + or 'NoHelpLuaObject' if the LuaObject does not have a help function + or 'InvalidLuaObject' if the LuaObject is invalid.
    Debug.print_position(position, message)Shows the given message if debug is on.
    Debug.cheat(callback)Executes the given callback if cheating is enabled.
    Debug.is_closure(func)Returns true if the function is a closure, false otherwise.
    + + +
    + + +

    Functions

    +
    +
    +
    +
    + # + Debug.print(message, trace_levels) +
    +
    +
    +
    + +

    Shows the given message if debug is enabled.

    +

    Uses serpent to print non scalars.

    + + + Parameters: + +
      + + + + + +
    • + + message + + : + + + + +
    • + + + + + +
    • + + trace_levels + + : + + + levels of stack trace to give, defaults to 1 level if nil + +
    • + + +
    + + + + + + + + + + + + + +
    +
    +
    +
    + # + Debug.get_meta_value(object, key) +
    +
    +
    +
    + +

    Returns the value of the key inside the object + or 'InvalidLuaObject' if the LuaObject is invalid.

    +

    + or 'InvalidLuaObjectKey' if the LuaObject does not have an entry at that key

    + + + Parameters: + +
    +
    +
    + + + + diff --git a/docs/modules/overrides.table.html b/docs/modules/overrides.table.html new file mode 100644 index 00000000..20f2ea68 --- /dev/null +++ b/docs/modules/overrides.table.html @@ -0,0 +1,2015 @@ + + + + + + + + overrides.table module + + + + + + + +
    +
    + + + + + + + +
    + + + + + + + + +

    overrides.table module

    +

    Searches a table to remove a specific element without an index

    +

    + + + + + + + + + + + + + +

    Dependencies

    + + + + + + + +
    overrides.inspect
    + + +

    Functions

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    remove_index(tbl, index)Removes an item from an array in O(1) time.
    merge_table(t1, t2)Adds the contents of table t2 to table t1
    array_insert(tbl[, start_index], values)Much faster method for inserting items into an array
    table_insert(tbl[, start_index], tbl2)Much faster method for inserting keys into a table
    get_key(t, e)Checks if a table contains an element
    get_index(t, e)Checks if the arrayed portion of a table contains an element
    contains(t, e)Checks if a table contains an element
    array_contains(t, e)Checks if the arrayed portion of a table contains an element
    extract_keys(tbl, ...)Extracts certain keys from a table
    set(t, index, element)Adds an element into a specific index position while shuffling the rest down
    get_random_dictionary_entry(t, key)Chooses a random entry from a table + because this uses math.random, it cannot be used outside of events
    get_random_weighted(weighted_table, item_index, weight_index)Chooses a random entry from a weighted table + because this uses math.random, it cannot be used outside of events
    clear_table(t, array)Clears all existing entries in a table
    shuffle_table(t, rng)Creates a fisher-yates shuffle of a sequential number-indexed table + because this uses math.random, it cannot be used outside of events if no rng is supplied + from: http://www.sdknews.com/cross-platform/corona/tutorial-how-to-shuffle-table-items
    get_values(tbl[, sorted][, as_string])Returns a copy of all of the values in the table.
    get_keys(tbl[, sorted][, as_string])Returns a copy of all of the keys in the table.
    alphanumsort(tbl)Returns the list is a sorted way that would be expected by people (this is by key)
    keysort(tbl)Returns the list is a sorted way that would be expected by people (this is by key) (faster alternative than above)
    + + +

    Fields

    + + + + + + + + + + + + + + + + + + + + + + + + +
    inspectSimilar to serpent.block, returns a string with a pretty representation of a table.
    sizeTakes a table and returns the number of entries in the table.
    deep_copyCreates a deepcopy of a table.
    mergeMerges multiple tables.
    equalsDetermines if two tables are structurally equal.
    + + +
    + + +

    Dependencies

    +
    +
    +
    +
    + # + overrides.inspect +
    +
    +
    +
    + + + + + + + + + + + + + + + +
    +
    +

    Functions

    +
    +
    +
    +
    + # + remove_index(tbl, index) +
    +
    +
    +
    + +

    Removes an item from an array in O(1) time.

    +

    + The catch is that fast_remove doesn't guarantee to maintain the order of items in the array.

    + + + Parameters: + +
      + + + + + +
    • + + tbl + + : + + + arrayed table + + + + + + + +
    • + + index + + : + + + Must be >= 0. The case where index > #tbl is handled. + +
    • + + + + + + + + + + + + + + + + + +
      +
      +
      + # + merge_table(t1, t2) +
      +
      +
      +
      + +

      Adds the contents of table t2 to table t1

      +

      + + + Parameters: + +
        + + + + + +
      • + + t1 + + : + + +
      to insert into + + + + + + + +
    • + + t2 + + : + + +
    • to insert from + + + + + + + + + + + + + + + + + + + +
      +
      +
      + # + array_insert(tbl[, start_index], values) +
      +
      +
      +
      + +

      Much faster method for inserting items into an array

      +

      + + + Parameters: + +
        + + + + + +
      • + + tbl + + : + + (table) + + the table that will have the values added to it + +
      • + + + + + +
      • + + start_index + + : + + (number) + + the index at which values will be added, nil means end of the array + + (optional) +
      • + + + + + +
      • + + values + + : + + (table) + + the new values that will be added to the table + +
      • + + +
      + + + + + Returns: +
        +
      • + (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
      +table.array_insert(tbl,500,values) -- around 0.4ms
      + + +
      +
      +
      +
      + # + table_insert(tbl[, start_index], tbl2) +
      +
      +
      +
      + +

      Much faster method for inserting keys into a table

      +

      + + + Parameters: + +
        + + + + + +
      • + + tbl + + : + + (table) + + the table that will have keys added to it + +
      • + + + + + +
      • + + start_index + + : + + (number) + + the index at which values will be added, nil means end of the array, numbered indexs only + + (optional) +
      • + + + + + +
      • + + tbl2 + + : + + (table) + + the table that may contain both string and numbered keys + +
      • + + +
      + + + + + Returns: +
        +
      • + (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
      +table.table_insert(tbl,50,tbl2)
      + + +
      +
      +
      +
      + # + get_key(t, e) +
      +
      +
      +
      + +

      Checks if a table contains an element

      +

      + + + Parameters: + +
        + + + + + +
      • + + t + + : + + +
      + + + + + + + +
    • + + e + + : + + + table element + +
    • + + + + + + + + Returns: +
        +
      • + the index of the element or nil +
      • +
      + + + + + + + + + + +
      +
      +
      + # + get_index(t, e) +
      +
      +
      +
      + +

      Checks if the arrayed portion of a table contains an element

      +

      + + + Parameters: + +
        + + + + + +
      • + + t + + : + + +
      + + + + + + + +
    • + + e + + : + + + table element + +
    • + + + + + + + + Returns: +
        +
      • + the index of the element or nil +
      • +
      + + + + + + + + + + +
      +
      +
      + # + contains(t, e) +
      +
      +
      +
      + +

      Checks if a table contains an element

      +

      + + + Parameters: + +
        + + + + + +
      • + + t + + : + + +
      + + + + + + + +
    • + + e + + : + + + table element + +
    • + + + + + + + + Returns: +
        +
      • + indicating success +
      • +
      + + + + + + + + + + +
      +
      +
      + # + array_contains(t, e) +
      +
      +
      +
      + +

      Checks if the arrayed portion of a table contains an element

      +

      + + + Parameters: + +
        + + + + + +
      • + + t + + : + + +
      + + + + + + + +
    • + + e + + : + + + table element + +
    • + + + + + + + + Returns: +
        +
      • + indicating success +
      • +
      + + + + + + + + + + +
      +
      +
      + # + extract_keys(tbl, ...) +
      +
      +
      +
      + +

      Extracts certain keys from a table

      +

      + + + Parameters: + +
        + + + + + +
      • + + tbl + + : + + (table) + + table the which contains the keys + +
      • + + + + + +
      • + + ... + + : + + (string) + + the names of the keys you want extracted + +
      • + + +
      + + + + + Returns: +
        +
      • + the keys in the order given +
      • +
      + + + + + + + + Usage: +
      local key_three, key_one = extract({key_one='foo',key_two='bar',key_three=true},'key_three','key_one')
      + + +
      +
      +
      +
      + # + set(t, index, element) +
      +
      +
      +
      + +

      Adds an element into a specific index position while shuffling the rest down

      +

      + + + Parameters: + +
        + + + + + +
      • + + t + + : + + +
      to add into + + + + + + + +
    • + + index + + : + + + the position in the table to add to + +
    • + + + + + +
    • + + element + + : + + + to add to the table + +
    • + + + + + + + + + + + + + + + + + +
      +
      +
      + # + get_random_dictionary_entry(t, key) +
      +
      +
      +
      + +

      Chooses a random entry from a table + because this uses math.random, it cannot be used outside of events

      +

      + + + Parameters: + +
        + + + + + +
      • + + t + + : + + +
      + + + + + + + +
    • + + key + + : + + + to indicate whether to return the key or value + +
    • + + + + + + + + Returns: +
        +
      • + a random element of table t +
      • +
      + + + + + + + + + + +
      +
      +
      + # + get_random_weighted(weighted_table, item_index, weight_index) +
      +
      +
      +
      + +

      Chooses a random entry from a weighted table + because this uses math.random, it cannot be used outside of events

      +

      + + + Parameters: + +
        + + + + + +
      • + + weighted_table + + : + + +
      of tables with items and their weights + + + + + + + +
    • + + item_index + + : + + + of the index of items, defaults to 1 + +
    • + + + + + +
    • + + weight_index + + : + + + of the index of the weights, defaults to 2 + +
    • + + + + + + + + Returns: +
        +
      • + table element +
      • +
      + + + + + + + + + + +
      +
      +
      + # + clear_table(t, array) +
      +
      +
      +
      + +

      Clears all existing entries in a table

      +

      + + + Parameters: + +
        + + + + + +
      • + + t + + : + + +
      to clear + + + + + + + +
    • + + array + + : + + + to indicate whether the table is an array or not + +
    • + + + + + + + + + + + + + + + + + +
      +
      +
      + # + shuffle_table(t, rng) +
      +
      +
      +
      + +

      Creates a fisher-yates shuffle of a sequential number-indexed table + because this uses math.random, it cannot be used outside of events if no rng is supplied + from: http://www.sdknews.com/cross-platform/corona/tutorial-how-to-shuffle-table-items

      +

      + + + Parameters: + +
        + + + + + +
      • + + t + + : + + +
      to shuffle + + + + + + + +
    • + + rng + + : + + + to provide random numbers + +
    • + + + + + + + + + + + + + + + + + +
      +
      +
      + # + get_values(tbl[, sorted][, as_string]) +
      +
      +
      +
      + +

      Returns a copy of all of the values in the table.

      +

      + + + Parameters: + +
        + + + + + +
      • + + tbl + + : + + (table) + + the to copy the keys from, or an empty table if tbl is nil + +
      • + + + + + +
      • + + sorted + + : + + (boolean) + + whether to sort the keys (slower) or keep the random order from pairs() + + (optional) +
      • + + + + + +
      • + + as_string + + : + + (boolean) + + whether to try and parse the values as strings, or leave them as their existing type + + (optional) +
      • + + +
      + + + + + Returns: +
        +
      • + (array) + an array with a copy of all the values in the table +
      • +
      + + + + + + + + + +
      +
      +
      +
      + # + get_keys(tbl[, sorted][, as_string]) +
      +
      +
      +
      + +

      Returns a copy of all of the keys in the table.

      +

      + + + Parameters: + +
        + + + + + +
      • + + tbl + + : + + (table) + + the to copy the keys from, or an empty table if tbl is nil + +
      • + + + + + +
      • + + sorted + + : + + (boolean) + + whether to sort the keys (slower) or keep the random order from pairs() + + (optional) +
      • + + + + + +
      • + + as_string + + : + + (boolean) + + whether to try and parse the keys as strings, or leave them as their existing type + + (optional) +
      • + + +
      + + + + + Returns: +
        +
      • + (array) + an array with a copy of all the keys in the table +
      • +
      + + + + + + + + + +
      +
      +
      +
      + # + alphanumsort(tbl) +
      +
      +
      +
      + +

      Returns the list is a sorted way that would be expected by people (this is by key)

      +

      + + + Parameters: + +
        + + + + + +
      • + + tbl + + : + + (table) + + the table to be sorted + +
      • + + +
      + + + + + Returns: +
        +
      • + (table) + the sorted table +
      • +
      + + + + + + + + + +
      +
      +
      +
      + # + keysort(tbl) +
      +
      +
      +
      + +

      Returns the list is a sorted way that would be expected by people (this is by key) (faster alternative than above)

      +

      + + + Parameters: + +
        + + + + + +
      • + + tbl + + : + + (table) + + the table to be sorted + +
      • + + +
      + + + + + Returns: +
        +
      • + (table) + the sorted table +
      • +
      + + + + + + + + + +
      + +

      Fields

      +
      +
      +
      +
      + # + inspect +
      +
      +
      +
      + +

      Similar to serpent.block, returns a string with a pretty representation of a table.

      +

      + Notice: This method is not appropriate for saving/restoring tables. It is meant to be used by the programmer mainly while debugging a program. + depth sets the maximum depth that will be printed out. When the max depth is reached, inspect will stop parsing tables and just return {...} + process is a function which allow altering the passed object before transforming it into a string. + A typical way to use it would be to remove certain values so that they don't appear at all. + return the prettied table

      + + + +
        + + + + + +
      • + + table + + : + + +
      the table to serialize + + + + + + + +
    • + + options + + : + + +
    • options are depth, newline, indent, process + + + + + + + + + + + + + + + + + + + +
      +
      +
      + # + size +
      +
      +
      +
      + +

      Takes a table and returns the number of entries in the table.

      +

      (Slower than #table, faster than iterating via pairs)

      + + + + + + + + + + + + + + +
      +
      +
      +
      + # + deep_copy +
      +
      +
      +
      + +

      Creates a deepcopy of a table.

      +

      Metatables and LuaObjects inside the table are shallow copies. + Shallow copies meaning it copies the reference to the object instead of the object itself.

      + + + +
        + + + + + +
      • + + object + + : + + +
      the object to copy + + + + + + + + + + + + + + + + + + + +
      +
      +
      + # + merge +
      +
      +
      +
      + +

      Merges multiple tables.

      +

      Tables later in the list will overwrite entries from tables earlier in the list. + Ex. merge({{1, 2, 3}, {[2] = 0}, {[3] = 0}}) will return {1, 0, 0}

      + + + +
        + + + + + +
      • + + tables + + : + + +
      takes a table of tables to merge + + + + + + + + + + + + + + + + + + + +
      +
      +
      + # + equals +
      +
      +
      +
      + +

      Determines if two tables are structurally equal.

      +

      + Notice: tables that are LuaObjects or contain LuaObjects won't be compared correctly, use == operator for LuaObjects

      + + + +
        + + + + + +
      • + + tbl1 + + : + + +
      + + + + + + + +
    • + + tbl2 + + : + + +
    • + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/modules/utils.alien_evolution_progress.html b/docs/modules/utils.alien_evolution_progress.html index 51092a84..fdb538e2 100644 --- a/docs/modules/utils.alien_evolution_progress.html +++ b/docs/modules/utils.alien_evolution_progress.html @@ -419,7 +419,7 @@ fraction will decide a chance to spawn. 1 alien for 2 spawner's will have 50% on generated by LDoc diff --git a/docs/modules/utils.core.html b/docs/modules/utils.core.html index 31b33120..c94a85ca 100644 --- a/docs/modules/utils.core.html +++ b/docs/modules/utils.core.html @@ -1164,7 +1164,7 @@ generated by LDoc diff --git a/docs/modules/utils.debug.html b/docs/modules/utils.debug.html index 3d92af43..d9fc0fa5 100644 --- a/docs/modules/utils.debug.html +++ b/docs/modules/utils.debug.html @@ -654,7 +654,7 @@ generated by LDoc diff --git a/docs/modules/utils.dump_env.html b/docs/modules/utils.dump_env.html index e54ef510..1a275d2f 100644 --- a/docs/modules/utils.dump_env.html +++ b/docs/modules/utils.dump_env.html @@ -323,7 +323,7 @@ generated by LDoc diff --git a/docs/modules/utils.event.html b/docs/modules/utils.event.html index 87ca10a6..beaa2b20 100644 --- a/docs/modules/utils.event.html +++ b/docs/modules/utils.event.html @@ -29,7 +29,7 @@

      ExpGaming Scenario

      -

      Explosive Gaming's server scenario for 0.17

      +

      Explosive Gaming's server scenario for 0.18

      @@ -51,18 +51,13 @@

      Modules

      @@ -70,13 +65,13 @@ @@ -105,10 +100,12 @@ + + @@ -117,8 +114,10 @@

      Guis

      @@ -156,7 +155,6 @@

      Configs

      @@ -343,7 +342,7 @@ - +
      utils.token
      utils.debugoverrides.debug
      @@ -488,8 +487,8 @@
      - # - utils.debug + # + overrides.debug
      @@ -1292,7 +1291,7 @@ generated by LDoc
    diff --git a/docs/modules/utils.event_core.html b/docs/modules/utils.event_core.html index e9fcbde4..c270c6ce 100644 --- a/docs/modules/utils.event_core.html +++ b/docs/modules/utils.event_core.html @@ -29,7 +29,7 @@

    ExpGaming Scenario

    -

    Explosive Gaming's server scenario for 0.17

    +

    Explosive Gaming's server scenario for 0.18

    @@ -50,18 +50,13 @@

    Modules

    @@ -69,13 +64,13 @@ @@ -104,10 +99,12 @@ + + @@ -116,8 +113,10 @@

    Guis

    @@ -155,7 +154,6 @@

    Configs

    @@ -434,7 +433,7 @@ generated by LDoc
    diff --git a/docs/modules/utils.math.html b/docs/modules/utils.math.html index 12045d90..24562934 100644 --- a/docs/modules/utils.math.html +++ b/docs/modules/utils.math.html @@ -353,7 +353,7 @@ generated by LDoc diff --git a/docs/modules/utils.recipe_locker.html b/docs/modules/utils.recipe_locker.html index 59d49a86..11b985c3 100644 --- a/docs/modules/utils.recipe_locker.html +++ b/docs/modules/utils.recipe_locker.html @@ -441,7 +441,7 @@ generated by LDoc diff --git a/docs/modules/utils.state_machine.html b/docs/modules/utils.state_machine.html index 68e88fea..0166e736 100644 --- a/docs/modules/utils.state_machine.html +++ b/docs/modules/utils.state_machine.html @@ -752,7 +752,7 @@ generated by LDoc diff --git a/docs/modules/utils.table.html b/docs/modules/utils.table.html index 5ffe1e8b..f5c0e283 100644 --- a/docs/modules/utils.table.html +++ b/docs/modules/utils.table.html @@ -1418,7 +1418,7 @@ generated by LDoc diff --git a/docs/modules/utils.task.html b/docs/modules/utils.task.html index cfc96b04..43b62a10 100644 --- a/docs/modules/utils.task.html +++ b/docs/modules/utils.task.html @@ -29,7 +29,7 @@

    ExpGaming Scenario

    -

    Explosive Gaming's server scenario for 0.17

    +

    Explosive Gaming's server scenario for 0.18

    @@ -51,18 +51,13 @@

    Modules

    @@ -70,13 +65,13 @@ @@ -105,10 +100,12 @@ + + @@ -117,8 +114,10 @@

    Guis

    @@ -156,7 +155,6 @@

    Configs

    @@ -651,7 +650,7 @@ generated by LDoc diff --git a/docs/modules/utils.timestamp.html b/docs/modules/utils.timestamp.html index fcf4b838..ffcfd375 100644 --- a/docs/modules/utils.timestamp.html +++ b/docs/modules/utils.timestamp.html @@ -442,7 +442,7 @@ generated by LDoc diff --git a/docs/topics/license.html b/docs/topics/license.html index 1eab766f..293edf6c 100644 --- a/docs/topics/license.html +++ b/docs/topics/license.html @@ -29,7 +29,7 @@

    ExpGaming Scenario

    -

    Explosive Gaming's server scenario for 0.17

    +

    Explosive Gaming's server scenario for 0.18

    @@ -50,13 +50,13 @@ @@ -85,10 +85,12 @@ + + @@ -97,8 +99,10 @@

    Guis

    @@ -136,7 +140,6 @@

    Configs

    @@ -169,18 +173,13 @@

    Modules

    @@ -789,7 +788,7 @@ Public License instead of this License. But first, please read generated by LDoc diff --git a/docs/topics/readme.md.html b/docs/topics/readme.md.html index 46789283..d9e08d04 100644 --- a/docs/topics/readme.md.html +++ b/docs/topics/readme.md.html @@ -29,7 +29,7 @@

    ExpGaming Scenario

    -

    Explosive Gaming's server scenario for 0.17

    +

    Explosive Gaming's server scenario for 0.18

    @@ -50,13 +50,13 @@ @@ -85,10 +85,12 @@ + + @@ -97,8 +99,10 @@

    Guis

    @@ -136,7 +140,6 @@

    Configs

    @@ -169,18 +173,13 @@

    Modules

    @@ -228,26 +227,29 @@

    ExpGaming Scenario Repository

    ## Explosive Gaming -

    Explosive Gaming (often ExpGaming) is a server hosting community with a strong focus on Factorio and games that follow similar ideas. Our factorio server are known for hosting large maps with the main goal of being a "mega base" which can produce as much as possible with in our reset schedule. Although these server tend to the more experienced players our server are open to everyone. You can find us through our [website], [discord], [wiki], or in the public games tab in factorio (ExpGaming S1). +

    Explosive Gaming (often ExpGaming) is a server hosting community with a strong focus on Factorio and games that follow similar ideas. Our Factorio server are known for hosting large maps with the main goal of being a "mega base" which can produce as much as possible within our reset schedule. Although these servers tend to attract the more experienced players, our servers are open to everyone. You can find us through our [website], [discord], [wiki], or in the public games tab in Factorio (ExpGaming S1, ExpGaming S2, etc.).

    ## Use and Installation

    1) Download this [git repository](https://github.com/explosivegaming/scenario/archive/master.zip) for the stable release. The dev branch can be found [here](https://github.com/explosivegaming/scenario/archive/dev.zip) for those who want the latest features. See [releases](#releases) for other release branches. -

    2) Extract the downloaded zip file from the branch you downloaded into factorio's scenario directory: +

    2) Extract the downloaded zip file from the branch you downloaded into Factorio's scenario directory: * Windows: `%appdata%\Factorio\scenarios` * Linux: `~/.factorio/scenarios`

    3) Within the scenario you can find `./config/_file_loader.lua` which contains a list of all the modules that will be loaded by the scenario; simply comment out (or remove) features you do not want but note that some modules may load other modules as dependencies even when removed from the list.

    4) More advanced users may want to play with the other configs files within `./config` but please be aware that some of the config files will require a basic understanding of lua while others may just be a list of values. -

    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). +

    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 do not 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]. All our docs can be found [here][docs]. 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]. To find out what we already have please read our [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. -* A release is merged into `master` on the following friday in time for the the weekly reset. -* Patches may be named `patch/X.Y.Z` and fill be merged into `master` and `dev` when appropriate. +* New features are merged into `dev` after it has been completed, this can be done through a pull request. +* After a number of features have been added a release branch is made: `release/X.Y.0` +* Bug fixes and localization can be made to the release branch with a pull request rather than into dev. +* A release is merged into `master` on the following friday after it is considered stable. +* Patches may be named `patch/X.Y.Z` and will be merged into `dev` and then `master` when appropriate.

    ## Releases

    | Scenario Version* | Version Name | Factorio Version** | |---|---|---| +| [v5.10][s5.10] | Data Store Rewrite | [v0.17.71][f0.17.71] | | [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] | @@ -265,7 +267,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.9]: https://github.com/explosivegaming/scenario/releases/tag/5.9.0 +

    [s5.10]: https://github.com/explosivegaming/scenario/releases/tag/5.10.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 @@ -280,7 +283,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.63]: https://wiki.factorio.com/Version_history/0.17.0#0.17.63 +

    [f0.17.71]: https://wiki.factorio.com/Version_history/0.17.0#0.17.71 +[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 @@ -333,7 +337,7 @@ generated by LDoc

    diff --git a/expcore/async.lua b/expcore/async.lua new file mode 100644 index 00000000..473580ae --- /dev/null +++ b/expcore/async.lua @@ -0,0 +1,101 @@ +--[[-- Core Module - Async +- An extention of task and token to allow a single require to register and run async functions. +@core Async +@alias Async + +@usage +-- To use Async you must register the allowed functions when the file is loaded, often this will just be giving access to +-- some functions within a module if you expect that at part may be blocked by in game permissions or a custom system you have made +-- you may also want to register functions that you want to have a time delay, such as waiting 2 seconds before printing a message + +-- When player.admin is called (either command or gui element event) by a player who isnt admin then it will error +-- here we register the function to promote the player so that it will run async and outside the player scope +local promote_player = +Async.register(function(player) + player.admin = true +end) + +-- This will allow us to bypass the error by running one tick later outside of any player scope +Async(promote_player,game.player) + +-- Here we make an sync function that we want to have a delay, note the delay is not defined here +local print_message = +Async.register(function(player,message) + player.print(message) +end) + +-- We can then call the async function with a delay using the wait function +Async.wait(60, print_message, game.player, 'One second has passed!') + +]] +local Task = require 'utils.task' --- @dep utils.task +local Token = require 'utils.token' --- @dep utils.token + +local Async = {} + +local internal_run = +Token.register(function(params) + local func = Token.get(params.token) + return func(unpack(params.params)) +end) + +--[[-- Register a new async function, must called when the file is loaded +@function register +@tparam function callback the function that can be called as an async function +@treturn string the uid of the async function which can be passed to Async.run and Async.wait + +@usage-- Registering a function to set the admin state of a player +local set_admin = +Async.register(function(player, state) + if player.valid then + player.admin = state + end +end) + +@usage-- Registering a function to print to a player +local print_to_player = +Async.register(function(player, message) + if player.valid then + player.print(message) + end +end) + +]] +Async.register = Token.register + +--[[-- Runs an async function, you may supply any number of arguments as required by that function +@tparam string token the token of the async function you want to run +@tparam[opt] any ... the other params that you want to pass to your function + +@usage-- Make a player admin regardless of if you are admin +Async.run(set_admin, player, true) + +]] +function Async.run(token,...) + Task.queue_task(internal_run, { + token = token, + params = {...} + }) +end + +--[[-- Runs an async function after the given number of ticks, you may supply any number of arguments as required by that function +@tparam number ticks the number of ticks that you want the function to run after +@tparam string token the token of the async function you want to run +@tparam[opt] any ... the other params that you want to pass to your function + +@usage-- Print a message to a player after 5 seconds +Async.wait(300, print_to_player, 'Hello, World!') + +]] +function Async.wait(ticks,token,...) + Task.set_timeout_in_ticks(ticks, internal_run, { + token = token, + params = {...} + }) +end + +return setmetatable(Async,{ + __call = function(self,...) + self.run(...) + end +}) \ No newline at end of file diff --git a/expcore/commands.lua b/expcore/commands.lua index a0b05475..a249ee93 100644 --- a/expcore/commands.lua +++ b/expcore/commands.lua @@ -1,236 +1,252 @@ --[[-- Core Module - Commands - - Factorio command making module that makes commands with better parse and more modularity - @core Commands - @alias Commands +- Factorio command making module that makes commands with better parse and more modularity +@core Commands +@alias Commands - @usage ----- Example Authenticator: - -- The command system is most useful when you can control who can use commands; to do this would would need to - -- define an authenticator which is ran every time a command is run; in this example I will show a simple one - -- that requires some commands to require the user to be a game admin: +@usage--- Full code example, see below for explaination +Commands.new_command('repeat-name', 'Will repeat you name a number of times in chat.') +:add_param('repeat-count', false, 'number-range-int', 1, 5) -- required int in range 1 to 5 inclusive +:add_param('smiley', true, function(input, player, reject) -- optional boolean default false + if not input then return end + if input:lower() == 'true' or input:lower() == 'yes' then + return true + else + return false + end +end) +:set_defaults{ smiley=false } +:set_flag('admin_only', true) -- command is admin only +:add_alias('name', 'rname') -- allow alias: name and rname +:register(function(player, repeat_count, smiley, raw) + game.print(player.name..' used a command with input: '..raw) - -- When the authenticator is called be the command handler it will be passed 4 vales: - -- 1) the player who used the command - -- 2) the name of the command that is being used - -- 3) any flags which have been set for this command, this is a table of values set using :set_flag(name,value) - -- 4) the reject function which is the preferred method to prevent execution of the command + local msg = ') '..player.name + if smiley then + msg = ':'..msg + end - -- For our admin only example we will set a flag to true when we want it do be admin only so when we define the - -- command will will use :set_flag('admin_only',true) and then inside the authenticator we will test if the flag - -- is present using: if flags.admin_only then + for 1 = 1,repeat_count do + Command.print(1..msg) + end +end) - -- Although no return is required to allow the command to execute it is best practice to return true; we do this in - -- two cases in our authenticator: - -- 1) when the "admin_only" flag is not set, which we take to mean any one can use it - -- 2) when the "admin_only" flag is set, and the player is admin +@usage--- Example Command: +-- How for the fun part making the commands, the commands can be set up with any number of params and flags that you want, +-- you can add aliases for the commands and set default values for optional params and of course register your command callback +-- in our example we will just have a command that will repeat the users name in chat X amount of times and only allow admins to use it. - -- Now when the user is not an admin and the command requires you to be an admin then we must reject the request: - -- 1) return false -- this is the most basic block and should only be used while testing - -- 2) return reject -- returning the reject function is only an option as a fail safe, same as returning false - -- 3) reject() -- this will block execution without returning to allow further code to be ran in the authenticator - -- 4) reject('This command is for admins only!') -- Using reject as a function allows a error message to be returned - -- 5) return reject() -- using return on either case above is best practice as you should execute all code before rejecting +-- First we create the new command, nb this will not register the command to the game this is done at the end, we will call +-- the command "repeat-name" and set the help message as follows: +Commands.new_command('repeat-name', 'Will repeat you name a number of times in chat.') - -- Example Code: - Commands.add_authenticator(function(player,command,flags,reject) - if flags.admin_only then -- our test for the "admin_only" flag - if player.admin then - return true -- true return 2 - else - return reject('This command is for admins only!') -- reject return 5 with a custom error message - end - else - return true -- true return 1 - end - end) +-- Now for our first param we will call "repeat-count" and it will be a required value between 1 and 5 inclusive: +:add_param('repeat-count', false, 'number-range-int', 1, 5) - @usage ----- Example Parse: - -- Before you go making commands it is important to understand the most powerful feature of this command handler, - -- when you define a command you are able to type the params and have then be parsed by an handler so before your - -- command is ever executed you can be sure that all the params are valid. This module should be paired with a general - -- command parse but you may want to create your own: +-- Our second param we need a custom parse for but we have not defined it, this is an option for when it is unlikely for +-- any other command to use the same input type; however in our case it will just be a boolean which should be noted as being +-- included in the general command parse config. As for the param its self it will be called "smiley" and will be optional with +-- a default value of false: +:add_param('smiley', true, function(input, player, reject) + -- since it is optional the input can be nil, in which case we just return + if not input then return end + -- if it is not nil then we check for a truthy value + if input:lower() == 'true' or input:lower() == 'yes' then + return true + else + -- note that because we did not return nil or reject then false will be passed to command callback, see example parse + return false + end +end) - -- For our example we will create a parse to accept only integer numbers in a given range: - -- 1) we will give it the name "number-range-int" this is the "type" that the input is expected to be - -- 2) when we define the type we will also define the min and max of the range so we can use the function more than once - -- Example parse usage: - :add_param('repeat_count',false,'number-range-int',5,10) -- range 5 to 10 inclusive +-- Once all params are defined you can now define some default values if you have optional params, the default value will be used only +-- when no value is given as input, if an invalid value is given then the command will still fail and this value will not be used, the +-- default can also be a function which is passed the player using the command and returns a value. Here we set the default for "smiley" to false: +:set_defaults{smiley=false} - -- The command parse will be passed 3 params and any other you define, in our case: - -- 1) the input that has been given by the user for this param, the role of this function is to transform this value - -- nb: the input is a string but can be nil if the param is marked as optional - -- 2) the player who is using the command, this is always present - -- 3) the reject function to throw an error to the user, this is always present - -- 4) the range min, this is user defined and has the value given when the param is defined - -- 5) the range max, this is user defined and has the value given when the param is defined +-- Another example of defaults if we have: item, amount[opt], player[opt] +:set_defaults{ + amount = 50, -- more than one value can be set at a time + player = function(player) + return player -- default is the player using the command + end +} - -- When returning from the param parse you again have a few options with how to do this: - -- 1) you return the new value for the param (any non nil value) this value is then passed to the command callback - -- 2) not returning will cause a generic invalid error and the command callback is blocked, not recommenced - -- 3) return reject -- this is just a failsafe in case the function is not called, same as no return - -- 4) return reject() -- will give a shorter error message as you pass a nil custom error - -- 5) return reject('Number entered is not in range: '..range_min..', '..range_max) -- returns a custom error the the user - -- nb: if you do not return reject after you call it then you are still returning nil so there will be a duplicate message +-- Now the params are set up we can alter how the command works, we can set auth flags, add aliases to this command or enable "auto concat" +-- which is when you want all extra words to be concatenated onto the end of the last param, useful for reason or messages: +:set_flag('admin_only', true) -- in our case we want "admin_only" to be set to true so only admins can use the command +:add_alias('name', 'rname') -- we also add two aliases here: "name" and "rname" which point to this command +-- :enable_auto_concat() we do not use this in our case but this can also be used to enable the "auto concat" feature - -- It should be noted that if you want to expand on an existing parse you can use Commands.parse(type,input,player,reject) - -- and this value will either return a new value for the input or nil, if it is nil you should return nil to prevent double - -- messages to the user: - input = Commands.parse('number-int',input,player,reject) - if not input then return end -- nil check +-- And finally we want to register a callback to this command, the callback is what defines what the command does, can be as complex as you +-- want it to be to as simple as our example; the command receives two params plus all that you have defines: +-- 1) the player who used the command +-- 2) in our case repeat_count which will be a number +-- 3) in our case smiley which will be a boolean +-- 4) the raw input; this param is always last as is always present as a catch all +:register(function(player, repeat_count, smiley, raw) + -- this is to show the value for raw as this is an example command, the log file will also show this + game.print(player.name..' used a command with input: '..raw) + local msg = ') '..player.name + if smiley then + -- this is where that smiley param is used + msg = ':'..msg + end + for 1 = 1,repeat_count do + -- this print function will return ANY value to the user in a desync safe manor, this includes if the command was used through rcon + Command.print(1..msg) + end + -- see below for what else can be used here +end) - -- Example Code: - Commands.add_parse('number-range-int',function(input,player,reject,range_min,range_max) - local rtn = tonumber(input) and math.floor(tonumber(input)) or nil -- converts input to number - if not rtn or rtn < range_min or rtn > range_max then - -- the input is either not a number or is outside the range - return reject('Number entered is not in range: '..range_min..', '..range_max) - else - -- returns the input as a number value rather than a string, thus the param is now the correct type - return rtn - end - end) +-- Other values that can be returned from register +Commands.print(any,colour[opt]) -- this will return any value value to the user including if it is ran through rcon console +Commands.error(message[opt]) -- this returns a warning to the user, aka an error that does not prevent execution of the command +return Commands.error(message[opt]) -- this returns an error to the user, and will halt the command execution, ie no success message is returned +Commands.success(message[opt]) -- used to return a success message however don't use this method see below +return Commands.success(message[opt]) -- will return the success message to the user and your given message, halts execution +return -- if any value is returned then it will be returned to the player via a Commands.success call - @usage ----- Example Command: - -- How for the fun part making the commands, the commands can be set up with any number of params and flags that you want, - -- you can add aliases for the commands and set default values for optional params and of course register your command callback - -- in our example we will just have a command that will repeat the users name in chat X amount of times and only allow admins to use it. +@usage--- Example Authenticator: +-- The command system is best used when you can control who uses commands; +-- to do this would would need to define an authenticator which is ran every time a command is run; +-- in this example I will show a simple one that requires certain commands to require the user to be a game admin. - -- First we create the new command, nb this will not register the command to the game this is done at the end, we will call - -- the command "repeat-name" and set the help message as follows: - Commands.new_command('repeat-name','Will repeat you name a number of times in chat.') +-- For our admin only example we will set a flag to true when we want it to be admin only; +-- when we define the command will will use :set_flag('admin_only', true); +-- then inside the authenticator we will test if the flag is present using: if flags.admin_only then - -- Now for our first param we will call "repeat-count" and it will be a required value between 1 and 5 inclusive: - :add_param('repeat-count',false,'number-range-int',1,5) +-- When the authenticator is called by the command handler it will be passed 4 arguments: +-- 1) player - the player who used the command +-- 2) command - the name of the command that is being used +-- 3) flags - the flags which have been set for this command, flags are set with :set_flag(name, value) +-- 4) reject - the reject function which is the preferred method to prevent execution of the command - -- Our second param we need a custom parse for but we have not defined it, this is an option for when it is unlikely for - -- any other command to use the same input type; however in our case it will just be a boolean which should be noted as being - -- included in the general command parse config. As for the param its self it will be called "smiley" and will be optional with - -- a default value of false: - :add_param('smiley',true,function(input,player,reject) - -- since it is optional the input can be nil, in which case we just return - if not input then return end - -- if it is not nil then we check for a truthy value - if input:lower() == 'true' or input:lower() == 'yes' then - return true - else - -- note that because we did not return nil or reject then false will be passed to command callback, see example parse - return false - end - end) +-- No return is required to allow the command to execute but it is best practice to return true; +-- we do this in two cases in our authenticator: +-- 1) when the "admin_only" flag is not set, which we take assume that any one can use it +-- 2) when the "admin_only" flag is set, and the player is admin - -- Once all params are defined you can now define some default values if you have optional params, the default value will be used only - -- when no value is given as input, if an invalid value is given then the command will still fail and this value will not be used, the - -- default can also be a function which is passed the player using the command and returns a value. Here we set the default for "smiley" to false: - :set_defaults{smiley=false} +-- When want to prevent exicution of the command we must reject it, listed is how that can be done: +-- 1) return false -- this is the most basic rejection and should only be used while testing +-- 2) return reject -- returning the reject function is as a fail safe in case you forget to call it, same as returning false +-- 3) reject() -- this will block execution without to allowing further code to be ran in your authenticator +-- 4) reject('This command is for admins only!') -- Using reject as a function allows a error message to be returned +-- 5) return reject() -- using return on either case above is best practice as you should execute all your code before rejecting - -- Another example of defaults if we have: item, amount[opt], player[opt] - :set_defaults{ - amount = 50, -- more than one value can be set at a time - player = function(player) - return player -- default is the player using the command - end - } +-- Example Code: +Commands.add_authenticator(function(player, command, flags, reject) + -- Check if the command is admin only + if flags.admin_only then + -- Return true if player is admin, or reject and return error message + return player.admin or reject('This command is for admins only!') + else + -- Return true if command was not admin only + return true + end +end) - -- Now the params are set up we can alter how the command works, we can set auth flags, add aliases to this command or enable "auto concat" - -- which is when you want all extra words to be concatenated onto the end of the last param, useful for reason or messages: - :set_flag('admin_only',true) -- in our case we want "admin_only" to be set to true so only admins can use the command - :add_alias('name','rname') -- we also add two aliases here: "name" and "rname" which point to this command - -- :enable_auto_concat() we do not use this in our case but this can also be used to enable the "auto concat" feature +@usage--- Example Parse: +-- Before you make a command it is important to understand the most powerful feature of this command handler; +-- when you define a command you are able to type the params and have then be parsed and validated before your command is executed; +-- This module should is paired with a general command parse but you may want to create your own. - -- And finally we want to register a callback to this command, the callback is what defines what the command does, can be as complex as you - -- want it to be to as simple as our example; the command receives two params plus all that you have defines: - -- 1) the player who used the command - -- 2) in our case repeat_count which will be a number - -- 3) in our case smiley which will be a boolean - -- 4) the raw input; this param is always last as is always present as a catch all - :register(function(player,repeat_count,smiley,raw) - -- this is to show the value for raw as this is an example command, the log file will also show this - game.print(player.name..' used a command with input: '..raw) - local msg = ') '..player.name - if smiley then - -- this is where that smiley param is used - msg = ':'..msg - end - for 1 = 1,repeat_count do - -- this print function will return ANY value to the user in a desync safe manor, this includes if the command was used through rcon - Command.print(1..msg) - end - -- see below for what else can be used here - end) +-- For our example we will create a parse to accept only integer numbers in a given range: +-- 1) we will give it the name "number-range-int" this is the "type" that the input is expected to be +-- 2) when we define the type we will also define the min and max of the range so we can use the function more than once +:add_param('repeat_count', false, 'number-range-int', 5, 10) -- "repeat_count" is required "number-range-int" in a range 5 to 10 inclusive - -- Some other useful functions that can be used are: - Commands.print(any,colour[opt]) -- this will return any value value to the user including if it is ran through rcon console - Commands.error(message[opt]) -- this returns a warning to the user, aka an error that does not prevent execution of the command - return Commands.error(message[opt]) -- this returns an error to the user, and will halt the command execution, ie no success message is returned - Commands.success(message[opt]) -- used to return a success message however don't use this method see below - return Commands.success(message[opt]) -- will return the success message to the user and your given message, halts execution - return if any value is returned then it will be returned to the player via a Commands.success call +-- The command parse will be passed 3 arguments plus any other which you define, in our case: +-- 1) input - the input that has been given by the user for this param, the role of this function is to transform this value +-- nb: the input is a string but can be nil if the param is marked as optional +-- 2) player - the player who is using the command, this is always present +-- 3) reject - the reject function to throw an error to the user, this is always present +-- 4) range_min - the range min, this is user defined and has the value given when the param is defined +-- 5) range_max - the range max, this is user defined and has the value given when the param is defined - -- Example Code: - Commands.new_command('repeat-name','Will repeat you name a number of times in chat.') - :add_param('repeat-count',false,'number-range-int',1,5) -- required int in range 1 to 5 inclusive - :add_param('smiley',true,function(input,player,reject) -- optional boolean default false - if not input then return end - if input:lower() == 'true' or input:lower() == 'yes' then - return true - else - return false - end - end) - :set_defaults{smiley=false} - :set_flag('admin_only',true) -- command is admin only - :add_alias('name','rname') -- allow alias: name and rname - :register(function(player,repeat_count,smiley,raw) - game.print(player.name..' used a command with input: '..raw) - local msg = ') '..player.name - if smiley then - msg = ':'..msg - end - for 1 = 1,repeat_count do - Command.print(1..msg) - end - end) +-- When returning from the param parse you have a few options with how to do this: +-- 1) you return the new value for the param (any non nil value) this value is then passed to the command callback +-- 2) not returning will cause a generic invalid error and the command is rejected, not recommenced +-- 3) return reject -- this is just a failsafe in case the function is not called, same as no return +-- 4) return reject() -- will give a shorter error message as you pass a nil custom error +-- 5) return reject('Number entered is not in range: '..range_min..', '..range_max) -- returns a custom error to the user +-- nb: if you do not return reject after you call it then you will still be returning nil so there will be a duplicate error message + +-- It should be noted that if you want to expand on an existing parse you can use Commands.parse(type, input, player, reject) +-- this function will either return a new value for the input or nil, if it is nil you should return nil to prevent duplicate +-- error messages to the user: +input = Commands.parse('number-int', input, player, reject) +if not input then return end -- nil check + +-- Example Code: +Commands.add_parse('number-range-int',function(input, player, reject, range_min, range_max) + local rtn = tonumber(input) and math.floor(tonumber(input)) or nil -- converts input to number + if not rtn or rtn < range_min or rtn > range_max then + -- the input is either not a number or is outside the range + return reject('Number entered is not in range: '..range_min..', '..range_max) + else + -- returns the input as a number value rather than a string, thus the param is now the correct type + return rtn + end +end) ]] local Game = require 'utils.game' --- @dep utils.game -local player_return,write_json = ext_require('expcore.common','player_return','write_json') --- @dep expcore.common +local player_return,write_json = _C.player_return, _C.write_json --- @dep expcore.common local Commands = { - defines={ -- common values are stored error like signals + --- Values returned by the signal functions to cause the command system to react + defines = { error='CommandError', unauthorized='CommandErrorUnauthorized', success='CommandSuccess' }, - commands={}, -- custom command data will be stored here - authorization_fail_on_error=false, -- set true to have authorize fail if a callback fails to run, more secure - authorization={}, -- custom function are stored here which control who can use what commands - parse_functions={}, -- used to store default functions which are common parse function such as player or number in range - print=player_return, -- short cut so player_return does not need to be required in every module - _prototype={}, -- used to store functions which gets added to new custom commands + --- Custom command data will be stored here + commands={}, + --- Set true to have authorize fail if a callback fails to run, more secure + authorization_fail_on_error=false, + --- Custom function are stored here which control who can use what commands + authorization={}, + --- Used to store default functions which are common parse function such as player or number in range + parse_functions={}, + -- Sends a value to the player, different to success as this does not signal the end of your command + print=player_return, + --- Used to store functions which gets added to new custom commands + _prototype={}, } --- Authenication. -- Functions that control who can use commands -- @section auth ---- Adds an authorization callback, function used to check if a player if allowed to use a command --- @tparam function callback the callback you want to register as an authenticator --- callback param - player: LuaPlayer - the player who is trying to use the command --- callback param - command: string - the name of the command which is being used --- callback param - flags: table - any flags which have been set for the command --- callback param - reject: function(error_message?: string) - call to fail authorize with optional error message --- @treturn number the index it was inserted at use to remove the callback, if anon function used +--[[-- Adds an authorization callback, function used to check if a player if allowed to use a command +@tparam function callback the callback you want to register as an authenticator +@treturn number the index it was inserted at use to remove the callback, if anon function used + +@usage-- Test if a command is admin only and if the player is admin +local admin_authenticator = +Commands.add_authenticator(function(player, command, flags, reject) + if flags.admin_only then + return player.admin or reject('This command is for admins only!') + else + return true + end +end) + +]] function Commands.add_authenticator(callback) table.insert(Commands.authorization,callback) return #Commands.authorization end ---- Removes an authorization callback --- @tparam function|number callback the callback to remove, an index returned by add_authenticator can be passed --- @treturn boolean was the callback found and removed +--[[-- Removes an authorization callback +@tparam function|number callback the callback to remove, an index returned by add_authenticator can be passed +@treturn boolean if the callback found and removed successfuly + +@usage-- Removing the admin authenticator, can not be done dueing runtime +Commands.remove_authenticator(admin_authenticator) + +]] function Commands.remove_authenticator(callback) if type(callback) == 'number' then -- if a number is passed then it is assumed to be the index @@ -256,13 +272,18 @@ function Commands.remove_authenticator(callback) return false end ---- Mostly used internally, calls all authorization callbacks, returns if the player is authorized --- @tparam LuaPlayer player the player that is using the command, passed to callbacks --- @tparam string command_name the command that is being used, passed to callbacks --- @treturn[1] boolean true player is authorized --- @treturn[1] string commands const for success --- @treturn[2] boolean false player is unauthorized --- @treturn[2] string|locale_string the reason given by the authenticator +--[[-- Mostly used internally, calls all authorization callbacks, returns if the player is authorized +@tparam LuaPlayer player the player that is using the command, passed to callbacks +@tparam string command_name the command that is being used, passed to callbacks +@treturn[1] boolean true player is authorized +@treturn[1] string commands const for success +@treturn[2] boolean false player is unauthorized +@treturn[2] string|locale_string the reason given by the authenticator + +@usage-- Test if a player can use "repeat-name" +local authorized, status = Commands.authorize(game.player, 'repeat-name') + +]] function Commands.authorize(player,command_name) local failed if not player then return true end @@ -300,13 +321,22 @@ function Commands.authorize(player,command_name) return true, Commands.defines.success end end + --- Getters. -- Functions that get commands -- @section getters ---- Gets all commands that a player is allowed to use, game commands not included --- @tparam[opt] LuaPlayer player the player that you want to get commands of, nil will return all commands --- @treturn table all commands that that player is allowed to use, or all commands +--[[-- Gets all commands that a player is allowed to use, game commands are not included +@tparam[opt] LuaPlayer player the player that you want to get commands of, nil will return all commands +@treturn table all commands that that player is allowed to use, or all commands + +@usage-- Get the command you are allowed to use +local commands = Commands.get(game.player) + +@usage-- Get all commands that are registered +local commands = Commands.get() + +]] function Commands.get(player) player = Game.get_player_from_any(player) if not player then return Commands.commands end @@ -319,12 +349,20 @@ function Commands.get(player) return allowed end ---- Searches command names and help messages to find possible commands, game commands included --- @tparam string keyword the word which you are trying to find --- @tparam[opt] LuaPlayer allowed_player the player to get allowed commands of, if nil all commands are searched --- @treturn table all commands that contain the key word, and allowed by player if player given -function Commands.search(keyword,allowed_player) - local custom_commands = Commands.get(allowed_player) +--[[-- Searches command names and help messages to find possible commands, game commands are included +@tparam string keyword the word which you are trying to find in your search +@tparam[opt] LuaPlayer player the player to get allowed commands of, if nil all commands are searched +@treturn table all commands that contain the key word, and allowed by player if player given + +@usage-- Get all commands which "repeat" +local commands = Commands.search('repeat') + +@usage-- Get all commands which "repeat" and you are allowed to use +local commands = Commands.search('repeat', game.player) + +]] +function Commands.search(keyword,player) + local custom_commands = Commands.get(player) local matches = {} keyword = keyword:lower() -- loops over custom commands @@ -354,15 +392,25 @@ end -- Functions that help with parsing -- @section parse ---- Adds a parse function which can be called by name rather than callback (used in add_param) --- nb: this is not needed as you can use the callback directly this just allows it to be called by name --- @tparam string name the name of the parse, should be the type like player or player_alive, must be unique --- @tparam function callback the callback that is ran to parse the input --- parse param - input: string - the input given by the user for this param --- parse param - player: LuaPlayer - the player who is using the command --- parse param - reject: function(error_message) - use this function to send a error to the user and fail running --- parse return - the value that will be passed to the command callback, must not be nil and if reject then command is not run --- @treturn boolean was the parse added will be false if the name is already used +--[[-- Adds a parse function which can be called by name (used in add_param) +nb: this is not required as you can use the callback directly this just allows it to be called by name +@tparam string name the name of the parse, should be the type like player or player_alive, must be unique +@tparam function callback the callback that is ran to parse the input +@treturn boolean was the parse added will be false if the name is already used + +@usage-- Adding a parse to validate ints in a given range +Commands.add_parse('number-range-int', function(input, player, reject, range_min, range_max) + local rtn = tonumber(input) and math.floor(tonumber(input)) or nil -- converts input to number + if not rtn or rtn < range_min or rtn > range_max then + -- the input is either not a number or is outside the range + return reject('Number entered is not in range: '..range_min..', '..range_max) + else + -- returns the input as a number rather than a string, thus the param is now the correct type + return rtn + end +end) + +]] function Commands.add_parse(name,callback) if Commands.parse_functions[name] then return false @@ -372,18 +420,28 @@ function Commands.add_parse(name,callback) end end ---- Removes a parse function, see add_parse for adding them --- @tparam string name the name of the parse to remove +--[[-- Removes a parse function, see add_parse for adding them +@tparam string name the name of the parse to remove + +@usage-- Removing a parse +Commands.remove_parse('number-range-int') + +]] function Commands.remove_parse(name) Commands.parse_functions[name] = nil end ---- Intended to be used within other parse functions, runs a parse and returns success and new value --- @tparam string name the name of the parse to call, must be registered and cant be a function --- @tparam string input string the input to pass to the parse, will always be a but might not be the original input --- @tparam LuaPlayer player the player that is calling using the command --- @tparam function reject the reject function that was passed by the command hander --- @treturn any the new value for the input, may be nil, if nil then either there was an error or input was nil +--[[-- Intended to be used within other parse functions, runs a parse and returns success and new value +@tparam string name the name of the parse to call, must be registered parse +@tparam string input string the input to pass to the parse, must be a string but not necessarily the original input +@tparam LuaPlayer player the player that is using the command +@tparam function reject the reject function that was passed by the command hander +@treturn any the new value for the input, may be nil, if nil then either there was an error or input was nil + +@usage-- Parsing a int in a given range +local parsed_input = Commands.parse('number-range-int', '7', player, reject, 1, 10) -- valid range 1 to 10 + +]] function Commands.parse(name,input,player,reject,...) if not Commands.parse_functions[name] then return end local success,rtn = pcall(Commands.parse_functions[name],input,player,reject,...) @@ -397,10 +455,16 @@ end -- Functions that create a new command -- @section creation ---- Creates a new command object to added details to, note this does not register the command to the game --- @tparam string name the name of the command to be created --- @tparam string help the help message for the command --- @treturn Commands._prototype this will be used with other functions to generate the command functions +--[[-- Creates a new command object to added details to, note this does not register the command to the game api +@tparam string name the name of the command to be created +@tparam string help the help message for the command +@treturn Commands._prototype this will be used with other functions to generate the command functions + +@usage-- Define a new command +local command = +Commands.new_command('repeat-name', 'Will repeat you name a number of times in chat.') + +]] function Commands.new_command(name,help) local command = setmetatable({ name=name, @@ -419,16 +483,23 @@ function Commands.new_command(name,help) return command end ---- Adds a new param to the command this will be displayed in the help and used to parse the input --- @tparam string name the name of the new param that is being added to the command --- @tparam[opt=false] boolean optional is this param required for this command, these must be after all required params --- @tparam[opt=pass function through] ?string|function parse this function will take the input and return a new (or same) value --- @param[opt] ... extra args you want to pass to the parse function; for example if the parse is general use --- parse param - input: string - the input given by the user for this param --- parse param - player: LuaPlayer - the player who is using the command --- parse param - reject: function(error_message) - use this function to send a error to the user and fail running --- parse return - the value that will be passed to the command callback, must not be nil and if reject then command is not run --- @treturn Commands._prototype pass through to allow more functions to be called +--[[-- Adds a new param to the command this will be displayed in the help and used to parse the input +@tparam string name the name of the new param that is being added to the command +@tparam[opt=false] boolean optional is this param required for this command, these must be after all required params +@tparam[opt=pass function through] ?string|function parse this function will take the input and return a new (or same) value +@param[opt] ... extra args you want to pass to the parse function; for example if the parse is general use +@treturn Commands._prototype pass through to allow more functions to be called + +@usage-- Adding a param which has an parse defined +command:add_param('repeat-count', false, 'number-range-int', 1, 5) + +@usage-- Adding a param which has a custom parse, see Commands.add_parse for details +command:add_param('smiley', true, function(input, player, reject) + if not input then return end + return input:lower() == 'true' or input:lower() == 'yes' or false +end) + +]] function Commands._prototype:add_param(name,optional,parse,...) local parse_args = {...} if type(optional) ~= 'boolean' then @@ -449,10 +520,20 @@ function Commands._prototype:add_param(name,optional,parse,...) return self end ---- Adds default values to params only matters if the param is optional, if default value is a function it is called with param player --- @tparam table defaults table a keyed by the name of the param with the value as the default value {paramName=defaultValue} --- callback param - player: LuaPlayer - the player using the command, default value does not need to be a function callback --- @treturn Commands._prototype pass through to allow more functions to be called +--[[-- Add default values to params, only as an effect if the param is optional, if default value is a function it is called with acting player +@tparam table defaults table which is keyed by the name of the param and the value is the default value +@treturn Commands._prototype pass through to allow more functions to be called + +@usage-- Adding default values +command:set_defaults{ + smiley = false, + -- not in example just used to show arguments given + player_name = function(player) + return player.name + end +} + +]] function Commands._prototype:set_defaults(defaults) for name,value in pairs(defaults) do if self.params[name] then @@ -462,26 +543,32 @@ function Commands._prototype:set_defaults(defaults) return self end ---- Adds a tag to the command which is passed via the flags param to the authenticators, can be used to assign command roles or type --- @tparam string name the name of the tag to be added; used to keep flags separate --- @tparam any value the tag that you want can be anything that the authenticators are expecting --- nb: if value is nil then name will be assumed as the value and added at a numbered index --- @treturn Commands._prototype pass through to allow more functions to be called +--[[-- Adds a tag to the command which is passed via the flags param to the authenticators, can be used to assign command roles or type +@tparam string name the name of the tag to be added, set to true if no value is given +@tparam[opt=true] any value the tag that you want can be anything that the authenticators are expecting +@treturn Commands._prototype pass through to allow more functions to be called + +@usage-- Setting a custom flag +command:set_flag('admin_only', true) + +@usage-- When value is true it does not need to be given +command:set_flag('admin_only') + +]] function Commands._prototype:set_flag(name,value) - if not value then - -- value not given so name is the value - table.insert(self.flags,name) - else - -- name is given so its key: value - self.flags[name] = value - end + value = value or true + self.flags[name] = value return self end ---- Adds an alias or multiple that will also be registered with the same callback, eg /teleport can be /tp with both working --- @usage command:add_alias('aliasOne','aliasTwo','etc') --- @tparam string any ... amount of aliases that you want this command to be callable with --- @treturn Commands._prototype pass through to allow more functions to be called +--[[-- Adds an alias, or multiple, that will also be registered with the same callback, eg /teleport can be used as /tp +@tparam string any ... amount of aliases that you want this command to be callable with +@treturn Commands._prototype pass through to allow more functions to be called + +@usage-- Added multiple aliases to a command +command:add_alias('name', 'rname') + +]] function Commands._prototype:add_alias(...) for _,alias in pairs({...}) do table.insert(self.aliases,alias) @@ -490,21 +577,35 @@ function Commands._prototype:add_alias(...) return self end ---- Enables auto concatenation of any params on the end so quotes are not needed for last param --- nb: this will disable max param checking as they will be concatenated onto the end of that last param --- this can be useful for reasons or longs text, can only have one per command --- @treturn Commands._prototype pass through to allow more functions to be called +--[[-- Enables auto concatenation of any params on the end so quotes are not needed for last param +nb: this will disable max param checking as they will be concatenated onto the end of that last param +this can be useful for reasons or longs text, can only have one per command +@treturn Commands._prototype pass through to allow more functions to be called + +@usage-- Enable auto concat for a command +command:enable_auto_concat() + +]] function Commands._prototype:enable_auto_concat() self.auto_concat = true return self end ---- Adds the callback to the command and registers all aliases, params and help message with the game --- nb: this must be the last function ran on the command and must be done for the command to work --- @tparam function callback the callback for the command, will receive the player running command, and params added with add_param --- callback param - player: LuaPlayer - the player who used the command --- callback param - ... - any params which were registered with add_param in the order they where registered --- callback param - raw: string - the raw input from the user, comes after every param added with add_param +--[[-- Adds the callback to the command and registers all aliases, params and help message with the game api +nb: this must be the last function ran on the command and must be done for the command to work +@tparam function callback the callback for the command, will receive the player running command, and params added with add_param + +@usage-- Registering your command to the game api +command:register(function(player, repeat_count, smiley, _) + local msg = ') '..player.name + if smiley then msg = ':'..msg end + + for 1 = 1,repeat_count do + Command.print(1..msg) + end +end) + +]] function Commands._prototype:register(callback) -- generates a description to be used self.callback = callback @@ -538,13 +639,16 @@ end -- Functions that indicate status -- @section status ---- Sends an error message to the player and returns a constant to return to command handler to exit execution --- nb: this is for non fatal errors meaning there is no log of this event --- nb: if reject is giving as a param to the callback use that instead --- @usage return Commands.error() --- @tparam[opt] string error_message an optional error message that can be sent to the user --- @tparam[opt] string play_sound the sound to play for the error --- @treturn Commands.defines.error return this to command handler to exit execution +--[[-- Sends an error message to the player and when returned will stop exicution of the command +nb: this is for non fatal errors meaning there is no log of this event, use during register callback +@tparam[opt=''] string error_message an optional error message that can be sent to the user +@tparam[opt=utility/wire_pickup] string play_sound the sound to play for the error +@treturn Commands.defines.error return this to command handler to exit execution + +@usage-- Send an error message to the player, and stops further code running +return Commands.error('The player you selected is offline') + +]] function Commands.error(error_message,play_sound) error_message = error_message or '' player_return({'expcore-commands.command-fail',error_message},'orange_red') @@ -555,12 +659,20 @@ function Commands.error(error_message,play_sound) return Commands.defines.error end ---- Sends an error to the player and logs the error, used with pcall within command handler please avoid direct use --- nb: use error(error_message) within your callback to trigger do not trigger directly as the handler may still continue --- @tparam boolean success the success value returned from pcall, or just false to trigger error --- @tparam string command_name the name of the command this is used within the log --- @tparam string error_message the error returned by pcall or some other error, this is logged and not returned to player --- @treturn boolean the opposite of success so true means to cancel execution, used internally +--[[-- Sends an error to the player and logs the error, used with pcall within command handler please avoid direct use +nb: use error(error_message) within your callback to trigger do not trigger directly as code exictuion may still continue +@tparam boolean success the success value returned from pcall, or just false to trigger error +@tparam string command_name the name of the command this is used within the log +@tparam string error_message the error returned by pcall or some other error, this is logged and not returned to player +@treturn boolean the opposite of success so true means to cancel execution, used internally + +@usage-- Used in the command system to log handler errors +local success, err = pcall(command_data.callback, player, unpack(params)) +if Commands.internal_error(success, command_data.name, err) then + return command_log(player, command_data, 'Internal Error: Command Callback Fail', raw_params, command_event.parameter, err) +end + +]] function Commands.internal_error(success,command_name,error_message) if not success then Commands.error('Internal Error, Please contact an admin','utility/cannot_build') @@ -569,16 +681,34 @@ function Commands.internal_error(success,command_name,error_message) return not success end ---- Sends a value to the player, followed by a command complete message --- nb: either return a value from your callback to trigger or return the return of this to prevent two messages --- @tparam[opt] any value the value to return to the player, if nil then only success message returned --- @treturn Commands.defines.success return this to the command handler to prevent two success messages +--[[-- Sends a value to the player, followed by a command complete message +nb: returning any value from your callback will trigger this function, return this function to prevent duplicate messages +@tparam[opt] any value the value to return to the player, if nil then only success message returned +@treturn Commands.defines.success return this to the command handler to prevent two success messages + +@usage-- Print a custom success message +return Commands.success('Your message has been printed') + +@usage-- Returning the value has the same result +return 'Your message has been printed' + +]] function Commands.success(value) if value ~= nil then player_return(value) end player_return({'expcore-commands.command-ran'},'cyan') return Commands.defines.success end +--[[-- Sends a value to the player, different to success as this does not signal the end of your command +@function print +@tparam any value the value that you want to return to the player +@tparam table colour the colour of the message that the player sees + +@usage-- Output a message to the player +Commands.print('Your command is in progress') + +]] + -- logs command usage to file local function command_log(player,command,comment,params,raw,details) local player_name = player and player.name or '' @@ -594,6 +724,7 @@ end --- Main event function that is ran for all commands, used internally please avoid direct use -- @tparam table command_event passed directly from command event from the add_command function +-- @usage Commands.run_command(event) function Commands.run_command(command_event) local command_data = Commands.commands[command_event.name] -- player can be nil when it is the server diff --git a/expcore/common.lua b/expcore/common.lua index 1d9ebef0..e51b3edb 100644 --- a/expcore/common.lua +++ b/expcore/common.lua @@ -1,62 +1,403 @@ ---[[-- Core Module - Common Library - - Adds some commonly used functions used in many modules - @core Common-Library - @alias Common +--[[-- Core Module - Common +- Adds some commonly used functions used in many modules +@core Common +@alias Common ]] -local Colours = require 'resources.color_presets' --- @dep resources.color_presets +local Colours = require 'utils.color_presets' --- @dep utils.color_presets local Game = require 'utils.game' --- @dep utils.game local Util = require 'util' --- @dep util -require 'utils.table' -require 'utils.math' local Common = {} ---- Compare types faster for faster validation of params --- @usage type_check('foo','string') -- return true --- @usage type_check('foo') -- return false --- @tparam any value the value to be tested --- @tparam[opt=nil] string test_type the type to test for if not given then it tests for nil --- @treturn boolean is v of type test_type -function Common.type_check(value,test_type) +--- Type Checking. +-- @section typeCheck + +--[[-- Asserts the argument is of type test_type +@tparam any value the value to be tested +@tparam[opt=nil] string test_type the type to test for if not given then it tests for nil +@treturn boolean is v of type test_type + +@usage-- Check for a string value +local is_string = type_check(value, 'string') + +@usage-- Check for a nil value +local is_nil = type_check(value) + +]] +function Common.type_check(value, test_type) return test_type and value and type(value) == test_type or not test_type and not value or false end ---- Raises an error if the value is of the wrong type --- @usage type_check_error('foo','number','Value must be a number') -- will raise error "Value must be a number" --- @tparam any value the value that you want to test the type of --- @tparam string test_type the type that the value should be --- @tparam string error_message the error message that is returned --- @tparam number level the level to call the error on (level = 1 means the caller) --- @treturn boolean true if no error was called -function Common.type_check_error(value,test_type,error_message,level) +--[[-- Raises an error if the value is of the wrong type +@tparam any value the value that you want to test the type of +@tparam string test_type the type that the value should be +@tparam string error_message the error message that is returned +@tparam number level the level to call the error on (level = 1 is the caller) +@treturn boolean true if no error was called + +@usage-- Raise error if value is not a number +type_error(value, 'number', 'Value must be a number') + +]] +function Common.type_error(value, test_type, error_message, level) level = level and level+1 or 2 - return Common.test_type(value,test_type) or error(error_message,level) + return Common.type_check(value,test_type) or error(error_message,level) end ---- Raises an error when the value is the incorrect type, uses a consistent error message format --- @usage param_check('foo','number','repeat_count',2) -- will raise error "Invalid param #02 given to ; repeat_count is not of type number" --- @tparam any value the value that you want to test the type of --- @tparam string test_type the type that the value should be --- @tparam string param_name the name of the param --- @tparam number param_number the number param it is --- @treturn boolean true if no error was raised -function Common.param_check(value,test_type,param_name,param_number) +--[[-- Asserts the argument is one of type test_types +@param value the variable to check +@param test_types the type as a table of strings +@treturn boolean true if value is one of test_types + +@usage-- Check for a string or table +local is_string_or_table = multi_type_check(value, {'string','table'}) + +]] +function Common.multi_type_check(value, test_types) + local vtype = type(value) + for _, arg_type in ipairs(test_types) do + if vtype == arg_type then + return true + end + end + return false +end + +--[[-- Raises an error if the value is of the wrong type +@tparam any value the value that you want to test the type of +@tparam table test_types the type as a table of strings +@tparam string error_message the error message that is returned +@tparam number level the level to call the error on (level = 1 is the caller) +@treturn boolean true if no error was called + +@usage-- Raise error if value is not a string or table +multi_type_error('foo', {'string','table'}, 'Value must be a string or table') + +]] +function Common.multi_type_error(value, test_types, error_message, level) + level = level and level+1 or 2 + return Common.mult_type_check(value, test_types) or error(error_message,level) +end + +--[[-- Raises an error when the value is the incorrect type, uses a consistent error message format +@tparam any value the value that you want to test the type of +@tparam string test_type the type that the value should be +@tparam number param_number the number param it is +@tparam[opt] string param_name the name of the param +@treturn boolean true if no error was raised + +@usage-- Output: "Bad argument #2 to ""; argument is of type string expected number" +validate_argument_type(value, 'number', 2) + +@usage-- Output: "Bad argument #2 to ""; "repeat_count" is of type string expected number" +validate_argument_type(value, 'number', 2, 'repeat_count') + +]] +function Common.validate_argument_type(value, test_type, param_number, param_name) if not Common.test_type(value,test_type) then local function_name = debug.getinfo(2,'n').name or '' - local error_message = string.format('Invalid param #%2d given to %s; %s is not of type %s',param_number,function_name,param_name,test_type) + local error_message + if param_name then + error_message = string.format('Bad argument #%d to %q; %q is of type %s expected %s', param_number, function_name, param_name, type(value), test_type) + else + error_message = string.format('Bad argument #%d to %q; argument is of type %s expected %s', param_number, function_name, type(value), test_type) + end return error(error_message,3) end return true end ---- Will return a value of any type to the player/server console, allows colour for in-game players --- @usage player_return('Hello, World!') -- returns 'Hello, World!' to game.player or server console --- @usage player_return('Hello, World!','green') -- returns 'Hello, World!' to game.player with colour green or server console --- @usage player_return('Hello, World!',nil,player) -- returns 'Hello, World!' to the given player --- @param value any value of any type that will be returned to the player or console --- @tparam[opt=defines.colour.white] ?defines.color|string colour the colour of the text for the player, ignored when printing to console --- @tparam[opt=game.player] LuaPlayer player the player that return will go to, if no game.player then returns to server +--[[-- Raises an error when the value is the incorrect type, uses a consistent error message format +@tparam any value the value that you want to test the type of +@tparam string test_types the types that the value should be +@tparam number param_number the number param it is +@tparam[opt] string param_name the name of the param +@treturn boolean true if no error was raised + +@usage-- Output: "Bad argument #2 to ""; argument is of type number expected string or table" +validate_argument_type(value, {'string','table'}, 2) + +@usage-- Output: "Bad argument #2 to ""; "player" is of type number expected string or table" +validate_argument_type(value, {'string','table'}, 2, 'player') + +]] +function Common.validate_argument_multi_type(value, test_types, param_number, param_name) + if not Common.multi_type_check(value,test_types) then + local function_name = debug.getinfo(2,'n').name or '' + local error_message + if param_name then + error_message = string.format('Bad argument #%2d to %q; %q is of type %s expected %s', param_number, function_name, param_name, type(value), table.concat(test_types,' or ')) + else + error_message = string.format('Bad argument #%2d to %q; argument is of type %s expected %s', param_number, function_name, type(value), table.concat(test_types,' or ')) + end + return error(error_message,3) + end + return true +end + +--- Will raise an error if called during runtime +-- @usage error_if_runtime() +function Common.error_if_runtime() + if _LIFECYCLE == 8 then + local function_name = debug.getinfo(2,'n').name or '' + error(function_name..' can not be called during runtime',3) + end +end + +--- Will raise an error if the function is a closure +-- @usage error_if_runetime_closure(func) +function Common.error_if_runetime_closure(func) + if _LIFECYCLE == 8 and Debug.is_closure(func) then + local function_name = debug.getinfo(2,'n').name or '' + error(function_name..' can not be called during runtime with a closure',3) + end +end + +--- Value Returns. +-- @section valueReturns + +--[[-- Tests if a string contains a given substring. +@tparam string s the string to check for the substring +@tparam string contains the substring to test for +@treturn boolean true if the substring was found in the string + +@usage-- Test if a string contains a sub string +local found = string_contains(str, 'foo') + +]] +function Common.string_contains(s, contains) + return s and string.find(s, contains) ~= nil +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 default value 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,...) + return value and type(value) == 'function' and value(...) or value +end + +--- Converts a varible into its boolean value, nil and false return false +-- @treturn boolean the boolean form of the varible +-- @usage local bool = cast_bool(var) +function Common.cast_bool(var) + return var and true or false +end + +--- Returns either the second or third argument based on the first argument +-- @usage ternary(input_string == 'test', 'Input is test', 'Input is not test') +function Common.ternary(c, t, f) + return c and t or f +end + +--- Returns a string for a number with comma seperators +-- @usage comma_value(input_number) +function Common.comma_value(n) -- credit http://richard.warburton.it + local left, num, right = string.match(n, '^([^%d]*%d)(%d*)(.-)$') + return left .. (num:reverse():gsub('(%d%d%d)', '%1,'):reverse()) .. right +end + +--[[-- Sets a table element to value while also returning value. +@tparam table tbl to change the element of +@tparam string key the key to set the value of +@tparam any value the value to set the key as +@treturn any the value that was set + +@usage-- Set and return value +local value = set_and_return(players, player.name, player.online_time) + +]] +function Common.set_and_return(tbl, key, value) + tbl[key] = value + return value +end + +--[[-- Writes a table object to a file in json format +@tparam string path the path of the file to write include / to use dir +@tparam table tbl the table that will be converted to a json string and wrote to file + +@usage-- Write a lua table as a json to script-outpt/dump +write_json('dump', tbl) + +]] +function Common.write_json(path,tbl) + game.write_file(path,game.table_to_json(tbl)..'\n',true,0) +end + +--[[-- Calls a require that will not error if the file is not found +@usage local file = opt_require('file.not.present') -- will not cause any error +@tparam string path the path that you want to require +@return the returns from that file or nil, error if not loaded + +@usage-- Require a file without causing errors, for when a file might not exist +local Module = opt_require 'expcore.common' + +]] +function Common.opt_require(path) + local success, rtn = pcall(require,path) + if success then return rtn + else return nil,rtn 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 + +@usage-- Get the current file path +local file_path = get_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 + +--[[-- Converts a table to an enum +@tparam table tbl table the that will be converted +@treturn table the new table that acts like an enum + +@usage-- Make an enum +local colors = enum{ + 'red', + 'green', + 'blue' +} + +]] +function Common.enum(tbl) + local rtn = {} + for k,v in pairs(tbl) do + if type(k) ~= 'number' then + rtn[v]=k + end + end + for k,v in pairs(tbl) do + if type(k) == 'number' then + table.insert(rtn,v) + end + end + for k,v in pairs(rtn) do + rtn[v]=k + end + return rtn +end + +--[[-- Returns the closest match to the input +@tparam table options table a of options for the auto complete +@tparam string input string the input that will be completed +@tparam[opt=false] boolean use_key when true the keys of options will be used as the options +@tparam[opt=false] boolean rtn_key when true the the key will be returned rather than the value +@return the list item found that matches the input + +@usage-- Get the element that includes "foo" +local value = auto_complete(tbl, "foo") + +@usage-- Get the element with a key that includes "foo" +local value = auto_complete(tbl, "foo", true) + +@usage-- Get the key with that includes "foo" +local key = auto_complete(tbl, "foo", true, true) + +]] +function Common.auto_complete(options,input,use_key,rtn_key) + local rtn = {} + if type(input) ~= 'string' then return end + input = input:lower() + for key,value in pairs(options) do + local check = use_key and key or value + if Common.string_contains(string.lower(check),input) then + return rtn_key and key or value + end + end +end + +--- Formating. +-- @section formating + +--[[-- Returns a valid string with the name of the actor of a command. +@tparam string player_name the name of the player to use rather than server, used only if game.player is nil +@treturn string the name of the current actor + +@usage-- Get the current actor +local player_name = get_actor() + +]] +function Common.get_actor(player_name) + return game.player and game.player.name or player_name or '' +end + +--[[-- Returns a message with valid chat tags to change its colour +@tparam string message the message that will be in the output +@tparam table color a color which contains r,g,b as its keys +@treturn string the message with the color tags included + +@usage-- Use factorio tags to color a chat message +local message = format_chat_colour('Hello, World!', { r=355, g=100, b=100 }) + +]] +function Common.format_chat_colour(message,color) + color = color or Colours.white + local color_tag = '[color='..math.round(color.r,3)..','..math.round(color.g,3)..','..math.round(color.b,3)..']' + return string.format('%s%s[/color]',color_tag,message) +end + +--[[-- Returns a message with valid chat tags to change its colour, using localization +@tparam ?string|table message the message that will be in the output +@tparam table color a color which contains r,g,b as its keys +@treturn table the message with the color tags included + +@usage-- Use factorio tags and locale strings to color a chat message +local message = format_chat_colour_localized('Hello, World!', { r=355, g=100, b=100 }) + +]] +function Common.format_chat_colour_localized(message,color) + color = color or Colours.white + color = math.round(color.r,3)..','..math.round(color.g,3)..','..math.round(color.b,3) + return {'color-tag',color,message} +end + +--[[-- Returns the players name in the players color +@tparam LuaPlayer player the player to use the name and color of +@tparam[opt=false] boolean raw_string when true a string is returned rather than a localized string +@treturn table the players name with tags for the players color + +@usage-- Format a players name using the players color as a string +local message = format_chat_player_name(game.player, true) + +]] +function Common.format_chat_player_name(player,raw_string) + player = Game.get_player_from_any(player) + local player_name = player and player.name or '' + local player_chat_colour = player and player.chat_color or Colours.white + if raw_string then + return Common.format_chat_colour(player_name,player_chat_colour) + else + return Common.format_chat_colour_localized(player_name,player_chat_colour) + end +end + +--[[-- Will return a value of any type to the player/server console, allows colour for in-game players +@tparam any value a value of any type that will be returned to the player or console +@tparam[opt=defines.colour.white] ?defines.color|string colour the colour of the text for the player, ignored when printing to console +@tparam[opt=game.player] LuaPlayer player the player that return will go to, if no game.player then returns to server + +@usage-- Return a value to the current actor, rcon included +player_return('Hello, World!') + +@usage-- Return a value to the current actor, with color +player_return('Hello, World!', 'green') + +@usage-- Return to a player other than the current +player_return('Hello, World!', nil, player) + +]] function Common.player_return(value,colour,player) colour = Common.type_check(colour,'table') and colour or Colours[colour] ~= Colours.white and Colours[colour] or Colours.white player = player or game.player @@ -91,44 +432,26 @@ function Common.player_return(value,colour,player) else rcon.print(returnAsString) end end ---- Writes a table object to a file in json format --- @tparam string path the path of the file to write include / to use dir --- @tparam table tbl the table that will be converted to a json string and wrote to file -function Common.write_json(path,tbl) - game.write_file(path,game.table_to_json(tbl)..'\n',true,0) -end - ---- Calls a require that will not error if the file is not found --- @usage local file = opt_require('file.not.present') -- will not cause any error --- @tparam string path the path that you want to require --- @return the returns from that file or nil, error if not loaded -function Common.opt_require(path) - local success, rtn = pcall(require,path) - if success then return rtn - else return nil,rtn end -end - ---- Calls a require and returns only the keys given, file must return a table --- @usage local extract, param_check = ext_require('expcore.common','extract','param_check') --- @dep expcore.common --- @tparam string path the path that you want to require --- @tparam string ... the name of the keys that you want returned --- @return the keys in the order given -function Common.ext_require(path,...) - local rtn = require(path) - if type(rtn) ~= 'table' then - error('File did not return a table, can not extract keys.',2) - end - return Common.extract_keys(rtn,...) -end - ---- Formats tick into a clean format, denominations from highest to lowest --- long will use words rather than letters +--[[-- Formats tick into a clean format, denominations from highest to lowest -- time will use : separates --- string will return a string not a locale string -- when a denomination is false it will overflow into the next one --- @tparam number ticks the number of ticks that represents a time --- @tparam table options table a of options to use for the format --- @treturn string a locale string that can be used +@tparam number ticks the number of ticks that represents a time +@tparam table options table a of options to use for the format +@treturn string a locale string that can be used + +@usage-- Output: "0h 5m" +local time = format_time(18000, { hours=true, minutes=true, string=true }) + +@usage-- Output: "0 hours and 5 minutes" +local time = format_time(18000, { hours=true, minutes=true, string=true, long=true }) + +@usage-- Output: "00:05:00" +local time = format_time(18000, { hours=true, minutes=true, seconds=true, string=true }) + +@usage-- Output: "--:--:--" +local time = format_time(18000, { hours=true, minutes=true, seconds=true, string=true, null=true }) + +]] function Common.format_time(ticks,options) -- Sets up the options options = options or { @@ -213,12 +536,21 @@ function Common.format_time(ticks,options) return rtn end ---- Moves items to the position and stores them in the closest entity of the type given --- @tparam table items items which are to be added to the chests, ['name']=count --- @tparam[opt=navies] LuaSurface surface the surface that the items will be moved to --- @tparam[opt={0,0}] table position the position that the items will be moved to {x=100,y=100} --- @tparam[opt=32] number radius the radius in which the items are allowed to be placed --- @tparam[opt=iron-chest] string chest_type the chest type that the items should be moved into +--- Factorio. +-- @section factorio + +--[[-- Moves items to the position and stores them in the closest entity of the type given +@tparam table items items which are to be added to the chests, ['name']=count +@tparam[opt=navies] LuaSurface surface the surface that the items will be moved to +@tparam[opt={0,0}] table position the position that the items will be moved to {x=100,y=100} +@tparam[opt=32] number radius the radius in which the items are allowed to be placed +@tparam[opt=iron-chest] string chest_type the chest type that the items should be moved into +@treturn LuaEntity the last chest that had items inserted into it + +@usage-- Copy all the items in a players inventory and place them in chests at {0,0} +move_items(game.player.get_main_inventory().get_contents()) + +]] function Common.move_items(items,surface,position,radius,chest_type) chest_type = chest_type or 'iron-chest' surface = surface or game.surfaces[1] @@ -264,14 +596,19 @@ function Common.move_items(items,surface,position,radius,chest_type) return last_chest end ---[[-- https://github.com/Refactorio/RedMew/blob/9184b2940f311d8c9c891e83429fc57ec7e0c4a2/map_gen/maps/diggy/debug.lua#L31 - Prints a colored value on a location. - @param value between -1 and 1 - @param surface LuaSurface - @param position Position {x, y} - @param scale float - @param offset float - @param immutable bool if immutable, only set, never do a surface lookup, values never change +--[[-- Prints a colored value on a location, color is based on the value. +nb: src is below but the gradent has been edited +https://github.com/Refactorio/RedMew/blob/9184b2940f311d8c9c891e83429fc57ec7e0c4a2/map_gen/maps/diggy/debug.lua#L31 +@tparam number value the value to show must be between -1 and 1, scale can be used to achive this +@tparam LuaSurface surface the surface to palce the value on +@tparam table position {x, y} the possition to palce the value at +@tparam[opt=1] number scale how much to scale the colours by +@tparam[opt=0] number offset the offset in the +x +y direction +@tparam[opt=false] boolean immutable if immutable, only set, never do a surface lookup, values never change + +@usage-- Place a 0 at {0,0} +print_grid_value(0, game.player.surface, { x=0, y=0 }) + ]] function Common.print_grid_value(value, surface, position, scale, offset, immutable) local is_string = type(value) == 'string' @@ -286,23 +623,9 @@ function Common.print_grid_value(value, surface, position, scale, offset, immuta scale = scale or 1 offset = offset or 0 position = {x = position.x + offset, y = position.y + offset} - local r = math.max(1, value) / scale - local g = 1 - math.abs(value) / scale - local b = math.min(1, value) / scale - - if (r > 0) then - r = 0 - end - - if (b < 0) then - b = 0 - end - - if (g < 0) then - g = 0 - end - - r = math.abs(r) + local r = math.clamp(-value/scale, 0, 1) + local g = math.clamp(1-math.abs(value)/scale, 0, 1) + local b = math.clamp(value/scale, 0, 1) color = { r = r, g = g, b = b} @@ -332,81 +655,13 @@ function Common.print_grid_value(value, surface, position, scale, offset, immuta }.active = false end ---[[-- - Prints a colored value on a location. When given a color_value and a delta_color, - will change the color of the text from the base to base + value * delta. This will - make the color of the text range from 'base_color' to 'base_color + delta_color' - as the color_value ranges from 0 to 1 - @param value of number to be displayed - @param surface LuaSurface - @param position Position {x, y} - @param offset float position offset - @param immutable bool if immutable, only set, never do a surface lookup, values never change - @param color_value float How far along the range of values of colors the value is to be displayed - @param base_color {r,g,b} The color for the text to be if color_value is 0 - @param delta_color {r,g,b} The amount to correct the base_color if color_value is 1 - @param under_bound {r,g,b} The color to be used if color_value < 0 - @param over_bound {r,g,b} The color to be used if color_value > 1 +--[[-- Clears all flying text entities on a surface +@tparam LuaSurface surface the surface to clear + +@usage-- Remove all flying text on the surface +clear_flying_text(game.player.surface) + ]] -function Common.print_colored_grid_value(value, surface, position, offset, immutable, - color_value, base_color, delta_color, under_bound, over_bound) - local is_string = type(value) == 'string' - -- default values: - local color = base_color or Colours.white - local d_color = delta_color or Colours.black - local u_color = under_bound or color - local o_color = over_bound or color - - if (color_value < 0) then - color = u_color - elseif (color_value > 1) then - color = o_color - else - color = { - r = color.r + color_value * d_color.r, - g = color.g + color_value * d_color.g, - b = color.b + color_value * d_color.b - } - end - - local text = value - - if type(immutable) ~= 'boolean' then - immutable = false - end - - if not is_string then - offset = offset or 0 - position = {x = position.x + offset, y = position.y + offset} - - -- round at precision of 2 - text = math.floor(100 * value) * 0.01 - - if (0 == text) then - text = '0.00' - end - end - - if not immutable then - local text_entity = surface.find_entity('flying-text', position) - - if text_entity then - text_entity.text = text - text_entity.color = color - return - end - end - - surface.create_entity{ - name = 'flying-text', - color = color, - text = text, - position = position - }.active = false -end - ---- Clears all flying text entities on a surface --- @tparam LuaSurface surface the surface to clear function Common.clear_flying_text(surface) local entities = surface.find_entities_filtered{name ='flying-text'} for _,entity in pairs(entities) do @@ -416,288 +671,4 @@ function Common.clear_flying_text(surface) end end ---- Tests if a string contains a given substring. --- @tparam string s the string to check for the substring --- @tparam string contains the substring to test for --- @treturn boolean true if the substring was found in the string -function Common.string_contains(s, contains) - return s and string.find(s, contains) ~= nil -end - ---- Extracts certain keys from a table --- @usage local key_three, key_one = extract({key_one='foo',key_two='bar',key_three=true},'key_three','key_one') --- @tparam table tbl table the which contains the keys --- @tparam string ... the names of the keys you want extracted --- @return the keys in the order given -function Common.extract_keys(tbl,...) - local values = {} - for _,key in pairs({...}) do - table.insert(values,tbl[key]) - end - return unpack(values) -end - ---- Converts a table to an enum --- @tparam table tbl table the that will be converted --- @treturn table the new table that acts like an enum -function Common.enum(tbl) - local rtn = {} - for k,v in pairs(tbl) do - if type(k) ~= 'number' then - rtn[v]=k - end - end - for k,v in pairs(tbl) do - if type(k) == 'number' then - table.insert(rtn,v) - end - end - for k,v in pairs(rtn) do - rtn[v]=k - end - return rtn -end - ---- Returns the closest match to the input --- @tparam table options table a of options for the auto complete --- @tparam string input string the input that will be completed --- @tparam[opt=false] boolean use_key when true the keys of options will be used as the options --- @tparam[opt=false] boolean rtn_key when true the the key will be returned rather than the value --- @return the list item found that matches the input -function Common.auto_complete(options,input,use_key,rtn_key) - local rtn = {} - if type(input) ~= 'string' then return end - input = input:lower() - for key,value in pairs(options) do - local check = use_key and key or value - if Common.string_contains(string.lower(check),input) then - local result = rtn_key and key or value - table.insert(rtn,result) - end - end - return rtn[1] -end - ---- Default table comparator sort function. --- @local --- @param x one comparator operand --- @param y the other comparator operand --- @return true if x logically comes before y in a list, false otherwise -local function sortFunc(x, y) --sorts tables with mixed index types. - local tx = type(x) - local ty = type(y) - if tx == ty then - if type(x) == 'string' then - return string.lower(x) < string.lower(y) - else - return x < y - end - elseif tx == 'number' then - return true --only x is a number and goes first - else - return false --only y is a number and goes first - end -end - ---- Returns a copy of all of the values in the table. --- @tparam table tbl the to copy the keys from, or an empty table if tbl is nil --- @tparam[opt] boolean sorted whether to sort the keys (slower) or keep the random order from pairs() --- @tparam[opt] boolean as_string whether to try and parse the values as strings, or leave them as their existing type --- @treturn array an array with a copy of all the values in the table -function Common.table_values(tbl, sorted, as_string) - if not tbl then return {} end - local valueset = {} - local n = 0 - if as_string then --checking as_string /before/ looping is faster - for _, v in pairs(tbl) do - n = n + 1 - valueset[n] = tostring(v) - end - else - for _, v in pairs(tbl) do - n = n + 1 - valueset[n] = v - end - end - if sorted then - table.sort(valueset,sortFunc) - end - return valueset -end - ---- Returns a copy of all of the keys in the table. --- @tparam table tbl the to copy the keys from, or an empty table if tbl is nil --- @tparam[opt] boolean sorted whether to sort the keys (slower) or keep the random order from pairs() --- @tparam[opt] boolean as_string whether to try and parse the keys as strings, or leave them as their existing type --- @treturn array an array with a copy of all the keys in the table -function Common.table_keys(tbl, sorted, as_string) - if not tbl then return {} end - local keyset = {} - local n = 0 - if as_string then --checking as_string /before/ looping is faster - for k, _ in pairs(tbl) do - n = n + 1 - keyset[n] = tostring(k) - end - else - for k, _ in pairs(tbl) do - n = n + 1 - keyset[n] = k - end - end - if sorted then - table.sort(keyset,sortFunc) - end - return keyset -end - ---- Returns the list is a sorted way that would be expected by people (this is by key) --- @tparam table tbl the table to be sorted --- @treturn table the sorted table -function Common.table_alphanumsort(tbl) - local o = Common.table_keys(tbl) - local function padnum(d) local dec, n = string.match(d, "(%.?)0*(.+)") - return #dec > 0 and ("%.12f"):format(d) or ("%s%03d%s"):format(dec, #n, n) end - table.sort(o, function(a,b) - return tostring(a):gsub("%.?%d+",padnum)..("%3d"):format(#b) - < tostring(b):gsub("%.?%d+",padnum)..("%3d"):format(#a) end) - local _tbl = {} - for _,k in pairs(o) do _tbl[k] = tbl[k] end - return _tbl -end - ---- Returns the list is a sorted way that would be expected by people (this is by key) (faster alternative than above) --- @tparam table tbl the table to be sorted --- @treturn table the sorted table -function Common.table_keysort(tbl) - local o = Common.table_keys(tbl,true) - local _tbl = {} - for _,k in pairs(o) do _tbl[k] = tbl[k] end - return _tbl -end - ---- Returns a message with valid chat tags to change its colour --- @tparam string message the message that will be in the output --- @tparam table color a color which contains r,g,b as its keys --- @treturn string the message with the color tags included -function Common.format_chat_colour(message,color) - color = color or Colours.white - local color_tag = '[color='..math.round(color.r,3)..','..math.round(color.g,3)..','..math.round(color.b,3)..']' - return string.format('%s%s[/color]',color_tag,message) -end - ---- Returns a message with valid chat tags to change its colour, using localization --- @tparam ?string|table message the message that will be in the output --- @tparam table color a color which contains r,g,b as its keys --- @treturn table the message with the color tags included -function Common.format_chat_colour_localized(message,color) - color = color or Colours.white - color = math.round(color.r,3)..','..math.round(color.g,3)..','..math.round(color.b,3) - return {'color-tag',color,message} -end - ---- Returns the players name in the players color --- @tparam LuaPlayer player the player to use the name and color of --- @tparam[opt=false] boolean raw_string when true a is returned rather than a localized string --- @treturn table the players name with tags for the players color -function Common.format_chat_player_name(player,raw_string) - player = Game.get_player_from_any(player) - local player_name = player and player.name or '' - local player_chat_colour = player and player.chat_color or Colours.white - if raw_string then - return Common.format_chat_colour(player_name,player_chat_colour) - else - return Common.format_chat_colour_localized(player_name,player_chat_colour) - 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/gui.lua b/expcore/gui.lua index 82257d43..70817151 100644 --- a/expcore/gui.lua +++ b/expcore/gui.lua @@ -1,284 +1 @@ ---[[-- 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 - - please read the files for more documentation that cant be shown here - - please note there is a rework planned but not started - @core Gui - @alias Gui -]] - -local Gui = require 'expcore.gui.core' --- @dep expcore.gui.core - ---[[ - Core - - 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.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.toggle_enabled(element) --- Will toggle the enabled state of an element - Gui.toggle_visible(element) --- Will toggle the visibility 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_alignment(element,flow_name) --- Allows the creation of a right align flow to place elements into - Gui.destroy_if_valid(element) --- Destroys 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_embedded_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' --- @dep expcore.gui.instances -Gui.new_instance_group = Instances.registers -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 instance group has a categorise function; must be registered - 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 - - 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' --- @dep expcore.gui.elements.buttons -Gui.new_button = Button.new_button -Gui.classes.button = Button ---[[ - Button.new_button(name) --- Creates a new button element define - - Button._prototype:on_click(player,element) --- Registers a handler for when the button is clicked - Button._prototype:on_left_click(player,element) --- Registers a handler for when the button is clicked with the left mouse button - Button._prototype:on_right_click(player,element) --- Registers a handler for when the button is clicked with the right mouse button - - Button._prototype:set_sprites(sprite,hovered_sprite,clicked_sprite) --- Adds sprites to a button making it a sprite button - Button._prototype:set_click_filter(filter,...) --- Adds a click / mouse button filter to the button - Button._prototype:set_key_filter(filter,...) --- Adds a control key filter to the button -]] - -local Checkbox = require 'expcore.gui.elements.checkbox' --- @dep expcore.gui.elements.checkbox -Gui.new_checkbox = Checkbox.new_checkbox -Gui.new_radiobutton = Checkbox.new_radiobutton -Gui.new_radiobutton_option_set = Checkbox.new_option_set -Gui.draw_option_set = Checkbox.draw_option_set -Gui.classes.checkbox = Checkbox ---[[ - Checkbox.new_checkbox(name) --- Creates a new checkbox element define - Checkbox._prototype_checkbox:on_element_update(callback) --- Registers a handler for when an element instance updates - Checkbox._prototype_checkbox:on_store_update(callback) --- Registers a handler for when the stored value updates - - Checkbox.new_radiobutton(name) --- Creates a new radiobutton element define - Checkbox._prototype_radiobutton:on_element_update(callback) --- Registers a handler for when an element instance updates - Checkbox._prototype_radiobutton:on_store_update(callback) --- Registers a handler for when the stored value updates - Checkbox._prototype_radiobutton:add_as_option(option_set,option_name) --- Adds this radiobutton to be an option in the given option set (only one can be true at a time) - - Checkbox.new_option_set(callback,categorize) --- Registers a new option set that can be linked to radiobuttons (only one can be true at a time) - Checkbox.draw_option_set(name,element) --- Draws all radiobuttons that are part of an option set at once (Gui.draw will not work) - - Checkbox.reset_radiobutton(element,exclude,recursive) --- Sets all radiobuttons in a element to false (unless excluded) and can act recursively -]] - -local Dropdown = require 'expcore.gui.elements.dropdown' --- @dep expcore.gui.elements.dropdown -Gui.new_dropdown = Dropdown.new_dropdown -Gui.new_list_box = Dropdown.new_list_box -Gui.classes.dropdown = Dropdown ---[[ - Dropdown.new_dropdown(name) --- Creates a new dropdown element define - Dropdown.new_list_box(name) --- Creates a new list box element define - - Dropdown._prototype:on_element_update(callback) --- Registers a handler for when an element instance updates - Dropdown._prototype:on_store_update(callback) --- Registers a handler for when the stored value updates - - Dropdown._prototype:new_static_options(options,...) --- Adds new static options to the dropdown which will trigger the general callback - Dropdown._prototype:new_dynamic_options(callback) --- Adds a callback which should return a table of values to be added as options for the dropdown (appended after static options) - Dropdown._prototype:add_option_callback(option,callback) --- Adds a case specific callback which will only run when that option is selected (general case still triggered) - - Dropdown.select_value(element,value) --- Selects the option from a dropdown or list box given the value rather than key - Dropdown.get_selected_value(element) --- Returns the currently selected value rather than index -]] - -local Slider = require 'expcore.gui.elements.slider' --- @dep expcore.gui.elements.slider -Gui.new_slider = Slider.new_slider -Gui.classes.slider = Slider ---[[ - Slider.new_slider(name) --- Creates a new slider element define - - 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: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.elements.text' --- @dep expcore.gui.elements.text -Gui.new_text_filed = Text.new_text_field -Gui.new_text_box = Text.new_text_box -Gui.classes.text = Text ---[[ - Text.new_text_field(name) --- Creates a new text field element define - Text._prototype_field:on_element_update(callback) --- Registers a handler for when an element instance updates - Text._prototype_field:on_store_update(callback) --- Registers a handler for when the stored value updates - - Text.new_text_box(name) --- Creates a new text box element define - Text._prototype_field:on_element_update(callback) --- Registers a handler for when an element instance updates - Text._prototype_field:on_store_update(callback) --- Registers a handler for when the stored value updates - Text._prototype_box:set_selectable(state) --- Sets the text box to be selectable - Text._prototype_box:set_word_wrap(state) --- Sets the text box to have word wrap - Text._prototype_box:set_read_only(state) --- Sets the text box to be read only -]] - -local ElemButton = require 'expcore.gui.elements.elem-button' --- @dep expcore.gui.elements.elem-button -Gui.new_elem_button = ElemButton.new_elem_button -Gui.classes.elem_button = ElemButton ---[[ - ElemButton.new_elem_button(name) --- Creates a new elem button element define - - ElemButton._prototype:on_element_update(callback) --- Registers a handler for when an element instance updates - ElemButton._prototype:on_store_update(callback) --- Registers a handler for when the stored value updates - - ElemButton._prototype:set_type(type) --- Sets the type of the elem button, the type is required so this must be called at least once - 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.elements.progress-bar' --- @dep expcore.gui.elements.progress-bar -Gui.new_progressbar = ProgressBar.new_progressbar -Gui.set_progressbar_maximum = ProgressBar.set_maximum -Gui.increment_progressbar = ProgressBar.increment -Gui.decrement_progressbar = ProgressBar.decrement -Gui.classes.progressbar = ProgressBar ---[[ - ProgressBar.set_maximum(element,amount,count_down) --- Sets the maximum value that represents the end value of the progress bar - ProgressBar.increment(element,amount) --- Increases the value of the progressbar, if a define is given all of its instances are incremented - ProgressBar.decrement(element,amount) --- Decreases the value of the progressbar, if a define is given all of its instances are decreased - - ProgressBar.new_progressbar(name) --- Creates a new progressbar element define - ProgressBar._prototype:set_maximum(amount,count_down) --- Sets the maximum value that represents the end value of the progress bar - ProgressBar._prototype:use_count_down(state) --- Will set the progress bar to start at 1 and trigger when it hits 0 - ProgressBar._prototype:increment(amount,category) --- Increases the value of the progressbar - ProgressBar._prototype:increment_filtered(amount,filter) --- Increases the value of the progressbar, if the filter condition is met, does not work with store - ProgressBar._prototype:decrement(amount,category) --- Decreases the value of the progressbar - ProgressBar._prototype:decrement_filtered(amount,filter) --- Decreases the value of the progressbar, if the filter condition is met, does not work with store - ProgressBar._prototype:add_element(element,maximum) --- Adds an element into the list of instances that will are waiting to complete, does not work with store - ProgressBar._prototype:reset_element(element) --- Resets an element, or its store, to be back at the start, either 1 or 0 - - ProgressBar._prototype:on_complete(callback) --- Triggers when a progress bar element completes (hits 0 or 1) - ProgressBar._prototype:on_complete(callback) --- Triggers when a store value completes (hits 0 or 1) - ProgressBar._prototype:event_counter(filter) --- Event handler factory that counts up by 1 every time the event triggers, can filter which elements are incremented - ProgressBar._prototype:event_countdown(filter) --- Event handler factory that counts down by 1 every time the event triggers, can filter which elements are decremented -]] - -local Toolbar = require 'expcore.gui.concepts.toolbar' --- @dep expcore.gui.concepts.toolbar -Gui.new_toolbar_button = Toolbar.new_button -Gui.add_button_to_toolbar = Toolbar.add_button -Gui.update_toolbar = Toolbar.update -Gui.classes.toolbar = Toolbar ---[[ - Toolbar.new_button(name) --- Adds a new button to the toolbar - 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 LeftFrames = require 'expcore.gui.concepts.left' --- @dep 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 -Gui.classes.left_frames = LeftFrames ---[[ - LeftFrames.get_flow(player) --- Gets the left frame flow for a player - LeftFrames.get_frame(name,player) --- Gets one frame from the left flow by its name - LeftFrames.get_open(player) --- Gets all open frames for a player, if non are open it will remove the close all button - LeftFrames.toggle_frame(name,player,state) --- Toggles the visibility of a left frame, or sets its visibility state - - LeftFrames.new_frame(permission_name) --- Creates a new left frame define - LeftFrames._prototype:set_open_by_default(state) --- Sets if the frame is visible when a player joins, can also be a function to return a boolean - LeftFrames._prototype:set_direction(direction) --- Sets the direction of the frame, either vertical or horizontal - LeftFrames._prototype:get_frame(player) --- Gets the frame for this define from the left frame flow - LeftFrames._prototype:is_open(player) --- Returns if the player currently has this define visible - LeftFrames._prototype:toggle(player) --- Toggles the visibility of the left frame - - LeftFrames._prototype:update(player) --- Updates the contents of the left frame, first tries update callback, other wise will clear and redraw - LeftFrames._prototype:update_all(update_offline) --- Updates the frame for all players, see update - LeftFrames._prototype:redraw(player) --- Redraws the frame by calling on_draw, will always clear the frame - LeftFrames._prototype:redraw_all(update_offline) --- Redraws the frame for all players, see redraw - - LeftFrames._prototype:on_draw(player,frame) --- Use to draw your elements to the new frame - LeftFrames._prototype:on_update(player,frame) --- Use to edit your frame when there is no need to redraw it - LeftFrames._prototype:on_player_toggle(player,frame) --- Triggered when the player toggle the left frame - 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.concepts.center' --- @dep 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 -Gui.redraw_center_frame = CenterFrames.redraw_frames -Gui.new_center_frame = CenterFrames.new_frame -Gui.classes.center_frames = CenterFrames ---[[ - CenterFrames.get_flow(player) --- Gets the center flow for a player - CenterFrames.clear_flow(player) --- Clears the center flow for a player - CenterFrames.draw_frame(player,name) --- Draws the center frame for a player, if already open then will do nothing - CenterFrames.redraw_frame(player,name) --- Draws the center frame for a player, if already open then will destroy it and redraw - CenterFrames.toggle_frame(player,name,state) --- Toggles if the frame is currently open or not, will open if closed and close if open - - CenterFrames.new_frame(permission_name) --- Sets the frame to be the current active gui when opened and closes all other frames - CenterFrames._prototype:on_draw(player,frame) --- Use to draw your elements onto the new frame - CenterFrames._prototype:set_auto_focus(state) --- Sets the frame to be the current active gui when opened and closes all other frames - CenterFrames._prototype:draw_frame(player) --- Draws this frame to the player, if already open does nothing (will call on_draw to draw to the frame) - CenterFrames._prototype:redraw_frame(player) --- Draws this frame to the player, if already open it will remove it and redraw it (will call on_draw to draw to the frame) - CenterFrames._prototype:toggle_frame(player) --- Toggles if the frame is open, if open it will close it and if closed it will open it - 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.concepts.popups' --- @dep expcore.gui.concepts.popups -Gui.get_popup_flow = PopupFrames.get_flow -Gui.open_popup = PopupFrames.open -Gui.new_popup = PopupFrames.new_popup -Gui.classes.popup_frames = PopupFrames ---[[ - PopupFrames.get_flow(player) --- Gets the left flow that contains the popup frames - PopupFrames.open(define_name,player,open_time,...) --- Opens a popup for the player, can give the amount of time it is open as well as params for the draw function - - PopupFrames.close_progress --- Progress bar which when depleted will close the popup frame - PopupFrames.close_button --- A button which can be used to close the gui before the timer runs out - - PopupFrames.new_popup(name) --- Creates a new popup frame define - PopupFrames._prototype:set_default_open_time(amount) --- Sets the default open time for the popup, will be used if non is provided with open - 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 -]] - -return Gui \ No newline at end of file +return require 'expcore.gui._require' \ No newline at end of file diff --git a/expcore/gui/_require.lua b/expcore/gui/_require.lua new file mode 100644 index 00000000..306c354d --- /dev/null +++ b/expcore/gui/_require.lua @@ -0,0 +1,131 @@ +--[[-- Core Module - Gui +- Used to simplify gui creation using factory functions called element defines +@core Gui +@alias Gui + +@usage-- To draw your element you only need to call the factory function +-- You are able to pass any other arguments that are used in your custom functions but the first is always the parent element +local example_button_element = example_button(parent_element) + +@usage-- Making a factory function for a button with the caption "Example Button" +-- This method has all the same features as LuaGuiElement.add +local example_button = +Gui.element{ + type = 'button', + caption = 'Example Button' +} + +@usage-- Making a factory function for a button which is contained within a flow +-- This method is for when you still want to register event handlers but cant use the table method +local example_flow_with_button = +Gui.element(function(event_trigger,parent,...) + -- ... shows that all other arguments from the factory call are passed to this function + -- Here we are adding a flow which we will then later add a button to + local flow = + parent.add{ -- paraent is the element which is passed to the factory function + name = 'example_flow', + type = 'flow' + } + + -- Now we add the button to the flow that we created earlier + local element = + flow.add{ + name = event_trigger, -- event_trigger should be the name of any elements you want to trigger your event handlers + type = 'button', + caption = 'Example Button' + } + + -- You must return a new element, this is so styles can be applied and returned to the caller + -- You may return any of your elements that you added, consider the context in which it will be used for which should be returned + return element +end) + +@usage-- Styles can be added to any element define, simplest way mimics LuaGuiElement.style[key] = value +local example_button = +Gui.element{ + type = 'button', + caption = 'Example Button', + style = 'forward_button' -- factorio styles can be applied here +} +:style{ + height = 25, -- same as element.style.height = 25 + width = 100 -- same as element.style.width = 25 +} + +@usage-- Styles can also have a custom function when the style is dynamic and depends on other factors +-- Use this method if your style is dynamic and depends on other factors +local example_button = +Gui.element{ + type = 'button', + caption = 'Example Button', + style = 'forward_button' -- factorio styles can be applied here +} +:style(function(style,element,...) + -- style is the current style object for the elemenent + -- element is the element that is being changed + -- ... shows that all other arguments from the factory call are passed to this function + local player = game.players[element.player_index] + style.height = 25 + style.width = 100 + style.font_color = player.color +end) + +@usage-- You are able to register event handlers to your elements, these can be factorio events or custom ones +-- All events are checked to be valid before raising any handlers, this means element.valid = true and player.valid = true +Gui.element{ + type = 'button', + caption = 'Example Button' +} +:on_click(function(player,element,event) + -- player is the player who interacted with the element to cause the event + -- element is a refrence to the element which caused the event + -- event is a raw refrence to the event data if player and element are not enough + player.print('Clicked: '..element.name) +end) + +@usage-- Example from core_defines, Gui.core_defines.hide_left_flow, called like: hide_left_flow(parent_element) +--- Button which hides the elements in the left flow, shows inside the left flow when frames are visible +-- @element hide_left_flow +local hide_left_flow = +Gui.element{ + type = 'sprite-button', + sprite = 'utility/close_black', + style = 'tool_button', + tooltip = {'expcore-gui.left-button-tooltip'} +} +:style{ + padding = -3, + width = 18, + height = 20 +} +:on_click(function(player,_,_) + Gui.hide_left_flow(player) +end) + +@usage-- Eample from defines, Gui.alignment, called like: Gui.alignment(parent, name, horizontal_align, vertical_align) +-- Notice how _ are used to blank arguments that are not needed in that context and how they line up with above +Gui.alignment = +Gui.element(function(_,parent,name,_,_) + return parent.add{ + name = name or 'alignment', + type = 'flow', + } +end) +:style(function(style,_,_,horizontal_align,vertical_align) + style.padding = {1,2} + style.vertical_align = vertical_align or 'center' + style.horizontal_align = horizontal_align or 'right' + style.vertically_stretchable = style.vertical_align ~= 'center' + style.horizontally_stretchable = style.horizontal_align ~= 'center' +end) + +]] + +local Gui = require 'expcore.gui.prototype' +require 'expcore.gui.core_defines' +require 'expcore.gui.top_flow' +require 'expcore.gui.left_flow' +require 'expcore.gui.helper_functions' +require 'expcore.gui.defines' + +return Gui \ No newline at end of file diff --git a/expcore/gui/concepts/center.lua b/expcore/gui/concepts/center.lua deleted file mode 100644 index ffbc3f9f..00000000 --- a/expcore/gui/concepts/center.lua +++ /dev/null @@ -1,198 +0,0 @@ ---[[-- Core Module - Gui - @module Gui - @alias Prototype -]] - ---- Center Guis. --- Gui structure define for center gui frames --- @section center - ---[[ ->>>> Functions - CenterFrames.get_flow(player) --- Gets the center flow for a player - CenterFrames.clear_flow(player) --- Clears the center flow for a player - CenterFrames.draw_frame(player,name) --- Draws the center frame for a player, if already open then will do nothing - CenterFrames.redraw_frame(player,name) --- Draws the center frame for a player, if already open then will destroy it and redraw - CenterFrames.toggle_frame(player,name,state) --- Toggles if the frame is currently open or not, will open if closed and close if open - - CenterFrames.new_frame(permission_name) --- Sets the frame to be the current active gui when opened and closes all other frames - CenterFrames._prototype:on_draw(player,frame) --- Use to draw your elements onto the new frame - CenterFrames._prototype:set_auto_focus(state) --- Sets the frame to be the current active gui when opened and closes all other frames - CenterFrames._prototype:draw_frame(player) --- Draws this frame to the player, if already open does nothing (will call on_draw to draw to the frame) - CenterFrames._prototype:redraw_frame(player) --- Draws this frame to the player, if already open it will remove it and redraw it (will call on_draw to draw to the frame) - CenterFrames._prototype:toggle_frame(player) --- Toggles if the frame is open, if open it will close it and if closed it will open it - 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' --- @dep expcore.gui.core -local Prototype = require 'expcore.gui.prototype' --- @dep expcore.gui.prototype -local Toolbar = require 'expcore.gui.concepts.toolbar' --- @dep expcore.gui.concepts.toolbar -local Game = require 'utils.game' --- @dep utils.game - -local CenterFrames = { - _prototype = Prototype.extend{ - on_creation = Prototype.event - } -} - ---- Gets the center flow for a player --- @tparam LuaPlayer player the player to get the flow for --- @treturn LuaGuiElement the center flow -function CenterFrames.get_flow(player) - player = Game.get_player_from_any(player) - return player.gui.center -end - ---- Clears the center flow for a player --- @tparam LuaPlayer player the player to clear the flow for -function CenterFrames.clear_flow(player) - local flow = CenterFrames.get_flow(player) - flow.clear() -end - ---- Draws the center frame for a player, if already open then will do nothing --- @tparam LuaPlayer player the player that will have the frame drawn --- @tparam string name the name of the hui that will drawn --- @treturn LuaGuiElement the new frame that was made -function CenterFrames.draw_frame(player,name) - local define = Gui.get_define(name,true) - if define then - return define:draw_frame(player) - end -end - ---- Draws the center frame for a player, if already open then will destroy it and redraw --- @tparam LuaPlayer player the player that will have the frame drawn --- @tparam string name the name of the hui that will drawn --- @treturn LuaGuiElement the new frame that was made -function CenterFrames.redraw_frame(player,name) - local define = Gui.get_define(name,true) - if define then - return define:draw_frame(player) - end -end - ---- Toggles if the frame is currently open or not, will open if closed and close if open --- @tparam LuaPlayer player the player that will have the frame toggled --- @tparam string name the name of the hui that will be toggled --- @tparam[opt] boolean state when set will force a state for the frame --- @treturn boolean if the frame if no open or closed -function CenterFrames.toggle_frame(player,name,state) - local define = Gui.get_define(name,true) - if define then - if state == true then - define:draw_frame(player) - return true - elseif state == false then - local flow = CenterFrames.get_flow(player) - if flow[define.name..'-frame'] then - flow[define.name..'-frame'].destroy() - end - return false - else - return define:toggle_frame(player) - end - end -end - ---- Creates a new center frame define --- @tparam string permission_name the name that can be used with the permission system --- @treturn table the new center frame define -function CenterFrames.new_frame(permission_name) - local self = Toolbar.new_button(permission_name) - - self:on_click(function(player,element) - self:toggle_frame(player) - end) - - local mt = getmetatable(self) - mt.__index = CenterFrames._prototype - mt.__call = self.event_handler - - Gui.on_custom_close(self.name..'-frame',function(event) - local element = event.element - if element and element.valid then element.destroy() end - end) - - return self -end - ---- Sets the frame to be the current active gui when opened and closes all other frames --- @tparam[opt=true] boolean state when true will auto close other frames and set this frame as player.opened -function CenterFrames._prototype:set_auto_focus(state) - if state == false then - self.auto_focus = false - else - self.auto_focus = true - end -end - ---- Draws this frame to the player, if already open does nothing (will call on_draw to draw to the frame) --- @tparam LuaPlayer player the player to draw the frame for --- @treturn LuaGuiElement the new frame that was drawn -function CenterFrames._prototype:draw_frame(player) - player = Game.get_player_from_any(player) - local flow = CenterFrames.get_flow(player) - - if flow[self.name..'-frame'] then - return flow[self.name..'-frame'] - end - - if self.auto_focus then - flow.clear() - end - - local frame = flow.add{ - type='frame', - name=self.name..'-frame' - } - - if self.auto_focus then - player.opened = frame - end - - self:raise_event('on_creation',player,frame) - - return frame -end - ---- Draws this frame to the player, if already open it will remove it and redraw it (will call on_draw to draw to the frame) --- @tparam LuaPlayer player the player to draw the frame for --- @treturn LuaGuiElement the new frame that was drawn -function CenterFrames._prototype:redraw_frame(player) - player = Game.get_player_from_any(player) - local flow = CenterFrames.get_flow(player) - - if flow[self.name..'-frame'] then - flow[self.name..'-frame'].destroy() - end - - return self:draw_frame(player) -end - ---- Toggles if the frame is open, if open it will close it and if closed it will open it --- @tparam LuaPlayer player the player to draw the frame for --- @treturn boolean with the gui frame is now open -function CenterFrames._prototype:toggle_frame(player) - player = Game.get_player_from_any(player) - local flow = CenterFrames.get_flow(player) - - if flow[self.name..'-frame'] then - flow[self.name..'-frame'].destroy() - return false - else - self:draw_frame(player) - return true - end -end - ---- Creates an event handler that will trigger one of its functions, use with Event.add --- @tparam[opt=update] string action the action to take on this event -function CenterFrames._prototype:event_handler(action) - action = action or 'update' - return function(event) - local player = Game.get_player_by_index(event.player_index) - self[action](self,player) - end -end - -return CenterFrames \ No newline at end of file diff --git a/expcore/gui/concepts/left.lua b/expcore/gui/concepts/left.lua deleted file mode 100644 index e827f36a..00000000 --- a/expcore/gui/concepts/left.lua +++ /dev/null @@ -1,322 +0,0 @@ ---[[-- Core Module - Gui - @module Gui - @alias Prototype -]] - ---- Left Guis. --- Gui structure define for left frames --- @section left - ---[[ ->>>> Example formating - - -- first we add config that relates to the button on the toolbar, all normal button functions are present - local left_frame = - Gui.new_left_frame('test-left-frame') - :set_caption('Test Left Gui') - :set_post_authenticator(function(player,button_name) - return global.show_test_gui - end) - - -- then we add the config for the left frame, on_draw should draw the gui from an empty frame, on_update should take a frame from on_draw on edit it - :set_open_by_default() - :on_draw(function(_player,frame) - for _,player in pairs(game.connected_players) do - frame.add{ - type='label', - caption=player.name - } - end - end) - - -- now we can use the action factory to call events on the gui, actions are: 'update', 'update_all', 'redraw', 'redraw_all' - Event.add(defines.events.on_player_joined_game,left_frame 'update_all') - Event.add(defines.events.on_player_left_game,left_frame 'update_all') - ->>>> Functions - LeftFrames.get_flow(player) --- Gets the left frame flow for a player - LeftFrames.get_frame(name,player) --- Gets one frame from the left flow by its name - LeftFrames.get_open(player) --- Gets all open frames for a player, if non are open it will remove the close all button - LeftFrames.toggle_frame(name,player,state) --- Toggles the visibility of a left frame, or sets its visibility state - - LeftFrames.new_frame(permission_name) --- Creates a new left frame define - LeftFrames._prototype:set_open_by_default(state) --- Sets if the frame is visible when a player joins, can also be a function to return a boolean - LeftFrames._prototype:set_direction(direction) --- Sets the direction of the frame, either vertical or horizontal - LeftFrames._prototype:get_frame(player) --- Gets the frame for this define from the left frame flow - LeftFrames._prototype:is_open(player) --- Returns if the player currently has this define visible - LeftFrames._prototype:toggle(player) --- Toggles the visibility of the left frame - - LeftFrames._prototype:update(player) --- Updates the contents of the left frame, first tries update callback, other wise will clear and redraw - LeftFrames._prototype:update_all(update_offline) --- Updates the frame for all players, see update - LeftFrames._prototype:redraw(player) --- Redraws the frame by calling on_draw, will always clear the frame - LeftFrames._prototype:redraw_all(update_offline) --- Redraws the frame for all players, see redraw - - LeftFrames._prototype:on_draw(player,frame) --- Use to draw your elements to the new frame - LeftFrames._prototype:on_update(player,frame) --- Use to edit your frame when there is no need to redraw it - LeftFrames._prototype:on_player_toggle(player,frame) --- Is triggered when the player presses the toggle button - 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' --- @dep expcore.gui.core -local Prototype = require 'expcore.gui.prototype' --- @dep expcore.gui.prototype -local Toolbar = require 'expcore.gui.concepts.toolbar' --- @dep expcore.gui.concepts.toolbar -local Buttons = require 'expcore.gui.elements.buttons' --- @dep expcore.gui.elements.buttons -local mod_gui = require 'mod-gui' --- @dep mod-gui -local Game = require 'utils.game' --- @dep utils.game -local Event = require 'utils.event' --- @dep utils.event - -local LeftFrames = { - frames={}, - _prototype=Prototype.extend{ - on_creation = Prototype.event, - on_update = Prototype.event, - on_player_toggle = Prototype.event - } -} -setmetatable(LeftFrames._prototype, { - __index = Buttons._prototype -}) - ---- Gets the left frame flow for a player --- @tparam LuaPlayer player the player to get the flow of --- @treturn LuaGuiElement the left frame flow for the player -function LeftFrames.get_flow(player) - player = Game.get_player_from_any(player) - return mod_gui.get_frame_flow(player) -end - ---- Gets one frame from the left flow by its name --- @tparam string name the name of the gui frame to get --- @tparam LuaPlayer player the player to get the frame of --- @treturn LuaGuiElement the frame in the left frame flow with that name -function LeftFrames.get_frame(name,player) - local define = LeftFrames.frames[name] - if not define then - return error('Left Frame '..name..' is not defined.',2) - end - return define:get_frame(player) -end - ---- Gets all open frames for a player, if non are open it will remove the close all button --- @tparam LuaPlayer player the player to get the flow of --- @treturn table contains all the open (and registered) frames for the player -function LeftFrames.get_open(player) - local open = {} - local flow = LeftFrames.get_flow(player) - - for _,define in pairs(LeftFrames.frames) do - if define:is_open(player) then - table.insert(open,define) - end - end - - flow[LeftFrames.toggle_button.name].visible = #open ~= 0 - - return open -end - ---- Toggles the visibility of a left frame, or sets its visibility state --- @tparam string name the name of the gui frame to toggle --- @tparam LuaPlayer player the player to get the frame of --- @tparam[opt] boolean state when given will be the state that the visibility is set to --- @treturn boolean the new state of the visibility -function LeftFrames.toggle_frame(name,player,state) - local define = LeftFrames.frames[name] - if not define then - return error('Left Frame '..name..' is not defined.',2) - end - - local frame = LeftFrames.get_frame(name,player) - if state ~= nil then - frame.visible = state - else - Gui.toggle_visible(frame) - end - - LeftFrames.get_open(player) - - return frame.visible -end - ---- Creates a new left frame define --- @tparam string permission_name the name that can be used with the permission system --- @treturn table the new left frame define -function LeftFrames.new_frame(permission_name) - local self = Toolbar.new_button(permission_name) - - local mt = getmetatable(self) - mt.__index = LeftFrames._prototype - mt.__call = self.event_handler - - self:on_click(function(player,_element) - local visible = self:toggle(player) - local frame = self:get_frame(player) - self:raise_event('on_player_toggle',player,frame,visible) - end) - - LeftFrames.frames[self.name] = self - - return self -end - ---- Sets if the frame is visible when a player joins, can also be a function to return a boolean --- @tparam[opt=true] ?boolean|function state the default state of the visibility, can be a function --- state param - player LuaPlayer - the player that has joined the game --- state param - define_name string - the define name for the frame --- state return - boolean - false will hide the frame -function LeftFrames._prototype:set_open_by_default(state) - if state == false then - self.open_by_default = false - elseif state == nil then - self.open_by_default = true - else - self.open_by_default = state - end - return self -end - ---- Sets the direction of the frame, either vertical or horizontal --- @tparam string direction the direction to have the elements be added to the frame -function LeftFrames._prototype:set_direction(direction) - self.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 -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 - ---- Returns if the player currently has this define visible --- @tparam LuaPlayer player the player to get the frame of --- @treturn boolean true if it is open/visible -function LeftFrames._prototype:is_open(player) - local frame = self:get_frame(player) - return frame and frame.visible or false -end - ---- Toggles the visibility of the left frame --- @tparam LuaPlayer player the player to toggle the frame of --- @treturn boolean the new state of the visibility -function LeftFrames._prototype:toggle(player) - local frame = self:get_frame(player) - Gui.toggle_visible(frame) - LeftFrames.get_open(player) - return frame.visible -end - ---- Updates the contents of the left frame, first tries update callback, other wise will clear and redraw --- @tparam LuaPlayer player the player to update the frame of -function LeftFrames._prototype:update(player) - local frame = self:get_frame(player) - if self:raise_event('on_update',player,frame) == 0 then - frame.clear() - self:raise_event('on_creation',player,frame) - end -end - ---- Updates the frame for all players, see update --- @tparam[opt=false] boolean update_offline when true will update the frame for offline players -function LeftFrames._prototype:update_all(update_offline) - local players = update_offline == true and game.players or game.connected_players - for _,player in pairs(players) do - self:update(player) - end -end - ---- Redraws the frame by calling on_draw, will always clear the frame --- @tparam LuaPlayer player the player to update the frame of -function LeftFrames._prototype:redraw(player) - local frame = self:get_frame(player) - frame.clear() - self:raise_event('on_creation',player,frame) -end - ---- Redraws the frame for all players, see redraw --- @tparam[opt=false] boolean update_offline when true will update the frame for offline players -function LeftFrames._prototype:redraw_all(update_offline) - local players = update_offline == true and game.players or game.connected_players - for _,player in pairs(players) do - self:redraw(player) - end -end - ---- Creates an event handler that will trigger one of its functions, use with Event.add --- @tparam[opt=update] string action the action to take on this event -function LeftFrames._prototype:event_handler(action) - action = action or 'update' - return function(event) - local player - if event and event.player_index then - player = Game.get_player_by_index(event.player_index) - end - self[action](self,player) - end -end - -LeftFrames.toggle_button = -Buttons.new_button() -:set_tooltip{'expcore-gui.left-button-tooltip'} -:set_caption('<') -:on_click(function(player,element) - for _,define in pairs(LeftFrames.frames) do - local frame = LeftFrames.get_frame(define.name,player) - frame.visible = false - define:raise_event('on_player_toggle',player,frame,false) - end - element.visible = false -end) - -Event.add(defines.events.on_player_created,function(event) - local player = Game.get_player_by_index(event.player_index) - local flow = LeftFrames.get_flow(player) - - local close_button = LeftFrames.toggle_button(flow) - Gui.set_padding(close_button) - local style = close_button.style - style.width = 18 - style.height = 36 - style.font = 'default-small-bold' - - for _,define in pairs(LeftFrames.frames) do - define:_internal_draw(player) - end - - LeftFrames.get_open(player) -end) - -return LeftFrames \ No newline at end of file diff --git a/expcore/gui/concepts/popups.lua b/expcore/gui/concepts/popups.lua deleted file mode 100644 index bda932b3..00000000 --- a/expcore/gui/concepts/popups.lua +++ /dev/null @@ -1,230 +0,0 @@ ---[[-- Core Module - Gui - @module Gui - @alias Prototype -]] - ---- Popups. --- Gui structure define for popup gui --- @section popups - ---[[ ->>>> Functions - PopupFrames.get_flow(player) --- Gets the left flow that contains the popup frames - PopupFrames.open(define_name,player,open_time,...) --- Opens a popup for the player, can give the amount of time it is open as well as params for the draw function - - PopupFrames.close_progress --- Progress bar which when depleted will close the popup frame - PopupFrames.close_button --- A button which can be used to close the gui before the timer runs out - - PopupFrames.new_popup(name) --- Creates a new popup frame define - PopupFrames._prototype:set_default_open_time(amount) --- Sets the default open time for the popup, will be used if non is provided with open - 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' --- @dep expcore.gui.core -local Prototype = require 'expcore.gui.prototype' --- @dep expcore.gui.prototype -local Game = require 'utils.game' --- @dep utils.game -local Event = require 'utils.event' --- @dep utils.event -local ProgressBar = require 'expcore.gui.elements.progress-bar' --- @dep expcore.gui.elements.progress-bar -local Button = require 'expcore.gui.elements.buttons' --- @dep expcore.gui.elements.buttons -local mod_gui = require 'mod-gui' --- @dep mod-gui -local Color = require 'resources.color_presets' --- @dep resources.color_presets -local Global = require 'utils.global' --- @dep utils.global - -local PopupFrames = { - paused_popups={}, - popup_flow_name = Gui.uid_name(), - main_frame_name = Gui.uid_name(), - close_frame_name = Gui.uid_name(), - _prototype = Prototype.extend{ - on_creation = Prototype.event - } -} -Global.register(PopupFrames.paused_popups,function(tbl) - PopupFrames.paused_popups = tbl -end) - ---- Sets the state of the element in the paused list, nil or true --- @tparam LuaGuiElement element the element to set the state of --- @tparam[opt] boolean state the state to set it to, true will pause the the progress bar -local function set_paused_state(element,state) - local name = element.player_index..':'..element.index - PopupFrames.paused_popups[name] = state -end - ---- Gets the state of the element in the paused list, nil or true --- @tparam LuaGuiElement element the element to get the state of -local function get_paused_state(element) - local name = element.player_index..':'..element.index - return PopupFrames.paused_popups[name] -end - ---- Gets the left flow that contains the popup frames --- @tparam LuaPlayer player the player to get the flow for --- @treturn LuaGuiElement the left flow that contains the popup frames -function PopupFrames.get_flow(player) - player = Game.get_player_from_any(player) - local flow = mod_gui.get_frame_flow(player) - return flow[PopupFrames.popup_flow_name] -end - ---- Opens a popup for the player, can give the amount of time it is open as well as params for the draw function --- @tparam string define_name the name of the define that you want to open for the player --- @tparam LuaPlayer player the player to open the popup for --- @tparam[opt] number open_time the minimum number of ticks you want the popup open for, 0 means no limit, nil will take default --- @tparam any ... the other params that you want to pass to your on_draw event --- @treturn LuaGuiElement the frame that was drawn, the inner gui flow which contains the content -function PopupFrames.open(define_name,player,open_time,...) - local define = Gui.get_define(define_name,true) - player = Game.get_player_from_any(player) - return define:open(player,open_time,...) -end - ---- Closes the popup, is called by progress bar and close button --- @tparam LuaGuiElement element either the progress bar or the close button -local function close_popup(element) - local frame = element.parent.parent.parent - if not frame or not frame.valid then return end - set_paused_state(element.parent[PopupFrames.close_progress:uid()]) - frame.destroy() -end - ---- Progress bar which when depleted will close the popup frame -PopupFrames.close_progress = -ProgressBar.new_progressbar() -:use_count_down() -:set_tooltip('Pause/Resume Auto-close') -:on_complete(function(player,element) - close_popup(element) -end) - ---- A button which can be used to close the gui before the timer runs out -PopupFrames.close_button = -Button.new_button() -:set_sprites('utility/close_white') -:set_tooltip('Close Popup') -:on_click(function(player,element) - close_popup(element) -end) - ---- When the progress bar is clicked it will pause its progress, or resume if previously paused -Gui.on_click(PopupFrames.close_progress:uid(),function(event) - local element = event.element - if get_paused_state(element) then - set_paused_state(element) - else - set_paused_state(element,true) - end -end) - ---- When the parent flow of the progress bar is clicked it will pause its progress, or resume if previously paused -Gui.on_click(PopupFrames.close_frame_name,function(event) - local element = event.element[PopupFrames.close_progress:uid()] - if get_paused_state(element) then - set_paused_state(element) - else - set_paused_state(element,true) - end -end) - ---- Creates a new popup frame define --- @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.new_define(PopupFrames._prototype,name) - self.draw_data.type = 'flow' - self.draw_data.direction = 'vertical' - - local mt = getmetatable(self) - mt.__call = function(tbl,player,open_time,...) - return tbl:open(player,open_time,...) - end - - self:on_draw(function(player,element,maximum,...) - -- main content frame - local frame = element.add{ - type='flow', - name=PopupFrames.main_frame_name - } - frame.style.horizontally_stretchable = true - - -- flow for progress bar and close button - local close_flow = element.add{ - type='flow', - name=PopupFrames.close_frame_name - } - close_flow.style.horizontally_stretchable = true - - -- progress bar, when 0 then a static full one is drawn - local progress_style - if maximum == 0 then - progress_style = close_flow.add{ - type='progressbar', - tooltip='No Auto-close', - value=1 - }.style - else - progress_style = PopupFrames.close_progress(close_flow,maximum).style - end - progress_style.top_padding = 6 - progress_style.bottom_padding = 3 - progress_style.height = 11 - progress_style.color = Color.grey - - -- close button, will close the popup when clicked - local close_button = PopupFrames.close_button(close_flow) - Gui.set_padding(close_button) - local close_button_style = close_button.style - close_button_style.width = 20 - close_button_style.height = 20 - - -- event trigger to draw the gui content - self:raise_event('on_creation',player,frame,...) - end) - - return self -end - ---- Sets the default open time for the popup, will be used if non is provided with open --- @tparam number amount the number of ticks, by default, the popup will be open for --- @treturn table the define to allow for chaining -function PopupFrames._prototype:set_default_open_time(amount) - self.default_open_time = amount - return self -end - ---- Opens this define for a player, can be given open time and any other params for the draw function --- @tparam LuaPlayer player the player to open the popup for --- @tparam[opt] number open_time the minimum number of ticks you want the popup open for, 0 means no limit, nil will take default --- @tparam any ... the other params that you want to pass to your on_draw event --- @treturn LuaGuiElement the frame that was drawn, the inner gui flow which contains the content -function PopupFrames._prototype:open(player,open_time,...) - open_time = open_time or self.default_open_time or 0 - player = Game.get_player_from_any(player) - - local flow = PopupFrames.get_flow(player) - local frame = flow.add{ - type='frame', - style='blurry_frame' - } - - Gui.set_padding(frame,3,3,4,4) - return self:draw_to(frame,open_time,...)[PopupFrames.main_frame_name] -end - ---- When player is first created the popup flow is added to they left flow -Event.add(defines.events.on_player_created,function(event) - local player = Game.get_player_by_index(event.player_index) - local flow = mod_gui.get_frame_flow(player) - - flow.add{ - type='flow', - direction='vertical', - name=PopupFrames.popup_flow_name - } -end) - ---- Every tick any, not paused, progress bars will go down by one tick -Event.add(defines.events.on_tick,PopupFrames.close_progress:event_countdown(function(element) - return not get_paused_state(element) -end)) - -return PopupFrames \ No newline at end of file diff --git a/expcore/gui/concepts/toolbar.lua b/expcore/gui/concepts/toolbar.lua deleted file mode 100644 index 10a8d971..00000000 --- a/expcore/gui/concepts/toolbar.lua +++ /dev/null @@ -1,114 +0,0 @@ ---[[-- Core Module - Gui - @module Gui - @alias Prototype -]] - ---- Toolbar. --- Gui structure for the toolbar (top left) --- @section toolbar - ---[[ ->>>> Example format - -- this is the same as any other button define, this just automatically draws it - -- you can use add_button if you already defined the button - local toolbar_button = - Toolbar.new_button('print-click') - :on_click(function(player,_element) - player.print('You clicked a button!') - end) - ->>>> Functions - Toolbar.new_button(name) --- Adds a new button to the toolbar - 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 Gui = require 'expcore.gui.core' --- @dep expcore.gui.core -local Buttons = require 'expcore.gui.elements.buttons' --- @dep expcore.gui.elements.buttons -local Roles = require 'expcore.roles' --- @dep expcore.roles -local Event = require 'utils.event' --- @dep utils.event -local Game = require 'utils.game' --- @dep utils.game -local mod_gui = require 'mod-gui' --- @dep mod-gui - -local Toolbar = { - permission_names = {}, - buttons = {} -} - -function Toolbar.allowed(player,define_name) - local permission_name = Toolbar.permission_names[define_name] or define_name - return Roles.player_allowed(player,permission_name) -end - -function Toolbar.permission_alias(define_name,permission_name) - Toolbar.permission_names[define_name] = permission_name -end - ---- Adds a new button to the toolbar --- @tparam[opt] string name when given allows an alias to the button for the permission system --- @treturn table the button define -function Toolbar.new_button(name) - local button = - Buttons.new_button() - :set_post_authenticator(Toolbar.allowed) - :set_style(mod_gui.button_style,function(style) - Gui.set_padding_style(style,-2,-2,-2,-2) - end) - Toolbar.add_button(button) - Toolbar.permission_alias(button.name,name) - return button -end - ---- Adds an existing buttton to the toolbar --- @tparam table button the button define for the button to be added -function Toolbar.add_button(button) - table.insert(Toolbar.buttons,button) - Gui.allow_player_to_toggle_top_element_visibility(button.name) - Gui.on_player_show_top(button.name,function(event) - if not button.post_authenticator(event.player,button.name) then - event.element.visible = false - end - end) - if not button.post_authenticator then - button:set_post_authenticator(function() return true end) - end -end - ---- Updates the player's toolbar with an new buttons or expected change in auth return --- @tparam LuaPlayer player the player to update the toolbar for -function Toolbar.update(player) - local top = Gui.get_top_element_flow(player) - if not top then return end - local visible = top[Gui.top_toggle_button_name].caption == '<' - for _,button in pairs(Toolbar.buttons) do - local element - if top[button.name] then element = top[button.name] - else element = button:draw_to(top) end - if button.post_authenticator(player,button.name) then - element.visible = visible - element.enabled = true - else - element.visible = false - element.enabled = false - end - end -end - ---- When there is a new player they will have the toolbar update -Event.add(defines.events.on_player_created,function(event) - local player = Game.get_player_by_index(event.player_index) - Toolbar.update(player) -end) - ---- When a player gets a new role they will have the toolbar updated -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.events.on_role_unassigned,function(event) - local player = Game.get_player_by_index(event.player_index) - Toolbar.update(player) -end) - -return Toolbar \ No newline at end of file diff --git a/expcore/gui/core.lua b/expcore/gui/core.lua deleted file mode 100644 index 1fd93480..00000000 --- a/expcore/gui/core.lua +++ /dev/null @@ -1,368 +0,0 @@ ---[[-- Core Module - Gui - @module Gui - @alias Prototype -]] - ---- Core. --- Core gui file for making element defines and element classes (use require 'expcore.gui') --- see utils.gui for event handlering --- see expcore.gui.test for examples for element defines --- @section core - ---[[ ->>>> Basic useage with no defines - This module can be igroned if you are only wanting only event handlers as utils.gui adds the following: - - Gui.uid_name() --- Generates a unqiue name to register events to - Gui.on_checked_state_changed(callback) --- Register a handler for the on_gui_checked_state_changed event - Gui.on_click(callback) --- Register a handler for the on_gui_click event - Gui.on_elem_changed(callback) --- Register a handler for the on_gui_elem_changed - Gui.on_selection_state_changed(callback) --- Register a handler for the on_gui_selection_state_changed event - Gui.on_text_changed(callback) --- Register a handler for the on_gui_text_changed event - Gui.on_value_changed(callback) --- Register a handler for the on_gui_value_changed event - - 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. - ->>>> 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() - - Although all class definations are stored in Gui.classes the main function used to make new element defination are - made aviable in the top level gui module. All functions which return a new element defination will accept a name argument - which is a name which is used while debuging and is not required to be used (has not been used in examples) - - Every element define will accept a caption and tooltip (although some may not show) and to do this you would use the two - set function provided for the element defines: - - checkbox_example:set_caption('Example Checkbox') - checkbox_example:set_tooltip('Example checkbox') - - Each element define can have event handlers set, for our example checkbox we only have access to on_change which will trigger - when the state of the checkbox changes; if we want to assign handlers using the utils.gui methods then we can get the uid by calling - the uid function on the element define; however, each element can only have one handler (of each event) so it is not possible to use - Gui.on_checked_state_changed and on_change at the same time in our example. - - checkbox_example:on_change(function(player,element,value) - player.print('Example checkbox is now: '..tostring(value)) - end) - - local checkbox_example_uid = checkbox_example:uid() - Gui.on_click(checkbox_example_uid,function(event) - event.player.print('You clicked the example checkbox!') - end) - - Finally you will want to draw your element defines for which you can call deirectly on the deinfe or use Gui.draw to do; when Gui.draw is - used it can be given either the element define, the define's uid or the debug name of the define (if set): - - checkbox_example:draw_to(parent_element) - Gui.draw(checkbox_example_uid,parent_element) - ->>>> Using authenticators with draw - When an element is drawn to its parent it can always be used but if you want to limit who can use it then you can use an authenticator. There - are two types which can be used: post and pre; using a pre authenticator will mean that the draw function is stoped before the element is added - to the parent element while using a post authenticator will draw the element to the parent but will disable the element from interaction. Both may - be used if you have use for such. - - -- unless global.checkbox_example_allow_pre_auth is true then the checkbox will not be drawn - checkbox_example:set_pre_authenticator(function(player,define_name) - player.print('Example checkbox pre auth callback ran') - return global.checkbox_example_allow_pre_auth - end) - - -- unless global.checkbox_example_allow_post_auth is true then the checkbox will be drawn but deactiveated (provided pre auth returns true) - checkbox_example:set_post_authenticator(function(player,define_name) - player.print('Example checkbox pre auth callback ran') - return global.checkbox_example_allow_post_auth - end) - ->>>> 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.categorize_by_player) - checkbox_example:add_store(function(element) - local player = Game.get_player_by_index(element.player_index) - return player.force.name - end) - - 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.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') - Gui.get_store(name,'Cooldude2606') - - checkbox_example:set_store('Cooldude2606',true) - Gui.set_store(name,'Cooldude2606',true) - - These methods use the Store module which means that if you have the need to access these sotre location (for example if you want to add a watch function) then - you can get the store location of any define using checkbox_example.store - - Important note about event handlers: when the store is updated it will also trigger the event handlers (such as on_element_update) for that define but only - for the valid instances of the define which means if a player does not have the element drawn on a gui then it will not trigger the events; if you want a - trigger for all updates then you can use on_store_update however you will be required to parse the category which may or may not be a - player name (depends what store categorize function you use) - ->>>> Example formating - - local checkbox_example = - Gui.new_checkbox() - :set_caption('Example Checkbox') - :set_tooltip('Example checkbox') - :add_store(Gui.categorize_by_player) - :on_element_update(function(player,element,value) - player.print('Example checkbox is now: '..tostring(value)) - end) - ->>>> Functions - 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.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.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_alignment(element,flow_name) --- Allows the creation of a right align flow to place elements into - Gui.destroy_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' --- @dep utils.gui -local Game = require 'utils.game' --- @dep utils.game - -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 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 --- @tparam[opt] string debug_name the name that you want to see while debuging --- @treturn table the new element define with all functions accessed via __index metamethod -function Gui.new_define(prototype,debug_name) - local name = Gui.uid_name() - local define = setmetatable({ - debug_name = debug_name, - name = name, - events = {}, - draw_data = { - name = name - } - },{ - __index = prototype, - __call = function(self,...) - return self:draw_to(...) - end - }) - Gui.defines[define.name] = define - return define -end - ---- Gets an element define give the uid, debug name or a copy of the element define --- @tparam ?string|table name 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) --- @treturn table the element define that was found or an error -function Gui.get_define(name,internal) - if type(name) == 'table' then - if name.name and Gui.defines[name.name] then - return Gui.defines[name.name] - end - end - - local define = Gui.defines[name] - - if not define and Gui.names[name] then - return Gui.defines[Gui.names[name]] - - elseif not define then - return error('Invalid name for element define, name not found.',internal and 3 or 2) or nil - - end - - return define -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.categorize_by_player(element) - local player = Game.get_player_by_index(element.player_index) - return player.name -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.categorize_by_force(element) - local player = Game.get_player_by_index(element.player_index) - return player.force.name -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.categorize_by_surface(element) - local player = Game.get_player_by_index(element.player_index) - return player.surface.name -end - ---- Draws a copy of the element define to the parent element, see draw_to --- @tparam ?string|table name the uid, debug name or define for the element define to draw --- @tparam LuaGuiEelement element the parent element that it the define will be drawn to --- @treturn LuaGuiElement the new element that was created -function Gui.draw(name,element,...) - local define = Gui.get_define(name,true) - return define:draw_to(element,...) -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_enabled(element) - if not element or not element.valid then return end - if not element.enabled then - element.enabled = true - else - element.enabled = false - end - return element.enabled -end - ---- Will toggle the visiblity of an element --- @tparam LuaGuiElement element the gui element to toggle --- @treturn boolean the new state that the element has -function Gui.toggle_visible(element) - if not element or not element.valid then return end - if not element.visible then - element.visible = true - else - element.visible = false - end - return element.visible -end - ---- Sets the padding for a gui element --- @tparam LuaGuiElement element the element to set the padding for --- @tparam[opt=0] number up the amount of padding on the top --- @tparam[opt=0] number down the amount of padding on the bottom --- @tparam[opt=0] number left the amount of padding on the left --- @tparam[opt=0] number right the amount of padding on the right -function Gui.set_padding(element,up,down,left,right) - local style = element.style - style.top_padding = up or 0 - style.bottom_padding = down or 0 - style.left_padding = left or 0 - style.right_padding = right or 0 -end - ---- Sets the padding for a gui style --- @tparam LuaStyle style the element to set the padding for --- @tparam[opt=0] number up the amount of padding on the top --- @tparam[opt=0] number down the amount of padding on the bottom --- @tparam[opt=0] number left the amount of padding on the left --- @tparam[opt=0] number right the amount of padding on the right -function Gui.set_padding_style(style,up,down,left,right) - style.top_padding = up or 0 - style.bottom_padding = down or 0 - style.left_padding = left or 0 - style.right_padding = right or 0 -end - ---- 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 --- @tparam LuaGuiElement element the element to be destroied --- @treturn boolean true if it was destoried -function Gui.destroy_if_valid(element) - if element and element.valid then - element.destroy() - return true - 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/core_defines.lua b/expcore/gui/core_defines.lua new file mode 100644 index 00000000..0a545a34 --- /dev/null +++ b/expcore/gui/core_defines.lua @@ -0,0 +1,87 @@ +--[[-- Core Module - Gui +- Gui defines that are used internally by the gui system +@module Gui +]] + +local Gui = require 'expcore.gui.prototype' +local Event = require 'utils.event' + +--- Core Defines. +-- @section coreDefines + +--- Button which toggles the top flow elements, version which shows inside the top flow when top flow is visible +-- @element hide_top_flow +local hide_top_flow = +Gui.element{ + type = 'sprite-button', + sprite = 'utility/preset', + style = 'tool_button', + tooltip = {'gui_util.button_tooltip'} +} +:style{ + padding = -2, + width = 18, + height = 36 +} +:on_click(function(player,_,_) + Gui.toggle_top_flow(player) +end) +Gui.core_defines.hide_top_flow = hide_top_flow + +--- Button which toggles the top flow elements, version which shows inside the left flow when top flow is hidden +-- @element show_top_flow +local show_top_flow = +Gui.element{ + type = 'sprite-button', + sprite = 'utility/preset', + style = 'tool_button', + tooltip = {'gui_util.button_tooltip'} +} +:style{ + padding = -2, + width = 18, + height = 20 +} +:on_click(function(player,_,_) + Gui.toggle_top_flow(player) +end) +Gui.core_defines.show_top_flow = show_top_flow + +--- Button which hides the elements in the left flow, shows inside the left flow when frames are visible +-- @element hide_left_flow +local hide_left_flow = +Gui.element{ + type = 'sprite-button', + sprite = 'utility/close_black', + style = 'tool_button', + tooltip = {'expcore-gui.left-button-tooltip'} +} +:style{ + padding = -3, + width = 18, + height = 20 +} +:on_click(function(player,_,_) + Gui.hide_left_flow(player) +end) +Gui.core_defines.hide_left_flow = hide_left_flow + +--- Draw the core elements when a player joins the game +Event.add(defines.events.on_player_created,function(event) + local player = game.players[event.player_index] + + -- Draw the top flow + local top_flow = Gui.get_top_flow(player) + hide_top_flow(top_flow) + Gui.update_top_flow(player) + + -- Draw the left flow + local left_flow = Gui.get_left_flow(player) + local button_flow = left_flow.add{ type = 'flow', name = 'gui_core_buttons', direction = 'vertical' } + local show_top = show_top_flow(button_flow) + local hide_left = hide_left_flow(button_flow) + show_top.visible = false + hide_left.visible = false + Gui.draw_left_flow(player) + +end) \ No newline at end of file diff --git a/expcore/gui/defines.lua b/expcore/gui/defines.lua new file mode 100644 index 00000000..b61322e7 --- /dev/null +++ b/expcore/gui/defines.lua @@ -0,0 +1,298 @@ +--[[-- Core Module - Gui +- Common defines that are used by other modules, non of these are used internally +@module Gui +]] + +local Gui = require 'expcore.gui.prototype' + +--- Defines. +-- @section defines + +--[[-- Draw a flow used to align its child elements, default is right align +@element Gui.alignment +@tparam LuaGuiElement parent the parent element to which the alignment will be added +@tparam[opt='alignment'] string name the name of the alignment flow which is added +@tparam[opt='right'] string horizontal_align the horizontal alignment of the elements in the flow +@tparam[opt='center'] string vertical_align the vertical alignment of the elements in the flow +@treturn LuaGuiElement the alignment flow that was created + +@usage-- Adding a right align flow +local alignment = Gui.alignment(element,'example_right_alignment') + +@usage-- Adding a horizontal center and top align flow +local alignment = Gui.alignment(element,'example_center_top_alignment','center','top') + +]] +Gui.alignment = +Gui.element(function(_,parent,name,_,_) + return parent.add{ + name = name or 'alignment', + type = 'flow', + } +end) +:style(function(style,_,_,horizontal_align,vertical_align) + style.padding = {1,2} + style.vertical_align = vertical_align or 'center' + style.horizontal_align = horizontal_align or 'right' + style.vertically_stretchable = style.vertical_align ~= 'center' + style.horizontally_stretchable = style.horizontal_align ~= 'center' +end) + +--[[-- Draw a scroll pane that has a table inside of it +@element Gui.scroll_table +@tparam LuaGuiElement parent the parent element to which the scroll table will be added +@tparam number height the maximum height for the scroll pane +@tparam number column_count the number of columns that the table will have +@tparam[opt='scroll'] string name the name of the scroll pane that is added, the table is always called "table" +@treturn LuaGuiElement the table that was created + +@usage-- Adding a scroll table with max height of 200 and column count of 3 +local scroll_table = Gui.scroll_table(element,200,3) + +]] +Gui.scroll_table = +Gui.element(function(_,parent,height,column_count,name) + -- Draw the scroll + local scroll_pane = + parent.add{ + name = name or 'scroll', + type = 'scroll-pane', + direction = 'vertical', + horizontal_scroll_policy = 'never', + vertical_scroll_policy = 'auto', + style = 'scroll_pane_under_subheader' + } + + -- Set the style of the scroll pane + local scroll_style = scroll_pane.style + scroll_style.padding = {1,3} + scroll_style.maximal_height = height + scroll_style.horizontally_stretchable = true + + -- Draw the table + local scroll_table = + scroll_pane.add{ + type = 'table', + name = 'table', + column_count = column_count + } + + -- Return the scroll table + return scroll_table +end) +:style{ + padding = 0, + cell_padding = 0, + vertical_align = 'center', + horizontally_stretchable = true +} + +--[[-- Used to add a frame with the header style, has the option for a right alignment flow for buttons +@element Gui.header +@tparam LuaGuiElement parent the parent element to which the header will be added +@tparam ?string|Concepts.LocalizedString caption the caption that will be shown on the header +@tparam[opt] ?string|Concepts.LocalizedString tooltip the tooltip that will be shown on the header +@tparam[opt=false] boolean add_alignment when true an alignment flow will be added to the header +@tparam[opt='header'] string name the name of the header that is being added, the alignment is always called "alignment" +@treturn LuaGuiElement either the header or the header alignment if add_alignment is true + +@usage-- Adding a custom header with a label +local header = Gui.header( + element, + 'Example Caption', + 'Example Tooltip' +) + +]] +Gui.header = +Gui.element(function(_,parent,caption,tooltip,add_alignment,name) + -- Draw the header + local header = + parent.add{ + name = name or 'header', + type = 'frame', + style = 'subheader_frame' + } + + -- Change the style of the header + local style = header.style + style.padding = {2,4} + style.use_header_filler = false + style.horizontally_stretchable = true + + -- Draw the caption label + if caption then + header.add{ + name = 'header_label', + type = 'label', + style = 'heading_1_label', + caption = caption, + tooltip = tooltip + } + end + + -- Return either the header or the added alignment + return add_alignment and Gui.alignment(header) or header +end) + +--[[-- Used to add a frame with the footer style, has the option for a right alignment flow for buttons +@element Gui.footer +@tparam LuaGuiElement parent the parent element to which the footer will be added +@tparam ?string|Concepts.LocalizedString caption the caption that will be shown on the footer +@tparam[opt] ?string|Concepts.LocalizedString tooltip the tooltip that will be shown on the footer +@tparam[opt=false] boolean add_alignment when true an alignment flow will be added to the footer +@tparam[opt='footer'] string name the name of the footer that is being added, the alignment is always called "alignment" +@treturn LuaGuiElement either the footer or the footer alignment if add_alignment is true + +@usage-- Adding a custom footer with a label +local footer = Gui.footer( + element, + 'Example Caption', + 'Example Tooltip' +) + +]] +Gui.footer = +Gui.element(function(_,parent,caption,tooltip,add_alignment,name) + -- Draw the header + local footer = + parent.add{ + name = name or 'footer', + type = 'frame', + style = 'subfooter_frame' + } + + -- Change the style of the footer + local style = footer.style + style.padding = {2,4} + style.use_header_filler = false + style.horizontally_stretchable = true + + -- Draw the caption label + if caption then + footer.add{ + name = 'footer_label', + type = 'label', + style = 'heading_1_label', + caption = caption, + tooltip = tooltip + } + end + + -- Return either the footer or the added alignment + return add_alignment and Gui.alignment(footer) or footer +end) + +--[[-- Used for left frames to give them a nice boarder +@element Gui.container +@tparam LuaGuiElement parent the parent element to which the container will be added +@tparam string name the name that you want to give to the outer frame, often just event_trigger +@tparam number width the minimal width that the frame will have + +@usage-- Adding a container as a base +local container = Gui.container(parent,'my_container',200) + +]] +Gui.container = +Gui.element(function(_,parent,name,_) + -- Draw the external container + local frame = + parent.add{ + name = name, + type = 'frame' + } + + -- Return the container + return frame.add{ + name = 'container', + type = 'frame', + direction = 'vertical', + style = 'window_content_frame_packed' + } +end) +:style(function(style,element,_,width) + style.vertically_stretchable = false + local frame_style = element.parent.style + frame_style.padding = 2 + frame_style.minimal_width = width +end) + +--[[-- Used to make a solid white bar in a gui +@element Gui.bar +@tparam LuaGuiElement parent the parent element to which the bar will be added +@tparam number width the width of the bar that will be made, if not given bar will strech to fill the parent + +@usage-- Adding a bar to a gui +local bar = Gui.bar(parent, 100) + +]] +Gui.bar = +Gui.element(function(_,parent) + return parent.add{ + type = 'progressbar', + size = 1, + value = 1 + } +end) +:style(function(style,_,width) + style.height = 3 + style.color = {r=255,g=255,b=255} + if width then style.width = width + else style.horizontally_stretchable = true end +end) + +--[[-- Used to make a label which is centered and of a certian size +@element Gui.centered_label +@tparam LuaGuiElement parent the parent element to which the label will be added +@tparam number width the width of the label, must be given in order to center the caption +@tparam ?string|Concepts.LocalizedString caption the caption that will be shown on the label +@tparam[opt] ?string|Concepts.LocalizedString tooltip the tooltip that will be shown on the label + +@usage-- Adding a centered label +local label = Gui.centered_label(parent, 100, 'This is centered') + +]] +Gui.centered_label = +Gui.element(function(_,parent,width,caption,tooltip) + local label = parent.add{ + type = 'label', + caption = caption, + tooltip = tooltip, + style = 'description_label' + } + + local style = label.style + style.horizontal_align = 'center' + style.single_line = false + style.width = width + + return label +end) + +--[[-- Used to make a title which has two bars on either side +@element Gui.title_label +@tparam LuaGuiElement parent the parent element to which the label will be added +@tparam number width the width of the first bar, this can be used to position the label +@tparam ?string|Concepts.LocalizedString caption the caption that will be shown on the label +@tparam[opt] ?string|Concepts.LocalizedString tooltip the tooltip that will be shown on the label + +@usage-- Adding a centered label +local label = Gui.centered_label(parent, 100, 'This is centered') + +]] +Gui.title_label = +Gui.element(function(_,parent,width,caption,tooltip) + local title_flow = parent.add{ type='flow' } + title_flow.style.vertical_align = 'center' + + Gui.bar(title_flow,width) + local title_label = title_flow.add{ + type = 'label', + caption = caption, + tooltip = tooltip, + style = 'heading_1_label' + } + Gui.bar(title_flow) + + return title_label +end) \ No newline at end of file diff --git a/expcore/gui/elements/buttons.lua b/expcore/gui/elements/buttons.lua deleted file mode 100644 index aa06f58b..00000000 --- a/expcore/gui/elements/buttons.lua +++ /dev/null @@ -1,128 +0,0 @@ ---[[-- Core Module - Gui - @module Gui - @alias Prototype -]] - ---- Buttons. --- Gui class define for buttons and sprite buttons --- @section Buttons - ---[[ ->>>> Functions - Button.new_button(name) --- Creates a new button element define - - Button._prototype:on_click(player,element) --- Registers a handler for when the button is clicked - Button._prototype:on_left_click(player,element) --- Registers a handler for when the button is clicked with the left mouse button - Button._prototype:on_right_click(player,element) --- Registers a handler for when the button is clicked with the right mouse button - - Button._prototype:set_sprites(sprite,hovered_sprite,clicked_sprite) --- Adds sprites to a button making it a sprite button - Button._prototype:set_click_filter(filter,...) --- Adds a click / mouse button filter to the button - Button._prototype:set_key_filter(filter,...) --- Adds a control key filter to the button - - Other functions present from expcore.gui.core -]] -local mod_gui = require 'mod-gui' --- @dep mod-gui -local Gui = require 'expcore.gui.core' --- @dep expcore.gui.core -local Prototype = require 'expcore.gui.prototype' --- @dep expcore.gui.prototype - -local Button = { - _prototype=Prototype.extend{ - on_raw_click = Prototype.event, - on_click = Prototype.event, - on_left_click = Prototype.event, - on_right_click = Prototype.event, - } -} - ---- Creates a new button element define --- @tparam[opt] string name the optional debug name that can be added --- @treturn table the new button element define -function Button.new_button(name) - - local self = Gui.new_define(Button._prototype,name) - self.draw_data.type = 'button' - self.draw_data.style = mod_gui.button_style - - 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 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:raise_event('on_right_click',player,element) - end - - if self.mouse_button_filter and not self.mouse_button_filter[mouse_button] then return end - if self.key_button_filter then - for key,state in pairs(self.key_button_filter) do - if state and not keys[key] then return end - end - end - - self:raise_event('on_click',player,element) - end) - - return self -end - ---- Adds sprites to a button making it a sprite button --- @tparam SpritePath sprite the sprite path for the default sprite for the button --- @tparam[opt] SpritePath hovered_sprite the sprite path for the sprite when the player hovers over the button --- @tparam[opt] SpritePath clicked_sprite the sprite path for the sprite when the player clicks the button --- @treturn self returns the button define to allow chaining -function Button._prototype:set_sprites(sprite,hovered_sprite,clicked_sprite) - self.draw_data.type = 'sprite-button' - self.draw_data.sprite = sprite - self.draw_data.hovered_sprite = hovered_sprite - self.draw_data.clicked_sprite = clicked_sprite - return self -end - ---- Adds a click / mouse button filter to the button --- @tparam table filter ?string|table either a of mouse buttons or the first mouse button to filter, with a table true means allowed --- @tparam[opt] table ... when filter is not a you can add the mouse buttons one after each other --- @treturn self returns the button define to allow chaining -function Button._prototype:set_click_filter(filter,...) - if type(filter) == 'string' then - filter = {[filter]=true} - for _,v in pairs({...}) do - filter[v] = true - end - end - - for k,v in pairs(filter) do - if type(v) == 'string' then - filter[k] = defines.mouse_button_type[v] - end - end - - self.mouse_button_filter = filter - return self -end - ---- Adds a control key filter to the button --- @tparam table filter ?string|table either a of control keys or the first control keys to filter, with a table true means allowed --- @tparam[opt] table ... when filter is not a you can add the control keys one after each other --- @treturn self returns the button define to allow chaining -function Button._prototype:set_key_filter(filter,...) - if type(filter) == 'string' then - filter = {[filter]=true} - for _,v in pairs({...}) do - filter[v] = true - end - end - - self.key_button_filter = filter - return self -end - -return Button \ No newline at end of file diff --git a/expcore/gui/elements/checkbox.lua b/expcore/gui/elements/checkbox.lua deleted file mode 100644 index ce9b2a8a..00000000 --- a/expcore/gui/elements/checkbox.lua +++ /dev/null @@ -1,247 +0,0 @@ ---[[-- Core Module - Gui - @module Gui - @alias Prototype -]] - ---- Checkboxs. --- Gui class define for checkbox and radiobuttons --- @section checkboxs - ---[[ ->>>> Using an option set - An option set is a set of radio buttons where only one of them can be active at a time, this means that when one - is clicked all the other ones are set to false, an option set must be defined before hand and will always store - its state but is not limited by how it can categorize the store. - - First you must register the store with a name and a update callback, and an optional function for categorize: - - 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.categorize_by_player) - - Then you must register some radiobutton defines and include them in the option set: - - local example_option_one = - Gui.new_radiobutton() - :set_caption('Option One') - :add_as_option(example_option_set,'One') - - local example_option_two = - Gui.new_radiobutton() - :set_caption('Option Two') - :add_as_option(example_option_set,'Two') - - Note that these radiobuttons can still have on_element_update events but this may result in a double trigger of events as - the option set update is always triggered; also add_store cant be used as the option set acts as the store however get - and set store will still work but will effect the option set rather than the individual radiobuttons. - ->>>> Functions - Checkbox.new_checkbox(name) --- Creates a new checkbox element define - Checkbox._prototype_checkbox:on_element_update(callback) --- Registers a handler for when an element instance updates - Checkbox._prototype_checkbox:on_store_update(callback) --- Registers a handler for when the stored value updates - - Checkbox.new_radiobutton(name) --- Creates a new radiobutton element define - Checkbox._prototype_radiobutton:on_element_update(callback) --- Registers a handler for when an element instance updates - Checkbox._prototype_radiobutton:on_store_update(callback) --- Registers a handler for when the stored value updates - Checkbox._prototype_radiobutton:add_as_option(option_set,option_name) --- Adds this radiobutton to be an option in the given option set (only one can be true at a time) - - Checkbox.new_option_set(name,callback,categorize) --- Registers a new option set that can be linked to radiobutton (only one can be true at a time) - Checkbox.draw_option_set(name,element) --- Draws all radiobuttons that are part of an option set at once (Gui.draw will not work) - - Checkbox.reset_radiobutton(element,exclude,recursive) --- Sets all radiobutton in a element to false (unless excluded) and can act recursively - - Other functions present from expcore.gui.core -]] -local Gui = require 'expcore.gui.core' --- @dep expcore.gui.core -local Prototype = require 'expcore.gui.prototype' --- @dep expcore.gui.prototype -local Store = require 'expcore.store' --- @dep expcore.store -local Game = require 'utils.game' --- @dep utils.game - ---- 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_update(define,element,value) - element.state = 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=Prototype.extend{ - on_element_update = Prototype.event, - on_store_update = Prototype.event, - add_store = Prototype.store(store_update) - }, - _prototype_radiobutton=Prototype.extend{ - on_element_update = Prototype.event, - on_store_update = Prototype.event, - add_store = Prototype.store(store_update) - } -} - ---- Creates a new checkbox element define --- @tparam[opt] string name the optional debug name that can be added --- @treturn table the new checkbox element define -function Checkbox.new_checkbox(name) - - local self = Gui.new_define(Checkbox._prototype_checkbox,name) - self.draw_data.type = 'checkbox' - self.draw_data.state = false - - self:on_draw(function(player,element) - if self.store then - local state = self:get_store(element,true) - if state then element.state = true end - end - end) - - Gui.on_checked_state_changed(self.name,function(event) - local element = event.element - - if self.option_set then - local value = Checkbox.option_sets[self.option_set][element.name] - self:set_store(element,value) - - elseif self.store then - local value = element.state - self:set_store(element,value) - - else - self:raise_event('on_element_update',event.player,element,element.state) - - end - end) - - return self -end - ---- Creates a new radiobutton element define, has all functions checkbox has --- @tparam[opt] string name the optional debug name that can be added --- @treturn table the new button element define -function Checkbox.new_radiobutton(name) - local self = Checkbox.new_checkbox(name) - self.draw_data.type = 'radiobutton' - - local mt = getmetatable(self) - mt.__index = Checkbox._prototype_radiobutton - - return self -end - ---- Adds this radiobutton to be an option in the given option set (only one can be true at a time) --- @tparam string option_set the name of the option set to add this element to --- @tparam string option_name the name of this option that will be used to identify it --- @treturn self the define to allow chaining -function Checkbox._prototype_radiobutton:add_as_option(option_set,option_name) - self.option_set = option_set - self.option_name = option_name or self.name - - Checkbox.option_sets[option_set][self.option_name] = self.name - Checkbox.option_sets[option_set][self.name] = self.option_name - - self:add_store(Checkbox.option_categorize[option_set]) - - return self -end - ---- Gets the stored value of the radiobutton or the option set if present --- @tparam string category[opt] the category to get such as player name or force name --- @tparam boolean internal used to prevent stackover flow --- @treturn any the value that is stored for this define -function Checkbox._prototype_radiobutton:get_store(category,internal) - if not self.store then return end - local location = not internal and self.option_set or self.store - return Store.get(location,category) -end - ---- Sets the stored value of the radiobutton or the option set if present --- @tparam string category[opt] the category to get such as player name or force name --- @tparam boolean value the value to set for this define, must be valid for its type ie for checkbox etc --- @tparam boolean internal used to prevent stackover flow --- @treturn boolean true if the value was set -function Checkbox._prototype_radiobutton:set_store(category,value,internal) - if not self.store then return end - local location = not internal and self.option_set or self.store - return Store.set(location,category,value) -end - ---- Registers a new option set that can be linked to radiobuttons (only one can be true at a time) --- @tparam function callback the update callback when the value of the option set changes --- callback param - value string - the new selected option for this option set --- callback param - category string - the category that updated if categorize was used --- @tparam function categorize the function used to convert an element into a string --- @treturn string the name of this option set to be passed to add_as_option -function Checkbox.new_option_set(callback,categorize) - local name = Store.register(categorize) - - Store.watch(name,function(value,category) - local options = Checkbox.option_sets[name] - for opt_name,define_name in pairs(options) do - if Gui.defines[define_name] then - local define = Gui.get_define(define_name) - local state = opt_name == value - define:set_store(category,state,true) - end - end - callback(value,category) - end) - - Checkbox.option_categorize[name] = categorize - Checkbox.option_sets[name] = {} - - return name -end - ---- Draws all radiobuttons that are part of an option set at once (Gui.draw will not work) --- @tparam string name the name of the option set to draw the radiobuttons of --- @tparam LuaGuiElement element the parent element that the radiobuttons will be drawn to -function Checkbox.draw_option_set(name,element) - if not Checkbox.option_sets[name] then return end - local options = Checkbox.option_sets[name] - - for _,option in pairs(options) do - if Gui.defines[option] then - Gui.defines[option]:draw_to(element) - end - end - -end - ---- Sets all radiobutton in a element to false (unless excluded) and can act recursively --- @tparam LuaGuiElement element the root gui element to start setting radio buttons from --- @tparam[opt] table exclude ?string|table the name of the radiobutton to exclude or a of radiobuttons where true will set the state true --- @tparam[opt=false] ?number|boolean recursive if true will recur as much as possible, if a will recur that number of times --- @treturn boolean true if successful -function Checkbox.reset_radiobuttons(element,exclude,recursive) - if not element or not element.valid then return end - exclude = type(exclude) == 'table' and exclude or exclude ~= nil and {[exclude]=true} or {} - recursive = type(recursive) == 'number' and recursive-1 or recursive - - for _,child in pairs(element.children) do - if child and child.valid and child.type == 'radiobutton' then - local state = exclude[child.name] or false - local define = Gui.defines[child.name] - - if define then - local category = define.categorize and define.categorize(child) or state - define:set_store(category,state) - - else - child.state = state - - end - - elseif child.children and (type(recursive) == 'number' and recursive >= 0 or recursive == true) then - Checkbox.reset_radiobutton(child,exclude,recursive) - - end - end - - return true -end - -return Checkbox \ No newline at end of file diff --git a/expcore/gui/elements/dropdown.lua b/expcore/gui/elements/dropdown.lua deleted file mode 100644 index ae6857c0..00000000 --- a/expcore/gui/elements/dropdown.lua +++ /dev/null @@ -1,184 +0,0 @@ ---[[-- Core Module - Gui - @module Gui - @alias Prototype -]] - ---- Dropdowns. --- Gui class define for dropdowns and list box --- @section dropdowns - ---[[ ->>>> Functions - Dropdown.new_dropdown(name) --- Creates a new dropdown element define - Dropdown.new_list_box(name) --- Creates a new list box element define - - Dropdown._prototype:on_element_update(callback) --- Registers a handler for when an element instance updates - Dropdown._prototype:on_store_update(callback) --- Registers a handler for when the stored value updates - - Dropdown._prototype:new_static_options(options,...) --- Adds new static options to the dropdown which will trigger the general callback - Dropdown._prototype:new_dynamic_options(callback) --- Adds a callback which should return a table of values to be added as options for the dropdown (appended after static options) - Dropdown._prototype:add_option_callback(option,callback) --- Adds a case specific callback which will only run when that option is selected (general case still triggered) - - Dropdown.select_value(element,value) --- Selects the option from a dropdown or list box given the value rather than key - Dropdown.get_selected_value(element) --- Returns the currently selected value rather than index - - Other functions present from expcore.gui.core -]] -local Gui = require 'expcore.gui.core' --- @dep expcore.gui.core -local Prototype = require 'expcore.gui.prototype' --- @dep expcore.gui.prototype -local Game = require 'utils.game' --- @dep utils.game - -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_update(define,element,value) - select_value(element,value) - local player = Game.get_player_by_index(element.player_index) - 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 Dropdown = { - _prototype=Prototype.extend{ - on_element_update = Prototype.event, - on_store_update = Prototype.event, - add_store = Prototype.store(store_update) - } -} - ---- Creates a new dropdown element define --- @tparam[opt] string name the optional debug name that can be added --- @treturn table the new dropdown element define -function Dropdown.new_dropdown(name) - - local self = Gui.new_define(Dropdown._prototype,name) - self.draw_data.type = 'drop-down' - - self:on_draw(function(player,element) - if self.dynamic_options then - local dynamic_options = self.dynamic_options(player,element) - local items = element.items - for _,v in pairs(dynamic_options) do - table.insert(items,v) - end - element.items = items - end - - if self.store then - local value = self:get_store(element) - if value then Dropdown.select_value(element,value) end - end - end) - - Gui.on_selection_state_changed(self.name,function(event) - local element = event.element - local value = Dropdown.get_selected_value(element) - - if self.store then - self:set_store(element,value) - - else - 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 - - end) - - return self -end - ---- Creates a new list box element define --- @tparam[opt] string name the optional debug name that can be added --- @treturn table the new list box element define -function Dropdown.new_list_box(name) - local self = Dropdown.new_dropdown(name) - self.draw_data.type = 'list-box' - - return self -end - ---- Adds new static options to the dropdown which will trigger the general callback --- @tparam table options ?string|table either a of option strings or the first option string, with a table values are the options --- @tparam[opt] table ... when options is not a you can add the options one after each other --- @tparam self the define to allow chaining -function Dropdown._prototype:new_static_options(options,...) - if type(options) == 'string' then - options = {options} - for _,v in pairs({...}) do - table.insert(options,v) - end - end - - self.options = options - self.draw_data.items = options - return self -end -Dropdown._prototype.add_options = Dropdown._prototype.new_static_options - ---- Adds a callback which should return a table of values to be added as options for the dropdown (appended after static options) --- @tparam function callback the function that will run to get the options for the dropdown --- callback param - player LuaPlayer - the player that the element is being drawn to --- callback param - element LuaGuiElement - the element that is being drawn --- callback return - table - the values of this table will be appended to the static options of the dropdown --- @treturn self the define to allow chaining -function Dropdown._prototype:new_dynamic_options(callback) - if type(callback) ~= 'function' then - return error('Dynamic options callback must be a function',2) - end - self.dynamic_options = callback - return self -end -Dropdown._prototype.add_dynamic = Dropdown._prototype.new_dynamic_options - ---- Adds a case specific callback which will only run when that option is selected (general case still triggered) --- @tparam string option the name of the option to trigger the callback on; if not already added then will be added as an option --- @tparam function callback the function that will be called when that option is selected --- callback param - player LuaPlayer - the player who owns the gui element --- callback param - element LuaGuiElement - the element which is being effected --- callback param - value string - the new option that has been selected --- @treturn self the define to allow chaining -function Dropdown._prototype:add_option_callback(option,callback) - if not self.option_callbacks then self.option_callbacks = {} end - if not self.options then self.options = {} end - - self.option_callbacks[option] = callback - if not table.contains(self.options,option) then - table.insert(self.options,option) - end - - return self -end - ---- Selects the option from a dropdown or list box given the value rather than key --- @tparam LuaGuiElement element the element that contains the option --- @tparam string value the option to select from the dropdown --- @treturn number the key where the value was -function Dropdown.select_value(element,value) - for k,item in pairs(element.items) do - if item == value then - element.selected_index = k - return k - end - end -end -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 --- @treturn string the value that is currently selected -function Dropdown.get_selected_value(element) - local index = element.selected_index - return element.items[index] -end - -return Dropdown \ No newline at end of file diff --git a/expcore/gui/elements/elem-button.lua b/expcore/gui/elements/elem-button.lua deleted file mode 100644 index 8b2b2b3c..00000000 --- a/expcore/gui/elements/elem-button.lua +++ /dev/null @@ -1,96 +0,0 @@ ---[[-- Core Module - Gui - @module Gui - @alias Prototype -]] - ---- Elem Buttons. --- Gui class defines for elem buttons --- @section elem-buttons - ---[[ ->>>> Functions - ElemButton.new_elem_button(name) --- Creates a new elem button element define - - ElemButton._prototype:on_element_update(callback) --- Registers a handler for when an element instance updates - ElemButton._prototype:on_store_update(callback) --- Registers a handler for when the stored value updates - - ElemButton._prototype:set_type(type) --- Sets the type of the elem button, the type is required so this must be called at least once - ElemButton._prototype:set_default(value) --- Sets the default value for the elem button, this may be a function or a string - - Other functions present from expcore.gui.core -]] -local Gui = require 'expcore.gui.core' --- @dep expcore.gui.core -local Prototype = require 'expcore.gui.prototype' --- @dep expcore.gui.prototype -local Game = require 'utils.game' --- @dep utils.game - ---- 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_update(define,element,value) - element.elem_value = value - local player = Game.get_player_by_index(element.player_index) - define:raise_event('on_element_update',player,element,value) -end - -local ElemButton = { - _prototype=Prototype.extend{ - on_element_update = Prototype.event, - on_store_update = Prototype.event, - add_store = Prototype.store(store_update) - } -} - ---- Creates a new elem button element define --- @tparam[opt] string name the optional debug name that can be added --- @treturn table the new elem button element define -function ElemButton.new_elem_button(name) - - local self = Gui.new_define(ElemButton._prototype,name) - self.draw_data.type = 'choose-elem-button' - - self:on_draw(function(player,element) - if type(self.default) == 'function' then - element.elem_value = self.default(player,element) - end - - if self.store then - local value = self:get_store(element) - if value then element.elem_value = value end - end - end) - - Gui.on_elem_changed(self.name,function(event) - local element = event.element - local value = element.elem_value - - if self.store then - self:set_store(element,value) - - else - self:raise_event('on_element_update',event.player,element,value) - - end - - end) - - return self -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 -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 --- @treturn the element define to allow for chaining -function ElemButton._prototype:set_default(value) - self.default = value - if type(value) ~= 'function' then - self.draw_data[self.draw_data.elem_type] = value - end - return self -end - -return ElemButton \ No newline at end of file diff --git a/expcore/gui/elements/progress-bar.lua b/expcore/gui/elements/progress-bar.lua deleted file mode 100644 index 0e096d42..00000000 --- a/expcore/gui/elements/progress-bar.lua +++ /dev/null @@ -1,387 +0,0 @@ ---[[-- Core Module - Gui - @module Gui - @alias Prototype -]] - ---- Progress Bars. --- Gui element define for progress bars --- @section progress-bars - ---[[ ->>>> Functions - ProgressBar.set_maximum(element,amount,count_down) --- Sets the maximum value that represents the end value of the progress bar - ProgressBar.increment(element,amount) --- Increases the value of the progressbar, if a define is given all of its instances have incremented - ProgressBar.decrement(element,amount) --- Decreases the value of the progressbar, if a define is given all of its instances have decremented - - ProgressBar.new_progressbar(name) --- Creates a new progressbar element define - ProgressBar._prototype:set_maximum(amount,count_down) --- Sets the maximum value that represents the end value of the progress bar - ProgressBar._prototype:use_count_down(state) --- Will set the progress bar to start at 1 and trigger when it hits 0 - ProgressBar._prototype:increment(amount,category) --- Increases the value of the progressbar - ProgressBar._prototype:increment_filtered(amount,filter) --- Increases the value of the progressbar, if the filter condition is met, does not work with store - ProgressBar._prototype:decrement(amount,category) --- Decreases the value of the progressbar - ProgressBar._prototype:decrement_filtered(amount,filter) --- Decreases the value of the progressbar, if the filter condition is met, does not work with store - ProgressBar._prototype:add_element(element,maximum) --- Adds an element into the list of instances that will are waiting to complete, does not work with store - ProgressBar._prototype:reset_element(element) --- Resets an element, or its store, to be back at the start, either 1 or 0 - - ProgressBar._prototype:on_complete(callback) --- Triggers when a progress bar element completes (hits 0 or 1) - ProgressBar._prototype:on_complete(callback) --- Triggers when a store value completes (hits 0 or 1) - ProgressBar._prototype:event_counter(filter) --- Event handler factory that counts up by 1 every time the event triggers, can filter which elements have incremented - ProgressBar._prototype:event_countdown(filter) --- Event handler factory that counts down by 1 every time the event triggers, can filter which elements have decremented -]] -local Gui = require 'expcore.gui.core' --- @dep expcore.gui.core -local Prototype = require 'expcore.gui.prototype' --- @dep expcore.gui.prototype -local Global = require 'utils.global' --- @dep utils.global -local Game = require 'utils.game' --- @dep utils.game - ---- Event call for when the value is outside the range 0-1 --- @tparam table define the define that this is acting on --- @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) - 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_update(define,element,value) - if value then - element.value = value - if define.count_down and value <= 0 - or not define.count_down and value >= 1 then - event_call(define,element) - end - end -end - -local ProgressBar = { - unregistered={}, -- elements with no callbacks - independent={}, -- elements with a link to a define - _prototype=Prototype.extend{ - on_complete = Prototype.event, - on_store_complete = Prototype.event, - add_store = Prototype.store(store_update) - } -} - -Global.register({ - unregistered = ProgressBar.unregistered, - independent = ProgressBar.independent -},function(tbl) - ProgressBar.unregistered = tbl.unregistered - ProgressBar.independent = tbl.independent -end) - ---- Gets the define data, cant use Gui.get_define as it would error --- @tparam ?table|string define the define to get --- @treturn table the define or nil -local function get_define(define) - if type(define) == 'table' then - if define.name and Gui.defines[define.name] then - return Gui.defines[define.name] - end - end - - return Gui.defines[define] -end - ---- Gets the element data, used when there is no define --- @tparam LuaGuiElement element the element to get the data of --- @treturn table the element data similar to define -local function get_element(element) - if not element.valid then return end - local name = element.player_index..':'..element.index - - if ProgressBar.unregistered[name] then - return ProgressBar.unregistered[name] - end -end - ---- Sets the maximum value that represents the end value of the progress bar --- @tparam ?LuaGuiElement|string element either a gui element or a registered define --- @tparam number amount the amount to have set as the maximum -function ProgressBar.set_maximum(element,amount) - amount = amount > 0 and amount or error('amount must be greater than 0') - - local define = get_define(element) - if define then - define:set_default_maximum(amount) - - else - local element_data = get_element(element) - - if element_data then - element_data.maximum = amount - - else - local name = element.player_index..':'..element.index - ProgressBar.unregistered[name] = { - element=element, - maximum=amount or 1 - } - - end - - end -end - ---- Increases the value of the progressbar, if a define is given all of its instances have incremented --- @tparam ?LuaGuiElement|string element either a gui element or a registered define --- @tparam[opt=1] number amount the amount to increase the progressbar by -function ProgressBar.increment(element,amount) - amount = type(amount) == 'number' and amount or 1 - - local define = get_define(element) - if define then - define:increment(amount) - - else - local element_data = get_element(element) - - if element_data then - local real_amount = amount/element_data.maximum - element.value = element.value + real_amount - - if element.value >= 1 then - local name = element.player_index..':'..element.index - ProgressBar.unregistered[name] = nil - return true - end - end - - end -end - ---- Decreases the value of the progressbar, if a define is given all of its instances have decremented --- @tparam ?LuaGuiElement|string element either a gui element or a registered define --- @tparam[opt=1] number amount the amount to decrease the progressbar by -function ProgressBar.decrement(element,amount) - amount = type(amount) == 'number' and amount or 1 - - local define = get_define(element) - if define then - define:decrement(amount) - - else - local element_data = get_element(element) - - if element_data then - local real_amount = amount/element_data.maximum - element.value = element.value - real_amount - - if element.value <= 0 then - local name = element.player_index..':'..element.index - ProgressBar.unregistered[name] = nil - return true - end - end - - end -end - ---- Creates a new progressbar element define --- @tparam[opt] string name the optional debug name that can be added --- @treturn table the new progressbar element define -function ProgressBar.new_progressbar(name) - - local self = Gui.new_define(ProgressBar._prototype,name) - self.draw_data.type = 'progressbar' - - self:on_draw(function(player,element,maximum) - if self.store then - local value = self:get_store(element) - if not value then - value = self.count_down and 1 or 0 - self:set_store(element,value) - end - element.value = value - - else - if self.count_down then - element.value = 1 - end - - if not ProgressBar.independent[self.name] then - ProgressBar.independent[self.name] = {} - end - - table.insert(ProgressBar.independent[self.name],{ - element = element, - maximum = maximum - }) - - end - - end) - - return self -end - ---- Sets the maximum value that represents the end value of the progress bar --- @tparam number amount the amount to have set as the maximum --- @treturn table the define to allow chaining -function ProgressBar._prototype:set_default_maximum(amount) - amount = amount > 0 and amount or error('amount must be greater than 0') - self.default_maximum = amount - return self -end - ---- Will set the progress bar to start at 1 and trigger when it hits 0 --- @tparam[opt=true] boolean state when true the bar will start filled, to be used with decrease --- @treturn table the define to allow chaining -function ProgressBar._prototype:use_count_down(state) - if state == false then - self.count_down = false - else - self.count_down = true - end - return self -end - ---- Main logic for changing the value of a progress bar, this only applies when its a registered define --- @tparam table self the define that is being changed --- @tparam number amount the amount which it is being changed by, may be negative --- @tparam[opt] string category the category to use with store --- @tparam[opt] function filter when given the filter must return true for the value of the element to be changed -local function change_value_prototype(self,amount,category,filter) - - local function reset_store() - local value = self.count_down and 1 or 0 - self:set_store(category,value) - end - - if self.store then - local value = self:get_store(category) or self.count_down and 1 or 0 - local maximum = self.default_maximum or 1 - local new_value = value + (amount/maximum) - - self:set_store(category,new_value) - - if self.count_down and new_value <= 0 - or not self.count_down and new_value >= 1 then - self:clear_store(category) - self:raise_event('on_store_complete',category,reset_store) - return - end - - return - end - - if ProgressBar.independent[self.name] then - for key,element_data in pairs(ProgressBar.independent[self.name]) do - local element = element_data.element - if not element or not element.valid then - ProgressBar.independent[self.name][key] = nil - - else - if not filter or filter(element) then - local maximum = element_data.maximum or self.default_maximum or 1 - element.value = element.value + (amount/maximum) - - if self.count_down and element.value <= 0 - or not self.count_down and element.value >= 1 then - ProgressBar.independent[self.name][key] = nil - event_call(self,element) - end - end - - end - end - end - -end - ---- Increases the value of the progressbar --- @tparam[opt=1] number amount the amount to increase the progressbar by --- @tparam[opt] string category the category that is used with a store -function ProgressBar._prototype:increment(amount,category) - amount = type(amount) == 'number' and amount or 1 - change_value_prototype(self,amount,category) -end - ---- Increases the value of the progressbar, if the filter condition is met, does not work with store --- @tparam[opt=1] number amount the amount to increase the progressbar by --- @tparam function filter the filter to be used -function ProgressBar._prototype:increment_filtered(amount,filter) - amount = type(amount) == 'number' and amount or 1 - change_value_prototype(self,amount,nil,filter) -end - ---- Decreases the value of the progressbar --- @tparam[opt=1] number amount the amount to decrease the progressbar by --- @tparam[opt] string category the category that is used with a store -function ProgressBar._prototype:decrement(amount,category) - amount = type(amount) == 'number' and amount or 1 - change_value_prototype(self,-amount,category) -end - ---- Decreases the value of the progressbar, if the filter condition is met, does not work with store --- @tparam[opt=1] number amount the amount to decrease the progressbar by --- @tparam function filter the filter to be used -function ProgressBar._prototype:decrement_filtered(amount,filter) - amount = type(amount) == 'number' and amount or 1 - change_value_prototype(self,-amount,nil,filter) -end - ---- Adds an element into the list of instances that will are waiting to complete, does not work with store --- note use store if you want persistent data, this only stores the elements not the values which they have --- @tparam LuaGuiElement element the element that you want to add into the waiting to complete list --- @tparam[opt] number maximum the maximum for this element if not given the default for this define is used -function ProgressBar._prototype:add_element(element,maximum) - if self.store then return end - if not ProgressBar.independent[self.name] then - ProgressBar.independent[self.name] = {} - end - table.insert(ProgressBar.independent[self.name],{ - element = element, - maximum = maximum - }) -end - ---- Resets an element, or its store, to be back at the start, either 1 or 0 --- @tparam LuaGuiElement element the element that you want to reset the progress of -function ProgressBar._prototype:reset_element(element) - if not element or not element.valid then return end - local value = self.count_down and 1 or 0 - if self.store then - self:set_store(element,value) - else - element.value = value - end -end - ---- Event handler factory that counts up by 1 every time the event triggers, can filter which elements have incremented --- @tparam[opt] function filter when given will use filtered increment --- @treturn function the event handler -function ProgressBar._prototype:event_counter(filter) - if type(filter) == 'function' then - return function() - self:increment_filtered(1,filter) - end - else - return function() - self:increment() - end - end -end - ---- Event handler factory that counts down by 1 every time the event triggers, can filter which elements have decremented --- @tparam[opt] function filter when given will use filtered decrement --- @treturn function the event handler -function ProgressBar._prototype:event_countdown(filter) - if type(filter) == 'function' then - return function() - self:decrement_filtered(1,filter) - end - else - return function() - self:decrement() - end - end -end - -return ProgressBar \ No newline at end of file diff --git a/expcore/gui/elements/slider.lua b/expcore/gui/elements/slider.lua deleted file mode 100644 index e8099b06..00000000 --- a/expcore/gui/elements/slider.lua +++ /dev/null @@ -1,173 +0,0 @@ ---[[-- Core Module - Gui - @module Gui - @alias Prototype -]] - ---- Sliders. --- Gui class define for sliders --- @section sliders - ---[[ ->>>> Functions - Slider.new_slider(name) --- Creates a new slider element define - - 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: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 - - Other functions present from expcore.gui.core -]] -local Gui = require 'expcore.gui.core' --- @dep expcore.gui.core -local Prototype = require 'expcore.gui.prototype' --- @dep expcore.gui.prototype -local Instances = require 'expcore.gui.instances' --- @dep expcore.gui.instances -local Game = require 'utils.game' --- @dep utils.game - ---- Event call for on_value_changed and 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 slider -local function event_call(define,element,value) - local player = Game.get_player_by_index(element.player_index) - - local min,max = element.get_slider_minimum(),element.get_slider_maximum() - local delta = max-min - local percent = delta == 0 and 0 or (value-min)/delta - - define:raise_event('on_element_update',player,element,value,percent) - - local category = player.name - if define.categorize then - category = define.categorize(element) - end - - Instances.unregistered_get_elements(define.name..'-label',category,function(label) - label.caption = tostring(math.round(value,2)) - 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 slider -local function store_update(define,element,value) - element.slider_value = value - event_call(define,element,value) -end - -local Slider = { - _prototype=Prototype.extend{ - on_element_update = Prototype.event, - on_store_update = Prototype.event, - add_store = Prototype.store(store_update) - } -} - ---- Creates a new slider element define --- @tparam[opt] string name the optional debug name that can be added --- @treturn table the new slider element define -function Slider.new_slider(name) - - local self = Gui.new_define(Slider._prototype,name) - self.draw_data.type = 'slider' - - self:on_draw(function(player,element) - local min,max = element.get_slider_minimum(),element.get_slider_maximum() - - if type(self.min) == 'function' then - min = self.min(player,element) - end - - if type(self.max) == 'function' then - max = self.max(player,element) - end - - element.set_slider_minimum_maximum(min,max) - - if self.store then - local value = self:get_store(element) - if value then element.slider_value = value end - end - - if self.auto_label then - self:draw_label(element.parent) - end - end) - - Gui.on_value_changed(self.name,function(event) - local element = event.element - local value = element.slider_value - - if self.store then - self:set_store(element,value) - - else - event_call(self,element,value) - - end - - 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 --- @treturn self the define to allow chaining -function Slider._prototype:set_range(min,max) - self.min = min - self.max = max - - if type(min) == 'number' then - self.draw_data.minimum_value = min - end - - if type(max) == 'number' then - self.draw_data.maximum_value = max - end - - return self -end - ---- 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 --- @tparam LuaGuiElement element the parent element that the label will be drawn to --- @treturn LuaGuiElement the new label element so that styles can be applied -function Slider._prototype:draw_label(element) - local name = self.name..'-label' - if element[name] then return end - - local value = 0 - if self.store then - value = self:get_store(element) or 0 - end - - local new_element = element.add{ - name=name, - type='label', - caption=tostring(math.round(value,2)) - } - - local categorise = self.categorise or Gui.categorize_by_player - local category = categorise(new_element) - - Instances.unregistered_add_element(name,category,new_element) - - return new_element -end - ---- Enables auto draw of the label, the label will share the same parent element as the slider --- @tparam[opt=true] boolean state when false will disable the auto draw of the label --- @treturn self the define to allow chaining -function Slider._prototype:enable_auto_draw_label(state) - if state == false then - self.auto_label = false - else - self.auto_label = true - end - return self -end - -return Slider \ No newline at end of file diff --git a/expcore/gui/elements/text.lua b/expcore/gui/elements/text.lua deleted file mode 100644 index 56709ede..00000000 --- a/expcore/gui/elements/text.lua +++ /dev/null @@ -1,145 +0,0 @@ ---[[-- Core Module - Gui - @module Gui - @alias Prototype -]] - ---- Text. --- Gui class define for text fields and text boxes --- @section text - ---[[ ->>>> Functions - Text.new_text_field(name) --- Creates a new text field element define - Text._prototype_field:on_element_update(callback) --- Registers a handler for when an element instance updates - Text._prototype_field:on_store_update(callback) --- Registers a handler for when the stored value updates - - Text.new_text_box(name) --- Creates a new text box element define - Text._prototype_field:on_element_update(callback) --- Registers a handler for when an element instance updates - Text._prototype_field:on_store_update(callback) --- Registers a handler for when the stored value updates - Text._prototype_box:set_selectable(state) --- Sets the text box to be selectable - Text._prototype_box:set_word_wrap(state) --- Sets the text box to have word wrap - Text._prototype_box:set_read_only(state) --- Sets the text box to be read only - - Other functions present from expcore.gui.core -]] -local Gui = require 'expcore.gui.core' --- @dep expcore.gui.core -local Prototype = require 'expcore.gui.prototype' --- @dep expcore.gui.prototype -local Game = require 'utils.game' --- @dep utils.game - ---- 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_update(define,element,value) - element.text = 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=Prototype.extend{ - on_element_update = Prototype.event, - on_store_update = Prototype.event, - add_store = Prototype.store(store_update) - }, - _prototype_box=Prototype.extend{ - on_element_update = Prototype.event, - on_store_update = Prototype.event, - add_store = Prototype.store(store_update) - } -} - ---- Creates a new text field element define --- @tparam[opt] string name the optional debug name that can be added --- @treturn table the new text field element define -function Text.new_text_field(name) - - local self = Gui.new_define(Text._prototype_field,name) - self.draw_data.type = 'textfield' - - self:on_draw(function(player,element) - if self.selectable then - element.selectable = true - end - - if self.word_wrap then - element.word_wrap = true - end - - if self.read_only then - element.read_only = true - end - - if self.store then - local value = self:get_store(element) - if value then element.text = value end - end - end) - - Gui.on_text_changed(self.name,function(event) - local element = event.element - local value = element.text - - if self.store then - self:set_store(element,value) - - else - self:raise_event('on_element_update',event.player,element,value) - - end - - end) - - return self -end - ---- Creates a new text box element define --- @tparam[opt] string name the optional debug name that can be added --- @treturn table the new text box element define -function Text.new_text_box(name) - local self = Text.new_text_field(name) - self.draw_data.type = 'text-box' - - local mt = getmetatable(self) - mt.__index = Text._prototype_box - - return self -end - ---- Sets the text box to be selectable --- @tparam[opt=true] boolean state when false will set the state to false --- @treturn self table the define to allow for chaining -function Text._prototype_box:set_selectable(state) - if state == false then - self.selectable = false - else - self.selectable = true - end - return self -end - ---- Sets the text box to have word wrap --- @tparam[opt=true] boolean state when false will set the state to false --- @treturn self table the define to allow for chaining -function Text._prototype_box:set_word_wrap(state) - if state == false then - self.word_wrap = false - else - self.word_wrap = true - end - return self -end - ---- Sets the text box to be read only --- @tparam[opt=true] boolean state when false will set the state to false --- @treturn self table the define to allow for chaining -function Text._prototype_box:set_read_only(state) - if state == false then - self.read_only = false - else - self.read_only = true - end - return self -end - -return Text \ No newline at end of file diff --git a/expcore/gui/helper_functions.lua b/expcore/gui/helper_functions.lua new file mode 100644 index 00000000..c303fb15 --- /dev/null +++ b/expcore/gui/helper_functions.lua @@ -0,0 +1,91 @@ +--[[-- Core Module - Gui +- Functions used to help with the use of guis +@module Gui +]] + +local Gui = require 'expcore.gui.prototype' + +--- Helper Functions. +-- @section helperFunctions + +--[[-- Get the player that owns a gui element +@tparam LuaGuiElement element the element to get the owner of +@treturn LuaPlayer the player that owns this element + +@usage-- Geting the owner of an element +local player = Gui.get_player_from_element(element) + +]] +function Gui.get_player_from_element(element) + if not element or not element.valid then return end + return game.players[element.player_index] +end + +--[[-- Will toggle the enabled state of an element or set it to the one given +@tparam LuaGuiElement element the element to toggle/set the enabled state of +@tparam[opt] boolean state with given will set the state, else state will be toggled +@treturn boolean the new enabled state that the element has + +@usage-- Toggling the the enabled state +local new_enabled_state = Gui.toggle_enabled_state(element) + +]] +function Gui.toggle_enabled_state(element,state) + if not element or not element.valid then return end + if state == nil then state = not element.enabled end + element.enabled = state + return state +end + +--[[-- Will toggle the visible state of an element or set it to the one given +@tparam LuaGuiElement element the element to toggle/set the visible state of +@tparam[opt] boolean state with given will set the state, else state will be toggled +@treturn boolean the new visible state that the element has + +@usage-- Toggling the the visible state +local new_visible_state = Gui.toggle_visible_state(element) + +]] +function Gui.toggle_visible_state(element,state) + if not element or not element.valid then return end + if state == nil then state = not element.visible end + element.visible = state + return state +end + +--[[-- Destory a gui element without causing any errors, often because the element was already removed +@tparam LuaGuiElement element the element that you want to remove +@treturn boolean true if the element was valid and has been removed + +@usage-- Remove a child element if it exists +Gui.destroy_if_valid(element[child_name]) + +]] +function Gui.destroy_if_valid(element) + if not element or not element.valid then return false end + element.destroy() + return true +end + +--[[-- Returns a table to be used as the style for a sprite buttons, produces a sqaure button +@tparam number size the size that you want the button to be +@tparam[opt=-2] number padding the padding that you want on the sprite +@tparam[opt] table style any extra style settings that you want to have +@treturn table the style table to be used with element_define:style() + +@usage-- Adding a sprite button with size 20 +local button = +Gui.element{ + type = 'sprite-button', + sprite = 'entity/inserter' +} +:style(Gui.sprite_style(20)) + +]] +function Gui.sprite_style(size,padding,style) + style = style or {} + style.padding = padding or -2 + style.height = size + style.width = size + return style +end \ No newline at end of file diff --git a/expcore/gui/instances.lua b/expcore/gui/instances.lua deleted file mode 100644 index 2db7273e..00000000 --- a/expcore/gui/instances.lua +++ /dev/null @@ -1,235 +0,0 @@ ---[[-- Core Module - Gui - @module Gui - @alias Prototype -]] - ---- Instances. --- This file is a breakout from core which forcues on instance management of defines --- @section instances - ---[[ ->>>> Using registered instance groups - The main use of this module is to register a group of elements referred here as "instances of an element define" in which - is meant that you define the name of a group of drawn elements that are really just multiple versions of a single element. - For example this might be that you have one label in multiple places (either for one player or many) and you want to update - the caption of all of them at once; this is where this module comes it. - - First you must register the way that the instances are stored and under what name, using Instances.register you will give the - name of the collective group of instances followed by an optional serializer function which allows variants to be stored under one - name (like one for each force or player) - - -- serializer works in the same way as store serializer - -- so the function will world here but no value is stored only gui elements - 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: - - Instances.add_element('score',new_element) - - Then when you want to get the instances you have two options; Instances.get_elements or Instances.apply_to_elements when you want loop - over the elements it is more efficient to use apply_to_elements: - - Instances.get_elements('score','player') -- returns all elements that were added with the 'player' category - Instances.apply_to_elements('score','player',function(element) -- runs the function on every valid element - element.caption = 0 - end) - - Note that if you don't give a serializer function then you don't need to give a category when getting the elements. - ->>>> Using unregistered instance groups - When using a registered group and the functions that go with them it is much simpler to use and more importantly includes error checking - for valid instance group names; the down side is that the group must be registered which can only be done during start-up and not during runtime. - To counter this there are two functions similar to those above in order to add and get instances but may lead to errors not being noticed due to - the error internal error checking being skipped to allow it to work. - - The main difference between the two groups of functions is that the category must always be present even if is nil; example below shows how a - instance group would work when registered vs unregistered: - - -- Registered with category - 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' - end) -- gets all instances from the player force and sets the caption to 0 - - -- Unregistered with category - Instances.unregistered_add_element('score','player',new_element) -- adds the new element to the player category - Instances.unregistered_apply_to_elements('score','player',function(element) - element.caption = '0' - end) -- gets all instances from the player force and sets the caption to 0 - - -- Registered without category; note that category can just be ignored - Instances.register('score') -- all instances will be under one group with no categories - Instances.add_element('score',new_element) -- adds the new element to the instance list - Instances.apply_to_elements('score',function(element) - element.caption = '0' - end) -- gets all instances and sets the element caption to 0 - - -- Unregistered without category; note that category must be given as nil - Instances.unregistered_add_element('score',nil,new_element) -- adds the new element to a single group with no categories - Instances.unregistered_apply_to_elements('score',nil,function(element) - element.caption = '0' - end) -- gets all instances and sets the element caption to 0 - ->>>> Functions - Instances.has_categories(name) --- Returns if a instance group has a serializer function; must be registered - Instances.is_registered(name) --- Returns if the given name is a registered instance group - Instances.register(name,serializer) --- Registers the name of an instance group to allow for storing element instances - - 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 Global = require 'utils.global' --- @dep utils.global - -local Instances = { - serializer={}, - data={} -} -Global.register(Instances.data,function(tbl) - Instances.data = tbl -end) - ---- Returns if a instance group has a serializer function; must be registered --- @tparam string name the name of the instance group --- @treturn boolean true if there is a serializer function -function Instances.has_categories(name) - return type(Instances.serializer[name]) == 'function' -end - ---- Returns if the given name is a registered instance group --- @tparam string name the name of the instance group you are testing --- @treturn boolean true if the name is registered -function Instances.is_registered(name) - return Instances.serializer[name] ~= nil -end - ---- Registers the name of an instance group to allow for storing element instances --- @tparam string name the name of the instance group; must to unique --- @tparam[opt] function serializer function used to turn the element into a string --- serializer param - element LuaGuiElement - the gui element to be turned into a string --- serializer return - string - the category that the element will be added to like the player's name or force's name --- @treturn string the name that was added so it can be used as a variable -function Instances.register(name,serializer) - if _LIFECYCLE ~= _STAGE.control then - return error('Can only be called during the control stage', 2) - end - - if Instances.serializer[name] then - return error('Instances for '..name..' already exist.',2) - end - - serializer = type(serializer) == 'function' and serializer or true - - Instances.data[name] = {} - Instances.serializer[name] = serializer - - return name -end - ---- Adds an element to the instance group under the correct category; must be registered --- @tparam string name the name of the instance group to add the element to --- @tparam LuaGuiElement element the element to add the the instance group -function Instances.add_element(name,element) - if not Instances.serializer[name] then - return error('Invalid name for instance group: '..name,2) - end - - if Instances.has_categories(name) then - local category = Instances.serializer[name](element) - if not Instances.data[name][category] then Instances.data[name][category] = {} end - table.insert(Instances.data[name][category],element) - else - table.insert(Instances.data[name],element) - end -end - ---- Gets all element instances without first removing any invalid ones; used internally and must be registered --- @tparam string name the name of the instance group to get the instances of --- @tparam[opt] string category the category to get the instance from, not needed when no serializer function --- @treturn table the table of element instances of which some may be invalid -function Instances.get_elements_raw(name,category) - if not Instances.serializer[name] then - return error('Invalid name for instance group: '..name,2) - end - - if Instances.has_categories(name) then - return Instances.data[name][category] or {} - else - return Instances.data[name] - end -end - ---- Gets all valid element instances and has the option of running a callback on those that are valid --- @tparam string name the name of the instance group to get the instances of --- @tparam[opt] string category the category to get the instances of, not needed when no serializer function --- @tparam[opt] function callback when given the callback will be ran on all valid elements --- callback param - element LuaGuiElement - the current valid element --- @treturn table the table of element instances with all invalid ones removed -function Instances.get_valid_elements(name,category,callback) - if not Instances.serializer[name] then - return error('Invalid name for instance group: '..name,2) - end - - category = category or callback - local elements = Instances.get_elements_raw(name,category) - local serializer = Instances.has_categories(name) - - for key,element in pairs(elements) do - if not element or not element.valid then - elements[key] = nil - else - if serializer and callback then callback(element) - elseif category then category(element) end - end - end - - return elements -end -Instances.get_elements = Instances.get_valid_elements -Instances.apply_to_elements = Instances.get_valid_elements - ---- A version of add_element that does not require the group to be registered --- @tparam string name the name of the instance group to add the element to --- @tparam ?string|nil category the category to add the element to, can be nil but must still be given --- @tparam LuaGuiElement element the element to add to the instance group -function Instances.unregistered_add_element(name,category,element) - if not Instances.data[name] then Instances.data[name] = {} end - if category then - if not Instances.data[name][category] then Instances.data[name][category] = {} end - table.insert(Instances.data[name][category],element) - else - table.insert(Instances.data[name],element) - end -end - ---- A version of get_elements that does not require the group to be registered --- @tparam string name the name of the instance group to get the instances of --- @tparam ?string|nil category the category to get the instances of, can be nil but must still be given --- @tparam[opt] function callback when given will be called on all valid instances --- callback param - element LuaGuiElement - the current valid element --- @treturn table the table of element instances with all invalid ones removed -function Instances.unregistered_get_elements(name,category,callback) - local elements = Instances.data[name] - if elements and category then - elements = elements[category] - end - - if not elements then return {} end - - for key,element in pairs(elements) do - if not element or not element.valid then - elements[key] = nil - else - if callback then callback(element) end - end - end - - return elements -end -Instances.unregistered_apply_to_elements = Instances.runtime_get_elements - -return Instances \ No newline at end of file diff --git a/expcore/gui/left_flow.lua b/expcore/gui/left_flow.lua new file mode 100644 index 00000000..4befce31 --- /dev/null +++ b/expcore/gui/left_flow.lua @@ -0,0 +1,243 @@ +--[[-- Core Module - Gui +- Used to define new gui elements and gui event handlers +@module Gui +]] + +local Gui = require 'expcore.gui.prototype' +local mod_gui = require 'mod-gui' + +local hide_left_flow = Gui.core_defines.hide_left_flow.name + +--- Left Flow. +-- @section leftFlow + +-- Triggered when a user changed the visibility of a left flow element by clicking a button +Gui.events.on_visibility_changed_by_click = 'on_visibility_changed_by_click' + +--- Contains the uids of the elements that will shown on the left flow and their join functions +-- @table left_elements +Gui.left_elements = {} + +--[[-- Gets the flow refered to as the left flow, each player has one left flow +@function Gui.get_left_flow(player) +@tparam LuaPlayer player the player that you want to get the left flow for +@treturn LuaGuiElement the left element flow + +@usage-- Geting your left flow +local left_flow = Gui.get_left_flow(game.player) + +]] +Gui.get_left_flow = mod_gui.get_frame_flow + +--[[-- Sets an element define to be drawn to the left flow when a player joins, includes optional check +@tparam[opt] ?boolean|function open_on_join called during first darw to decide if the element should be visible +@treturn table the new element define that is used to register events to this element + +@usage-- Adding the example button +example_flow_with_button:add_to_left_flow(true) + +]] +function Gui._prototype_element:add_to_left_flow(open_on_join) + Gui.left_elements[self.name] = open_on_join or false + return self +end + +--[[-- Creates a button on the top flow which will toggle the given element define, the define must exist in the left flow +@tparam string sprite the sprite that you want to use on the button +@tparam ?string|Concepts.LocalizedString tooltip the tooltip that you want the button to have +@tparam table element_define the element define that you want to have toggled by this button, define must exist on the left flow +@tparam[opt] function authenticator used to decide if the button should be visible to a player + +@usage-- Add a button to toggle a left element +local toolbar_button = +Gui.left_toolbar_button('entity/inserter', 'Nothing to see here', example_flow_with_button, function(player) + return player.admin +end) + +]] +function Gui.left_toolbar_button(sprite,tooltip,element_define,authenticator) + local button = Gui.toolbar_button(sprite,tooltip,authenticator) + + -- Add on_click handler to handle click events comming from the player + button:on_click(function(player,_,_) + local top_flow = Gui.get_top_flow(player) + local element = top_flow[button.name] + local visibility_state = Gui.toggle_left_element(player, element_define) + + -- Raise custom event that tells listening elements if the element has changed visibility by a player clicking + -- Used in warp gui to handle the keep open logic + button:raise_custom_event{ + name = Gui.events.on_visibility_changed_by_click, + element = element, + state = visibility_state + } + end) + + -- Add property to the left flow element with the name of the button + -- This is for the ability to reverse lookup the button from the left flow element + element_define.toolbar_button = button.name + return button +end + +--[[-- Draw all the left elements onto the left flow, internal use only with on join +@tparam LuaPlayer player the player that you want to draw the elements for + +@usage-- Draw all the left elements +Gui.draw_left_flow(player) + +]] +function Gui.draw_left_flow(player) + local left_flow = Gui.get_left_flow(player) + local hide_button = left_flow.gui_core_buttons[hide_left_flow] + local show_hide_button = false + + for name, open_on_join in pairs(Gui.left_elements) do + -- Draw the element to the left flow + local draw_success, left_element = pcall(function() + return Gui.defines[name](left_flow) + end) + + if not draw_success then + error('There as been an error with an element draw function:\n\t'..left_element) + end + + -- Check if it should be open by default + local visible = type(open_on_join) == 'boolean' and open_on_join or false + if type(open_on_join) == 'function' then + local success, err = pcall(open_on_join, player) + if not success then + error('There as been an error with an open on join hander for a gui element:\n\t'..err) + end + visible = err + end + + -- Set the visible state of the element + left_element.visible = visible + show_hide_button = show_hide_button or visible + + -- Get the assosiated element define + local element_define = Gui.defines[name] + local top_flow = Gui.get_top_flow(player) + + -- Check if the the element has a button attached + if element_define.toolbar_button then + -- Check if the topflow contains the button + local button = top_flow[element_define.toolbar_button] + if button then + -- Style the button + Gui.toolbar_button_style(button, visible) + end + end + end + + hide_button.visible = show_hide_button +end + +--[[-- Update the visible state of the hide button, can be used to check if any frames are visible +@tparam LuaPlayer player the player to update the left flow for +@treturn boolean true if any left element is visible + +@usage-- Check if any left elements are visible +local visible = Gui.update_left_flow(player) + +]] +function Gui.update_left_flow(player) + local left_flow = Gui.get_left_flow(player) + local hide_button = left_flow.gui_core_buttons[hide_left_flow] + for name, _ in pairs(Gui.left_elements) do + local left_element = left_flow[name] + if left_element.visible then + hide_button.visible = true + return true + end + end + hide_button.visible = false + return false +end + +--[[-- Hides all left elements for a player +@tparam LuaPlayer player the player to hide the elements for + +@usage-- Hide your left elements +Gui.hide_left_flow(game.player) + +]] +function Gui.hide_left_flow(player) + local top_flow = Gui.get_top_flow(player) + local left_flow = Gui.get_left_flow(player) + local hide_button = left_flow.gui_core_buttons[hide_left_flow] + + -- Set the visible state of all elements in the flow + hide_button.visible = false + for name,_ in pairs(Gui.left_elements) do + left_flow[name].visible = false + + -- Check if the the element has a toobar button attached + local element_define = Gui.defines[name] + if element_define.toolbar_button then + -- Check if the topflow contains the button + local button = top_flow[element_define.toolbar_button] + if button then + -- Style the button + Gui.toolbar_button_style(button, false) + -- Get the button define from the reverse lookup on the element + local button_define = Gui.defines[element_define.toolbar_button] + -- Raise the custom event if all of the top checks have passed + button_define:raise_custom_event{ + name = Gui.events.on_visibility_changed_by_click, + element = button, + state = false + } + end + end + end +end + +--[[-- Get the element define that is in the left flow, use in events without an element refrence +@tparam LuaPlayer player the player that you want to get the element for +@tparam table element_define the element that you want to get +@treturn LuaGuiElement the gui element linked to this define for this player + +@usage-- Get your left element +local frame = Gui.get_left_element(game.player, example_flow_with_button) + +]] +function Gui.get_left_element(player,element_define) + local left_flow = Gui.get_left_flow(player) + return left_flow[element_define.name] +end + +--[[-- Toggles the visible state of a left element for a given player, can be used to set the visible state +@tparam LuaPlayer player the player that you want to toggle the element for +@tparam table element_define the element that you want to toggle +@tparam[opt] boolean state with given will set the state, else state will be toggled +@treturn boolean the new visible state of the element + +@usage-- Toggle your example button +Gui.toggle_top_flow(game.player, example_flow_with_button) + +@usage-- Show your example button +Gui.toggle_top_flow(game.player, example_flow_with_button, true) + +]] +function Gui.toggle_left_element(player,element_define,state) + local left_flow = Gui.get_left_flow(player) + local top_flow = Gui.get_top_flow(player) + + -- Set the visible state + local element = left_flow[element_define.name] + if state == nil then state = not element.visible end + element.visible = state + Gui.update_left_flow(player) + + -- Check if the the element has a button attached + if element_define.toolbar_button then + -- Check if the topflow contains the button + local button = top_flow[element_define.toolbar_button] + if button then + -- Style the button + Gui.toolbar_button_style(button, state) + end + end + return state +end \ No newline at end of file diff --git a/expcore/gui/prototype.lua b/expcore/gui/prototype.lua index 790375aa..f7803602 100644 --- a/expcore/gui/prototype.lua +++ b/expcore/gui/prototype.lua @@ -1,300 +1,325 @@ --[[-- Core Module - Gui - @module Gui - @alias Prototype +- Used to simplify gui creation using factory functions called element defines +@module Gui ]] ---- Prototype. --- Used to create new gui prototypes see elements and concepts --- @section prototype +local Event = require 'utils.event' --- @dep utils.event ---[[ - >>>> 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 +local Gui = { + --- The current highest uid that is being used by a define, will not increase during runtime + uid = 0, + --- String indexed table used to avoid conflict with custom event names, similar to how defines.events works + events = {}, + --- Uid indexed array that stores all the factory functions that were defined, no new values will be added during runtime + defines = {}, + --- An string indexed table of all the defines which are used by the core of the gui system, used for internal refrence + core_defines = {}, + --- Used to store the file names where elements were defined, this can be useful to find the uid of an element, mostly for debuging + file_paths = {}, + --- Used to store extra infomation about elements as they get defined such as the params used and event handlers registered to them + debug_info = {}, + --- The prototype used to store the functions of an element define + _prototype_element = {}, + --- The prototype metatable applied to new element defines + _mt_element = { + __call = function(self,parent,...) + local element = self._draw(self.name,parent,...) + if self._style then self._style(element.style,element,...) end + return element + end + } +} - 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_embedded_flow(state) --- Sets the element to be drawn inside a nameless flow, can be given a name using a function +Gui._mt_element.__index = Gui._prototype_element - 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 +--- Element Define. +-- @section elementDefine - 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 +--[[-- Used to define new elements for your gui, can be used like LuaGuiElement.add or a custom function +@tparam ?table|function element_define the define information for the gui element, same data as LuaGuiElement.add, or a custom function may be used +@treturn table the new element define, this can be considered a factory for the element which can be called to draw the element to any other element + +@usage-- Using element defines like LuaGuiElement.add +-- This returns a factory function to draw a button with the caption "Example Button" +local example_button = +Gui.element{ + type = 'button', + caption = 'Example Button' +} + +@usage-- Using element defines with a custom factory function +-- This method can be used if you still want to be able register event handlers but it is too complex to be compatible with LuaGuiElement.add +local example_flow_with_button = +Gui.element(function(event_trigger,parent,...) + -- ... shows that all other arguments from the factory call are passed to this function + -- parent is the element which was passed to the factory function where you should add your new element + -- here we are adding a flow which we will then later add a button to + local flow = + parent.add{ + name = 'example_flow', + type = 'flow' + } + + -- event_trigger should be the name of any elements you want to trigger your event handlers, such as on_click or on_state_changed + -- now we add the button to the flow that we created earlier + local element = + flow.add{ + name = event_trigger, + type = 'button', + caption = 'Example Button' + } + + -- you must return your new element, this is so styles can be applied and returned to the caller + -- you may return any of your elements that you add, consider the context in which it will be used for what should be returned + return element +end) - Prototype:get_store(category) --- Gets the value in this elements store, category needed if serializer function used - Prototype:set_store(category,value) --- Sets the value in this elements store, category needed if serializer function used - Prototype:clear_store(category) --- Sets the value in this elements store to nil, category needed if serializer function used ]] -local Game = require 'utils.game' --- @dep utils.game -local Store = require 'expcore.store' --- @dep expcore.store -local Instances = require 'expcore.gui.instances' --- @dep expcore.gui.instances +function Gui.element(element_define) + -- Set the metatable to allow access to register events + local element = setmetatable({}, Gui._mt_element) -local Constructor = {} -local Prototype = {} + -- Increment the uid counter + local uid = Gui.uid + 1 + Gui.uid = uid + local name = tostring(uid) + element.name = name + Gui.debug_info[name] = { draw = 'None', style = 'None', events = {} } ---- 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) + -- Add the defination function + if type(element_define) == 'table' then + Gui.debug_info[name].draw = element_define + element_define.name = name + element._draw = function(_,parent) + return parent.add(element_define) 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 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(callback) - --- Adds a store for the define that is shared between all instances of the define in the same category, serializer is a function that returns a string - -- @tparam self table the gui define being acted on - -- @tparam[opt] function serializer function used to determine the category of a LuaGuiElement, when omitted all share one single category - -- serializer param - LuaGuiElement element - the element that needs to be converted - -- serializer return - string - a deterministic string that references to a category such as player name or force name - -- @treturn self the element define to allow chaining - return function(self,serializer) - if self.store then return end - serializer = serializer or function() return '' end - - self.store = Store.register(serializer) - - Instances.register(self.name,serializer) - - Store.watch(self.store,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 v_type = type(value) - if v_type ~= value_type and (not locale or v_type ~= '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] function callback 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 ?boolean|function state when true a padless flow is created to contain the element --- @treturn self the element define to allow chaining -function Prototype:set_embedded_flow(state) - if state == false or type(state) == 'function' then - self.embedded_flow = state else - self.embedded_flow = true + Gui.debug_info[name].draw = 'Function' + element._draw = element_define + end + + -- Add the define to the base module + local file_path = debug.getinfo(2, 'S').source:match('^.+/currently%-playing/(.+)$'):sub(1, -5) + Gui.file_paths[name] = file_path + Gui.defines[name] = element + + -- Return the element so event handers can be accessed + return element +end + +--[[-- Used to extent your element define with a style factory, this style will be applied to your element when created, can also be a custom function +@tparam ?table|function style_define style table where each key and value pair is treated like LuaGuiElement.style[key] = value, a custom function can be used +@treturn table the element define is returned to allow for event handlers to be registered + +@usage-- Using the table method of setting the style +local example_button = +Gui.element{ + type = 'button', + caption = 'Example Button', + style = 'forward_button' -- factorio styles can be applied here +} +:style{ + height = 25, -- same as element.style.height = 25 + width = 100 -- same as element.style.width = 25 +} + +@usage-- Using the function method to set the style +-- Use this method if your style is dynamic and depends on other factors +local example_button = +Gui.element{ + type = 'button', + caption = 'Example Button', + style = 'forward_button' -- factorio styles can be applied here +} +:style(function(style,element,...) + -- style is the current style object for the elemenent + -- element is the element that is being changed + -- ... shows that all other arguments from the factory call are passed to this function + local player = game.players[element.player_index] + style.height = 25 + style.width = 100 + style.font_color = player.color +end) + +]] +function Gui._prototype_element:style(style_define) + -- Add the defination function + if type(style_define) == 'table' then + Gui.debug_info[self.name].style = style_define + self._style = function(style) + for key,value in pairs(style_define) do + style[key] = value + end + end + else + Gui.debug_info[self.name].style = 'Function' + self._style = style_define + end + + -- Return the element so event handers can be accessed + return self +end + +--[[-- Set the handler which will be called for a custom event, only one handler can be used per event per element +@tparam string event_name the name of the event you want to handler to be called on, often from Gui.events +@tparam function handler the handler that you want to be called when the event is raised +@treturn table the element define so more handleres can be registered + +@usage-- Register a handler to "my_custom_event" for this element +element_deinfe:on_custom_event('my_custom_event', function(event) + event.player.print(player.name) +end) + +]] +function Gui._prototype_element:on_custom_event(event_name,handler) + table.insert(Gui.debug_info[self.name].events,event_name) + Gui.events[event_name] = event_name + self[event_name] = handler + return self +end + +--[[-- Raise the handler which is attached to an event; external use should be limited to custom events +@tparam table event the event table passed to the handler, must contain fields: name, element +@treturn table the element define so more events can be raised + +@usage Raising a custom event +element_define:raise_custom_event{ + name = 'my_custom_event', + element = element +} + +]] +function Gui._prototype_element:raise_custom_event(event) + -- Check the element is valid + local element = event.element + if not element or not element.valid then + return self + end + + -- Get the event handler for this element + local handler = self[event.name] + if not handler then + return self + end + + -- Get the player for this event + local player_index = event.player_index or element.player_index + local player = game.players[player_index] + if not player or not player.valid then + return self + end + event.player = player + + local success, err = pcall(handler,player,element,event) + if not success then + error('There as been an error with an event handler for a gui element:\n\t'..err) 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 +-- This function is used to link element define events and the events from the factorio api +local function event_handler_factory(event_name) + Event.add(event_name, function(event) + local element = event.element + if not element or not element.valid then return end + local element_define = Gui.defines[element.name] + if not element_define then return end + element_define:raise_custom_event(event) + end) + + return function(self,handler) + table.insert(Gui.debug_info[self.name].events,debug.getinfo(1, "n").name) + self[event_name] = handler + return self 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) +--- Element Events. +-- @section elementEvents - if self.pre_authenticator then - if not self.pre_authenticator(player,self.name) then return end - end +--- Called when the player opens a GUI. +-- @tparam function handler the event handler which will be called +-- @usage element_define:on_open(function(event) +-- event.player.print(table.inspect(event)) +--end) +Gui._prototype_element.on_open = event_handler_factory(defines.events.on_gui_opened) - if self.embedded_flow then - local embedded_name - if type(self.embedded_flow) == 'function' then - embedded_name = self.embedded_flow(element,...) - end - element = element.add{type='flow',name=embedded_name} - element.style.padding = 0 - end +--- Called when the player closes the GUI they have open. +-- @tparam function handler the event handler which will be called +-- @usage element_define:on_close(function(event) +-- event.player.print(table.inspect(event)) +--end) +Gui._prototype_element.on_close = event_handler_factory(defines.events.on_gui_closed) - local new_element = element.add(self.draw_data) +--- Called when LuaGuiElement is clicked. +-- @tparam function handler the event handler which will be called +-- @usage element_define:on_click(function(event) +-- event.player.print(table.inspect(event)) +--end) +Gui._prototype_element.on_click = event_handler_factory(defines.events.on_gui_click) - self:raise_event('on_style_update',new_element.style) +--- Called when a LuaGuiElement is confirmed, for example by pressing Enter in a textfield. +-- @tparam function handler the event handler which will be called +-- @usage element_define:on_confirmed(function(event) +-- event.player.print(table.inspect(event)) +--end) +Gui._prototype_element.on_confirmed = event_handler_factory(defines.events.on_gui_confirmed) - if self.post_authenticator then - new_element.enabled = self.post_authenticator(player,self.name) - end +--- Called when LuaGuiElement checked state is changed (related to checkboxes and radio buttons). +-- @tparam function handler the event handler which will be called +-- @usage element_define:on_checked_changed(function(event) +-- event.player.print(table.inspect(event)) +--end) +Gui._prototype_element.on_checked_changed = event_handler_factory(defines.events.on_gui_checked_state_changed) - if Instances.is_registered(self.name) then - Instances.add_element(self.name,new_element) - end +--- Called when LuaGuiElement element value is changed (related to choose element buttons). +-- @tparam function handler the event handler which will be called +-- @usage element_define:on_elem_changed(function(event) +-- event.player.print(table.inspect(event)) +--end) +Gui._prototype_element.on_elem_changed = event_handler_factory(defines.events.on_gui_elem_changed) - self:raise_event('on_draw',player,new_element,...) +--- Called when LuaGuiElement element location is changed (related to frames in player.gui.screen). +-- @tparam function handler the event handler which will be called +-- @usage element_define:on_location_changed(function(event) +-- event.player.print(table.inspect(event)) +--end) +Gui._prototype_element.on_location_changed = event_handler_factory(defines.events.on_gui_location_changed) - return new_element -end +--- Called when LuaGuiElement selected tab is changed (related to tabbed-panes). +-- @tparam function handler the event handler which will be called +-- @usage element_define:on_tab_changed(function(event) +-- event.player.print(table.inspect(event)) +--end) +Gui._prototype_element.on_tab_changed = event_handler_factory(defines.events.on_gui_selected_tab_changed) ---- Gets the value in this elements store, category needed if serializer 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 +--- Called when LuaGuiElement selection state is changed (related to drop-downs and listboxes). +-- @tparam function handler the event handler which will be called +-- @usage element_define:on_selection_changed(function(event) +-- event.player.print(table.inspect(event)) +--end) +Gui._prototype_element.on_selection_changed = event_handler_factory(defines.events.on_gui_selection_state_changed) ---- Sets the value in this elements store, category needed if serializer 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 +--- Called when LuaGuiElement switch state is changed (related to switches). +-- @tparam function handler the event handler which will be called +-- @usage element_define:on_switch_changed(function(event) +-- event.player.print(table.inspect(event)) +--end) +Gui._prototype_element.on_switch_changed = event_handler_factory(defines.events.on_gui_switch_state_changed) ---- Sets the value in this elements store to nil, category needed if serializer 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 +--- Called when LuaGuiElement text is changed by the player. +-- @tparam function handler the event handler which will be called +-- @usage element_define:on_text_changed(function(event) +-- event.player.print(table.inspect(event)) +--end) +Gui._prototype_element.on_text_changed = event_handler_factory(defines.events.on_gui_text_changed) -return Constructor \ No newline at end of file +--- Called when LuaGuiElement slider value is changed (related to the slider element). +-- @tparam function handler the event handler which will be called +-- @usage element_define:on_value_changed(function(event) +-- event.player.print(table.inspect(event)) +--end) +Gui._prototype_element.on_value_changed = event_handler_factory(defines.events.on_gui_value_changed) + +-- Module return +return Gui diff --git a/expcore/gui/test.lua b/expcore/gui/test.lua deleted file mode 100644 index 37cc54f8..00000000 --- a/expcore/gui/test.lua +++ /dev/null @@ -1,663 +0,0 @@ ---[[-- Core Module - Gui - @module Gui - @alias tests -]] - ---- Test. --- This file creates a test gui that is used to test every input method --- note that this does not cover every permutation only features in independence --- for example store in most cases is just by player name, but other store methods are tested with checkbox --- @section test - -local Gui = require 'expcore.gui' --- @dep expcore.gui -local format_chat_colour,table_keys = ext_require('expcore.common','format_chat_colour','table_keys') --- @dep expcore.common -local Colors = require 'resources.color_presets' --- @dep resources.color_presets -local Event = require 'utils.event' --- @dep utils.event -local Store = require 'expcore.store' --- @dep expcore.store - -local tests = {} - ---[[ - Toolbar Tests - > No display - Toolbar button with no display - > With caption - Toolbar button with a caption display - > With icons - Toolbar button with an icon -]] - -Gui.new_toolbar_button('click-1') -:set_post_authenticator(function(player,button_name) - return global.click_one -end) -:on_click(function(player,element) - player.print('CLICK 1') -end) - -Gui.new_toolbar_button('click-2') -:set_caption('Click Two') -:set_post_authenticator(function(player,button_name) - return global.click_two -end) -:on_click(function(player,element) - player.print('CLICK 2') -end) - -Gui.new_toolbar_button('click-3') -:set_sprites('utility/questionmark') -:set_post_authenticator(function(player,button_name) - return global.click_three -end) -:on_click(function(player,element) - player.print('CLICK 3') -end) - ---[[ - Center Frame Tests - > Main test gui - Main test gui triggers all other tests -]] - -local test_gui = -Gui.new_center_frame('gui-test-open') -:set_caption('Open Test Gui') -:set_tooltip('Main test gui triggers all other tests') -:set_post_authenticator(function(player,button_name) - return global.show_test_gui -end) - -: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)) - - local pass_count = 0 - local test_count = 0 - - local flow = frame.add{ - type='flow', - name=test_group_name, - direction='vertical' - } - - for test_name,test in pairs(test_group) do - local test_function = type(test) == 'function' and test or test.draw_to - test_count = test_count+1 - - local success,err = pcall(test_function,test,flow) - if success then - pass_count = pass_count+1 - else - player.print('Failed Test: '..format_chat_colour(test_name,Colors.red)) - log('Gui Test Failed: '..test_name..' stacktrace:\n'..err) - end - - end - - if pass_count == test_count then - player.print('All tests '..format_chat_colour('passed',Colors.green)..' ('..test_group_name..')') - else - player.print('Passed '..format_chat_colour(pass_count..'/'..test_count,Colors.cyan)..' ('..test_group_name..')') - end - - end -end) - ---[[ - Left Frame Test - > Left frame which holds all online player names, updates when player leaves or joins -]] - -local left_frame = -Gui.new_left_frame('test-left-frame') -:set_caption('Test Left Gui') -:set_tooltip('Left frame which holds all online player names, updates when player leaves or joins') -:set_post_authenticator(function(player,button_name) - return global.show_test_gui -end) - -:set_open_by_default() -:on_creation(function(_player,frame) - for _,player in pairs(game.connected_players) do - frame.add{ - type='label', - caption=player.name - } - end -end) - -Event.add(defines.events.on_player_joined_game,left_frame 'update_all') -Event.add(defines.events.on_player_left_game,left_frame 'update_all') - ---[[ - Popup Test - > Allows opening a popup which contains the players name and tick it was opened -]] - -local test_popup = -Gui.new_popup('test-popup') -:on_creation(function(player,frame) - frame.add{ - type='label', - caption=player.name - } - frame.add{ - type='label', - caption=game.tick - } -end) - -Gui.new_toolbar_button('test-popup-open') -:set_caption('Test Popup') -:set_tooltip('Allows opening a popup which contains the players name and tick it was opened') -:set_post_authenticator(function(player,button_name) - return global.show_test_gui -end) -:on_click(function(player,element) - test_popup(player,300) -end) - ---[[ - Button Tests - > No display - Simple button which has no display - > Caption - Simple button but has a caption on it - > Icons - Button with an icon display plus two icons for hover and select - > Auth - Button which can only be passed when auth is true (press no display to toggle; needs reopen) -]] - -local button_no_display = -Gui.new_button('test-button-no-display') -:set_tooltip('Button no display') -:on_click(function(player,element) - player.print('Button no display') - global.test_auth_button = not global.test_auth_button - player.print('Auth Button auth state: '..tostring(global.test_auth_button)) -end) - -local button_with_caption = -Gui.new_button('test-button-with-caption') -:set_tooltip('Button with caption') -:set_caption('Button Caption') -:on_click(function(player,element) - player.print('Button with caption') -end) - -local button_with_icon = -Gui.new_button('test-button-with-icon') -:set_tooltip('Button with icons') -:set_sprites('utility/warning_icon','utility/warning','utility/warning_white') -:on_click(function(player,element) - player.print('Button with icons') -end) - -local button_with_auth = -Gui.new_button('test-button-with-auth') -:set_tooltip('Button with auth') -:set_post_authenticator(function(player,button_name) - return global.test_auth_button -end) -:on_click(function(player,element) - player.print('Button with auth') -end) - -tests.Buttons = { - ['No display']=button_no_display, - ['Caption']=button_with_caption, - ['Icons']=button_with_icon, - ['Auth']=button_with_auth -} - ---[[ - Checkbox Test - > Local -- Simple checkbox that can toggle - > Game store -- Checkbox which syncs its state between all players - > Force store -- Checkbox which syncs its state with all players on the same force - > Player store -- Checkbox that stores its state between re-draws -]] - -local checkbox_local = -Gui.new_checkbox('test-checkbox-local') -:set_tooltip('Checkbox local') -:set_caption('Checkbox Local') -:on_element_update(function(player,element,state) - player.print('Checkbox local: '..tostring(state)) -end) - -local checkbox_game = -Gui.new_checkbox('test-checkbox-store-game') -:set_tooltip('Checkbox store game') -:set_caption('Checkbox Store Game') -:add_store() -:on_element_update(function(player,element,state) - player.print('Checkbox store game: '..tostring(state)) -end) - -local checkbox_force = -Gui.new_checkbox('test-checkbox-store-force') -:set_tooltip('Checkbox store force') -:set_caption('Checkbox Store Force') -:add_store(Gui.categorize_by_force) -:on_element_update(function(player,element,state) - player.print('Checkbox store force: '..tostring(state)) -end) - -local checkbox_player = -Gui.new_checkbox('test-checkbox-store-player') -:set_tooltip('Checkbox store player') -:set_caption('Checkbox Store Player') -:add_store(Gui.categorize_by_player) -:on_element_update(function(player,element,state) - player.print('Checkbox store player: '..tostring(state)) -end) - -tests.Checkboxes = { - ['Local']=checkbox_local, - ['Game store']=checkbox_game, - ['Force store']=checkbox_force, - ['Player store']=checkbox_player -} - ---[[ - Radiobutton Tests - > Local -- Simple radiobutton that can only be toggled true - > Player store -- Radio button that saves its state between re-draws - > Option set -- A set of radio buttons where only one can be true at a time -]] - -local radiobutton_local = -Gui.new_radiobutton('test-radiobutton-local') -:set_tooltip('Radiobutton local') -:set_caption('Radiobutton Local') -:on_element_update(function(player,element,state) - player.print('Radiobutton local: '..tostring(state)) -end) - -local radiobutton_player = -Gui.new_radiobutton('test-radiobutton-store') -:set_tooltip('Radiobutton store') -:set_caption('Radiobutton Store') -:add_store(Gui.categorize_by_player) -:on_element_update(function(player,element,state) - player.print('Radiobutton store: '..tostring(state)) -end) - -local radiobutton_option_set = -Gui.new_radiobutton_option_set(function(value,category) - game.print('Radiobutton option set for: '..category..' is now: '..tostring(value)) -end,Gui.categorize_by_player) - -local radiobutton_option_one = -Gui.new_radiobutton('test-radiobutton-option-one') -:set_tooltip('Radiobutton option set') -:set_caption('Radiobutton Option One') -:add_as_option(radiobutton_option_set,'One') -:on_element_update(function(player,element,state) - player.print('Radiobutton option one: '..tostring(state)) -end) - -local radiobutton_option_two = -Gui.new_radiobutton('test-radiobutton-option-two') -:set_tooltip('Radiobutton option set') -:set_caption('Radiobutton Option Two') -:add_as_option(radiobutton_option_set,'Two') -:on_element_update(function(player,element,state) - player.print('Radiobutton option two: '..tostring(state)) -end) - -local radiobutton_option_three = -Gui.new_radiobutton('test-radiobutton-option-three') -:set_tooltip('Radiobutton option set') -:set_caption('Radiobutton Option Three') -:add_as_option(radiobutton_option_set,'Three') -:on_element_update(function(player,element,state) - player.print('Radiobutton option three: '..tostring(state)) -end) - -tests.Radiobuttons = { - ['Local']=radiobutton_local, - ['Player store']=radiobutton_player, - ['Option set']=function(self,frame) - Gui.draw_option_set(radiobutton_option_set,frame) - end -} - ---[[ - Dropdown Test - > Local static general -- Simple dropdown with all static options and general handler - > Player startic general -- Dropdown with all static options and general handler and stores option between re-draws - > Local static case -- Dropdown with all static options but case handlers and a general handler - > Player static case -- Dropdown with all static options but case handlers and a general handler and stores option between re-draws - > Local dynamic -- Dropdown with one static option with the reset generated by a function - > Player dynamic -- Dropdown with one static option with the reset generated by a function and stores option between re-draws -]] - -local dropdown_local_static_general = -Gui.new_dropdown('test-dropdown-local-static-general') -:set_tooltip('Dropdown local static general') -:add_options('One','Two','Three','Four') -:on_element_update(function(player,element,value) - player.print('Dropdown local static general: '..tostring(value)) -end) - -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.categorize_by_player) -:on_element_update(function(player,element,value) - player.print('Dropdown store static general: '..tostring(value)) -end) - -local function print_option_selected_1(player,element,value) - player.print('Dropdown local static case (case): '..tostring(value)) -end - -local dropdown_local_static_case = -Gui.new_dropdown('test-dropdown-local-static-case') -:set_tooltip('Dropdown local static case') -:add_options('One','Two') -:add_option_callback('One',print_option_selected_1) -:add_option_callback('Two',print_option_selected_1) -:add_option_callback('Three',print_option_selected_1) -:add_option_callback('Four',print_option_selected_1) -:on_element_update(function(player,element,value) - player.print('Dropdown local static case (general): '..tostring(value)) -end) - -local function print_option_selected_2(player,element,value) - player.print('Dropdown store static case (case): '..tostring(value)) -end - -local dropdown_player_static_case = -Gui.new_dropdown('test-dropdown-store-static-case') -:set_tooltip('Dropdown store static case') -: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) -:add_option_callback('Three',print_option_selected_2) -:add_option_callback('Four',print_option_selected_2) -:on_element_update(function(player,element,value) - player.print('Dropdown store static case (general): '..tostring(value)) -end) - -local dropdown_local_dynamic = -Gui.new_dropdown('test-dropdown-local-dynamic') -:set_tooltip('Dropdown local dynamic') -:add_options('Static') -:add_dynamic(function(player,element) - return table_keys(Colors) -end) -:on_element_update(function(player,element,value) - player.print('Dropdown local dynamic: '..tostring(value)) -end) - -local dropdown_player_dynamic = -Gui.new_dropdown('test-dropdown-store-dynamic') -:set_tooltip('Dropdown store dynamic') -:add_options('Static') -:add_dynamic(function(player,element) - return table_keys(Colors) -end) -:add_store(Gui.categorize_by_player) -:on_element_update(function(player,element,value) - player.print('Dropdown store dynamic: '..tostring(value)) -end) - -tests.Dropdowns = { - ['Local static general']=dropdown_local_static_general, - ['Player startic general']=dropdown_player_static_general, - ['Local static case']=dropdown_local_static_case, - ['Player static case']=dropdown_player_static_case, - ['Local dynamic general']=dropdown_local_dynamic, - ['Player dynamic general']=dropdown_player_dynamic -} - ---[[ - List Box Tests - > Local -- A list box with all static options and general handler - > Store -- A list box with all static options and general handler and stores options between re-draws -]] - -local list_box_local = -Gui.new_list_box('test-list-box-local') -:set_tooltip('List box local') -:add_options('One','Two','Three','Four') -:on_element_update(function(player,element,value) - player.print('Dropdown local: '..tostring(value)) -end) - -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.categorize_by_player) -:on_element_update(function(player,element,value) - player.print('Dropdown store: '..tostring(value)) -end) - -tests["List Boxes"] = { - ['Local']=list_box_local, - ['Player']=list_box_player -} - ---[[ - Slider Tests - > Local default -- Simple slider with default range - > 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 - > Local label -- Simple slider with default range which has a label - > Store label -- Slider with default range which has a label and stores value between re-draws -]] - -local slider_local_default = -Gui.new_slider('test-slider-local-default') -:set_tooltip('Slider local default') -:on_element_update(function(player,element,value,percent) - player.print('Slider local default: '..tostring(math.round(value))..' '..tostring(math.round(percent,1))) -end) - - -local slider_player_default = -Gui.new_slider('test-slider-store-default') -:set_tooltip('Slider store default') -: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) - -local slider_static = -Gui.new_slider('test-slider-static-range') -:set_tooltip('Slider static range') -:set_range(5,50) -:on_element_update(function(player,element,value,percent) - player.print('Slider static range: '..tostring(math.round(value))..' '..tostring(math.round(percent,1))) -end) - -local slider_dynamic = -Gui.new_slider('test-slider-dynamic-range') -:set_tooltip('Slider dynamic range') -:set_range(function(player,element) - return player.index - 5 -end,function(player,element) - return player.index + 4 -end) -:on_element_update(function(player,element,value,percent) - player.print('Slider dynamic range: '..tostring(math.round(value))..' '..tostring(math.round(percent,1))) -end) - -local label_slider_local = -Gui.new_slider('test-slider-local-label') -:set_tooltip('Slider local label') -:enable_auto_draw_label() -:on_element_update(function(player,element,value,percent) - player.print('Slider local label: '..tostring(math.round(value))..' '..tostring(math.round(percent,1))) -end) - -local label_slider_player = -Gui.new_slider('test-slider-store-label') -:set_tooltip('Slider store label') -:enable_auto_draw_label() -: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, - ['Player default']=slider_player_default, - ['Static range']=slider_static, - ['Dynamic range']=slider_dynamic, - ['Local label']=function(self,frame) - local flow = frame.add{type='flow'} - label_slider_local:draw_to(flow) - end, - ['Player label']=function(self,frame) - local flow = frame.add{type='flow'} - label_slider_player:draw_to(flow) - end -} - ---[[ - Text Tests - > Local field -- Simple text field - > Store field -- Test field that stores text between re-draws - > Local box -- Simple text box - > Wrap box -- Text box which has word wrap and selection disabled -]] - -local text_filed_local = -Gui.new_text_filed('test-text-field-local') -:set_tooltip('Text field local') -:on_element_update(function(player,element,value) - player.print('Text field local: '..value) -end) - -local text_filed_store = -Gui.new_text_filed('test-text-field-store') -:set_tooltip('Text field store') -:add_store(Gui.categorize_by_player) -:on_element_update(function(player,element,value) - player.print('Text field store: '..value) -end) - -local text_box_local = -Gui.new_text_box('test-text-box-local') -:set_tooltip('Text box local') -:on_element_update(function(player,element,value) - player.print('Text box local: '..value) -end) - -local text_box_wrap = -Gui.new_text_box('test-text-box-wrap') -:set_tooltip('Text box wrap') -:set_selectable(false) -:set_word_wrap() -:on_element_update(function(player,element,value) - player.print('Text box wrap: '..value) -end) - -tests.Texts = { - ['Local field']=text_filed_local, - ['Store field']=text_filed_store, - ['Local box']=text_box_local, - ['Wrap box']=text_box_wrap -} - ---[[ - Elem Button Tests - > Local -- Simple elem button - > Default -- Simple elem button which has a default value - > Function -- Elem button which has a dynamic default - > Store -- Elem button which stores its value between re-draws -]] - -local elem_local = -Gui.new_elem_button('test-elem-local') -:set_tooltip('Elem') -:set_type('item') -:on_element_update(function(player,element,value) - player.print('Elem: '..value) -end) - -local elem_default = -Gui.new_elem_button('test-elem-default') -:set_tooltip('Elem default') -:set_type('item') -:set_default('iron-plate') -:on_element_update(function(player,element,value) - player.print('Elem default: '..value) -end) - -local elem_function = -Gui.new_elem_button('test-elem-function') -:set_tooltip('Elem function') -:set_type('item') -:set_default(function(player,element) - return 'iron-plate' -end) -:on_element_update(function(player,element,value) - player.print('Elem function: '..value) -end) - -local elem_store = -Gui.new_elem_button('test-elem-store') -:set_tooltip('Elem store') -:set_type('item') -:add_store(Gui.categorize_by_player) -:on_element_update(function(player,element,value) - player.print('Elem store: '..value) -end) - -tests["Elem Buttons"] = { - ['Local']=elem_local, - ['Default']=elem_default, - ['Function']=elem_function, - ['Store']=elem_store -} - ---[[ - Progress bar tests - > Simple -- Progress bar that fills every 2 seconds - > Store -- Progress bar that fills every 5 seconds with synced value - > Reverse -- Progress bar that decreases every 2 seconds -]] - -local progressbar_one = -Gui.new_progressbar('test-prog-one') -:set_default_maximum(120) -:on_complete(function(player,element,reset_element) - reset_element() -end) - -local progressbar_two = -Gui.new_progressbar('test-prog-one') -:set_default_maximum(300) -:add_store(Gui.categorize_by_force) -:on_complete(function(player,element,reset_element) - reset_element() -end) -:on_store_complete(function(category,reset_store) - reset_store() -end) - -local progressbar_three = -Gui.new_progressbar('test-prog-one') -:set_default_maximum(120) -:use_count_down() -:on_complete(function(player,element,reset_element) - reset_element() -end) - -Event.add(defines.events.on_tick,function() - progressbar_one:increment() - progressbar_three:decrement() - local categories = Store.get(progressbar_two.store) or {} - for category,_ in pairs(categories) do - progressbar_two:increment(1,category) - end -end) - -tests["Progress Bars"] = { - ['Simple']=progressbar_one, - ['Store']=progressbar_two, - ['Reverse']=progressbar_three -} \ No newline at end of file diff --git a/expcore/gui/top_flow.lua b/expcore/gui/top_flow.lua new file mode 100644 index 00000000..1f50fc47 --- /dev/null +++ b/expcore/gui/top_flow.lua @@ -0,0 +1,167 @@ +--[[-- Core Module - Gui +- Controls the elements on the top flow +@module Gui +]] + +local Gui = require 'expcore.gui.prototype' +local mod_gui = require 'mod-gui' --- @dep mod-gui + +local hide_top_flow = Gui.core_defines.hide_top_flow.name +local show_top_flow = Gui.core_defines.show_top_flow.name + +--- Top Flow. +-- @section topFlow + +--- Contains the uids of the elements that will shown on the top flow and their auth functions +-- @table top_elements +Gui.top_elements = {} + +--- The style that should be used for buttons on the top flow +-- @field Gui.top_flow_button_style +Gui.top_flow_button_style = mod_gui.button_style + +--- The style that should be used for buttons on the top flow when their flow is visible +-- @field Gui.top_flow_button_visible_style +Gui.top_flow_button_visible_style = 'menu_button_continue' + +--[[-- Gets the flow refered to as the top flow, each player has one top flow +@function Gui.get_top_flow(player) +@tparam LuaPlayer player the player that you want to get the flow for +@treturn LuaGuiElement the top element flow + +@usage-- Geting your top flow +local top_flow = Gui.get_top_flow(game.player) + +]] +Gui.get_top_flow = mod_gui.get_button_flow + +--[[-- Sets an element define to be drawn to the top flow when a player joins, includes optional authenticator +@tparam[opt] function authenticator called during toggle or update to decide weather the element should be visible +@treturn table the new element define to allow event handlers to be registered + +@usage-- Adding an element to the top flow on join +example_button:add_to_top_flow(function(player) + -- example button will only be shown if the player is an admin + -- note button will not update its state when player.admin is changed Gui.update_top_flow must be called for this + return player.admin +end) + +]] +function Gui._prototype_element:add_to_top_flow(authenticator) + Gui.top_elements[self.name] = authenticator or true + return self +end + +--[[-- Updates the visible state of all the elements on the players top flow, uses authenticator +@tparam LuaPlayer player the player that you want to update the top flow for + +@usage-- Update your top flow +Gui.update_top_flow(game.player) + +]] +function Gui.update_top_flow(player) + local top_flow = Gui.get_top_flow(player) + local hide_button = top_flow[hide_top_flow] + local is_visible = hide_button.visible + + -- Set the visible state of all elements in the flow + for name, authenticator in pairs(Gui.top_elements) do + -- Ensure the element exists + local element = top_flow[name] + if not element then + element = Gui.defines[name](top_flow) + end + + -- Set the visible state + element.visible = is_visible and authenticator(player) or false + end +end + +--[[-- Toggles the visible state of all the elements on a players top flow, effects all elements +@tparam LuaPlayer player the player that you want to toggle the top flow for +@tparam[opt] boolean state if given then the state will be set to this +@treturn boolean the new visible state of the top flow + +@usage-- Toggle your flow +Gui.toggle_top_flow(game.player) + +@usage-- Open your top flow +Gui.toggle_top_flow(game.player,true) + +]] +function Gui.toggle_top_flow(player,state) + -- Get the top flow and hide button + local top_flow = Gui.get_top_flow(player) + if state == nil then state = not top_flow.visible end + + -- Change the visiblty of the flow + local left_flow = Gui.get_left_flow(player) + local show_button = left_flow.gui_core_buttons[show_top_flow] + show_button.visible = not state + top_flow.visible = state + + return state +end + +--[[-- Get the element define that is in the top flow, use in events without an element refrence +@tparam LuaPlayer player the player that you want to get the element for +@tparam table element_define the element that you want to get +@treturn LuaGuiElement the gui element linked to this define for this player + +@usage-- Get your top element +local button = Gui.get_top_element(game.player, example_button) + +]] +function Gui.get_top_element(player, element_define) + local top_flow = Gui.get_top_flow(player) + return top_flow[element_define.name] +end + +--[[-- Creates a button on the top flow with consistent styling +@tparam string sprite the sprite that you want to use on the button +@tparam ?string|Concepts.LocalizedString tooltip the tooltip that you want the button to have +@tparam[opt] function authenticator used to decide if the button should be visible to a player + +@usage-- Add a button to the toolbar +local toolbar_button = +Gui.left_toolbar_button('entity/inserter', 'Nothing to see here', function(player) + return player.admin +end) + +]] +function Gui.toolbar_button(sprite,tooltip,authenticator) + return Gui.element{ + type = 'sprite-button', + sprite = sprite, + tooltip = tooltip, + style = Gui.top_flow_button_style + } + :style{ + minimal_width = 36, + height = 36, + padding = -2 + } + :add_to_top_flow(authenticator) +end + +--[[-- Styles a top flow button depending on the state given +@tparam LuaGuiElement button the button element to style +@tparam boolean state The state the button is in + +@usage-- Sets the button to the visible style +Gui.toolbar_button_style(button, true) + +@usage-- Sets the button to the hidden style +Gui.toolbar_button_style(button, false) + +]] +function Gui.toolbar_button_style(button, state) + if state then + button.style = Gui.top_flow_button_visible_style + else + button.style = Gui.top_flow_button_style + end + button.style.minimal_width = 36 + button.style.height = 36 + button.style.padding = -2 +end \ No newline at end of file diff --git a/expcore/permission_groups.lua b/expcore/permission_groups.lua index 4fb10c05..5b88331f 100644 --- a/expcore/permission_groups.lua +++ b/expcore/permission_groups.lua @@ -1,49 +1,64 @@ --[[-- Core Module - Permission Groups - - Permission group making for factorio so you never have to make one by hand again - @core Permissions-Groups - @alias Permissions_Groups +- Permission group making for factorio so you never have to make one by hand again +@core Groups +@alias Permissions_Groups - @usage ----- Example Group (Allow All) +@usage--- Example Group (Allow All) +-- here we will create an admin group however we do not want them to use the map editor or mess with the permission groups +Permission_Groups.new_group('Admin') -- this defines a new group called "Admin" +:allow_all() -- this makes the default to allow any input action unless set other wise +:disallow{ -- here we disallow the input action we don't want them to use + 'add_permission_group', + 'delete_permission_group', + 'import_permissions_string', + 'map_editor_action', + 'toggle_map_editor' +} - -- here we will create an admin group however we do not want them to use the map editor or mess with the permission groups - Permission_Groups.new_group('Admin') -- this defines a new group called "Admin" - :allow_all() -- this makes the default to allow any input action unless set other wise - :disallow{ -- here we disallow the input action we don't want them to use - 'add_permission_group', - 'delete_permission_group', - 'import_permissions_string', - 'map_editor_action', - 'toggle_map_editor' - } - - @usage ----- Example Group (Disallow All) - - -- here we will create a group that cant do anything but talk in chat - Permission_Groups.new_group('Restricted') -- this defines a new group called "Restricted" - :disallow_all() -- this makes the default to disallow any input action unless set other wise - :allow('write_to_console') -- here we allow them to chat, {} can be used here if we had more than one action +@usage--- Example Group (Disallow All) +-- here we will create a group that cant do anything but talk in chat +Permission_Groups.new_group('Restricted') -- this defines a new group called "Restricted" +:disallow_all() -- this makes the default to disallow any input action unless set other wise +:allow('write_to_console') -- here we allow them to chat, {} can be used here if we had more than one action ]] local Game = require 'utils.game' --- @dep utils.game local Event = require 'utils.event' --- @dep utils.event -local Sudo = require 'expcore.sudo' --- @dep expcore.sudo +local Async = require 'expcore.async' --- @dep expcore.async local Permissions_Groups = { groups={}, -- store for the different groups that are created _prototype={} -- stores functions that are used on group instances } +-- Async function to add players to permission groups +local add_to_permission_group = +Async.register(function(permission_group,player) + permission_group.add_player(player) +end) +Permissions_Groups.async_token_add_to_permission_group = add_to_permission_group + +-- Async function to remove players from permission groups +local remove_from_permission_group = +Async.register(function(permission_group,player) + permission_group.remove_player(player) +end) +Permissions_Groups.async_token_remove_from_permission_group = remove_from_permission_group + --- Getters. -- Functions that get permission groups -- @section getters ---- Defines a new permission group that can have it actions set in the config --- @tparam string name the name of the new group --- @treturn Permissions_Groups._prototype the new group made with function to allow and disallow actions +--[[-- Defines a new permission group that can have it actions set in the config +@tparam string name the name of the new group +@treturn Permissions_Groups._prototype the new group made with function to allow and disallow actions + +@usage-- Defining a new permission group +Groups.new_group('Admin') + +]] function Permissions_Groups.new_group(name) local group = setmetatable({ name=name, @@ -56,16 +71,26 @@ function Permissions_Groups.new_group(name) return group end ---- Returns the group with the given name, case sensitive --- @tparam string name the name of the group to get --- @treturn ?Permissions_Groups._prototype|nil the group with that name or nil if non found +--[[-- Returns the group with the given name, case sensitive +@tparam string name the name of the group to get +@treturn ?Permissions_Groups._prototype|nil the group with that name or nil if non found + +@usage-- Getting a permision group +local admin_group = Groups.get_group_by_name('Admin') + +]] function Permissions_Groups.get_group_by_name(name) return Permissions_Groups.groups[name] end ---- Returns the group that a player is in --- @tparam LuaPlayer player the player to get the group of can be name index etc --- @treturn ?Permissions_Groups._prototype|nil the group with that player or nil if non found +--[[-- Returns the group that a player is in +@tparam LuaPlayer player the player to get the group of can be name index etc +@treturn ?Permissions_Groups._prototype|nil the group with that player or nil if non found + +@usage-- Get your permission group +local group = Groups.get_group_from_player(game.player) + +]] function Permissions_Groups.get_group_from_player(player) player = Game.get_player_from_any(player) if not player then return end @@ -79,43 +104,27 @@ end -- Functions that control all groups -- @section players ---- Reloads/creates all permission groups and sets them to they configured state +--[[-- Reloads/creates all permission groups and sets them to they configured state + +@usage-- Reload the permission groups, used internally +Groups.reload_permissions() + +]] function Permissions_Groups.reload_permissions() for _,group in pairs(Permissions_Groups.groups) do group:create() end end ---- Removes all permissions from every permission group except for "Default" and any passed as exempt --- @tparam ?string|Array exempt groups that you want to be except, "Default" is always exempt --- @treturn number the number of groups that had they permissions removed -function Permissions_Groups.lockdown_permissions(exempt) - local count = 0 - if type(exempt) ~= 'table' then - exempt = {exempt} - end - for _,group in pairs(exempt) do - if type(group) == 'string' then - exempt[group:lower()] = true - elseif type(group) == 'table' then - exempt[group.name:lower()] = true - end - end - for _,group in pairs(game.permissions.groups) do - if not exempt[group.name:lower()] and not group.name == 'Default' then - count = count +1 - for _,action in pairs(defines.input_action) do - group.set_allows_action(action,false) - end - end - end - return count -end +--[[-- Sets a player's group to the one given, a player can only have one group at a time +@tparam LuaPlayer player the player to effect can be name index etc +@tparam string group the name of the group to give to the player +@treturn boolean true if the player was added successfully, false other wise ---- Sets a player's group to the one given, a player can only have one group at a time --- @tparam LuaPlayer player the player to effect can be name index etc --- @tparam string group the name of the group to give to the player --- @treturn boolean true if the player was added successfully, false other wise +@usage-- Set your permission group +Groups.set_player_group(game.player, 'Admin') + +]] function Permissions_Groups.set_player_group(player,group) player = Game.get_player_from_any(player) group = Permissions_Groups.get_group_by_name(group) @@ -128,10 +137,15 @@ end -- Functions that control group actions -- @section actions ---- Sets the allow state of an action for this group, used internally but is safe to use else where --- @tparam ?string|defines.input_action action the action that you want to set the state of --- @tparam boolean state the state that you want to set it to, true = allow, false = disallow --- @treturn Permissions_Groups._prototype returns self so function can be chained +--[[-- Sets the allow state of an action for this group, used internally but is safe to use else where +@tparam ?string|defines.input_action action the action that you want to set the state of +@tparam boolean state the state that you want to set it to, true = allow, false = disallow +@treturn Permissions_Groups._prototype returns self so function can be chained + +@usage-- Set an action to be disalowed +group:set_action('toggle_map_editor', false) + +]] function Permissions_Groups._prototype:set_action(action,state) if type(action) == 'string' then action = defines.input_action[action] @@ -140,9 +154,16 @@ function Permissions_Groups._prototype:set_action(action,state) return self end ---- Sets an action or actions to be allowed for this group even with disallow_all triggered, Do not use in runtime --- @tparam string|Array actions the action or actions that you want to allow for this group --- @treturn Permissions_Groups._prototype returns self so function can be chained +--[[-- Sets an action or actions to be allowed for this group even with disallow_all triggered, Do not use in runtime +@tparam string|Array actions the action or actions that you want to allow for this group +@treturn Permissions_Groups._prototype returns self so function can be chained + +@usage-- Allow some actions +group:allow{ + 'write_to_console' +} + +]] function Permissions_Groups._prototype:allow(actions) if type(actions) ~= 'table' then actions = {actions} @@ -153,9 +174,20 @@ function Permissions_Groups._prototype:allow(actions) return self end ---- Sets an action or actions to be disallowed for this group even with allow_all triggered, Do not use in runtime --- @tparam string|Array actions the action or actions that you want to disallow for this group --- @treturn Permissions_Groups._prototype returns self so function can be chained +--[[-- Sets an action or actions to be disallowed for this group even with allow_all triggered, Do not use in runtime +@tparam string|Array actions the action or actions that you want to disallow for this group +@treturn Permissions_Groups._prototype returns self so function can be chained + +@usage-- Disalow some actions +group:disallow{ + 'add_permission_group', + 'delete_permission_group', + 'import_permissions_string', + 'map_editor_action', + 'toggle_map_editor' +} + +]] function Permissions_Groups._prototype:disallow(actions) if type(actions) ~= 'table' then actions = {actions} @@ -166,23 +198,38 @@ function Permissions_Groups._prototype:disallow(actions) return self end ---- Sets the default state for any actions not given to be allowed, useful with :disallow --- @treturn Permissions_Groups._prototype returns self so function can be chained +--[[-- Sets the default state for any actions not given to be allowed, useful with :disallow +@treturn Permissions_Groups._prototype returns self so function can be chained + +@usage-- Allow all actions unless given by disallow +group:allow_all() + +]] function Permissions_Groups._prototype:allow_all() self.allow_all_actions = true return self end ---- Sets the default state for any action not given to be disallowed, useful with :allow --- @treturn Permissions_Groups._prototype returns self so function can be chained +--[[-- Sets the default state for any action not given to be disallowed, useful with :allow +@treturn Permissions_Groups._prototype returns self so function can be chained + +@usage-- Disallow all actions unless given by allow +group:disallow_all() + +]] function Permissions_Groups._prototype:disallow_all() self.allow_all_actions = false return self end ---- Returns if an input action is allowed for this group --- @tparam ?string|defines.input_action action the action that you want to test for --- @treturn boolean true if the group is allowed the action, false other wise +--[[-- Returns if an input action is allowed for this group +@tparam ?string|defines.input_action action the action that you want to test for +@treturn boolean true if the group is allowed the action, false other wise + +@usage-- Test if a group is allowed an action +local allowed = group:is_allowed('write_to_console') + +]] function Permissions_Groups._prototype:is_allowed(action) if type(action) == 'string' then action = defines.input_action[action] @@ -198,14 +245,13 @@ end -- Functions that control group players -- @section players ---- Returns the LuaPermissionGroup that was created with this group object, used internally --- @treturn LuaPermissionGroup the raw lua permission group -function Permissions_Groups._prototype:get_raw() - return game.permissions.get_group(self.name) -end +--[[-- Creates or updates the permission group with the configured actions, used internally +@treturn LuaPermissionGroup the permission group that was created ---- Creates or updates the permission group with the configured actions, used internally --- @treturn LuaPermissionGroup the permission group that was created +@usage-- Create the permission group so players can be added, used internally +group:create() + +]] function Permissions_Groups._prototype:create() local group = self:get_raw() if not group then @@ -217,31 +263,60 @@ function Permissions_Groups._prototype:create() return group end ---- Adds a player to this group --- @tparam LuaPlayer player LuaPlayer the player you want to add to this group can be name or index etc --- @treturn boolean true if the player was added successfully, false other wise +--[[-- Returns the LuaPermissionGroup that was created with this group object, used internally +@treturn LuaPermissionGroup the raw lua permission group + +@usage-- Get the factorio api permision group, used internally +local permission_group = group:get_raw() + +]] +function Permissions_Groups._prototype:get_raw() + return game.permissions.get_group(self.name) +end + +--[[-- Adds a player to this group +@tparam LuaPlayer player LuaPlayer the player you want to add to this group can be name or index etc +@treturn boolean true if the player was added successfully, false other wise + +@usage-- Add a player to this permission group +group:add_player(game.player) + +]] function Permissions_Groups._prototype:add_player(player) player = Game.get_player_from_any(player) local group = self:get_raw() if not group or not player then return false end - Sudo('add-player-to-permission-group',group,player) + Async(add_to_permission_group, group, player) return true end ---- Removes a player from this group --- @tparam LuaPlayer player LuaPlayer the player you want to remove from this group can be name or index etc --- @treturn boolean true if the player was removed successfully, false other wise +--[[-- Removes a player from this group +@tparam LuaPlayer player LuaPlayer the player you want to remove from this group can be name or index etc +@treturn boolean true if the player was removed successfully, false other wise + +@usage-- Remove a player from this permission group +group:remove_player(game.player) + +]] function Permissions_Groups._prototype:remove_player(player) player = Game.get_player_from_any(player) local group = self:get_raw() if not group or not player then return false end - Sudo('remove-player-from-permission-group',group,player) + Async(remove_from_permission_group, group, player) return true end ---- Returns all player that are in this group with the option to filter to online/offline only --- @tparam[opt] boolean online if nil returns all players, if true online players only, if false returns online players only --- @treturn table a table of players that are in this group; filtered if online param is given +--[[-- Returns all player that are in this group with the option to filter to online/offline only +@tparam[opt] boolean online if nil returns all players, if true online players only, if false returns online players only +@treturn table a table of players that are in this group; filtered if online param is given + +@usage-- Get all players in this group +local online_players = group:get_players() + +@usage-- Get all online players in this group +local online_players = group:get_players(true) + +]] function Permissions_Groups._prototype:get_players(online) local players = {} local group = self:get_raw() @@ -259,9 +334,14 @@ function Permissions_Groups._prototype:get_players(online) return players end ---- Prints a message to every player in this group --- @tparam string message the message that you want to send to the players --- @treturn number the number of players that received the message +--[[-- Prints a message to every player in this group +@tparam string message the message that you want to send to the players +@treturn number the number of players that received the message + +@usage-- Print a message to all players in thie group +group:print('Hello, World!') + +]] function Permissions_Groups._prototype:print(message) local players = self:get_players(true) for _,player in pairs(players) do @@ -275,11 +355,4 @@ Event.on_init(function() Permissions_Groups.reload_permissions() end) -Sudo.register('add-player-to-permission-group',function(permission_group,player) - permission_group.add_player(player) -end) -Sudo.register('remove-player-from-permission-group',function(permission_group,player) - permission_group.remove_player(player) -end) - return Permissions_Groups \ No newline at end of file diff --git a/expcore/roles.lua b/expcore/roles.lua index e6b6e956..65485c00 100644 --- a/expcore/roles.lua +++ b/expcore/roles.lua @@ -1,124 +1,120 @@ --[[-- Core Module - Roles - - Factorio role system to manage custom permissions. - @core Roles - @alias Roles +- Factorio role system to manage custom permissions. +@core Roles +@alias Roles - @usage ----- Using Role System (Frontend): - When a map first starts you will want to define on mass all the players you expect to join and the roles to give them: - Roles.override_player_roles{ - Cooldude2606 = {'Owner','Admin','Member'}, - NotCooldude2606 = {'Member'} - } +@usage--- Using Role System (assignment): +--When a map first starts you will want to define on mass all the players you expect to join and the roles to give them: +Roles.override_player_roles{ + Cooldude2606 = {'Owner','Admin','Member'}, + NotCooldude2606 = {'Member'} +} - Once the game is running you still want to be able to give role and remove them which is when you would use: - Roles.assign_player(player,'Admin',by_player_name) -- this will give the "Admin" role to the player - Roles.unassign_player(player,{'Admin','Moderator'},by_player_name) -- this will remove "Admin" and "Moderator" role in one go +--Once the game is running you still want to be able to give role and remove them which is when you would use: +Roles.assign_player(player,'Admin',by_player_name) -- this will give the "Admin" role to the player +Roles.unassign_player(player,{'Admin','Moderator'},by_player_name) -- this will remove "Admin" and "Moderator" role in one go - @usage ----- Using Role System (Backend): - To comparer two players you can comparer the index of they highest roles, can be used when you want to allow a "write" down type system: - Roles.get_player_highest_role(playerOne).index < Roles.get_player_highest_role(playerTwo).index -- remember that less means a higher role +@usage--- Using Role System (role testing): +--To comparer two players you can comparer the index of they highest roles, can be used when you want to allow a "write" down type system: +Roles.get_player_highest_role(playerOne).index < Roles.get_player_highest_role(playerTwo).index -- remember that less means a higher role - Listing all of a players roles can also be useful which is when you would want to use: - Roles.get_player_roles(player) -- the return is an array that can be looped over however this is not in particular order +--Listing all of a players roles can also be useful which is when you would want to use: +Roles.get_player_roles(player) -- the return is an array that can be looped over however this is not in particular order - Finally you may want to test if a player has a certain role, flag or action allowed which is when you would use: - Roles.player_has_role(player,'Admin') -- you can provide a role name if you only want a name based system - Roles.player_has_flag(player,'is_donator') -- your roles can be grouped together with flags such as is_donator - Roles.player_allowed(player,'game modifiers') -- or you can have an action based system where each action is something the player can do +--Finally you may want to test if a player has a certain role, flag or action allowed which is when you would use: +Roles.player_has_role(player,'Admin') -- you can provide a role name if you only want a name based system +Roles.player_has_flag(player,'is_donator') -- your roles can be grouped together with flags such as is_donator +Roles.player_allowed(player,'game modifiers') -- or you can have an action based system where each action is something the player can do - @usage ----- Example Flag Define: - Flags can be used to group multiple roles and actions under one catch all, for example if you want a piece of code to only - be active for your donators then you would add a "is_donator" flag to all your donator roles and then in the code test if - a player has that tag present: +@usage--- Example Flag Define: +--Flags can be used to group multiple roles and actions under one catch all, for example if you want a piece of code to only +--be active for your donators then you would add a "is_donator" flag to all your donator roles and then in the code test if +--a player has that tag present: - -- give you donators a speed boost when they join; these functions aren't required but can be useful - Roles.define_flag_trigger('is_donator',function(player,state) - if state then - player.character_running_speed_modifier = 1.5 - else - player.character_running_speed_modifier = 1 - end - end) - - -- then on all your donator roles you would add - Roles.new_role('Donator') - :set_flag('is_donator') - - -- and in your code you would test for - if Roles.player_has_flag(player,'is_donator') then - -- some donator only code +-- give you donators a speed boost when they join; these functions aren't required but can be useful +Roles.define_flag_trigger('is_donator',function(player,state) + if state then + player.character_running_speed_modifier = 1.5 + else + player.character_running_speed_modifier = 1 end +end) - @usage ----- Example Role Define: - You can't use a role system without any roles so first you must define your roles; each role has a minimum of a name with - the option for a shorthand: - Roles.new_role('Administrator','Admin') +-- then on all your donator roles you would add +Roles.new_role('Donator') +:set_flag('is_donator') - Next you will want to add any extras you want to have, such as a tag, colour, permission group or any custom flags: - Roles.new_role('Administrator','Admin') - :set_custom_tag('[Admin]') - :set_custom_color('red') -- this can be {r=0,g=0,b=0} or a predefined value - :set_permission_group('Staff') -- a second argument can be added if you have not used the custom permission group config - :set_flag('is_admin') +-- and in your code you would test for +if Roles.player_has_flag(player,'is_donator') then + -- some donator only code +end - You will then want to decide if you want to allow all actions, this should of course be used sparely: - Roles.new_role('Administrator','Admin') - ...extras... - :set_allow_all() +@usage--- Example Role Define: +--You can't use a role system without any roles so first you must define your roles; each role has a minimum of a name with +--the option for a shorthand: +Roles.new_role('Administrator','Admin') - If you don't do this want this as i would advise you do then you will want to define what the role can do; this comes with - an optional inheritance system if you like those sort of things in which case disallow may also be of some use to you: - Roles.new_role('Administrator','Admin') - ...extras... - :set_parent('Moderator') -- the admin can do anything that a moderator can do - :allow{ -- these actions can be anything just try to keep them without conflicts - 'command/kill', - 'gui/game settings' - } +--Next you will want to add any extras you want to have, such as a tag, colour, permission group or any custom flags: +Roles.new_role('Administrator','Admin') +:set_custom_tag('[Admin]') +:set_custom_color('red') -- this can be {r=0,g=0,b=0} or a predefined value +:set_permission_group('Staff') -- a second argument can be added if you have not used the custom permission group config +:set_flag('is_admin') - Here is what the finished admin role would look like: - Roles.new_role('Administrator','Admin') - :set_custom_tag('[Admin]') - :set_custom_color('red') - :set_permission_group('Staff') - :set_flag('is_admin') - :set_parent('Moderator') - :allow{ - 'command/kill', - 'gui/game settings' - } +--You will then want to decide if you want to allow all actions, this should of course be used sparely: +Roles.new_role('Administrator','Admin') +...extras... +:set_allow_all() - @usage ----- Example System Define: - Once all roles are defined these steps must be done to ensure the system is ready to use, this includes setting a default - role, assigning a root (all permission) role that the server/system will use and the linear order that the roles fall into: +--If you don't do this want this as i would advise you do then you will want to define what the role can do; this comes with +--an optional inheritance system if you like those sort of things in which case disallow may also be of some use to you: +Roles.new_role('Administrator','Admin') +...extras... +:set_parent('Moderator') -- the admin can do anything that a moderator can do +:allow{ -- these actions can be anything just try to keep them without conflicts + 'command/kill', + 'gui/game settings' +} - Roles.set_default('Guest') - Roles.set_root('System') +--Here is what the finished admin role would look like: +Roles.new_role('Administrator','Admin') +:set_custom_tag('[Admin]') +:set_custom_color('red') +:set_permission_group('Staff') +:set_flag('is_admin') +:set_parent('Moderator') +:allow{ + 'command/kill', + 'gui/game settings' +} - Roles.define_role_order{ - 'System', - 'Administrator', - 'Moderator', - 'Donator', - 'Guest' - } +@usage--- Example System Define: +--Once all roles are defined these steps must be done to ensure the system is ready to use, this includes setting a default +--role, assigning a root (all permission) role that the server/system will use and the linear order that the roles fall into: + +Roles.set_default('Guest') +Roles.set_root('System') + +Roles.define_role_order{ + 'System', + 'Administrator', + 'Moderator', + 'Donator', + 'Guest' +} + +--Just remember that in this example all these roles have not been defined; so make sure all your roles that are used are defined +--before hand; a config file on load is useful for this to ensure that its loaded before the first player even joins. - Just remember that in this example all these roles have not been defined; so make sure all your roles that are used are defined - before hand; a config file on load is useful for this to ensure that its loaded before the first player even joins. ]] local Game = require 'utils.game' --- @dep utils.game local Global = require 'utils.global' --- @dep utils.global local Event = require 'utils.event' --- @dep utils.event local Groups = require 'expcore.permission_groups' --- @dep expcore.permission_groups -local Sudo = require 'expcore.sudo' --- @dep expcore.sudo -local Colours = require 'resources.color_presets' --- @dep resources.color_presets -local write_json = ext_require('expcore.common','write_json') --- @dep expcore.common +local Async = require 'expcore.async' --- @dep expcore.async +local Colours = require 'utils.color_presets' --- @dep utils.color_presets +local write_json = _C.write_json --- @dep expcore.common local Roles = { _prototype={}, @@ -127,7 +123,7 @@ local Roles = { roles={}, -- Contains the raw info for the roles, indexed by role name flags={}, -- Contains functions that run when a flag is added/removed from a player internal={}, -- Contains all internally accessed roles, such as root, default - players={} + players={} -- Contains the roles that players have }, events = { on_role_assigned=script.generate_event_name(), @@ -182,7 +178,7 @@ local function emit_player_roles_updated(player,type,roles,by_player_name,skip_g player.play_sound{path='utility/game_lost'} end script.raise_event(event,{ - name=Roles.player_roles_updated, + name=event, tick=game.tick, player_index=player.index, by_player_index=by_player_index, @@ -196,8 +192,13 @@ local function emit_player_roles_updated(player,type,roles,by_player_name,skip_g }) end ---- Returns a string which contains all roles in index order displaying all data for them --- @treturn string the debug output string +--[[-- Returns a string which contains all roles in index order displaying all data for them +@treturn string the debug output string + +@usage-- Print the debug string +game.player.print(Roles.debug()) + +]] function Roles.debug() local output = '' for index,role_name in pairs(Roles.config.order) do @@ -209,9 +210,14 @@ function Roles.debug() return output end ---- Prints a message to all players in the given roles, may send duplicate message however factorio blocks spam --- @tparam table roles table a of roles which to send the message to --- @tparam string message the message to send to the players +--[[-- Prints a message to all players in the given roles, may send duplicate message however factorio blocks spam +@tparam table roles table a of roles which to send the message to +@tparam string message the message to send to the players + +@usage-- Print a message to the given roles +Roles.print_to_roles({'Administrator','Moderator'}, 'Hello, World!') + +]] function Roles.print_to_roles(roles,message) for _,role in pairs(roles) do role = Roles.get_role_from_any(role) @@ -219,9 +225,14 @@ function Roles.print_to_roles(roles,message) end end ---- Prints a message to all players who have the given role or one which is higher (excluding default) --- @tparam string role the name of the role to send the message to --- @tparam string message the message to send to the players +--[[-- Prints a message to all players who have the given role or one which is higher (excluding default) +@tparam string role the name of the role to send the message to +@tparam string message the message to send to the players + +@usage-- Print a message to the roles above this role, includes the given role +Roles.print_to_roles_higher('Moderator', 'Hello, World!') + +]] function Roles.print_to_roles_higher(role,message) role = Roles.get_role_from_any(role) if not role then return end @@ -234,9 +245,14 @@ function Roles.print_to_roles_higher(role,message) Roles.print_to_roles(roles,message) end ---- Prints a message to all players who have the given role or one which is lower (excluding default) --- @tparam string role the name of the role to send the message to --- @tparam string message the message to send to the players +--[[-- Prints a message to all players who have the given role or one which is lower (excluding default) +@tparam string role the name of the role to send the message to +@tparam string message the message to send to the players + +@usage-- Print a message to the roles below this role, includes the given role +Roles.print_to_roles_higher('Moderator', 'Hello, World!') + +]] function Roles.print_to_roles_lower(role,message) role = Roles.get_role_from_any(role) if not role then return end @@ -249,25 +265,40 @@ function Roles.print_to_roles_lower(role,message) Roles.print_to_roles(roles,message) end ---- Get a role for the given name --- @tparam string name the name of the role to get --- @treturn Roles._prototype the role with that name or nil +--[[-- Get a role for the given name +@tparam string name the name of the role to get +@treturn Roles._prototype the role with that name or nil + +@usage-- Get a role by its name +local role = Roles.get_role_by_name('Moderator') + +]] function Roles.get_role_by_name(name) return Roles.config.roles[name] end ---- Get a role with the given order index --- @tparam number index the place in the order list of the role to get --- @treturn Roles._prototype the role with that index in the order list or nil +--[[-- Get a role with the given order index +@tparam number index the place in the order list of the role to get +@treturn Roles._prototype the role with that index in the order list or nil + +@usage-- Get a role by its index in the order list +local role = Roles.get_role_by_name(2) + +]] function Roles.get_role_by_order(index) local name = Roles.config.order[index] return Roles.config.roles[name] end ---- Gets a role from a name,index or role object (where it is just returned) --- nb: this function is used for the input for most outward facing functions --- @tparam ?number|string|table any the value used to find the role --- @treturn Roles._prototype the role that was found or nil see above +--[[-- Gets a role from a name,index or role object (where it is just returned) +nb: this function is used for the input for most outward facing functions +@tparam ?number|string|table any the value used to find the role +@treturn Roles._prototype the role that was found or nil see above + +@usage-- Get a role by its name or order +local role = Roles.get_role_from_any('Moderator') + +]] function Roles.get_role_from_any(any) local t_any = type(any) if t_any == 'number' or tonumber(any) then @@ -280,9 +311,14 @@ function Roles.get_role_from_any(any) end end ---- Gets all the roles of the given player, this will always contain the default role --- @tparam LuaPlayer player the player to get the roles of --- @treturn table a table where the values are the roles which the player has +--[[-- Gets all the roles of the given player, this will always contain the default role +@tparam LuaPlayer player the player to get the roles of +@treturn table a table where the values are the roles which the player has + +@usage-- Get the roles that a player has +local roles = Roles.get_player_roles(game.player) + +]] function Roles.get_player_roles(player) player = Game.get_player_from_any(player) if not player then return {Roles.config.roles[Roles.config.internal.root]} end @@ -295,9 +331,14 @@ function Roles.get_player_roles(player) return rtn end ---- Gets the highest role which the player has, can be used to compeer one player to another --- @tparam LuaPlayer player the player to get the highest role of --- @treturn the role with the highest order index which this player has +--[[-- Gets the highest role which the player has, can be used to compeer one player to another +@tparam LuaPlayer player the player to get the highest role of +@treturn the role with the highest order index which this player has + +@usage-- Get the highest role that a player has +local role = Roles.get_player_highest_role(game.player) + +]] function Roles.get_player_highest_role(player) local roles = Roles.get_player_roles(player) if not roles then return end @@ -314,13 +355,54 @@ end -- Functions for changing player's roles -- @section assinment ---- Gives a player the given role(s) with an option to pass a by player name used in the log --- @tparam LuaPlayer player the player that will be assigned the roles --- @tparam table roles table a of roles that the player will be given, can be one role and can be role names --- @tparam[opt=] string by_player_name the name of the player that will be shown in the log --- @tparam[opt=false] boolean silent when true there will be no game message printed -function Roles.assign_player(player,roles,by_player_name,silent) - player = Game.get_player_from_any(player) +--[[-- Gives a player the given role(s) with an option to pass a by player name used in the log +@tparam LuaPlayer player the player that will be assigned the roles +@tparam table roles table a of roles that the player will be given, can be one role and can be role names +@tparam[opt=] string by_player_name the name of the player that will be shown in the log +@tparam[opt=false] boolean skip_checks when true there will be no checks are done for if the player is valid +@tparam[opt=false] boolean silent when true there will be no game message printed + +@usage-- Assign a player to the Moderator role +Roles.assign_player(game.player, 'Moderator') + +@usage-- Assign a player to the Moderator role, even if the player has never been on the map +Roles.assign_player('Cooldude2606', 'Moderator', nil, true) + +]] +function Roles.assign_player(player,roles,by_player_name,skip_checks,silent) + local valid_player = Game.get_player_from_any(player) + if not skip_checks and not valid_player then return end + if type(roles) ~= 'table' or roles.name then + roles = {roles} + end + for _,role in pairs(roles) do + role = Roles.get_role_from_any(role) + if role then + role:add_player(valid_player or player, valid_player == nil, true) + end + end + if valid_player then + emit_player_roles_updated(valid_player, 'assign', roles, by_player_name, silent) + end +end + +--[[-- Removes a player from the given role(s) with an option to pass a by player name used in the log +@tparam LuaPlayer player the player that will have the roles removed +@tparam table roles table a of roles to be removed from the player, can be one role and can be role names +@tparam[opt=] string by_player_name the name of the player that will be shown in the logs +@tparam[opt=false] boolean skip_checks when true there will be no checks are done for if the player is valid +@tparam[opt=false] boolean silent when true there will be no game message printed + +@usage-- Unassign a player from the Moderator role +Roles.unassign_player(game.player, 'Moderator') + +@usage-- Unassign a player from the Moderator role, even if the player has never been on the map +Roles.unassign_player('Cooldude2606', 'Moderator', nil, true) + +]] +function Roles.unassign_player(player,roles,by_player_name,skip_checks,silent) + local valid_player = Game.get_player_from_any(player) + if not skip_checks and not valid_player then return end if not player then return end if type(roles) ~= 'table' or roles.name then roles = {roles} @@ -328,46 +410,49 @@ function Roles.assign_player(player,roles,by_player_name,silent) for _,role in pairs(roles) do role = Roles.get_role_from_any(role) if role then - role:add_player(player,false,true) + role:remove_player(valid_player or player, valid_player == nil, true) end end - emit_player_roles_updated(player,'assign',roles,by_player_name,silent) + if valid_player then + emit_player_roles_updated(valid_player, 'unassign', roles, by_player_name, silent) + end end ---- Removes a player from the given role(s) with an option to pass a by player name used in the log --- @tparam LuaPlayer player the player that will have the roles removed --- @tparam table roles table a of roles to be removed from the player, can be one role and can be role names --- @tparam[opt=] string by_player_name the name of the player that will be shown in the logs --- @tparam[opt=false] boolean silent when true there will be no game message printed -function Roles.unassign_player(player,roles,by_player_name,silent) - player = Game.get_player_from_any(player) - if not player then return end - if type(roles) ~= 'table' or roles.name then - roles = {roles} - end - for _,role in pairs(roles) do - role = Roles.get_role_from_any(role) - if role then - role:remove_player(player,false,true) - end - end - emit_player_roles_updated(player,'unassign',roles,by_player_name,silent) -end +--[[-- Overrides all player roles with the given table of roles, useful to mass set roles on game start +@tparam[opt] string player_name the player to set the roles for, if not given all roles are overriden +@tparam table roles table a which is indexed by case sensitive player names and has the value of a table of role names ---- Overrides all player roles with the given table of roles, useful to mass set roles on game start --- @tparam table roles table a which is indexed by case sensitive player names and has the value of a table of role names -function Roles.override_player_roles(roles) - Roles.config.players = roles +@usage-- Override the roles of a single player, other users are not effected +Roles.override_player_roles('Cooldude2606', {'Moderator'}) + +@usage-- Override all existing roles, effects all users not just ones listed +Roles.override_player_roles{ + ['Cooldude2606'] = {'Administrator','Moderator'}, + ['arty714'] = {'Administrator','Moderator'}, +} + +]] +function Roles.override_player_roles(player_name,roles) + if not roles then + Roles.config.players = player_name + else + Roles.config.players[player_name] = roles + end end --- Checks. -- Functions for checking player's roles -- @section checks ---- A test for weather a player has the given role --- @tparam LuaPlayer player the player to test the roles of --- @tparam ?string|number|table search_role a pointer to the role that is being searched for --- @treturn boolean true if the player has the role, false otherwise, nil for errors +--[[-- A test for weather a player has the given role +@tparam LuaPlayer player the player to test the roles of +@tparam ?string|number|table search_role a pointer to the role that is being searched for +@treturn boolean true if the player has the role, false otherwise, nil for errors + +@usage-- Test if a player has a role +local has_role = Roles.player_has_role(game.player, 'Moderator') + +]] function Roles.player_has_role(player,search_role) local roles = Roles.get_player_roles(player) if not roles then return end @@ -379,10 +464,15 @@ function Roles.player_has_role(player,search_role) return false end ---- A test for weather a player has the given flag true for at least one of they roles --- @tparam LuaPlayer player the player to test the roles of --- @tparam string flag_name the name of the flag that is being looked for --- @treturn boolean true if the player has at least one role which has the flag set to true, false otherwise, nil for errors +--[[-- A test for weather a player has the given flag true for at least one of they roles +@tparam LuaPlayer player the player to test the roles of +@tparam string flag_name the name of the flag that is being looked for +@treturn boolean true if the player has at least one role which has the flag set to true, false otherwise, nil for errors + +@usage-- Test if a player has a role +local has_flag = Roles.player_has_flag(game.player, 'is_donator') + +]] function Roles.player_has_flag(player,flag_name) local roles = Roles.get_player_roles(player) if not roles then return end @@ -394,10 +484,15 @@ function Roles.player_has_flag(player,flag_name) return false end ---- A test for weather a player has at least one role which is allowed the given action --- @tparam LuaPlayer player the player to test the roles of --- @tparam string action the name of the action that is being tested for --- @treturn boolean true if the player has at least one role which is allowed this action, false otherwise, nil for errors +--[[-- A test for weather a player has at least one role which is allowed the given action +@tparam LuaPlayer player the player to test the roles of +@tparam string action the name of the action that is being tested for +@treturn boolean true if the player has at least one role which is allowed this action, false otherwise, nil for errors + +@usage-- Test if a player has a role +local has_flag = Roles.player_has_flag(game.player, 'is_donator') + +]] function Roles.player_allowed(player,action) local roles = Roles.get_player_roles(player) if not roles then return end @@ -413,22 +508,46 @@ end -- Functions which are used to define roles -- @section checks ---- Used to set the role order, higher in the list is better, must be called at least once in config +--[[-- Used to set the role order, higher in the list is better, must be called at least once in config -- nb: function also re links parents due to expected position in the config file --- @tparam table order table a which is keyed only by numbers (start 1) and values are roles in order with highest first +@tparam table order table a which is keyed only by numbers (start 1) and values are roles in order with highest first + +@usage-- Define which roles are higher than others +Roles.define_role_order{ + 'System', + 'Administrator', + 'Moderator', + 'Donator', + 'Guest' +} + +]] function Roles.define_role_order(order) -- Clears and then rebuilds the order table + _C.error_if_runtime() Roles.config.order = {} + local done = {} for _,role in ipairs(order) do if type(role) == 'table' and role.name then + done[role.name] = true table.insert(Roles.config.order,role.name) else + done[role] = true table.insert(Roles.config.order,role) end end + -- Check no roles were missed + for role_name,_ in pairs(Roles.config.roles) do + if not done[role_name] then + error('Role missing '..role_name..' from role order, all defined roles must be included.',2) + end + end -- Re-links roles to they parents as this is called at the end of the config - for index,role in pairs(Roles.config.order) do - role = Roles.config.roles[role] + for index,role_name in pairs(Roles.config.order) do + local role = Roles.config.roles[role_name] + if not role then + error('Role with name '..role_name..' has not beed defined, either define it or remove it from the order list.',2) + end role.index = index local parent = Roles.config.roles[role.parent] if parent then @@ -437,27 +556,41 @@ function Roles.define_role_order(order) end end ---- Defines a new trigger for when a tag is added or removed from a player --- @tparam string name the name of the flag which the roles will have --- @tparam function callback the function that is called when roles are assigned --- flag param - player - the player that has had they roles changed --- flag param - state - the state of the flag, aka if the flag is present +--[[-- Defines a new trigger for when a tag is added or removed from a player +@tparam string name the name of the flag which the roles will have +@tparam function callback the function that is called when roles are assigned + +@usage-- Defineing a flag trigger +Roles.define_flag_trigger('is_donator', function(player, state) + player.character_running_speed_modifier = state and 1.5 or 1 +end) + +]] function Roles.define_flag_trigger(name,callback) - local sudo_name = 'role-flag-'..name - Roles.config.flags[name] = sudo_name - Sudo.register(sudo_name,callback) + _C.error_if_runtime() + Roles.config.flags[name] = Async.register(callback) end ---- Sets the default role which every player will have, this needs to be called at least once --- @tparam string name the name of the default role +--[[-- Sets the default role which every player will have, this needs to be called at least once +@tparam string name the name of the default role + +@usage-- Setting the default role +Roles.set_default('Guest') + +]] function Roles.set_default(name) local role = Roles.config.roles[name] if not role then return end Roles.config.internal.default = name end ---- Sets the root role which will always have all permissions, any server actions act from this role --- @tparam string name the name of the root role +--[[-- Sets the root role which will always have all permissions, any server actions act from this role +@tparam string name the name of the root role + +@usage-- Setting the root role +Roles.set_root('System') + +]] function Roles.set_root(name) local role = Roles.config.roles[name] if not role then return end @@ -465,11 +598,17 @@ function Roles.set_root(name) Roles.config.internal.root = name end ---- Defines a new role and returns the prototype to allow configuration --- @tparam string name the name of the new role, must be unique --- @tparam[opt=name] string short_hand the shortened version of the name --- @treturn Roles._prototype the start of the config chain for this role +--[[-- Defines a new role and returns the prototype to allow configuration +@tparam string name the name of the new role, must be unique +@tparam[opt=name] string short_hand the shortened version of the name +@treturn Roles._prototype the start of the config chain for this role + +@usage-- Defineing a new role +local role = Roles.new_role('Moderator', 'Mod') + +]] function Roles.new_role(name,short_hand) + _C.error_if_runtime() if Roles.config.roles[name] then return error('Role name is non unique') end local role = setmetatable({ name=name, @@ -486,18 +625,31 @@ end -- Functions for using the role action system -- @section actions ---- Sets the default allow state of the role, true will allow all actions --- @tparam[opt=true] boolean state true will allow all actions --- @treturn Roles._prototype allows chaining +--[[-- Sets the default allow state of the role, true will allow all actions +@tparam[opt=true] boolean state true will allow all actions +@treturn Roles._prototype allows chaining + +@usage-- Allow all actions for this role, useful for root like roles +role:set_allow_all() + +]] function Roles._prototype:set_allow_all(state) if state == nil then state = true end self.allow_all_actions = not not state -- not not forces a boolean value return self end ---- Sets the allow actions for this role, actions in this list will be allowed for this role --- @tparam table actions indexed with numbers and is an array of action names, order has no effect --- @treturn Roles._prototype allows chaining +--[[-- Sets the allow actions for this role, actions in this list will be allowed for this role +@tparam table actions indexed with numbers and is an array of action names, order has no effect +@treturn Roles._prototype allows chaining + +@usage-- Allow some actions for a role +role:allow{ + 'command/kill', + 'gui/game settings' +} + +]] function Roles._prototype:allow(actions) if type(actions) ~= 'table' then actions = {actions} @@ -508,9 +660,17 @@ function Roles._prototype:allow(actions) return self end ---- Sets the disallow actions for this role, will prevent actions from being allowed regardless of inheritance --- @tparam table actions indexed with numbers and is an array of action names, order has no effect --- @treturn Roles._prototype allows chaining +--[[-- Sets the disallow actions for this role, will prevent actions from being allowed regardless of inheritance +@tparam table actions indexed with numbers and is an array of action names, order has no effect +@treturn Roles._prototype allows chaining + +@usage-- Disalow an action for a role, useful if inherit an action from a parent +role:disallow{ + 'command/kill', + 'gui/game settings' +} + +]] function Roles._prototype:disallow(actions) if type(actions) ~= 'table' then actions = {actions} @@ -521,9 +681,14 @@ function Roles._prototype:disallow(actions) return self end ---- Test for if a role is allowed the given action, mostly internal see Roles.player_allowed --- @tparam string action the name of the action to test if it is allowed --- @treturn boolean true if action is allowed, false otherwise +--[[-- Test for if a role is allowed the given action, mostly internal see Roles.player_allowed +@tparam string action the name of the action to test if it is allowed +@treturn boolean true if action is allowed, false otherwise + +@usage-- Test if a role is allowed an action +local allowed = role:is_allowed('command/kill') + +]] function Roles._prototype:is_allowed(action) local is_root = Roles.config.internal.root.name == self.name return self.allowed_actions[action] or self.allow_all_actions or is_root @@ -533,26 +698,41 @@ end -- Functions for using the role flag system -- @section flags ---- Sets the state of a flag for a role, flags can be used to apply effects to players --- @tparam string name the name of the flag to set the value of --- @tparam[opt=true] boolean value the state to set the flag to --- @treturn Roles._prototype allows chaining +--[[-- Sets the state of a flag for a role, flags can be used to apply effects to players +@tparam string name the name of the flag to set the value of +@tparam[opt=true] boolean value the state to set the flag to +@treturn Roles._prototype allows chaining + +@usage-- Set a flag for a role +role:set_flag('is_admin') + +]] function Roles._prototype:set_flag(name,value) if value == nil then value = true end self.flags[name] = not not value -- not not forces a boolean value return self end ---- Clears all flags from this role, individual flags can be removed with set_flag(name,false) --- @treturn Roles._prototype allows chaining +--[[-- Clears all flags from this role, individual flags can be removed with set_flag(name,false) +@treturn Roles._prototype allows chaining + +@usage-- Remove all flags from a role +role:clear_flags() + +]] function Roles._prototype:clear_flags() self.flags = {} return self end ---- A test for if the role has a flag set --- @tparam string name the name of the flag to test for --- @treturn boolean true if the flag is set, false otherwise +--[[-- A test for if the role has a flag set +@tparam string name the name of the flag to test for +@treturn boolean true if the flag is set, false otherwise + +@usage-- Test if a role has a flag +local has_flag = role:has_flag('is_admin') + +]] function Roles._prototype:has_flag(name) return self.flags[name] or false end @@ -561,17 +741,27 @@ end -- Functions for chaning other proerties -- @section properties ---- Sets a custom player tag for the role, can be accessed by other code --- @tparam string tag the value that the tag will be --- @treturn Roles._prototype allows chaining +--[[-- Sets a custom player tag for the role, can be accessed by other code +@tparam string tag the value that the tag will be +@treturn Roles._prototype allows chaining + +@usage-- Set a custom tag for this role, other code is required to set the tag +role:set_custom_tag('Mod') + +]] function Roles._prototype:set_custom_tag(tag) self.custom_tag = tag return self end ---- Sets a custom colour for the role, can be accessed by other code --- @tparam table color ?string|table can either be and rgb colour or the name of a colour defined in the presets --- @treturn Roles._prototype allows chaining +--[[-- Sets a custom colour for the role, can be accessed by other code +@tparam table color ?string|table can either be and rgb colour or the name of a colour defined in the presets +@treturn Roles._prototype allows chaining + +@usage-- Set a custom colour for this role, other code is required to use this value +role:set_custom_color{ r=255, g=100, b=100} + +]] function Roles._prototype:set_custom_color(color) if type(color) ~= 'table' then color = Colours[color] @@ -580,11 +770,17 @@ function Roles._prototype:set_custom_color(color) return self end ---- Sets the permission group for this role, players will be moved to the group of they highest role --- @tparam string name the name of the permission group to have players moved to --- @tparam[opt=false] boolean use_factorio_api when true the custom permission group module is ignored --- @treturn Roles._prototype allows chaining +--[[-- Sets the permission group for this role, players will be moved to the group of they highest role +@tparam string name the name of the permission group to have players moved to +@tparam[opt=false] boolean use_factorio_api when true the custom permission group module is ignored +@treturn Roles._prototype allows chaining + +@usage-- Set the permission group for this role, see permission_groups.lua +role:set_permission_group('Admin') + +]] function Roles._prototype:set_permission_group(name,use_factorio_api) + _C.error_if_runtime() if use_factorio_api then self.permission_group = {true,name} else @@ -595,11 +791,17 @@ function Roles._prototype:set_permission_group(name,use_factorio_api) return self end ---- Sets the parent for a role, any action not in allow or disallow will be looked for in its parents --- nb: this is a recursive action, and changing the allows and disallows will effect all children roles --- @tparam string role the name of the role that will be the parent; has imminent effect if role is already defined --- @treturn Roles._prototype allows chaining +--[[-- Sets the parent for a role, any action not in allow or disallow will be looked for in its parents +nb: this is a recursive action, and changing the allows and disallows will effect all children roles +@tparam string role the name of the role that will be the parent; has imminent effect if role is already defined +@treturn Roles._prototype allows chaining + +@usage-- Set the parent for this role to inherit all actions allowed +role:set_parent('Guest') + +]] function Roles._prototype:set_parent(role) + _C.error_if_runtime() self.parent = role role = Roles.get_role_from_any(role) if not role then return self end @@ -607,18 +809,31 @@ function Roles._prototype:set_parent(role) return self end ---- Sets an auto promote condition that is checked every 5 seconds, if true is returned then the player will receive the role --- nb: this is one way, failing false after already gaining the role will not revoke the role --- @tparam function callback receives only one param which is player to promote, return true to promote the player --- @treturn Roles._prototype allows chaining -function Roles._prototype:set_auto_promote_condition(callback) +--[[-- Sets an auto assign condition that is checked every 60 seconds, if true is returned then the player will receive the role +nb: this is one way, failing false after already gaining the role will not revoke the role +@tparam function callback receives only one param which is player to promote, return true to promote the player +@treturn Roles._prototype allows chaining + +@usage-- Give this role to a user if there are admin, ran every 60 seconds +role:set_auto_assign_condition(function(player) + return player.admin +end) + +]] +function Roles._prototype:set_auto_assign_condition(callback) + _C.error_if_runetime_closure(callback) self.auto_promote_condition = callback return self end ---- Sets the role to not allow players to have auto promote effect them, useful to keep people locked to a punishment --- @tparam[opt=true] boolean state when true the players with this role will not be auto promoted --- @treturn Roles._prototype allows chaining +--[[-- Sets the role to not allow players to have auto assign effect them, useful to keep people locked to a role +@tparam[opt=true] boolean state when true the players with this role will not be auto assigned to other roles +@treturn Roles._prototype allows chaining + +@usage-- Make a role stop players from being auto assigned to other roles +role:set_block_auto_promote() + +]] function Roles._prototype:set_block_auto_promote(state) if state == nil then state = true end self.block_auto_promote = not not state -- forces a boolean value @@ -629,11 +844,16 @@ end -- Functions that control players in a role -- @section players ---- Adds a player to this role, players can have more than one role at a time, used internally see Roles.assign --- @tparam LuaPlayer player the player that will be given this role --- @tparam boolean skip_check when true player will be taken as the player name (use when player has not yet joined) --- @tparam boolean skip_event when true the event emit will be skipped, this is used internally with Roles.assign --- @treturn boolean true if the player was added successfully +--[[-- Adds a player to this role, players can have more than one role at a time, used internally see Roles.assign +@tparam LuaPlayer player the player that will be given this role +@tparam boolean skip_check when true player will be taken as the player name (use when player has not yet joined) +@tparam boolean skip_event when true the event emit will be skipped, this is used internally with Roles.assign +@treturn boolean true if the player was added successfully + +@usage-- Assign a player to this role +role:add_player(game.player) + +]] function Roles._prototype:add_player(player,skip_check,skip_event) player = Game.get_player_from_any(player) -- Default role cant have players added or removed @@ -663,11 +883,16 @@ function Roles._prototype:add_player(player,skip_check,skip_event) return true end ---- Removes a player from this role, players can have more than one role at a time, used internally see Roles.unassign --- @tparam LuaPlayer player the player that will lose this role --- @tparam boolean skip_check when true player will be taken as the player name (use when player has not yet joined) --- @tparam boolean skip_event when true the event emit will be skipped, this is used internally with Roles.unassign --- @treturn boolean true if the player was removed successfully +--[[-- Removes a player from this role, players can have more than one role at a time, used internally see Roles.unassign +@tparam LuaPlayer player the player that will lose this role +@tparam boolean skip_check when true player will be taken as the player name (use when player has not yet joined) +@tparam boolean skip_event when true the event emit will be skipped, this is used internally with Roles.unassign +@treturn boolean true if the player was removed successfully + +@usage-- Unassign a player from this role +role:remove_player(game.player) + +]] function Roles._prototype:remove_player(player,skip_check,skip_event) player = Game.get_player_from_any(player) -- Default role cant have players added or removed @@ -702,9 +927,17 @@ function Roles._prototype:remove_player(player,skip_check,skip_event) return rtn end ---- Returns an array of all the players who have this role, can be filtered by online status --- @tparam[opt=nil] boolean online when given will filter by this online state, nil will return all players --- @treturn table all the players who have this role, indexed order is meaningless +--[[-- Returns an array of all the players who have this role, can be filtered by online status +@tparam[opt=nil] boolean online when given will filter by this online state, nil will return all players +@treturn table all the players who have this role, indexed order is meaningless + +@usage-- Get all the players with this role +local players = role:get_players() + +@usage-- Get all online players with this role +local players = role:get_players(true) + +]] function Roles._prototype:get_players(online) local players = {} -- Gets all players that have this role @@ -733,9 +966,14 @@ function Roles._prototype:get_players(online) end end ---- Will print a message to all players with this role --- @tparam string message the message that will be printed to the players --- @treturn number the number of players who received the message +--[[-- Will print a message to all players with this role +@tparam string message the message that will be printed to the players +@treturn number the number of players who received the message + +@usage-- Print a message to all players with this role +role:print('Hello, World!') + +]] function Roles._prototype:print(message) local players = self:get_players(true) for _,player in pairs(players) do @@ -748,9 +986,9 @@ end local function role_update(event) local player = Game.get_player_by_index(event.player_index) -- Updates flags given to the player - for flag,sudo_name in pairs(Roles.config.flags) do + for flag, async_token in pairs(Roles.config.flags) do local state = Roles.player_has_flag(player,flag) - Sudo(sudo_name,player,state) + Async(async_token, player, state) end -- Updates the players permission group local highest = Roles.get_player_highest_role(player) @@ -758,10 +996,10 @@ local function role_update(event) if highest.permission_group[1] then local group = game.permissions.get_group(highest.permission_group[2]) if group then - Sudo('add-player-to-permission-group',group,player) + Async(Groups.async_token_add_to_permission_group, group, player) end else - Groups.set_player_group(player,highest.permission_group) + Groups.set_player_group(player, highest.permission_group) end end end diff --git a/expcore/store.lua b/expcore/store.lua index f58e41b9..ffb2afa8 100644 --- a/expcore/store.lua +++ b/expcore/store.lua @@ -27,7 +27,7 @@ local player_scores = Store.register(function(player) -- Use player name as the end) -- When any key in the store is changed this function will trigger -Store.watch(player_scores,function(value,key) +Store.watch(player_scores,function(value,key,old_value) game.print(key..' now has a score of '..value) end) @@ -175,7 +175,7 @@ local player_scores = Store.register(function(player) end) -- Register the watcher so that when we change the value the message is printed -Store.watch(player_scores,function(value,key) +Store.watch(player_scores,function(value,key,old_value) game.print(key..' now has a score of '..value) end) @@ -274,18 +274,21 @@ Store.clear(player_scores) ]] function Store.clear(store,key) key = Store.validate(store,key,2) + local old_value -- Check if there is a key being used if key then if type(data_store[store]) == 'table' then + old_value = data_store[store][key] data_store[store][key] = nil end else + old_value = data_store[store] data_store[store] = nil end -- Trigger any watch functions - Store.raw_trigger(store,key,nil) + Store.raw_trigger(store,key,nil,old_value) end --[[-- Used to set the data in a store, will trigger any watchers, key is optional depending on if you are using them @@ -325,19 +328,22 @@ function Store.set(store,key,value) -- Check the store is valid key = Store.validate(store,key,2) + local old_value -- If there is a key being used then the store must be a able if key then if type(data_store[store]) ~= 'table' then data_store[store] = {_value = data_store[store]} end + old_value = data_store[store][key] data_store[store][key] = value else + old_value = data_store[store] data_store[store] = value end -- Trigger any watchers - Store.raw_trigger(store,key,value) + Store.raw_trigger(store,key,value,old_value) end --[[-- Used to update the data in a store, use this with tables, will trigger any watchers, key is optional depending on if you are using them @@ -386,7 +392,7 @@ function Store.update(store,key,updater) -- Check the store is valid key = Store.validate(store,key,2) - local value + local value, old_value -- If a key is used then the store must be a table if key then @@ -397,6 +403,7 @@ function Store.update(store,key,updater) -- Call the updater and if it returns a value then set this value local rtn = updater(data_store[store][key]) if rtn then + old_value = data_store[store][key] data_store[store][key] = rtn end value = data_store[store][key] @@ -405,6 +412,7 @@ function Store.update(store,key,updater) -- Call the updater and if it returns a value then set this value local rtn = updater(data_store[store]) if rtn then + old_value = data_store[store][key] data_store[store] = rtn end value = data_store[store] @@ -412,7 +420,7 @@ function Store.update(store,key,updater) end -- Trigger any watchers - Store.raw_trigger(store,key,value) + Store.raw_trigger(store,key,value,old_value) end --[[-- Used to update all values that are in a store, similar to Store.update but acts on all keys at once, will trigger watchers for every key present @@ -445,7 +453,7 @@ function Store.map(store,updater) -- Get all that data in the store and check its a table local data = data_store[store] - if not type(data) == 'table' then + if type(data) ~= 'table' then return end @@ -455,7 +463,7 @@ function Store.map(store,updater) if rtn then data[key] = rtn end - Store.raw_trigger(store,key,data[key]) + Store.raw_trigger(store,key,data[key],value) end end @@ -476,9 +484,10 @@ function Store.trigger(store,key) -- Get the data from the data store local data = data_store[store] if key then - Store.raw_trigger(store,key,data[key]) + data = data[key] + Store.raw_trigger(store,key,data,data) else - Store.raw_trigger(store,key,data) + Store.raw_trigger(store,key,data,data) end end @@ -486,6 +495,7 @@ end @tparam number store the uid of the store that you want to trigger @tparam[opt] ?string|any key the key that you want to trigger, must be a string unless you have a serializer @tparam[opt] any value the new value that is at this key or store, passed directly to the watcher +@tparam[opt] any old_value the old value that was at this key or store often the same if value is a table, passed directly to the watcher @usage-- Triggering a manule call of the watchers -- The type of store we use does not really matter for this as long as you pass it what you watchers are expecting @@ -493,16 +503,16 @@ local scenario_diffculty = Store.register() -- Trigger the watchers with a fake change of diffculty -- This is mostly used internally but it can be useful in other cases -Store.raw_trigger(scenario_diffculty,nil,'normal') +Store.raw_trigger(scenario_diffculty,nil,'normal','normal') ]] -function Store.raw_trigger(store,key,value) +function Store.raw_trigger(store,key,value,old_value) key = Store.validate(store,key,2) -- Get the watchers and then loop over them local watchers = Store.watchers[store] or {} for _,watcher in pairs(watchers) do - local success, err = pcall(watcher,value,key) + local success, err = pcall(watcher,value,key,old_value) if not success then error('Store watcher casued an error:\n\t'..err) end diff --git a/expcore/sudo.lua b/expcore/sudo.lua deleted file mode 100644 index 630e50af..00000000 --- a/expcore/sudo.lua +++ /dev/null @@ -1,76 +0,0 @@ ---[[-- Core Module - Sudo - - An extention of task and token to allow a single require to register and run functions bypassing all permissions. - @core Sudo - @alias Sudo - - @usage - -- To use sudo you must register the allowed functions when the files are loaded, often this will just be giving access to - -- some functions within a module if you expect that some parts may be blocked by in game permissions or a custom system you have made - - -- This will be blocked if the current player (from a command or gui) is not admin - local function make_admin(player) - player.admin = true - end - - -- Here we give sudo access to the function under the name "make-admin" - Sudo.register('make-admin',make_admin) - - -- This will allow us to bypass this by running one tick later outside of any player scope - Sudo.run('make-admin',game.player) -]] -local Task = require 'utils.task' --- @dep utils.task -local Token = require 'utils.token' --- @dep utils.token - -local Sudo = { - tokens={} -} - -local internal_run = -Token.register(function(params) - local func = Token.get(params.token) - func(unpack(params.params)) -end) - ---- Registers a new callback under the given name, used to avoid desyncs --- @tparam string name the name that will be used to call this function --- @tparam function callback the function that will be called by this name -function Sudo.register(name,callback) - if _LIFECYCLE == 8 then - error('Calling Sudo.register after on_init() or on_load() has run is a desync risk.', 2) - end - - if Sudo.tokens[name] then - error(name..' is already registered',2) - end - - Sudo.tokens[name] = Token.register(callback) -end - ---- Gets the function that is registered under the given name --- @tparam string name the name of the function you want to get -function Sudo.get(name) - local token = Sudo.tokens[name] - return token and Token.get(token) -end - ---- Runs the function that is registered under the given name, you may supply any number of params as needed --- @tparam string name the name of the function you want to run --- @tparam[opt] any ... the other params that you want to pass to your function -function Sudo.run(name,...) - local token = Sudo.tokens[name] - - if not token then - error('Sudo does not have access to run "'..tostring(name)..'" please make sure it is registered to sudo',2) - end - - Task.set_timeout_in_ticks(1, internal_run, { - token = token, - params = {...} - }) -end - -return setmetatable(Sudo,{ - __call = function(self,...) - self.run(...) - end -}) \ No newline at end of file diff --git a/locale/en/addons.cfg b/locale/en/addons.cfg index ef2102fe..4cb4c837 100644 --- a/locale/en/addons.cfg +++ b/locale/en/addons.cfg @@ -13,6 +13,7 @@ wiki=https://wiki.explosivegaming.nl/ feedback=https://exp.fider.io/ status=https://status.explosivegaming.nl github=https://github.com/explosivegaming/scenario +patreon=https://www.patreon.com/ExpGaming [info] players-online=There are __1__ players online @@ -23,8 +24,9 @@ wiki=You can get more information about us and the custom scenario from our wiki feedback=Do you have feedback? leave it at https://exp.fider.io/ status=Want to check if out servers are down? Visit: https://status.explosivegaming.nl github=Want to help improve our server with some extra features? Help us at: https://github.com/explosivegaming/scenario +patreon=Consider supporting our server at: https://www.patreon.com/ExpGaming 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) +read-readme=Make sure you have read the information gui (It can be found through the info mark on the top left) softmod=We run a softmod on our servers. A softmod is a custom scenario that runs on this server, an example is the player list. redmew=We don't talk about redmew here; they beat us to 1000 members ;-; lhd=All trains must be LHD! This is a long standing rule on our servers, please respect this. @@ -33,11 +35,11 @@ lhd=All trains must be LHD! This is a long standing rule on our servers, please received=You received a warning from __1__. You have __2__ warnings. __3__ pre-kick=This is your last warning before you are kicked. kick=You were kicked for having too many warnings; you may rejoin if you wish. -pre-pre-ban=You are close to receiving a ban; Successful ban appeals are unlikely. +pre-pre-ban=You are close to receiving a ban; successful ban appeals are unlikely. pre-ban=This your LAST warning before you are BANNED! Successful ban appeals are unlikely. -ban=You were banned for having too many warnings; Visit __1__ to request a ban appeal. -script-warning=You are receiving script warnings; if you receive too many you will receive a permanent warning (__1__/__2__) -script-wrning-removed=A script warning has expired (__1__/__2__) +ban=You were banned for having too many warnings; visit __1__ to request a ban appeal. +script-warning=You are receiving script warnings; if you recive too many you will receive a permanent warning (__1__/__2__) +script-warning-removed=A script warning has expired (__1__/__2__) script-warning-limit=__1__ has received a permanent warning from the script. [chat-bot] @@ -45,7 +47,6 @@ reply=[Chat Bot] __1__ disallow=You can't 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 and is not a factorio dev. softmod=A softmod is a custom scenario that runs on this server,an example is the player list. blame=Blame __1__ for what just happened! @@ -57,3 +58,26 @@ riot=(admins) ┬┴┬┴┤ᵒ_ᵒ)├┬┴┬┴ ‹ ‹\(´ω` )/››‹ loops=NO LOOPS; LOOPS ARE BAD; JUST NO LOOPS!!!!!; IF YOU MAKE A LOOP.... IT WILL NOT END WELL!!!!!!! lenny=( ͡° ͜ʖ ͡°) hodor=Hodor +get-popcorn-1=Heating the oil and waiting for the popping sound... +get-popcorn-2=__1__ your popcorn is finished. Lean backwards and watch the drama unfold. +get-snaps-1=Pouring the glasses and finding the correct song book... +get-snaps-2=Singing a song...🎤🎶 +get-snaps-3=schkål, my friends! +get-cocktail-1= 🍸 Inintiating mind reading unit... 🍸 +get-cocktail-2= 🍸 Mixing favourite ingredients of __1__ 🍸 +get-cocktail-3=🍸 __1__ your cocktail is done.🍸 +make-coffee-1= ☕ Boiling the water and grinding the coffee beans... ☕ +make-coffee-2= ☕ __1__ we ran out of coffe beans! Have some tea instead. ☕ +order-pizza-1= 🍕 Finding nearest pizza supplier... 🍕 +order-pizza-2= 🍕 Figuring out the favourite pizza of __1__ 🍕 +order-pizza-3= 🍕 __1__ your pizza is here! 🍕 +make-tea-1= ☕ Boiling the water... ☕ +make-tea-2= ☕ __1__ your tea is done! ☕ +get-mead-1= Filling the drinking horn +get-mead-2= Skål! +get-beer-1= 🍺 Pouring A Glass 🍺 +get-beer-2= 🍻 Chears Mate 🍻 +verify=Please return to our discord and type r!verify __1__ + +[greetings] +greet=[color=0,1,0] Welcome to explosive gaming community server! If you like the server join our discord: __1__ [/color] \ No newline at end of file diff --git a/locale/en/commands.cfg b/locale/en/commands.cfg index 2fdbea0b..081b8f36 100644 --- a/locale/en/commands.cfg +++ b/locale/en/commands.cfg @@ -10,7 +10,7 @@ to-self=Player can not be teleported to themselves. [expcom-chelp] title=Help results for "__1__": -footer=[__1__ results found; page __2__ of __3__] +footer=[__1__ results found: page __2__ of __3__] format=/__1__ __2__ - __3__ __4__ alias=Alias: __1__ out-of-range=__1__ is an invalid page number. @@ -59,9 +59,20 @@ result=__1__ entites were revived and __2__ were healed to max health. set=Your bonus has been set to __1__. wip=This command is temporary and will be replaced at some point in the future. +[expcom-ratio] +notSelecting=Please select an entetiy with a recpie. +item-in=You need __1__ per second of [item=__2__]. +fluid-in=You need __1__ per second of [fluid=__2__]. +item-out=This will result in: __1__ [item=__2__] per second. +fluid-out=This will result in: __1__ [fluid=__2__] per second. +machines=And you will need __1__ machines (with the same speed as this one) for this. + [expcom-home] no-home=You have no home set. no-return=You can't 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__ + +[expcom-server-ups] +no-ext=No external source was found, cannot display server ups. \ No newline at end of file diff --git a/locale/en/gui.cfg b/locale/en/gui.cfg index 91d1faf2..4adc9626 100644 --- a/locale/en/gui.cfg +++ b/locale/en/gui.cfg @@ -46,6 +46,8 @@ data-caption-avg-launch-n=Average Time __1__ data-tooltip-avg-launch-n=The average amount of time taken to launch the last __1__ rockets data-caption-milestone-n=Milestone __1__ data-tooltip-milestone-n=Time taken to each __1__ rockets +data-caption-milestone-next=N/A +data-tooltip-milestone-next=Not yet achieved progress-x-pos=X __1__ progress-y-pos=Y __1__ progress-label-tooltip=View on map @@ -91,7 +93,66 @@ cancel-tooltip=Discard changes edit-tooltip=Currently being edited by: __1__ edit-tooltip-none=Currently being edited by: Nobody discard-tooltip=Remove warp -timer-tooltip=Warp charge, charge time __1__ seconds +timer-tooltip=Warp cooldown takes __1__ seconds goto-tooltip=Go to x __1__ y __2__ goto-disabled=You must be on a warp point and have a full charge to warp goto-edit=Edit warp icon + +[readme] +main-tooltip=Infomation +welcome-tab=Welcome +welcome-tooltip=Welcome to Explosive Gaming +welcome-general=Welcome to Explosive Gaming; we host many factorio servers. While you are here, we ask you to follow our rules. You can find these in the tab above. You can also find our custom commands and links to our other servers. This map has been online for __2__.\nPlease note that our servers reset periodically, the next reset is: __1__ +welcome-roles=We run a custom role system to help protect the work of others. As a result you may not be able to use your deconstruction planner yet or drop item on the groud. Roles also give you access to some custom features such as adding tasks to our task list or making new warp points.\nYou have been assigned the roles: __1__ +welcome-chat=Chatting can be difficult for new players because it’s different than other games! It’s very simple, the button you need to press is the “GRAVE/TILDE” key (which is located under the “ESC key”) - If you would like to change the key, go to your Controls tab in options.\nThe setting you need to change is “Toggle chat (and Lua console)” you currently have it set to "__CONTROL__toggle-console__" +rules-tab=Rules +rules-tooltip=Rules for our server +rules-general=By playing on our servers you accept the rules below. If you are supected of breaking a rule then you will be questioned by one of our moderators. If required you will be banned from our servers, appeals can be made by contacting an Administrator on our discord. +rules-1=Hacking / cheating / abusing bugs will not be tolerated. +rules-2=Any bugs or exploits found should be reported to our staff members. +rules-3=Be respectful to other players in chat, this includes any other forms of communication. +rules-4=Taking all items from a belt or logistics network is forbidden: sharing resources is mandatory. +rules-5=Spamming of chat, bots, unlimited chests, or concrete is not allowed. +rules-6=Before removing major parts of the factory tell other players why you are removing it. +rules-7=Do not cause unnecessary lag by placing/removing tiles with bots or using active provider chests, if think some thing might cause lag please ask staff first. +rules-8=Do not walk in random directions with no reason, this is to reduce map download times. +rules-9=Do not use speakers on global or with alerts without prior permission, no one wants to hear your music at full volume without knowing where the off switch is. +rules-10=Do not rotate belts, deactivate belts with wires, or cause production to stop without good reason, this goes for inserters and spliters as well. +rules-11=Do not make train roundabouts. Other loops such as RoRo stations are allowed. +rules-12=When using trains, use the same size other players have used, many players use 1-2-1, 2-4-2, or 3-8-3, meaning 1 engine 2 cargo 1 engine. +rules-13=Trains are Left Hand Drive (LHD) only, this means trains drive on the left side of the tracks. +rules-14=Do not beg for roles, advertise other servers, or link to harmful sites. +rules-15=Use common sense, report rule breakers, and Administrators have the final word. +commands-tab=Commands +commands-tooltip=Commands which you are able to use +commands-general=We have lots of custom commands which you are able to use. Below you can find a list of all the commands that you are allowed to use and what they do. If you need more information or want to search for a command you can use our /search-help command. +servers-tab=Servers +servers-tooltip=Links to our other servers and sites +servers-general=This is only one of our servers for factorio, we host many of others as well. Below you can find details about all the servers that we host as well as links to our external services such as discord or github. +servers-factorio=Factorio Servers +servers-1=S1 Public +servers-d1=This is our 48 hour reset experimental server. +servers-2=S2 Public +servers-d2=This is our 48 hour reset stable server. +servers-3=S3 Weekly +servers-d3=This is our weekly reset experimental server. +servers-4=S4 Weekly +servers-d4=This is our weekly reset stable server. +servers-5=S5 Modded +servers-d5=This is our modded server, see discord for details. +servers-6=S6 Donator +servers-d6=This is our donator only server, online when requested. +servers-7=S7 Event +servers-d7=This is our event server, we try to run events at least once per week. +servers-8=S8 T̷-̶s̶-̴:̷ +servers-d8=N̵o̴ ̶o̷-̶e̵ ̴k̸n̷-̶w̵s̸ ̴w̷h̷a̶-̶ ̷h̴a̴p̷p̴e̷n̷s̸ ̷o̶n̴ ̷t̶h̴-̶s̶ ̷s̷e̶r̸v̸e̴r̷,̶ ̸i̸t̴ ̷m̶-̸g̴h̶t̷ ̸n̸-̶t̵ ̷e̴v̸e̸n̶t̷ ̵-̷x̴i̵s̶t̸.̸ +servers-external=External Links +servers-open-in-browser=Open in your browser +backers-tab=Backers +backers-tooltip=People who have helped make our server +backers-general=We would like to thank all our staff and backers who have helped our community grow. Our staff have helped to keep our servers safe from trolls and a fun place to play. Our backers have helped us to cover our running costs and provide a great community for us all to enjoy together. +backers-management=Administrators +backers-board=Board Members and Senior Backers +backers-staff=Staff Members +backers-backers=Sponsors and Supporters +backers-active=Active Players \ No newline at end of file diff --git a/modules/addons/advanced-start.lua b/modules/addons/advanced-start.lua index fea02aea..3e93c853 100644 --- a/modules/addons/advanced-start.lua +++ b/modules/addons/advanced-start.lua @@ -22,6 +22,7 @@ Event.add(defines.events.on_player_created, function(event) local stats = player.force.item_production_statistics local made = stats.get_input_count(item) local success,count = pcall(callback,made,stats.get_input_count,player) + count = math.floor(count) if success and count > 0 then player.insert{name=item,count=count} end diff --git a/modules/addons/chat-popups.lua b/modules/addons/chat-popups.lua index 814478a5..d27672a6 100644 --- a/modules/addons/chat-popups.lua +++ b/modules/addons/chat-popups.lua @@ -9,6 +9,7 @@ local config = require 'config.popup_messages' --- @dep config.popup_messages local send_text = Game.print_player_floating_text -- (player_index, text, color) Event.add(defines.events.on_console_chat,function(event) + if not event.player_index or event.player_index < 1 then return end local player = Game.get_player_by_index(event.player_index) -- Some basic sanity checks @@ -28,7 +29,7 @@ Event.add(defines.events.on_console_chat,function(event) -- Loops over online players to see if they name is included for _,mentioned_player in pairs(game.connected_players) do if mentioned_player.index ~= player.index then - if search_string:match(mentioned_player.name:lower()) then + if search_string:match(mentioned_player.name:lower(), 1, true) then send_text(mentioned_player.index,{'chat-popup.ping',player.name},player.chat_color) end end diff --git a/modules/addons/chat-reply.lua b/modules/addons/chat-reply.lua index 4a17d70c..a4685ef3 100644 --- a/modules/addons/chat-reply.lua +++ b/modules/addons/chat-reply.lua @@ -28,7 +28,7 @@ Event.add(defines.events.on_console_chat,function(event) else player.print{'chat-bot.disallow'} end - else + elseif not allowed then player.print{'chat-bot.reply',reply} end end diff --git a/modules/addons/death-logger.lua b/modules/addons/death-logger.lua index fb188f82..2e6d90d0 100644 --- a/modules/addons/death-logger.lua +++ b/modules/addons/death-logger.lua @@ -5,7 +5,7 @@ local Event = require 'utils.event' --- @dep utils.event local Game = require 'utils.game' --- @dep utils.game local Global = require 'utils.global' --- @dep utils.global local config = require 'config.death_logger' --- @dep config.death_logger -local format_time,move_items = ext_require('expcore.common','format_time','move_items') --- @dep expcore.common +local format_time,move_items = _C.format_time, _C.move_items --- @dep expcore.common local deaths = { archive={} -- deaths moved here after body is gone diff --git a/modules/addons/discord-alerts.lua b/modules/addons/discord-alerts.lua index 5aabc77e..a76c4a79 100644 --- a/modules/addons/discord-alerts.lua +++ b/modules/addons/discord-alerts.lua @@ -3,8 +3,8 @@ local Event = require 'utils.event' --- @dep utils.event local Game = require 'utils.game' --- @dep utils.game -local Colors = require 'resources.color_presets' --- @dep resources.color_presets -local write_json,format_time = ext_require('expcore.common','write_json','format_time') --- @dep expcore.common +local Colors = require 'utils.color_presets' --- @dep utils.color_presets +local write_json,format_time = _C.write_json, _C.format_time --- @dep expcore.common local config = require 'config.discord_alerts' --- @dep config.discord_alerts local function get_player_name(event) @@ -20,7 +20,7 @@ local function to_hex(color) return hex_digits:sub(major,major)..hex_digits:sub(minor,minor) end - return hex(color.r)..hex(color.g)..hex(color.b) + return '0x'..hex(color.r)..hex(color.g)..hex(color.b) end local function emit_event(args) @@ -129,6 +129,58 @@ if config.player_warnings then end) end +--- When a player is jailed or unjailed +if config.player_jail then + local Jail = require 'modules.control.jail' + Event.add(Jail.events.on_player_jailed,function(event) + local player_name,by_player_name = get_player_name(event) + emit_event{ + title='Jail', + description='A player has been jailed', + color=Colors.yellow, + ['Player:']=''..player_name, + ['By:']=''..by_player_name, + ['Reason:']=event.reason + } + end) + Event.add(Jail.events.on_player_unjailed,function(event) + local player_name,by_player_name = get_player_name(event) + emit_event{ + title='Unjail', + description='A player has been unjailed', + color=Colors.green, + ['Player:']=''..player_name, + ['By:']=''..by_player_name + } + end) +end + +--- When a player is tempbanned +if config.player_temp_ban then + local Jail = require 'modules.control.jail' + Event.add(Jail.events.on_player_temp_banned,function(event) + local player_name,by_player_name = get_player_name(event) + emit_event{ + title='Temp Ban', + description='A player has been temp banned', + color=Colors.red, + ['Player:']=''..player_name, + ['By:']=''..by_player_name, + ['Reason:']=event.reason + } + end) + Event.add(Jail.events.on_player_untemp_banned,function(event) + local player_name,by_player_name = get_player_name(event) + emit_event{ + title='Temp Ban Removed', + description='A player has been untemp banned', + color=Colors.green, + ['Player:']=''..player_name, + ['By:']=''..by_player_name + } + end) +end + --- Ban and unban if config.player_bans then Event.add(defines.events.on_player_banned,function(event) @@ -230,7 +282,7 @@ Event.add(defines.events.on_console_command,function(event) description='/'..event.command..' was used', color=Colors.grey, ['By:']=''..player_name, - ['Details:']=event.parameters + ['Details:'] = event.parameters ~= '' and event.parameters or nil } end end diff --git a/modules/addons/greetings.lua b/modules/addons/greetings.lua new file mode 100644 index 00000000..4541f42e --- /dev/null +++ b/modules/addons/greetings.lua @@ -0,0 +1,26 @@ +--- Greets players on join +-- @addon greetings + +local Event = require 'utils.event' --- @dep utils.event +local Game = require 'utils.game' --- @dep utils.event +local config = require 'config.join_messages' --- @dep config.join_messages +local Global = require 'utils.global' --- @dep utils.global +require 'overrides.table' + +Global.register(config,function(tbl) + config = tbl +end) + +local greet = +function(event) + local player = Game.get_player_by_index(event.player_index) + local custom_message = config[player.name] + if custom_message then + game.print(custom_message,player.color) + else + player.print{'greetings.greet',{'links.discord'}} + end + +end + +Event.add(defines.events.on_player_joined_game, greet) \ No newline at end of file diff --git a/modules/addons/random-player-colours.lua b/modules/addons/random-player-colours.lua index 0677faa1..30526f20 100644 --- a/modules/addons/random-player-colours.lua +++ b/modules/addons/random-player-colours.lua @@ -1,12 +1,12 @@ --- Gives players random colours when they join, also applies preset colours to those who have them -- @addon Player-Colours -local Colours = require 'resources.color_presets' --- @dep resources.color_presets +local Colours = require 'utils.color_presets' --- @dep utils.color_presets local Game = require 'utils.game' --- @dep utils.game local Event = require 'utils.event' --- @dep utils.event local config = require 'config.preset_player_colours' --- @dep config.preset_player_colours local Global = require 'utils.global' --- @dep utils.global -require 'utils.table' +require 'overrides.table' Global.register(config,function(tbl) config = tbl diff --git a/modules/addons/scorched-earth.lua b/modules/addons/scorched-earth.lua index 82c361de..c6c822c5 100644 --- a/modules/addons/scorched-earth.lua +++ b/modules/addons/scorched-earth.lua @@ -4,7 +4,7 @@ local Event = require 'utils.event' --- @dep utils.event local Game = require 'utils.game' --- @dep utils.game local Global = require 'utils.global' --- @dep utils.global -local print_grid_value, clear_flying_text = ext_require('expcore.common','print_grid_value','clear_flying_text') --- @dep expcore.common +local print_grid_value, clear_flying_text = _C.print_grid_value, _C.clear_flying_text --- @dep expcore.common local config = require 'config.scorched_earth' --- @dep config.scorched_earth -- Loops over the config and finds the wile which has the highest value for strength diff --git a/modules/addons/station-auto-name.lua b/modules/addons/station-auto-name.lua new file mode 100644 index 00000000..feb8cd19 --- /dev/null +++ b/modules/addons/station-auto-name.lua @@ -0,0 +1,66 @@ +---LuaPlayerBuiltEntityEventFilters +---Events.set_event_filter(defines.events.on_built_entity, {{filter = "name", name = "fast-inserter"}}) +local Event = require 'utils.event' --- @dep utils.event +local station_name_changer = +function(event) + local enetety = event.created_entity + local name = enetety.name + + if name == "train-stop" then --only do the event if its a trainstop + local boundingbox = enetety.bounding_box + -- expanded box for recourse search: + local bounding2 = { {boundingbox.left_top.x -100 ,boundingbox.left_top.y -100} , {boundingbox.right_bottom.x +100,boundingbox.right_bottom.y +100 } } + --gets all resources in bounding_box2: + local recoursec = game.surfaces[1].find_entities_filtered{area = bounding2, type = "resource"} + + if #recoursec > 0 then -- save cpu time if their are no recourses in bounding_box2 + local closest_distance + local px,py = boundingbox.left_top.x,boundingbox.left_top.y + local recourse_closed + + --Check which recource is closest + for i, item in ipairs(recoursec) do + local dx, dy = px - item.bounding_box.left_top.x, py - item.bounding_box.left_top.y + local distance = (dx*dx)+(dy*dy) + if not closest_distance or distance < closest_distance then + recourse_closed = item + closest_distance = distance + end + + end + + + local item_name = recourse_closed.name + if item_name then -- prevent errors if something went wrong + local item_name2 = item_name:gsub("^%l", string.upper):gsub('-',' ') -- removing the - and making first letter capital + --Final string: + enetety.backer_name = string.format("[L] [img=item.%s] %s %s (%s)",item_name,item_name2,enetety.backer_name,Angle( enetety )) + end + end + end +end +--add func to robot and player build entities +Event.add(defines.events.on_built_entity,station_name_changer) +Event.add(defines.events.on_robot_built_entity,station_name_changer) + + +--Credit to Cooldude2606 for using his lua magic to make this function. +local directions = { + ['W'] = -0.875, + ['NW'] = -0.625, + ['N'] = -0.375, + ['NE'] = -0.125, + ['E'] = 0.125, + ['SE'] = 0.375, + ['S'] = 0.625, + ['SW'] = 0.875 +} +function Angle( enetety ) + local angle = math.atan2(enetety.position.y,enetety.position.x)/math.pi + for direction, requiredAngle in pairs(directions) do + if angle < requiredAngle then + return direction + end + end +end + \ No newline at end of file diff --git a/modules/addons/tree-decon.lua b/modules/addons/tree-decon.lua new file mode 100644 index 00000000..75f5738b --- /dev/null +++ b/modules/addons/tree-decon.lua @@ -0,0 +1,77 @@ +--- Makes trees which are marked for decon "decay" quickly to allow faster building +-- @addon Tree-Decon + +local Event = require 'utils.event' --- @dep utils.event +local Game = require 'utils.game' --- @dep utils.game +local Global = require 'utils.global' --- @dep utils.global +local Roles = require 'expcore.roles' --- @dep expcore.roles + +-- Global queue used to store trees that need to be removed, also chache for player roles +local chache = {} +local tree_queue = { _head=0 } +Global.register({ tree_queue, chache }, function(tbl) + tree_queue = tbl[1] + chache = tbl[2] +end) + +-- Add trees to queue when marked, only allows simple entities and for players with role permission +Event.add(defines.events.on_marked_for_deconstruction, function(event) + -- Check which type of decon a player is allowed + local index = event.player_index + if chache[index] == nil then + local player = Game.get_player_by_index(index) + if Roles.player_allowed(player, 'fast-tree-decon') then chache[index] = 'fast' + elseif Roles.player_allowed(player, 'standard-decon') then chache[index] = 'standard' + else chache[index] = player.force end + end + + -- Check what should happen to this entity + local entity = event.entity + local allow = chache[index] + if not entity or not entity.valid then return end + + -- Not allowed to decon this entity + local last_user = entity.last_user + if last_user and allow ~= 'standard' and allow ~= 'fast' then + entity.cancel_deconstruction(allow) + return + end + + -- Allowed to decon this entity, but not fast + if allow ~= 'fast' then return end + + -- Allowed fast decon on this entity, just trees + local head = tree_queue._head + 1 + if not last_user and entity.type ~= 'cliff' then + tree_queue[head] = entity + tree_queue._head = head + end + +end) + +-- Remove trees at random till the queue is empty +Event.add(defines.events.on_tick, function() + local head = tree_queue._head + if head == 0 then return end + + local max_remove = math.floor(head/100)+1 + local remove_count = math.random(0, max_remove) + while remove_count > 0 and head > 0 do + local remove_index = math.random(1,head) + local entity = tree_queue[remove_index] + tree_queue[remove_index] = tree_queue[head] + head = head - 1 + if entity and entity.valid then + remove_count = remove_count - 1 + entity.destroy() + end + end + tree_queue._head = head +end) + +-- Clear the chache +Event.on_nth_tick(300, function() + for key,_ in pairs(chache) do + chache[key] = nil + end +end) \ No newline at end of file diff --git a/modules/commands/admin-chat.lua b/modules/commands/admin-chat.lua index 63a5447d..19aae6cb 100644 --- a/modules/commands/admin-chat.lua +++ b/modules/commands/admin-chat.lua @@ -4,8 +4,8 @@ ]] local Commands = require 'expcore.commands' --- @dep expcore.commands -local format_chat_player_name = ext_require('expcore.common','format_chat_player_name') --- @dep expcore.common -require 'config.expcore-commands.parse_general' +local format_chat_player_name = _C.format_chat_player_name --- @dep expcore.common +require 'config.expcore.command_general_parse' --- Sends a message in chat that only admins can see -- @command admin-chat @@ -13,7 +13,7 @@ require 'config.expcore-commands.parse_general' Commands.new_command('admin-chat','Sends a message in chat that only admins can see.') :add_param('message',false) :enable_auto_concat() -:set_flag('admin_only',true) +:set_flag('admin_only') :add_alias('ac') :register(function(player,message,raw) local player_name_colour = format_chat_player_name(player) diff --git a/modules/commands/bonus.lua b/modules/commands/bonus.lua index 2a63c6d5..b39fc1f1 100644 --- a/modules/commands/bonus.lua +++ b/modules/commands/bonus.lua @@ -9,7 +9,7 @@ local Event = require 'utils.event' --- @dep utils.event local Game = require 'utils.game' --- @dep utils.game local Store = require 'expcore.store' --- @dep expcore.store local config = require 'config.bonuses' --- @dep config.bonuses -require 'config.expcore-commands.parse_general' +require 'config.expcore.command_general_parse' -- Store bonus percentages keyed by player name local bonus_store = Store.register(function(player) diff --git a/modules/commands/cheat-mode.lua b/modules/commands/cheat-mode.lua index caef97c9..c2eb462a 100644 --- a/modules/commands/cheat-mode.lua +++ b/modules/commands/cheat-mode.lua @@ -4,7 +4,7 @@ ]] local Commands = require 'expcore.commands' --- @dep expcore.commands -require 'config.expcore-commands.parse_general' +require 'config.expcore.command_general_parse' --- Toggles cheat mode for your player, or another player. -- @command toggle-cheat-mode @@ -14,7 +14,7 @@ Commands.new_command('toggle-cheat-mode','Toggles cheat mode for your player, or :set_defaults{player=function(player) return player -- default is the user using the command end} -:set_flag('admin_only',true) +:set_flag('admin_only') :register(function(player,action_player,raw) action_player.cheat_mode = not action_player.cheat_mode end) \ No newline at end of file diff --git a/modules/commands/clear-inventory.lua b/modules/commands/clear-inventory.lua index 587e8ce2..e684fb5e 100644 --- a/modules/commands/clear-inventory.lua +++ b/modules/commands/clear-inventory.lua @@ -4,8 +4,8 @@ ]] local Commands = require 'expcore.commands' --- @dep expcore.commands -local move_items = ext_require('expcore.common','move_items') --- @dep expcore.common -require 'config.expcore-commands.parse_roles' +local move_items = _C.move_items --- @dep expcore.common +require 'config.expcore.command_role_parse' --- Clears a players inventory -- @command clear-inventory diff --git a/modules/commands/debug.lua b/modules/commands/debug.lua index f0be73ba..e29786a6 100644 --- a/modules/commands/debug.lua +++ b/modules/commands/debug.lua @@ -9,6 +9,6 @@ local Commands = require 'expcore.commands' --- @dep expcore.commands --- Opens the debug pannel for viewing tables. -- @command debug Commands.new_command('debug','Opens the debug pannel for viewing tables.') -:register(function(player,raw) +:register(function(player) DebugView.open_dubug(player) end) \ No newline at end of file diff --git a/modules/commands/find.lua b/modules/commands/find.lua index f2770ab6..58ab5530 100644 --- a/modules/commands/find.lua +++ b/modules/commands/find.lua @@ -4,7 +4,7 @@ ]] local Commands = require 'expcore.commands' --- @dep expcore.commands -require 'config.expcore-commands.parse_general' +require 'config.expcore.command_general_parse' --- Find a player on your map. -- @command find-on-map diff --git a/modules/commands/help.lua b/modules/commands/help.lua index 92904650..af43910d 100644 --- a/modules/commands/help.lua +++ b/modules/commands/help.lua @@ -5,7 +5,7 @@ local Commands = require 'expcore.commands' --- @dep expcore.commands local Global = require 'utils.global' --- @dep utils.global -require 'config.expcore-commands.parse_general' +require 'config.expcore.command_general_parse' local results_per_page = 5 @@ -18,7 +18,8 @@ end) -- @command chelp -- @tparam string keyword the keyword that will be looked for -- @tparam number page the page of help to view, must be in range of pages -Commands.new_command('chelp','Searches for a keyword in all commands you are allowed to use.') +Commands.new_command('search-help','Searches for a keyword in all commands you are allowed to use.') +:add_alias('chelp','shelp','commands') :add_param('keyword',true) :add_param('page',true,'integer') :set_defaults{keyword='',page=1} diff --git a/modules/commands/home.lua b/modules/commands/home.lua index 0d0dd92a..c6ce9078 100644 --- a/modules/commands/home.lua +++ b/modules/commands/home.lua @@ -5,7 +5,7 @@ local Commands = require 'expcore.commands' --- @dep expcore.commands local Global = require 'utils.global' --- @dep utils.global -require 'config.expcore-commands.parse_general' +require 'config.expcore.command_general_parse' local homes = {} Global.register(homes,function(tbl) diff --git a/modules/commands/interface.lua b/modules/commands/interface.lua index 51b20ebf..5f105d45 100644 --- a/modules/commands/interface.lua +++ b/modules/commands/interface.lua @@ -17,7 +17,7 @@ local interface_modules = { ['Roles']='expcore.roles', ['Store']='expcore.store', ['Gui']='expcore.gui', - ['Sudo']='expcore.sudo' + ['Async']='expcore.async' } -- loads all the modules given in the above table @@ -63,7 +63,7 @@ end Commands.new_command('interface','Sends an innovation to be ran and returns the result.') :add_param('innovation',false) :enable_auto_concat() -:set_flag('admin_only',true) +:set_flag('admin_only') :register(function(player,innovation,raw) if not innovation:find('%s') and not innovation:find('return') then -- if there are no spaces and return is not present then return is appended to the start diff --git a/modules/commands/jail.lua b/modules/commands/jail.lua index c6c92954..59e12500 100644 --- a/modules/commands/jail.lua +++ b/modules/commands/jail.lua @@ -5,8 +5,8 @@ local Commands = require 'expcore.commands' --- @dep expcore.commands local Jail = require 'modules.control.jail' --- @dep modules.control.jail -local format_chat_player_name = ext_require('expcore.common','format_chat_player_name') --- @dep expcore.common -require 'config.expcore-commands.parse_roles' +local format_chat_player_name = _C.format_chat_player_name --- @dep expcore.common +require 'config.expcore.command_role_parse' --- Puts a player into jail and removes all other roles. -- @command jail @@ -20,7 +20,8 @@ Commands.new_command('jail','Puts a player into jail and removes all other roles reason = reason or 'Non Given.' local action_player_name_color = format_chat_player_name(action_player) local by_player_name_color = format_chat_player_name(player) - if Jail.jail_player(action_player,player.name,reason) then + local player_name = player and player.name or '' + if Jail.jail_player(action_player, player_name, reason) then game.print{'expcom-jail.give',action_player_name_color,by_player_name_color,reason} else return Commands.error{'expcom-jail.already-jailed',action_player_name_color} @@ -37,7 +38,8 @@ Commands.new_command('unjail','Removes a player from jail.') :register(function(player,action_player,raw) local action_player_name_color = format_chat_player_name(action_player) local by_player_name_color = format_chat_player_name(player) - if Jail.unjail_player(action_player,player.name) then + local player_name = player and player.name or '' + if Jail.unjail_player(action_player, player_name) then game.print{'expcom-jail.remove',action_player_name_color,by_player_name_color} else return Commands.error{'expcom-jail.not-jailed',action_player_name_color} diff --git a/modules/commands/kill.lua b/modules/commands/kill.lua index 2396be52..3fea3e9a 100644 --- a/modules/commands/kill.lua +++ b/modules/commands/kill.lua @@ -5,8 +5,8 @@ local Commands = require 'expcore.commands' --- @dep expcore.commands local Roles = require 'expcore.roles' --- @dep expcore.roles -require 'config.expcore-commands.parse_general' -require 'config.expcore-commands.parse_roles' +require 'config.expcore.command_general_parse' +require 'config.expcore.command_role_parse' --- Kills yourself or another player. -- @command kill diff --git a/modules/commands/rainbow.lua b/modules/commands/rainbow.lua index a5c03e53..350e0ae6 100644 --- a/modules/commands/rainbow.lua +++ b/modules/commands/rainbow.lua @@ -4,7 +4,7 @@ ]] local Commands = require 'expcore.commands' --- @dep expcore.commands -local format_chat_colour = ext_require('expcore.common','format_chat_colour') --- @dep expcore.common +local format_chat_colour = _C.format_chat_colour --- @dep expcore.common local function step_component(c1,c2) if c1 < 0 then diff --git a/modules/commands/ratio.lua b/modules/commands/ratio.lua new file mode 100644 index 00000000..dcdcb116 --- /dev/null +++ b/modules/commands/ratio.lua @@ -0,0 +1,85 @@ + + +local Commands = require 'expcore.commands' + + +Commands.new_command('ratio','This command will give the input and ouput ratios of the selected machine. Use the parameter for calcualting the machines needed for that amount of items per second.') + :add_param('itemsPerSecond',true,'number') + :register(function(player,itemsPerSecond,raw) + + local machine = player.selected -- selected machine + if not machine then --nil check + return Commands.error{'expcom-ratio.notSelecting'} + end + + if machine.type ~= "assembling-machine" and machine.type ~= "furnace" then + return Commands.error{'expcom-ratio.notSelecting'} + end + local recpie = machine.get_recipe() -- recpie + + if not recpie then --nil check + return Commands.error{'expcom-ratio.notSelecting'} + end + + local items = recpie.ingredients -- items in that recpie + local product = recpie.products -- output items + local amountOfMachines + local moduleInvetory = machine.get_module_inventory()--the module Invetory of the machine + local mult = Modules(moduleInvetory) --function for the productivety moduals + + if itemsPerSecond then + amountOfMachines = math.ceil( AmountOfMachines(itemsPerSecond,1/recpie.energy*machine.crafting_speed*product[1].amount*mult)) -- amount of machines + end + if not amountOfMachines then + amountOfMachines = 1 --set to 1 to make it not nil + end + ----------------------------items---------------------------- + for i, item in ipairs(items) do + local sprite -- string to make the icon work either fluid ore item + + if item.type == "item" then + sprite = 'expcom-ratio.item-in' + else + sprite = 'expcom-ratio.fluid-in' + end + + + local ips = item.amount/recpie.energy*machine.crafting_speed*amountOfMachines --math on the items/fluids per second + Commands.print {sprite,math.round(ips,3),item.name}-- full string + end + ----------------------------products---------------------------- + + for i, product in ipairs(product) do + local sprite -- string to make the icon work either fluid ore item + + if product.type == "item" then + sprite = 'expcom-ratio.item-out' + else + sprite = 'expcom-ratio.fluid-out' + end + + local output = 1/recpie.energy*machine.crafting_speed*product.amount*mult --math on the outputs per second + Commands.print {sprite,math.round(output*amountOfMachines,3),product.name} -- full string + + end + + if amountOfMachines ~= 1 then + Commands.print{'expcom-ratio.machines',amountOfMachines} + end + + end) +function Modules(moduleInvetory) -- returns the multeplier of the modules + local effect1 = moduleInvetory.get_item_count("productivity-module") -- type 1 + local effect2 = moduleInvetory.get_item_count("productivity-module-2")-- type 2 + local effect3 = moduleInvetory.get_item_count("productivity-module-3") -- type 3 + + local mult = effect1*4+effect2*6+effect3*10 + return mult/100+1 +end + +function AmountOfMachines(itemsPerSecond,output) + if(itemsPerSecond) then + return itemsPerSecond/output + + end +end diff --git a/modules/commands/repair.lua b/modules/commands/repair.lua index cd7d67d6..f7ff434c 100644 --- a/modules/commands/repair.lua +++ b/modules/commands/repair.lua @@ -5,7 +5,7 @@ local Commands = require 'expcore.commands' --- @dep expcore.commands local config = require 'config.repair' --- @dep config.repair -require 'config.expcore-commands.parse_general' +require 'config.expcore.command_general_parse' local max_time_to_live = 4294967295 -- unit32 max --- Repairs entities on your force around you diff --git a/modules/commands/reports.lua b/modules/commands/reports.lua index 8baaf5f3..93ab6008 100644 --- a/modules/commands/reports.lua +++ b/modules/commands/reports.lua @@ -6,8 +6,8 @@ local Roles = require 'expcore.roles' --- @dep expcore.roles local Commands = require 'expcore.commands' --- @dep expcore.commands local Reports = require 'modules.control.reports' --- @dep modules.control.reports -local format_chat_player_name = ext_require('expcore.common','format_chat_player_name') --- @dep expcore.common -require 'config.expcore-commands.parse_general' +local format_chat_player_name = _C.format_chat_player_name--- @dep expcore.common +require 'config.expcore.command_general_parse' --- Reports a player and notifies moderators -- @command report diff --git a/modules/commands/roles.lua b/modules/commands/roles.lua index 63575732..1005b322 100644 --- a/modules/commands/roles.lua +++ b/modules/commands/roles.lua @@ -5,11 +5,8 @@ local Commands = require 'expcore.commands' --- @dep expcore.commands local Roles = require 'expcore.roles' --- @dep expcore.roles -local Colours = require 'resources.color_presets' --- @dep resources.color_presets -local format_chat_player_name, format_chat_colour_localized = ext_require('expcore.common', - 'format_chat_player_name', - 'format_chat_colour_localized' -) +local Colours = require 'utils.color_presets' --- @dep utils.color_presets +local format_chat_player_name, format_chat_colour_localized = _C.format_chat_player_name, _C.format_chat_colour_localized --- Assigns a role to a player -- @command assign-role @@ -18,7 +15,7 @@ local format_chat_player_name, format_chat_colour_localized = ext_require('expco Commands.new_command('assign-role','Assigns a role to a player') :add_param('player',false,'player-role') :add_param('role',false,'role') -:set_flag('admin-only',true) +:set_flag('admin-only') :add_alias('rpromote','assign','role','add-role') :register(function(player,action_player,role,raw) local player_highest = Roles.get_player_highest_role(player) @@ -36,7 +33,7 @@ end) Commands.new_command('unassign-role','Unassigns a role from a player') :add_param('player',false,'player-role') :add_param('role',false,'role') -:set_flag('admin-only',true) +:set_flag('admin-only') :add_alias('rdemote','unassign','rerole','remove-role') :register(function(player,action_player,role,raw) local player_highest = Roles.get_player_highest_role(player) diff --git a/modules/commands/tag.lua b/modules/commands/tag.lua index e8c51e9b..a0400cf2 100644 --- a/modules/commands/tag.lua +++ b/modules/commands/tag.lua @@ -5,8 +5,8 @@ local Commands = require 'expcore.commands' --- @dep expcore.commands local Roles = require 'expcore.roles' --- @dep expcore.roles -require 'config.expcore-commands.parse_general' -require 'config.expcore-commands.parse_roles' +require 'config.expcore.command_general_parse' +require 'config.expcore.command_role_parse' --- Sets your player tag. -- @command tag diff --git a/modules/commands/teleport.lua b/modules/commands/teleport.lua index 2117f18d..5e8ea3b4 100644 --- a/modules/commands/teleport.lua +++ b/modules/commands/teleport.lua @@ -4,7 +4,7 @@ ]] local Commands = require 'expcore.commands' --- @dep expcore.commands -require 'config.expcore-commands.parse_general' +require 'config.expcore.command_general_parse' local function teleport(from_player,to_player) local surface = to_player.surface @@ -23,7 +23,7 @@ Commands.new_command('teleport','Teleports a player to another player.') :add_param('from_player',false,'player-alive') :add_param('to_player',false,'player-online') :add_alias('tp') -:set_flag('admin_only',true) +:set_flag('admin_only') :register(function(player,from_player,to_player,raw) if from_player.index == to_player.index then -- return if attempting to teleport to self @@ -40,7 +40,7 @@ end) -- @tparam LuaPlayer player the player that will be teleported, must be alive Commands.new_command('bring','Teleports a player to you.') :add_param('player',false,'player-alive') -:set_flag('admin_only',true) +:set_flag('admin_only') :register(function(player,from_player,raw) if from_player.index == player.index then -- return if attempting to teleport to self @@ -58,7 +58,7 @@ end) Commands.new_command('goto','Teleports you to a player.') :add_param('player',false,'player-online') :add_alias('tp-me','tpme') -:set_flag('admin_only',true) +:set_flag('admin_only') :register(function(player,to_player,raw) if to_player.index == player.index then -- return if attempting to teleport to self diff --git a/modules/commands/warnings.lua b/modules/commands/warnings.lua index 2cd5509c..42f7b868 100644 --- a/modules/commands/warnings.lua +++ b/modules/commands/warnings.lua @@ -5,9 +5,9 @@ local Commands = require 'expcore.commands' --- @dep expcore.commands local Warnings = require 'modules.control.warnings' --- @dep modules.control.warnings -local format_chat_player_name = ext_require('expcore.common','format_chat_player_name') --- @dep expcore.common +local format_chat_player_name = _C.format_chat_player_name --- @dep expcore.common local config = require 'config.warnings' --- @dep config.warnings -require 'config.expcore-commands.parse_roles' +require 'config.expcore.command_role_parse' --- Gives a warning to a player; may lead to automatic script action. -- @command give-warning diff --git a/modules/control/jail.lua b/modules/control/jail.lua index 89c9043c..a188d984 100644 --- a/modules/control/jail.lua +++ b/modules/control/jail.lua @@ -23,7 +23,7 @@ local Roles = require 'expcore.roles' --- @dep expcore.roles local Game = require 'utils.game' --- @dep utils.game local Global = require 'utils.global' --- @dep utils.global -local move_items = ext_require('expcore.common','move_items') --- @dep expcore.common +local move_items = _C.move_items --- @dep expcore.common local valid_player = Game.get_player_from_any local assign_roles = Roles.assign_player @@ -114,10 +114,10 @@ function Jail.jail_player(player,by_player_name,reason) local roles = get_roles(player) old_roles[player.name] = roles - assign_roles(player,'Jail',by_player_name,true) - unassign_roles(player,old_roles,by_player_name,true) + assign_roles(player, 'Jail', by_player_name, nil, true) + unassign_roles(player, roles, by_player_name, nil, true) - event_emit(Jail.events.on_player_jailed,player,by_player_name,reason) + event_emit(Jail.events.on_player_jailed, player, by_player_name, reason) return true end @@ -134,10 +134,10 @@ function Jail.unjail_player(player,by_player_name) if not has_role(player,'Jail') then return end local roles = old_roles[player.name] or {} - assign_roles(player,roles,by_player_name,true) - unassign_roles(player,'Jail',by_player_name,true) + assign_roles(player, roles, by_player_name, nil, true) + unassign_roles(player, 'Jail', by_player_name, nil, true) - event_emit(Jail.events.on_player_unjailed,player,by_player_name) + event_emit(Jail.events.on_player_unjailed, player, by_player_name) return true end @@ -174,8 +174,8 @@ function Jail.temp_ban_player(player,by_player_name,reason) local roles = get_roles(player) old_roles[player.name] = roles - assign_roles(player,'Jail',by_player_name,true) - unassign_roles(player,roles,by_player_name,true) + assign_roles(player, 'Jail', by_player_name, nil, true) + unassign_roles(player, roles, by_player_name, nil, true) end local inv = player.get_main_inventory() @@ -202,8 +202,8 @@ function Jail.untemp_ban_player(player,by_player_name) if has_role(player,'Jail') then local roles = old_roles[player.name] - assign_roles(player,roles,by_player_name,true) - unassign_roles(player,'Jail',by_player_name,true) + assign_roles(player, roles, by_player_name, nil, true) + unassign_roles(player, 'Jail', by_player_name, nil, true) end event_emit(Jail.events.on_player_untemp_banned,player,by_player_name) diff --git a/modules/control/production.lua b/modules/control/production.lua index d12c8477..026bad7c 100644 --- a/modules/control/production.lua +++ b/modules/control/production.lua @@ -32,8 +32,8 @@ ]] -local Colors = require 'resources.color_presets' --- @dep resources.color_presets -local format_number = ext_require('util','format_number') --- @dep util +local Colors = require 'utils.color_presets' --- @dep utils.color_presets +local format_number = require('util').format_number --- @dep util local precision_index = defines.flow_precision_index local Production = {} diff --git a/modules/control/rockets.lua b/modules/control/rockets.lua index 63e4928e..a09c74ce 100644 --- a/modules/control/rockets.lua +++ b/modules/control/rockets.lua @@ -27,7 +27,7 @@ local Event = require 'utils.event' --- @dep utils.event local Global = require 'utils.global' --- @dep utils.global -local config = require 'config.rockets' --- @dep config.rockets +local config = require 'config.gui.rockets' --- @dep config.rockets local largest_rolling_avg = 0 for _,avg_over in pairs(config.stats.rolling_avg) do @@ -135,12 +135,14 @@ end function Rockets.get_rolling_average(force_name,count) local force = game.forces[force_name] local rocket_count = force.rockets_launched + if rocket_count == 0 then return 0 end + local last_launch_time = rocket_times[force_name][rocket_count] local start_rocket_time = 0 if count < rocket_count then start_rocket_time = rocket_times[force_name][rocket_count-count+1] rocket_count = count end - return rocket_count > 0 and math.floor((game.tick-start_rocket_time)/rocket_count) or 0 + return math.floor((last_launch_time-start_rocket_time)/rocket_count) end --- Event used to update the stats and the hui when a rocket is launched diff --git a/modules/control/tasks.lua b/modules/control/tasks.lua index 6b2d9630..0806efde 100644 --- a/modules/control/tasks.lua +++ b/modules/control/tasks.lua @@ -89,8 +89,8 @@ Tasks.remove_task(task_id) function Tasks.remove_task(task_id) local task = Store.get(task_store,task_id) local force_name = task.force_name - Store.clear(task_store,task_id) table.remove_element(force_tasks[force_name],task_id) + Store.clear(task_store,task_id) end --[[-- Update the message and last edited information for a task diff --git a/modules/control/warnings.lua b/modules/control/warnings.lua index ebd3612d..2e6d057b 100644 --- a/modules/control/warnings.lua +++ b/modules/control/warnings.lua @@ -113,8 +113,8 @@ function Warnings.add_warning(player,by_player_name,reason) local warning_count = #warnings - script.raise_event(Warnings.on_warning_added,{ - name = Warnings.on_warning_added, + script.raise_event(Warnings.events.on_warning_added,{ + name = Warnings.events.on_warning_added, tick = game.tick, player_index = player.index, warning_count = warning_count, @@ -146,8 +146,8 @@ end -- @tparam string removed_by_name the name of the player who is doing the action -- @tparam number warning_count the number of warnings that the player how has local function warning_removed_event(player,warning_by_name,removed_by_name,warning_count) - script.raise_event(Warnings.on_warning_removed,{ - name = Warnings.on_warning_removed, + script.raise_event(Warnings.events.on_warning_removed,{ + name = Warnings.events.on_warning_removed, tick = game.tick, player_index = player.index, warning_count = warning_count, @@ -234,8 +234,8 @@ function Warnings.add_script_warning(player,reason) local warning_count = #warnings - script.raise_event(Warnings.on_script_warning_added,{ - name = Warnings.on_script_warning_added, + script.raise_event(Warnings.events.on_script_warning_added,{ + name = Warnings.events.on_script_warning_added, tick = game.tick, player_index = player.index, warning_count = warning_count, @@ -253,8 +253,8 @@ end -- @tparam LuaPlayer player the player who is having a script warning removed -- @tparam number warning_count the number of warning that the player has local function script_warning_removed_event(player,warning_count) - script.raise_event(Warnings.on_script_warning_removed,{ - name = Warnings.on_script_warning_removed, + script.raise_event(Warnings.events.on_script_warning_removed,{ + name = Warnings.events.on_script_warning_removed, tick = game.tick, player_index = player.index, warning_count = warning_count diff --git a/modules/control/warps.lua b/modules/control/warps.lua index ad503c3a..897b2bc1 100644 --- a/modules/control/warps.lua +++ b/modules/control/warps.lua @@ -24,8 +24,7 @@ Warps.make_warp_tag(warp_id) local Store = require 'expcore.store' --- @dep expcore.store local Global = require 'utils.global' --- @dep utils.global local Token = require 'utils.token' --- @dep utils.token -local config = require 'config.warps' --- @dep config.warps -local table_values,table_keysort = ext_require('expcore.common','table_values','table_keysort') --- @dep expcore.common +local config = require 'config.gui.warps' --- @dep config.warps local Warps = {} @@ -64,7 +63,7 @@ Store.watch(warp_store,function(warp,warp_id) end -- Sort the warp names in alphabetical order - local new_warp_ids = table_values(table_keysort(warp_names)) + local new_warp_ids = table.get_values(table.keysort(warp_names)) table.insert(new_warp_ids,1,spawn_id) new_warp_ids.spawn = spawn_id force_warps[force_name] = new_warp_ids @@ -150,7 +149,7 @@ function Warps.make_warp_area(warp_id) local position = warp.position local posx = position.x local posy = position.y - local radius = config.activation_range + local radius = config.standard_proximity_radius local radius2 = radius^2 -- Get the tile that is being replaced, store.update not needed as we dont want it to trigger @@ -203,7 +202,7 @@ function Warps.remove_warp_area(warp_id) local warp = Store.get(warp_store,warp_id) local position = warp.position local surface = warp.surface - local radius = config.activation_range + local radius = config.standard_proximity_radius local radius2 = radius^2 -- Check that a warp area was created previously diff --git a/modules/gui/debug/_g_view.lua b/modules/gui/debug/_g_view.lua index 33005bd2..2cf7490a 100644 --- a/modules/gui/debug/_g_view.lua +++ b/modules/gui/debug/_g_view.lua @@ -1,6 +1,6 @@ local Gui = require 'utils.gui' --- @dep utils.gui local Model = require 'modules.gui.debug.model' --- @dep modules.gui.debug.model -local Color = require 'resources.color_presets' --- @dep resources.color_presets +local Color = require 'utils.color_presets' --- @dep utils.color_presets local dump = Model.dump diff --git a/modules/gui/debug/event_view.lua b/modules/gui/debug/event_view.lua index bc372007..b56cb34f 100644 --- a/modules/gui/debug/event_view.lua +++ b/modules/gui/debug/event_view.lua @@ -1,7 +1,7 @@ -local Event = require 'utils.event' --- @dep utils.event -local table = require 'utils.table' --- @dep utils.table -local Gui = require 'utils.gui' --- @dep utils.gui -local Model = require 'modules.gui.debug.model' --- @dep modules.gui.debug.model +local Event = require 'utils.event' +local table = require 'overrides.table' +local Gui = require 'utils.gui' +local Model = require 'modules.gui.debug.model' local format = string.format local insert = table.insert @@ -19,13 +19,16 @@ local name_lookup = {} -- GUI names local checkbox_name = Gui.uid_name() +local filter_name = Gui.uid_name() +local clear_filter_name = Gui.uid_name() -- global tables local enabled = {} local last_events = {} global.debug_event_view = { enabled = enabled, - last_events = last_events + last_events = last_events, + filter = '' } function Public.on_open_debug() @@ -90,24 +93,73 @@ end table.sort(grid_builder) -function Public.show(container) - local main_frame_flow = container.add({type = 'flow', direction = 'vertical'}) - local scroll_pane = main_frame_flow.add({type = 'scroll-pane'}) - local gui_table = scroll_pane.add({type = 'table', column_count = 3, draw_horizontal_lines = true}) - +local function redraw_event_table(gui_table, filter) for _, event_name in pairs(grid_builder) do - local index = events[event_name] - gui_table.add({type = 'flow'}).add { - name = checkbox_name, - type = 'checkbox', - state = enabled[index] or false, - caption = event_name - } + if filter == '' or event_name:find(filter) then + local index = events[event_name] + gui_table.add({type = 'flow'}).add { + name = checkbox_name, + type = 'checkbox', + state = enabled[index] or false, + caption = event_name + } + end end end +function Public.show(container) + local filter = global.debug_event_view.filter + + local main_frame_flow = container.add({type = 'flow', direction = 'vertical'}) + + local filter_flow = main_frame_flow.add({type = 'flow', direction = 'horizontal'}) + filter_flow.add({type = 'label', caption = 'filter'}) + local filter_textfield = filter_flow.add({type = 'textfield', name = filter_name, text = filter}) + local clear_button = filter_flow.add({type = 'button', name = clear_filter_name, caption = 'clear'}) + + local scroll_pane = main_frame_flow.add({type = 'scroll-pane'}) + local gui_table = scroll_pane.add({type = 'table', column_count = 3, draw_horizontal_lines = true}) + + Gui.set_data(filter_textfield, gui_table) + Gui.set_data(clear_button, {gui_table = gui_table, filter_textfield = filter_textfield}) + + redraw_event_table(gui_table, filter) +end + Gui.on_checked_state_changed(checkbox_name, on_gui_checked_state_changed) +Gui.on_text_changed( + filter_name, + function(event) + local element = event.element + local gui_table = Gui.get_data(element) + + local filter = element.text:gsub(' ', '_') + + global.debug_event_view.filter = filter + element.text = filter + + gui_table.clear() + redraw_event_table(gui_table, filter) + end +) + +Gui.on_click( + clear_filter_name, + function(event) + local element = event.element + local data = Gui.get_data(element) + local filter_textfield = data.filter_textfield + local gui_table = data.gui_table + + filter_textfield.text = '' + global.debug_event_view.filter = '' + + gui_table.clear() + redraw_event_table(gui_table, '') + end +) + -- Event registers (TODO: turn to removable hooks.. maybe) for name, id in pairs(events) do name_lookup[id] = name diff --git a/modules/gui/debug/expcore_gui_view.lua b/modules/gui/debug/expcore_gui_view.lua new file mode 100644 index 00000000..468196e4 --- /dev/null +++ b/modules/gui/debug/expcore_gui_view.lua @@ -0,0 +1,128 @@ +local Gui = require 'utils.gui' --- @dep utils.gui +local ExpGui = require 'expcore.gui' --- @dep utils.global +local Color = require 'utils.color_presets' --- @dep utils.color_presets +local Model = require 'modules.gui.debug.model' --- @dep modules.gui.debug.model + +local dump = Model.dump +local dump_text = Model.dump_text +local concat = table.concat + +local Public = {} + +local header_name = Gui.uid_name() +local left_panel_name = Gui.uid_name() +local right_panel_name = Gui.uid_name() +local input_text_box_name = Gui.uid_name() +local refresh_name = Gui.uid_name() + +Public.name = 'Elements' + +function Public.show(container) + local main_flow = container.add {type = 'flow', direction = 'horizontal'} + + local left_panel = main_flow.add {type = 'scroll-pane', name = left_panel_name} + local left_panel_style = left_panel.style + left_panel_style.width = 300 + + for element_id, file_path in pairs(ExpGui.file_paths) do + local header = left_panel.add({type = 'flow'}).add {type = 'label', name = header_name, caption = element_id..' - '..file_path} + Gui.set_data(header, element_id) + end + + local right_flow = main_flow.add {type = 'flow', direction = 'vertical'} + + local right_top_flow = right_flow.add {type = 'flow', direction = 'horizontal'} + + local input_text_box = right_top_flow.add {type = 'text-box', name = input_text_box_name} + local input_text_box_style = input_text_box.style + input_text_box_style.horizontally_stretchable = true + input_text_box_style.height = 32 + input_text_box_style.maximal_width = 1000 + + local refresh_button = + right_top_flow.add {type = 'sprite-button', name = refresh_name, sprite = 'utility/reset', tooltip = 'refresh'} + local refresh_button_style = refresh_button.style + refresh_button_style.width = 32 + refresh_button_style.height = 32 + + local right_panel = right_flow.add {type = 'text-box', name = right_panel_name} + right_panel.read_only = true + right_panel.selectable = true + + local right_panel_style = right_panel.style + right_panel_style.vertically_stretchable = true + right_panel_style.horizontally_stretchable = true + right_panel_style.maximal_width = 1000 + right_panel_style.maximal_height = 1000 + + local data = { + right_panel = right_panel, + input_text_box = input_text_box, + selected_header = nil + } + + Gui.set_data(input_text_box, data) + Gui.set_data(left_panel, data) + Gui.set_data(refresh_button, data) +end + +Gui.on_click( + header_name, + function(event) + local element = event.element + local element_id = Gui.get_data(element) + + local left_panel = element.parent.parent + local data = Gui.get_data(left_panel) + local right_panel = data.right_panel + local selected_header = data.selected_header + local input_text_box = data.input_text_box + + if selected_header then + selected_header.style.font_color = Color.white + end + + element.style.font_color = Color.orange + data.selected_header = element + + input_text_box.text = concat {'Gui.defines[', element_id, ']'} + input_text_box.style.font_color = Color.black + + local content = dump(ExpGui.debug_info[element_id]) or 'nil' + right_panel.text = content + end +) + +local function update_dump(text_input, data, player) + local suc, ouput = dump_text(text_input.text, player) + if not suc then + text_input.style.font_color = Color.red + else + text_input.style.font_color = Color.black + data.right_panel.text = ouput + end +end + +Gui.on_text_changed( + input_text_box_name, + function(event) + local element = event.element + local data = Gui.get_data(element) + + update_dump(element, data, event.player) + end +) + +Gui.on_click( + refresh_name, + function(event) + local element = event.element + local data = Gui.get_data(element) + + local input_text_box = data.input_text_box + + update_dump(input_text_box, data, event.player) + end +) + +return Public diff --git a/modules/gui/debug/expcore_store_view.lua b/modules/gui/debug/expcore_store_view.lua index 2d115992..36ab8027 100644 --- a/modules/gui/debug/expcore_store_view.lua +++ b/modules/gui/debug/expcore_store_view.lua @@ -1,6 +1,6 @@ local Gui = require 'utils.gui' --- @dep utils.gui local Store = require 'expcore.store' --- @dep utils.global -local Color = require 'resources.color_presets' --- @dep resources.color_presets +local Color = require 'utils.color_presets' --- @dep utils.color_presets local Model = require 'modules.gui.debug.model' --- @dep modules.gui.debug.model local dump = Model.dump @@ -24,8 +24,8 @@ function Public.show(container) local left_panel_style = left_panel.style left_panel_style.width = 300 - for store_id, token_name in pairs(Store.file_paths) do - local header = left_panel.add({type = 'flow'}).add {type = 'label', name = header_name, caption = store_id..' - '..token_name} + for store_id, file_path in pairs(Store.file_paths) do + local header = left_panel.add({type = 'flow'}).add {type = 'label', name = header_name, caption = store_id..' - '..file_path} Gui.set_data(header, store_id) end diff --git a/modules/gui/debug/global_view.lua b/modules/gui/debug/global_view.lua index df057c47..3ab51d8d 100644 --- a/modules/gui/debug/global_view.lua +++ b/modules/gui/debug/global_view.lua @@ -1,6 +1,6 @@ local Gui = require 'utils.gui' --- @dep utils.gui local Model = require 'modules.gui.debug.model' --- @dep modules.gui.debug.model -local Color = require 'resources.color_presets' --- @dep resources.color_presets +local Color = require 'utils.color_presets' --- @dep utils.color_presets local dump = Model.dump local dump_text = Model.dump_text diff --git a/modules/gui/debug/main_view.lua b/modules/gui/debug/main_view.lua index 3c286a46..0771bdb1 100644 --- a/modules/gui/debug/main_view.lua +++ b/modules/gui/debug/main_view.lua @@ -1,11 +1,12 @@ local Gui = require 'utils.gui' --- @dep utils.gui -local Color = require 'resources.color_presets' --- @dep resources.color_presets +local Color = require 'utils.color_presets' --- @dep utils.color_presets local Public = {} local pages = { require 'modules.gui.debug.redmew_global_view', require 'modules.gui.debug.expcore_store_view', + require 'modules.gui.debug.expcore_gui_view', require 'modules.gui.debug.global_view', require 'modules.gui.debug.package_view', require 'modules.gui.debug._g_view', @@ -31,7 +32,7 @@ function Public.open_dubug(player) return end - frame = center.add {type = 'frame', name = main_frame_name, caption = 'Debuggertron 3001', direction = 'vertical'} + frame = center.add {type = 'frame', name = main_frame_name, caption = 'Debuggertron 3002', direction = 'vertical'} local frame_style = frame.style frame_style.height = 600 frame_style.width = 900 diff --git a/modules/gui/debug/model.lua b/modules/gui/debug/model.lua index ff120941..101ba30b 100644 --- a/modules/gui/debug/model.lua +++ b/modules/gui/debug/model.lua @@ -1,5 +1,5 @@ local Gui = require 'utils.gui' --- @dep utils.gui -local table = require 'utils.table' --- @dep utils.table +local table = require 'overrides.table' --- @dep overrides.table local gui_names = Gui.names local type = type diff --git a/modules/gui/debug/package_view.lua b/modules/gui/debug/package_view.lua index f29aafbb..292bf9d7 100644 --- a/modules/gui/debug/package_view.lua +++ b/modules/gui/debug/package_view.lua @@ -1,5 +1,5 @@ local Gui = require 'utils.gui' --- @dep utils.gui -local Color = require 'resources.color_presets' --- @dep resources.color_presets +local Color = require 'utils.color_presets' --- @dep utils.color_presets local Model = require 'modules.gui.debug.model' --- @dep modules.gui.debug.model local dump_function = Model.dump_function @@ -17,9 +17,9 @@ local ignore = { math = true, debug = true, serpent = true, - ['utils.math'] = true, + ['overrides.math'] = true, util = true, - ['utils.inspect'] = true, + ['overrides.inspect'] = true, ['mod-gui'] = true } diff --git a/modules/gui/debug/redmew_global_view.lua b/modules/gui/debug/redmew_global_view.lua index a62a6151..4bff705f 100644 --- a/modules/gui/debug/redmew_global_view.lua +++ b/modules/gui/debug/redmew_global_view.lua @@ -1,7 +1,7 @@ local Gui = require 'utils.gui' --- @dep utils.gui local Global = require 'utils.global' --- @dep utils.global local Token = require 'utils.token' --- @dep utils.token -local Color = require 'resources.color_presets' --- @dep resources.color_presets +local Color = require 'utils.color_presets' --- @dep utils.color_presets local Model = require 'modules.gui.debug.model' --- @dep modules.gui.debug.model local dump = Model.dump diff --git a/modules/gui/logo.png b/modules/gui/logo.png new file mode 100644 index 00000000..cef59c4d Binary files /dev/null and b/modules/gui/logo.png differ diff --git a/modules/gui/player-list.lua b/modules/gui/player-list.lua index 80e81c13..3eea3587 100644 --- a/modules/gui/player-list.lua +++ b/modules/gui/player-list.lua @@ -1,5 +1,5 @@ --[[-- Gui Module - Player List - - Adds a player list to show names and play time; also includes action buttons which can apply to players + - Adds a player list to show names and play time; also includes action buttons which can preform actions to players @gui Player-List @alias player_list ]] @@ -9,9 +9,9 @@ local Roles = require 'expcore.roles' --- @dep expcore.roles local Store = require 'expcore.store' --- @dep expcore.store local Game = require 'utils.game' --- @dep utils.game local Event = require 'utils.event' --- @dep utils.event -local format_time = ext_require('expcore.common','format_time') --- @dep expcore.common -local config = require 'config.action_buttons' --- @dep config.action_buttons -local Colors = require 'resources.color_presets' --- @dep resources.color_presets +local config = require 'config.gui.player_list_actions' --- @dep config.gui.player_list_actions +local Colors = require 'utils.color_presets' --- @dep utils.color_presets +local format_time = _C.format_time --- @dep expcore.common -- Stores the name of the player a player has selected local selected_player_store = Store.register(function(player) @@ -26,42 +26,21 @@ end) -- Set the config to use these stores config.set_store_uids(selected_player_store,selected_action_store) ---- Used to open the map on a player or toggle the settings -local zoom_to_map_name = Gui.uid_name() -Gui.on_click(zoom_to_map_name,function(event) - local selected_player_name = event.element.caption - local selected_player = Game.get_player_from_any(selected_player_name) - if event.button == defines.mouse_button_type.left then - -- LMB will open the map to the selected player - local position = selected_player.position - event.player.zoom_to_world(position,1.75) - else - -- RMB will toggle the settings - local player = event.player - local old_selected_player_name = Store.get(selected_player_store,player) - if selected_player_name == old_selected_player_name then - Store.clear(selected_player_store,player) - else - Store.set(selected_player_store,player,selected_player_name) - end - end -end) - --- Button used to open the action bar -- @element open_action_bar local open_action_bar = -Gui.new_button() -:set_sprites('utility/expand_dots_white') -:set_tooltip{'player-list.open-action-bar'} -:set_embedded_flow(function(element,selected_player_name) - return selected_player_name -end) -:set_style('frame_button',function(style) - Gui.set_padding_style(style,-2,-2,-2,-2) - style.width = 8 - style.height = 14 -end) -:on_click(function(player,element) +Gui.element{ + type = 'sprite-button', + sprite = 'utility/expand_dots_white', + tooltip = {'player-list.open-action-bar'}, + style = 'frame_button' +} +:style{ + padding = -2, + width = 8, + height = 14 +} +:on_click(function(player,element,_) local selected_player_name = element.parent.name local old_selected_player_name = Store.get(selected_player_store,player) if selected_player_name == old_selected_player_name then @@ -74,15 +53,14 @@ end) --- Button used to close the action bar -- @element close_action_bar local close_action_bar = -Gui.new_button() -:set_sprites('utility/close_black','utility/close_white') -:set_tooltip{'player-list.close-action-bar'} -:set_style('tool_button',function(style) - Gui.set_padding_style(style,-1,-1,-1,-1) - style.height = 28 - style.width = 28 -end) -:on_click(function(player,element) +Gui.element{ + type = 'sprite-button', + sprite = 'utility/close_black', + tooltip = {'player-list.close-action-bar'}, + style = 'shortcut_bar_button_red' +} +:style(Gui.sprite_style(30,-1,{ top_margin = -1, right_margin = -1 })) +:on_click(function(player,_) Store.clear(selected_player_store,player) Store.clear(selected_action_store,player) end) @@ -90,14 +68,13 @@ end) --- Button used to confirm a reason -- @element reason_confirm local reason_confirm = -Gui.new_button() -:set_sprites('utility/confirm_slot') -:set_tooltip{'player-list.reason-confirm'} -:set_style('tool_button',function(style) - Gui.set_padding_style(style,-1,-1,-1,-1) - style.height = 28 - style.width = 28 -end) +Gui.element{ + type = 'sprite-button', + sprite = 'utility/confirm_slot', + tooltip = {'player-list.reason-confirm'}, + style = 'shortcut_bar_button_green' +} +:style(Gui.sprite_style(30,-1,{ left_margin = -2, right_margin = -1 })) :on_click(function(player,element) local reason = element.parent.entry.text or 'Non Given' local action_name = Store.get(selected_action_store,player) @@ -108,109 +85,97 @@ end) element.parent.entry.text = '' end) ---[[ Creates the main gui areas for the player list - element - > container - >> scroll - >>> table - >> action_bar -]] -local function generate_container(player,element) - Gui.set_padding(element,2,2,2,2) - element.style.minimal_width = 200 +--- Set of elements that are used to make up a row of the player table +-- @element add_player_base +local add_player_base = +Gui.element(function(event_trigger,parent,player_data) + -- Add the button to open the action bar + local toggle_action_bar_flow = parent.add{ type = 'flow', name = player_data.name } + open_action_bar(toggle_action_bar_flow) - -- main container which contains the other elements - local container = - element.add{ - name='container', - type='frame', - direction='vertical', - style='window_content_frame_packed' + -- Add the player name + local player_name_flow = parent.add{ type = 'flow', name = 'player-name-'..player_data.index } + local player_name = player_name_flow.add{ + type = 'label', + name = event_trigger, + caption = player_data.name, + tooltip = {'player-list.open-map',player_data.name,player_data.tag,player_data.role_name} } - Gui.set_padding(container) + player_name.style.padding = {0,2,0,0} + player_name.style.font_color = player_data.chat_color - -- 3 wide table to contain: action button, player name, and play time - local list_table = Gui.create_scroll_table(container,3,188) - - -- action bar which contains the different action buttons - local action_bar = - container.add{ - name='action_bar', - type='frame', - style='subfooter_frame' + -- Add the time played label + local alignment = Gui.alignment(parent,'player-time-'..player_data.index) + local time_label = alignment.add{ + name = 'label', + type = 'label', + caption = player_data.caption, + tooltip = player_data.tooltip } - Gui.set_padding(action_bar,1,1,3,3) - action_bar.style.horizontally_stretchable = true - action_bar.style.height = 35 + time_label.style.padding = 0 - -- reason bar which contains the reason text field and confirm button - local reason_bar = - container.add{ - name='reason_bar', - type='frame', - style='subfooter_frame' - } - Gui.set_padding(reason_bar,-1,-1,3,3) - reason_bar.style.horizontally_stretchable = true - reason_bar.style.height = 35 - local action_name = Store.get(selected_action_store,player) - reason_bar.visible = action_name ~= nil + return time_label +end) +:on_click(function(player,element,event) + local selected_player_name = element.caption + local selected_player = Game.get_player_from_any(selected_player_name) + if event.button == defines.mouse_button_type.left then + -- LMB will open the map to the selected player + local position = selected_player.position + event.player.zoom_to_world(position,1.75) + else + -- RMB will toggle the settings + local old_selected_player_name = Store.get(selected_player_store,player) + if selected_player_name == old_selected_player_name then + Store.clear(selected_player_store,player) + else + Store.set(selected_player_store,player,selected_player_name) + end + end +end) - -- text entry for the reason bar - local reason_field = - reason_bar.add{ - name='entry', - type='textfield', - style='stretchable_textfield', - tooltip={'player-list.reason-entry'} - } - Gui.set_padding(reason_field) - reason_field.style.height = 28 - reason_field.style.minimal_width = 160 - - reason_confirm(reason_bar) - - return list_table, action_bar +-- Removes the three elements that are added as part of the base +local function remove_player_base(parent,player) + Gui.destroy_if_valid(parent[player.name]) + Gui.destroy_if_valid(parent['player-name-'..player.index]) + Gui.destroy_if_valid(parent['player-time-'..player.index]) end ---- Adds buttons and permission flows to the action bar -local function generate_action_bar(player,element) - close_action_bar(element) - local selected_player_name = Store.get(selected_player_store,player) +-- Update the time label for a player using there player time data +local function update_player_base(parent,player_time) + local time_element = parent[player_time.element_name] + if time_element and time_element.valid then + time_element.label.caption = player_time.caption + time_element.label.tooltip = player_time.tooltip + end +end - for action_name,buttons in pairs(config.buttons) do - local permission_flow = - element.add{ - type='flow', - name=action_name - } - - for _,button in ipairs(buttons) do +--- Adds all the buttons and flows that make up the action bar +-- @element add_action_bar +local add_action_bar_buttons = +Gui.element(function(_,parent) + close_action_bar(parent) + -- Loop over all the buttons in the config + for action_name,button_data in pairs(config.buttons) do + -- Added the permission flow + local permission_flow = parent.add{ type = 'flow', name = action_name } + permission_flow.visible = false + -- Add the buttons under that permission + for _,button in ipairs(button_data) do button(permission_flow) end - - if not Roles.player_allowed(player,action_name) then - permission_flow.visible = false - end - - if buttons.auth and selected_player_name and not buttons.auth(player,selected_player_name) then - permission_flow.visible = false - end end - if not selected_player_name then - element.visible = false - end -end + return parent +end) ---- Updates the action bar -local player_list_name -local function update_action_bar(player) - local frame = Gui.classes.left_frames.get_frame(player_list_name,player) - local element = frame.container.action_bar +--- Updates the visible state of the action bar buttons +local function update_action_bar(element) + local player = Gui.get_player_from_element(element) local selected_player_name = Store.get(selected_player_store,player) if not selected_player_name then + -- Hide the action bar when no player is selected element.visible = false else @@ -236,132 +201,219 @@ local function update_action_bar(player) end end ---- Adds a player to the player list -local function add_player(list_table,player,role_name) - open_action_bar(list_table,player.name) +--- Main player list container for the left flow +-- @element player_list_container +local player_list_container = +Gui.element(function(event_trigger,parent) + -- Draw the internal container + local container = Gui.container(parent,event_trigger,200) - -- flow to contain player_name to allow all to have trigger for zoom to map - local player_name_flow = - list_table.add{ - type='flow' + -- Draw the scroll table for the players + local scroll_table = Gui.scroll_table(container,184,3) + + -- Change the style of the scroll table + local scroll_table_style = scroll_table.style + scroll_table_style.padding = {1,0,1,2} + + -- Add the action bar + local action_bar = Gui.footer(container,nil,nil,false,'action_bar') + + -- Change the style of the action bar + local action_bar_style = action_bar.style + action_bar_style.height = 35 + action_bar_style.padding = {1,3} + action_bar.visible = false + + -- Add the buttons to the action bar + add_action_bar_buttons(action_bar) + + -- Add the reason bar + local reason_bar = Gui.footer(container,nil,nil,false,'reason_bar') + + -- Change the style of the reason bar + local reason_bar_style = reason_bar.style + reason_bar_style.height = 35 + reason_bar_style.padding = {-1,3} + reason_bar.visible = false + + -- Add the text entry for the reason bar + local reason_field = + reason_bar.add{ + name = 'entry', + type = 'textfield', + style = 'stretchable_textfield', + tooltip = {'player-list.reason-entry'} } - Gui.set_padding(player_name_flow) - -- player name with the tooltip of their highest role and in they colour - local player_name = - player_name_flow.add{ - name=zoom_to_map_name, - type='label', - caption=player.name, - tooltip={'player-list.open-map',player.name,player.tag,role_name} - } - Gui.set_padding(player_name,0,0,0,2) - player_name.style.font_color = player.chat_color + -- Change the style of the text entry + local reason_entry_style = reason_field.style + reason_entry_style.padding = 0 + reason_entry_style.height = 28 + reason_entry_style.minimal_width = 160 - -- flow which allows right align for the play time - local time_flow = Gui.create_alignment(list_table,'player-time-'..player.index) + -- Add the confirm reason button + reason_confirm(reason_bar) - -- time given in Xh Ym and is right aligned + -- Return the exteral container + return container.parent +end) +:add_to_left_flow(true) + +--- Button on the top flow used to toggle the player list container +-- @element toggle_left_element +Gui.left_toolbar_button('entity/character', {'player-list.main-tooltip'}, player_list_container, function(player) + return Roles.player_allowed(player,'gui/player-list') +end) + +-- Get caption and tooltip format for a player +local function get_time_formats(online_time,afk_time) local tick = game.tick > 0 and game.tick or 1 - local percent = math.round(player.online_time/tick,3)*100 - local time = - time_flow.add{ - name='label', - type='label', - caption=format_time(player.online_time), - tooltip={'player-list.afk-time',percent,format_time(player.afk_time,{minutes=true,long=true})} - } - Gui.set_padding(time) + local percent = math.round(online_time/tick,3)*100 + local caption = format_time(online_time) + local tooltip = {'player-list.afk-time', percent, format_time(afk_time,{minutes=true,long=true})} + return caption, tooltip end ---- Adds fake players to the player list -local function add_fake_players(list_table,count) - local role_name = 'Fake Player' - for i = 1,count do - add_player(list_table,{ - name='Player '..i, - index=0-i, - tag='', - online_time=math.random(0,game.tick), - afk_time=math.random(0,game.tick), - chat_color=table.get_random_dictionary_entry(Colors) - },role_name) +-- Get the player time to be used to update time label +local function get_player_times() + local ctn = 0 + local player_times = {} + for _, player in pairs(game.connected_players) do + ctn = ctn + 1 + -- Add the player time details to the array + local caption, tooltip = get_time_formats(player.online_time, player.afk_time) + player_times[ctn] = { + element_name = 'player-time-'..player.index, + caption = caption, + tooltip = tooltip + } end + + return player_times end ---- Registers the player list --- @element player_list -local player_list = -Gui.new_left_frame('gui/player-list') -:set_sprites('entity/character') -:set_tooltip{'player-list.main-tooltip'} -:set_open_by_default() -:set_direction('vertical') -:on_creation(function(player,element) - local list_table,action_bar = generate_container(player,element) - generate_action_bar(player,action_bar) - +-- Get a sorted list of all online players +local function get_player_list_order() + -- Sort all the online players into roles local players = {} - for _,next_player in pairs(game.connected_players) do - local highest_role = Roles.get_player_highest_role(next_player) + for _,player in pairs(game.connected_players) do + local highest_role = Roles.get_player_highest_role(player) if not players[highest_role.name] then players[highest_role.name] = {} end - table.insert(players[highest_role.name],next_player) + table.insert(players[highest_role.name],player) end + -- Sort the players from roles into a set order + local ctn = 0 + local player_list_order = {} for _,role_name in pairs(Roles.config.order) do if players[role_name] then - for _,next_player in pairs(players[role_name]) do - add_player(list_table,next_player,role_name) + for _,player in pairs(players[role_name]) do + ctn = ctn + 1 + -- Add the player data to the array + local caption, tooltip = get_time_formats(player.online_time, player.afk_time) + player_list_order[ctn] = { + name = player.name, + index = player.index, + tag = player.tag, + role_name = role_name, + chat_color = player.chat_color, + caption = caption, + tooltip = tooltip + } end end end - --add_fake_players(list_table,6) - --add_fake_players(list_table,20) -end) -:on_update(function(player,element) - local list = element.container.scroll.table - for _,next_player in pairs(game.connected_players) do - local time_element_name = 'player-time-'..next_player.index - local time_element = list[time_element_name] - if time_element and time_element.valid then - time_element.label.caption = format_time(next_player.online_time) - local tick = game.tick > 0 and game.tick or 1 - local percent = math.round(next_player.online_time/tick,3)*100 - time_element.label.tooltip = {'player-list.afk-time',percent,format_time(next_player.afk_time,{minutes=true,long=true})} + --[[Adds fake players to the player list + for i = 1, 10 do + local online_time = math.random(1,tick) + local afk_time = math.random(online_time-(tick/10),tick) + local caption, tooltip = get_time_formats(online_time, afk_time) + player_list_order[ctn+i] = { + name='Player '..i, + index=0-i, + tag='', + role_name = 'Fake Player', + chat_color = table.get_random_dictionary_entry(Colors), + caption = caption, + tooltip = tooltip + } + end]] + + return player_list_order +end + +--- Update the play times every 30 sections +Event.on_nth_tick(1800,function() + local player_times = get_player_times() + for _,player in pairs(game.connected_players) do + local frame = Gui.get_left_element(player,player_list_container) + local scroll_table = frame.container.scroll.table + for _,player_time in pairs(player_times) do + update_player_base(scroll_table,player_time) end end end) -player_list_name = player_list:uid() +--- When a player leaves only remove they entry +Event.add(defines.events.on_player_left_game,function(event) + local remove_player = Game.get_player_by_index(event.player_index) + for _,player in pairs(game.connected_players) do + local frame = Gui.get_left_element(player,player_list_container) + local scroll_table = frame.container.scroll.table + remove_player_base(scroll_table,remove_player) + + local selected_player_name = Store.get(selected_player_store,player) + if selected_player_name == remove_player.name then + Store.clear(selected_player_store,player) + Store.clear(selected_action_store,player) + end + end +end) + +--- All other events require a full redraw of the table +local function redraw_player_list() + local player_list_order = get_player_list_order() + for _,player in pairs(game.connected_players) do + local frame = Gui.get_left_element(player,player_list_container) + local scroll_table = frame.container.scroll.table + scroll_table.clear() + for _,next_player_data in ipairs(player_list_order) do + add_player_base(scroll_table,next_player_data) + end + end +end + +Event.add(defines.events.on_player_joined_game,redraw_player_list) +Event.add(Roles.events.on_role_assigned,redraw_player_list) +Event.add(Roles.events.on_role_unassigned,redraw_player_list) --- When the action player is changed the action bar will update Store.watch(selected_player_store,function(value,player_name) local player = Game.get_player_from_any(player_name) - update_action_bar(player) - - -- Change the style of the option buttons - local frame = player_list:get_frame(player) - local data_table = frame.container.scroll.table + local frame = Gui.get_left_element(player,player_list_container) + local scroll_table = frame.container.scroll.table + update_action_bar(frame.container.action_bar) for _,next_player in pairs(game.connected_players) do - local element = data_table[next_player.name][open_action_bar.name] + local element = scroll_table[next_player.name][open_action_bar.name] local style = 'frame_button' if next_player.name == value then style = 'tool_button' end element.style = style - Gui.set_padding(element,-2,-2,-2,-2) - element.style.width = 8 - element.style.height = 14 + local element_style = element.style + element_style.padding = -2 + element_style.width = 8 + element_style.height = 14 end end) --- When the action name is changed the reason input will update Store.watch(selected_action_store,function(value,player_name) local player = Game.get_player_from_any(player_name) - local frame = Gui.classes.left_frames.get_frame(player_list_name,player) + local frame = Gui.get_left_element(player,player_list_container) local element = frame.container.reason_bar if value then -- if there is a new value then check the player is still online @@ -379,13 +431,4 @@ Store.watch(selected_action_store,function(value,player_name) element.visible = false end -end) - ---- Many events which trigger the gui to be re drawn, it will also update the times every 30 seconds -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.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 +end) \ No newline at end of file diff --git a/modules/gui/readme.lua b/modules/gui/readme.lua new file mode 100644 index 00000000..1f8e8ad4 --- /dev/null +++ b/modules/gui/readme.lua @@ -0,0 +1,344 @@ +--[[-- Gui Module - Readme + - Adds a main gui that contains lots of important information about our server + @gui Readme + @alias readme +]] + +local Gui = require 'expcore.gui' --- @dep expcore.gui +local Roles = require 'expcore.roles' --- @dep expcore.roles +local Commands = require 'expcore.commands' --- @dep expcore.commands +local Event = require 'utils.event' --- @dep utils.event +local Game = require 'utils.game' --- @dep utils.game +local format_time = _C.format_time --- @dep expcore.common + +local tabs = {} +local function Tab(caption,tooltip,element_define) + tabs[#tabs+1] = {caption, tooltip, element_define} +end + +local frame_width = 595 -- controls width of top descritions +local title_width = 270 -- controls the centering of the titles +local scroll_hieght = 275 -- controls the height of the scrolls + +--- Sub content area used within the content areas +-- @element sub_content +local sub_content = +Gui.element(function(_,parent) + return parent.add{ + type = 'frame', + direction = 'vertical', + style = 'image_frame' + } +end) +:style{ + horizontally_stretchable = true, + horizontal_align = 'center' +} + +--- Table which has a title above it above it +-- @element title_table +local title_table = +Gui.element(function(_,parent,bar_size,caption,column_count) + Gui.title_label(parent, bar_size, caption) + + return parent.add{ + type = 'table', + column_count = column_count, + style = 'bordered_table' + } +end) +:style{ + padding = 0, + cell_padding = 0, + vertical_align = 'center', + horizontally_stretchable = true +} + +--- Scroll to be used with Gui.title_label tables +-- @element title_table_scroll +local title_table_scroll = +Gui.element{ + type = 'scroll-pane', + direction = 'vertical', + horizontal_scroll_policy = 'never', + vertical_scroll_policy = 'auto', + style = 'scroll_pane_under_subheader' +} +:style{ + padding = {1,3}, + maximal_height = scroll_hieght, + horizontally_stretchable = true, +} + +--- Content area for the welcome tab +-- @element welcome_content +Tab({'readme.welcome-tab'},{'readme.welcome-tooltip'}, +Gui.element(function(_,parent) + local server_details = global.server_details or { name='ExpGaming S0 - Local', description='Failed to load description: disconnected from sync api.', reset_time='Non Set', branch='Unknown'} + local container = parent.add{ type='flow', direction='vertical' } + local player = Gui.get_player_from_element(parent) + + -- Set up the top flow with logos + local top_flow = container.add{ type='flow' } + top_flow.add{ type='sprite', sprite='file/modules/gui/logo.png' } + local top_vertical_flow = top_flow.add{ type='flow', direction='vertical' } + top_flow.add{ type='sprite', sprite='file/modules/gui/logo.png' } + top_vertical_flow.style.horizontal_align = 'center' + + -- Add the title and description to the top flow + Gui.title_label(top_vertical_flow, 62, 'Welcome to '..server_details.name) + Gui.centered_label(top_vertical_flow, 380, server_details.description) + Gui.bar(container) + + -- Get the names of the roles the player has + local player_roles = Roles.get_player_roles(player) + local role_names = {} + for i,role in ipairs(player_roles) do + role_names[i] = role.name + end + + -- Add the other information to the gui + container.add{ type='flow' }.style.height = 4 + local online_time = format_time(game.tick,{days=true,hours=true,minutes=true,long=true}) + Gui.centered_label(sub_content(container), frame_width, {'readme.welcome-general', server_details.reset_time, online_time}) + Gui.centered_label(sub_content(container), frame_width, {'readme.welcome-roles', table.concat(role_names,', ')}) + Gui.centered_label(sub_content(container), frame_width, {'readme.welcome-chat'}) + + return container +end)) + +--- Content area for the rules tab +-- @element rules_content +Tab({'readme.rules-tab'},{'readme.rules-tooltip'}, +Gui.element(function(_,parent) + local container = parent.add{ type='flow', direction='vertical' } + + -- Add the title and description to the content + Gui.title_label(container, title_width-3, {'readme.rules-tab'}) + Gui.centered_label(container, frame_width, {'readme.rules-general'}) + Gui.bar(container) + container.add{ type='flow' } + + -- Add a table for the rules + local rules = Gui.scroll_table(container, scroll_hieght, 1) + rules.style = 'bordered_table' + rules.style.cell_padding = 4 + + -- Add the rules to the table + for i = 1,15 do + Gui.centered_label(rules, 565, {'readme.rules-'..i}) + end + + return container +end)) + +--- Content area for the commands tab +-- @element commands_content +Tab({'readme.commands-tab'},{'readme.commands-tooltip'}, +Gui.element(function(_,parent) + local container = parent.add{ type='flow', direction='vertical' } + local player = Gui.get_player_from_element(parent) + + -- Add the title and description to the content + Gui.title_label(container, title_width-20, {'readme.commands-tab'}) + Gui.centered_label(container, frame_width, {'readme.commands-general'}) + Gui.bar(container) + container.add{ type='flow' } + + -- Add a table for the commands + local commands = Gui.scroll_table(container, scroll_hieght, 2) + commands.style = 'bordered_table' + commands.style.cell_padding = 0 + + -- Add the rules to the table + for name,command in pairs(Commands.get(player)) do + Gui.centered_label(commands, 120, name) + Gui.centered_label(commands, 450, command.help) + end + + return container +end)) + +--- Content area for the servers tab +-- @element servers_content +Tab({'readme.servers-tab'},{'readme.servers-tooltip'}, +Gui.element(function(_,parent) + local container = parent.add{ type='flow', direction='vertical' } + + -- Add the title and description to the content + Gui.title_label(container, title_width-10, {'readme.servers-tab'}) + Gui.centered_label(container, frame_width, {'readme.servers-general'}) + Gui.bar(container) + container.add{ type='flow' } + + -- Draw the scroll + local scroll_pane = title_table_scroll(container) + scroll_pane.style.maximal_height = scroll_hieght + 20 -- the text is a bit shorter + + -- Add the factorio servers + local factorio_servers = title_table(scroll_pane, 225, {'readme.servers-factorio'}, 2) + for i = 1,8 do + Gui.centered_label(factorio_servers, 110, {'readme.servers-'..i}) + Gui.centered_label(factorio_servers, 460, {'readme.servers-d'..i}) + end + + -- Add the external links + local external_links = title_table(scroll_pane, 235, {'readme.servers-external'}, 2) + for _,key in ipairs{'discord','website','patreon','status','github'} do + Gui.centered_label(external_links, 110, key:gsub("^%l", string.upper)) + Gui.centered_label(external_links, 460, {'links.'..key}, {'readme.servers-open-in-browser'}) + end + + return container +end)) + +--- Content area for the servers tab +-- @element backers_content +Tab({'readme.backers-tab'},{'readme.backers-tooltip'}, +Gui.element(function(_,parent) + local container = parent.add{ type='flow', direction='vertical' } + + -- Add the title and description to the content + Gui.title_label(container, title_width-10, {'readme.backers-tab'}) + Gui.centered_label(container, frame_width, {'readme.backers-general'}) + Gui.bar(container) + container.add{ type='flow' } + + -- Find which players will go where + local done = {} + local groups = { + { _roles={'Senior Administrator','Administrator'}, _title={'readme.backers-management'}, _width=230 }, + { _roles={'Board Member','Senior Backer'}, _title={'readme.backers-board'}, _width=145 }, -- change role to board + { _roles={'Sponsor','Supporter'}, _title={'readme.backers-backers'}, _width=196 }, -- change to backer + { _roles={'Moderator','Trainee'}, _title={'readme.backers-staff'}, _width=235 }, + { _roles={}, _title={'readme.backers-active'}, _width=235 }, + } + + -- Fill by player roles + for player_name, player_roles in pairs(Roles.config.players) do + for _, players in ipairs(groups) do + for _, role_name in pairs(players._roles) do + if table.contains(player_roles, role_name) then + done[player_name] = true + table.insert(players,player_name) + break + end + end + end + end + + -- Fill by active times + local active_time = 3*3600*60 + for _, player in pairs(game.players) do + if not done[player.name] then + if player.online_time > active_time then + table.insert(groups.Active,player.name) + end + end + end + + -- Add the different tables + local scroll_pane = title_table_scroll(container) + for _, players in ipairs(groups) do + local table = title_table(scroll_pane, players._width, players._title, 4) + for _,player_name in ipairs(players) do + Gui.centered_label(table, 140, player_name) + end + + if #players < 4 then + for i = 1,4-#players do + Gui.centered_label(table, 140) + end + end + end + + return container +end)) + +--- Main readme container for the center flow +-- @element readme +local readme_toggle +local readme = +Gui.element(function(event_trigger,parent) + local container = parent.add{ + name = event_trigger, + type = 'frame', + style = 'invisible_frame' + } + + -- Add the left hand side of the frame back, removed because of frame_tabbed_pane style + local left_alignment = Gui.alignment(container, nil, nil, 'bottom') + left_alignment.style.padding = {32,0,0,0} + + local left_side = + left_alignment.add{ + type = 'frame', + style = 'frame_without_right_side' + } + left_side.style.vertically_stretchable = true + left_side.style.padding = 0 + left_side.style.width = 5 + + -- Add the tab pane + local tab_pane = container.add{ + name = 'pane', + type = 'tabbed-pane', + style = 'frame_tabbed_pane' + } + + -- Add the different content areas + for _,tab_details in ipairs(tabs) do + local tab = tab_pane.add{ type = 'tab', style = 'frame_tab', caption = tab_details[1], tooltip = tab_details[2] } + tab_pane.add_tab(tab, tab_details[3](tab_pane)) + end + + return container +end) +:on_open(function(player) + local toggle_button = Gui.get_top_element(player, readme_toggle) + Gui.toolbar_button_style(toggle_button, true) +end) +:on_close(function(player,element) + local toggle_button = Gui.get_top_element(player, readme_toggle) + Gui.toolbar_button_style(toggle_button, false) + Gui.destroy_if_valid(element) +end) + +--- Toggle button for the readme gui +-- @element readme_toggle +readme_toggle = +Gui.toolbar_button('virtual-signal/signal-info',{'readme.main-tooltip'},function(player) + return Roles.player_allowed(player,'gui/readme') +end) +:on_click(function(player,_) + local center = player.gui.center + if center[readme.name] then + player.opened = nil + else + player.opened = readme(center) + end +end) + +--- When a player joins the game for the first time show this gui +Event.add(defines.events.on_player_created,function(event) + local player = Game.get_player_by_index(event.player_index) + local element = readme(player.gui.center) + element.pane.selected_tab_index = 1 + player.opened = element +end) + +--- When a player joins clear center unless the player has something open +Event.add(defines.events.on_player_joined_game,function(event) + local player = Game.get_player_by_index(event.player_index) + if not player.opened then + player.gui.center.clear() + end +end) + +--- When a player respawns clear center unless the player has something open +Event.add(defines.events.on_player_respawned,function(event) + local player = Game.get_player_by_index(event.player_index) + if not player.opened then + player.gui.center.clear() + end +end) \ No newline at end of file diff --git a/modules/gui/rocket-info.lua b/modules/gui/rocket-info.lua index fd384627..c15ea688 100644 --- a/modules/gui/rocket-info.lua +++ b/modules/gui/rocket-info.lua @@ -7,13 +7,20 @@ local Gui = require 'expcore.gui' --- @dep expcore.gui local Roles = require 'expcore.roles' --- @dep expcore.roles local Event = require 'utils.event' --- @dep utils.event -local config = require 'config.rockets' --- @dep config.rockets -local format_time = ext_require('expcore.common','format_time') --- @dep expcore.common -local Colors = require 'resources.color_presets' --- @dep resources.color_presets +local config = require 'config.gui.rockets' --- @dep config.gui.rockets +local Colors = require 'utils.color_presets' --- @dep utils.color_presets local Rockets = require 'modules.control.rockets' --- @dep modules.control.rockets +local format_time = _C.format_time --- @dep expcore.common ---- Gets if a player is allowed to use the action buttons -local function player_allowed(player,action) +local time_formats = { + caption = function(value) return format_time(value, {minutes=true, seconds=true}) end, + caption_hours = function(value) return format_time(value) end, + tooltip = function(value) return format_time(value, {minutes=true, seconds=true, long=true}) end, + tooltip_hours = function(value) return format_time(value, {hours=true, minutes=true, seconds=true, long=true}) end +} + +--- Check if a player is allowed to use certain interactions +local function check_player_permissions(player,action) if not config.progress['allow_'..action] then return false end @@ -22,68 +29,27 @@ local function player_allowed(player,action) return false end - if config.progress[action..'_role_permission'] and not Roles.player_allowed(player,config.progress[action..'_role_permission']) then + if config.progress[action..'_role_permission'] + and not Roles.player_allowed(player,config.progress[action..'_role_permission']) then return false end return true end ---- Used on the name label to allow zoom to map --- @element zoom_to_map -local zoom_to_map_name = Gui.uid_name() -Gui.on_click(zoom_to_map_name,function(event) - local rocket_silo_name = event.element.parent.caption - local rocket_silo = Rockets.get_silo_entity(rocket_silo_name) - event.player.zoom_to_world(rocket_silo.position,2) -end) - ---- Used to launch the rocket, when it is ready --- @element launch_rocket -local launch_rocket = -Gui.new_button() -:set_sprites('utility/center') -:set_tooltip{'rocket-info.launch-tooltip'} -:set_embedded_flow(function(element,rocket_silo_name) - return 'launch-'..rocket_silo_name -end) -:set_style('tool_button',function(style) - Gui.set_padding_style(style,-2,-2,-2,-2) - style.width = 16 - style.height = 16 -end) -:on_click(function(player,element) - local rocket_silo_name = element.parent.name:sub(8) - local silo_data = Rockets.get_silo_data_by_name(rocket_silo_name) - if silo_data.entity.launch_rocket() then - silo_data.awaiting_reset = true - element.enabled = false - local progress_label = element.parent.parent[rocket_silo_name].label - progress_label.caption = {'rocket-info.progress-launched'} - progress_label.style.font_color = Colors.green - else - player.print({'rocket-info.launch-failed'},Colors.orange_red) - end -end) - ---- Used to toggle the auto launch on a rocket --- @element toggle_rocket -local toggle_rocket = -Gui.new_button() -:set_sprites('utility/play') -:set_tooltip{'rocket-info.toggle-rocket-tooltip'} -:set_embedded_flow(function(element,rocket_silo_name) - return 'toggle-'..rocket_silo_name -end) -:set_style('tool_button',function(style) - Gui.set_padding_style(style,-2,-2,-2,-2) - style.width = 16 - style.height = 16 -end) -:on_click(function(player,element) - local rocket_silo_name = element.parent.name:sub(8) - local rocket_silo = Rockets.get_silo_entity(rocket_silo_name) - if rocket_silo.auto_launch then +--- Button to toggle the auto launch on a rocket silo +-- @element toggle_launch +local toggle_launch = +Gui.element{ + type = 'sprite-button', + sprite = 'utility/play', + tooltip = {'rocket-info.toggle-rocket-tooltip'} +} +:style(Gui.sprite_style(16)) +:on_click(function(_,element,_) + local rocket_silo_name = element.parent.name:sub(8) + local rocket_silo = Rockets.get_silo_entity(rocket_silo_name) + if rocket_silo.auto_launch then element.sprite = 'utility/play' element.tooltip = {'rocket-info.toggle-rocket-tooltip'} rocket_silo.auto_launch = false @@ -94,429 +60,546 @@ end) end end) ---- Used to toggle the visibility of the different sections --- @element toggle_section -local toggle_section = -Gui.new_button() -:set_sprites('utility/expand_dark','utility/expand') -:set_tooltip{'rocket-info.toggle-section-tooltip'} -:set_style('tool_button',function(style) - Gui.set_padding_style(style,-2,-2,-2,-2) - style.height = 20 - style.width = 20 -end) -:on_click(function(player,element) - local flow_name = element.parent.caption - local flow = element.parent.parent.parent[flow_name] - if Gui.toggle_visible(flow) then - element.sprite = 'utility/collapse_dark' - element.hovered_sprite = 'utility/collapse' - element.tooltip = {'rocket-info.toggle-section-collapse-tooltip'} +--- Button to remotely launch a rocket from a silo +-- @element launch_rocket +local launch_rocket = +Gui.element{ + type = 'sprite-button', + sprite = 'utility/center', + tooltip = {'rocket-info.launch-tooltip'} +} +:style(Gui.sprite_style(16,-1)) +:on_click(function(player,element,_) + local rocket_silo_name = element.parent.name:sub(8) + local silo_data = Rockets.get_silo_data_by_name(rocket_silo_name) + if silo_data.entity.launch_rocket() then + element.enabled = false else - element.sprite = 'utility/expand_dark' - element.hovered_sprite = 'utility/expand' - element.tooltip = {'rocket-info.toggle-section-tooltip'} + player.print({'rocket-info.launch-failed'},Colors.orange_red) end end) ---- Used to create the three different sections -local function create_section(container,section_name,table_size) - -- Header for the section - local header_area = Gui.create_header( - container, - {'rocket-info.section-caption-'..section_name}, - {'rocket-info.section-tooltip-'..section_name}, - true, - section_name..'-header' - ) +--- XY cords that allow zoom to map when pressed +-- @element silo_cords +local silo_cords = +Gui.element(function(event_trigger,parent,silo_data) + local silo_name = silo_data.silo_name + local pos = silo_data.position + local name = config.progress.allow_zoom_to_map and event_trigger or nil + local tooltip = config.progress.allow_zoom_to_map and {'rocket-info.progress-label-tooltip'} or nil - -- Right aligned button to toggle the section - header_area.caption = section_name - toggle_section(header_area) + -- Add the x cord flow + local flow_x = parent.add{ + type ='flow', + name = 'label-x-'..silo_name, + caption = silo_name + } + flow_x.style.padding = {0,2,0,1} - -- Table used to store the data - local flow_table = Gui.create_scroll_table(container,table_size,215,section_name) - flow_table.parent.visible = false + -- Add the x cord label + flow_x.add{ + type = 'label', + name = name, + caption = {'rocket-info.progress-x-pos',pos.x}, + tooltip = tooltip + } + -- Add the y cord flow + local flow_y = parent.add{ + type ='flow', + name = 'label-y-'..silo_name, + caption = silo_name + } + flow_y.style.padding = {0,2,0,1} + + -- Add the y cord label + flow_y.add{ + type = 'label', + name = name, + caption = {'rocket-info.progress-y-pos',pos.y}, + tooltip = tooltip + } + +end) +:on_click(function(player,element,_) + local rocket_silo_name = element.parent.caption + local rocket_silo = Rockets.get_silo_entity(rocket_silo_name) + player.zoom_to_world(rocket_silo.position,2) +end) + +--- Base element for each rocket in the progress list +-- @element rocket_entry +local rocket_entry = +Gui.element(function(_,parent,silo_data) + local silo_name = silo_data.silo_name + local player = Gui.get_player_from_element(parent) + + -- Add the toggle auto launch if the player is allowed it + if check_player_permissions(player,'toggle_active') then + local flow = parent.add{ type = 'flow', name = 'toggle-'..silo_name} + local button = toggle_launch(flow) + button.tooltip = silo_data.toggle_tooltip + button.sprite = silo_data.toggle_sprite + end + + -- Add the remote launch if the player is allowed it + if check_player_permissions(player,'remote_launch') then + local flow = parent.add{ type = 'flow', name = 'launch-'..silo_name} + local button = launch_rocket(flow) + button.enabled = silo_data.allow_launch + end + + -- Draw the silo cords element + silo_cords(parent,silo_data) + + -- Add a progress label + local alignment = Gui.alignment(parent,silo_name) + local element = + alignment.add{ + type = 'label', + name = 'label', + caption = silo_data.progress_caption, + tooltip = silo_data.progress_tooltip + } + + -- Return the progress label + return element +end) + +--- Data label which contains a name and a value label pair +-- @element data_label +local data_label = +Gui.element(function(_,parent,label_data) + local data_name = label_data.name + local data_subname = label_data.subname + local data_fullname = data_subname and data_name..data_subname or data_name + + -- Add the name label + local name_label = parent.add{ + type = 'label', + name = data_fullname..'-label', + caption = {'rocket-info.data-caption-'..data_name,data_subname}, + tooltip = {'rocket-info.data-tooltip-'..data_name,data_subname} + } + name_label.style.padding = {0,2} + + --- Right aligned label to store the data + local alignment = Gui.alignment(parent,data_fullname) + local element = + alignment.add{ + type = 'label', + name = 'label', + caption = label_data.value, + tooltip = label_data.tooltip + } + element.style.padding = {0,2} + + return element +end) + +-- Used to update the captions and tooltips on the data labels +local function update_data_labels(parent,data_label_data) + for _, label_data in ipairs(data_label_data) do + local data_name = label_data.subname and label_data.name..label_data.subname or label_data.name + if not parent[data_name] then + data_label(parent,label_data) + else + local data_label_element = parent[data_name].label + data_label_element.tooltip = label_data.tooltip + data_label_element.caption = label_data.value + end + end end ---[[ Creates the main structure for the gui - element - > container +local function get_progress_data(force_name) + local force_silos = Rockets.get_silos(force_name) + local progress_data = {} - >> stats-header - >>> stats - >>>> toggle_section.name - >> stats - >>> table + for _, silo_data in pairs(force_silos) do + local rocket_silo = silo_data.entity + if not rocket_silo or not rocket_silo.valid then + -- Remove from list if not valid + force_silos[silo_data.name] = nil + table.insert(progress_data,{ + silo_name = silo_data.name, + remove = true + }) - >> milestones-header - >>> milestones - >>>> toggle_section.name - >> milestones - >>> table + else + -- Get the progress caption and tooltip + local progress_color = Colors.white + local progress_caption = {'rocket-info.progress-caption',rocket_silo.rocket_parts} + local progress_tooltip = {'rocket-info.progress-tooltip',silo_data.launched or 0} + local status = rocket_silo.status == defines.entity_status.waiting_to_launch_rocket + if status and silo_data.awaiting_reset then + progress_caption = {'rocket-info.progress-launched'} + progress_color = Colors.green + elseif status then + progress_caption = {'rocket-info.progress-caption',100} + progress_color = Colors.cyan + else + silo_data.awaiting_reset = false + end - >> progress-header - >>> progress - >>>> toggle_section.name - >> progress - >>> table -]] -local function generate_container(player,element) - Gui.set_padding(element,1,2,2,2) - element.style.minimal_width = 200 + -- Get the toggle button data + local toggle_tooltip = {'rocket-info.toggle-rocket-tooltip-disabled'} + local toggle_sprite = 'utility/play' + if rocket_silo.auto_launch then + toggle_tooltip = {'rocket-info.toggle-rocket-tooltip'} + toggle_sprite = 'utility/stop' + end - -- main container which contains the other elements - local container = - element.add{ - name='container', - type='frame', - direction='vertical', - style='window_content_frame_packed' - } - Gui.set_padding(container) - - if config.stats.show_stats then - create_section(container,'stats',2) - end - - if config.milestones.show_milestones then - create_section(container,'milestones',2) - end - - if config.progress.show_progress then - local col_count = 3 - if player_allowed(player,'remote_launch') then col_count = col_count+1 end - if player_allowed(player,'toggle_active') then col_count = col_count+1 end - create_section(container,'progress',col_count) - --- label used when no active silos - container.progress.add{ - type='label', - name='no_silos', - caption={'rocket-info.progress-no-silos'} - } - end + -- Insert the gui data + table.insert(progress_data,{ + silo_name = silo_data.name, + position = rocket_silo.position, + allow_launch = not silo_data.awaiting_reset and status or false, + progress_color = progress_color, + progress_caption = progress_caption, + progress_tooltip = progress_tooltip, + toggle_tooltip = toggle_tooltip, + toggle_sprite = toggle_sprite + }) + end + end + return progress_data end ---[[ Creates a text label followed by a data label, or updates them if already present - element - > "data_name_extra"-label - > "data_name_extra" - >> label -]] -local function create_label_value_pair(element,data_name,value,tooltip,extra) - local data_name_extra = extra and data_name..extra or data_name - if element[data_name_extra] then - element[data_name_extra].label.caption = value - element[data_name_extra].label.tooltip = tooltip - else - --- Label used with the data - element.add{ - type='label', - name=data_name_extra..'-label', - caption={'rocket-info.data-caption-'..data_name,extra}, - tooltip={'rocket-info.data-tooltip-'..data_name,extra} - } - --- Right aligned label to store the data - local right_flow = Gui.create_alignment(element,data_name_extra) - right_flow.add{ - type='label', - name='label', - caption=value, - tooltip=tooltip - } - end +--- Update the build progress section +local function update_build_progress(parent,progress_data) + local show_message = true + for _, silo_data in ipairs(progress_data) do + parent.no_silos.visible = false + local silo_name = silo_data.silo_name + local progress_label = parent[silo_name] + if silo_data.remove then + -- Remove the rocket from the list + Gui.destroy_if_valid(parent['toggle-'..silo_name]) + Gui.destroy_if_valid(parent['launch-'..silo_name]) + Gui.destroy_if_valid(parent['label-x-'..silo_name]) + Gui.destroy_if_valid(parent['label-y-'..silo_name]) + Gui.destroy_if_valid(parent[silo_name]) + + elseif not progress_label then + -- Add the rocket to the list + show_message = false + rocket_entry(parent,silo_data) + + else + show_message = false + -- Update the existing labels + progress_label = progress_label.label + progress_label.caption = silo_data.progress_caption + progress_label.tooltip = silo_data.progress_tooltip + progress_label.style.font_color = silo_data.progress_color + + -- Update the toggle button + local toggle_button = parent['toggle-'..silo_name] + if toggle_button then + toggle_button = toggle_button[toggle_launch.name] + toggle_button.tooltip = silo_data.toggle_tooltip + toggle_button.sprite = silo_data.toggle_sprite + end + + -- Update the launch button + local launch_button = parent['launch-'..silo_name] + if launch_button then + launch_button = launch_button[launch_rocket.name] + launch_button.enabled = silo_data.allow_launch + end + end + end + if show_message then parent.no_silos.visible = true end end ---- Creates a text and data label using times as the data -local function create_label_value_pair_time(element,data_name,raw_value,no_hours,extra) - local value = no_hours and format_time(raw_value,{minutes=true,seconds=true}) or format_time(raw_value) - local tooltip = format_time(raw_value,{hours=not no_hours,minutes=true,seconds=true,long=true}) - create_label_value_pair(element,data_name,value,tooltip,extra) -end - ---- Adds the different data values to the stats section -local function generate_stats(player,frame) - if not config.stats.show_stats then return end - local element = frame.container.stats.table - local force_name = player.force.name +--- Gets the label data for all the different stats +local function get_stats_data(force_name) local force_rockets = Rockets.get_rocket_count(force_name) - local stats = Rockets.get_stats(force_name) + local stats = Rockets.get_stats(force_name) + local stats_data = {} - if config.stats.show_first_rocket then - create_label_value_pair_time(element,'first-launch',stats.first_launch or 0) + -- Format the first launch data + if config.stats.show_first_rocket then + local value = stats.first_launch or 0 + table.insert(stats_data,{ + name = 'first-launch', + value = time_formats.caption_hours(value), + tooltip = time_formats.tooltip_hours(value) + }) + end + + -- Format the last launch data + if config.stats.show_last_rocket then + local value = stats.last_launch or 0 + table.insert(stats_data,{ + name = 'last-launch', + value = time_formats.caption_hours(value), + tooltip = time_formats.tooltip_hours(value) + }) end - if config.stats.show_last_rocket then - create_label_value_pair_time(element,'last-launch',stats.last_launch or 0) - end - - if config.stats.show_fastest_rocket then - create_label_value_pair_time(element,'fastest-launch',stats.fastest_launch or 0,true) + -- Format fastest launch data + if config.stats.show_fastest_rocket then + local value = stats.fastest_launch or 0 + table.insert(stats_data,{ + name = 'fastest-launch', + value = time_formats.caption_hours(value), + tooltip = time_formats.tooltip_hours(value) + }) end + -- Format total rocket data if config.stats.show_total_rockets then local total_rockets = Rockets.get_game_rocket_count() total_rockets = total_rockets == 0 and 1 or total_rockets - local percentage = math.round(force_rockets/total_rockets,3)*100 - create_label_value_pair(element,'total-rockets',force_rockets,{'rocket-info.value-tooltip-total-rockets',percentage}) + local percentage = math.round(force_rockets/total_rockets,3)*100 + table.insert(stats_data,{ + name = 'total-rockets', + value = force_rockets, + tooltip = {'rocket-info.value-tooltip-total-rockets',percentage} + }) end + -- Format game avg data if config.stats.show_game_avg then - local avg = force_rockets > 0 and math.floor(game.tick/force_rockets) or 0 - create_label_value_pair_time(element,'avg-launch',avg,true) + local avg = force_rockets > 0 and math.floor(game.tick/force_rockets) or 0 + table.insert(stats_data,{ + name = 'avg-launch', + value = time_formats.caption(avg), + tooltip = time_formats.tooltip(avg) + }) end + -- Format rolling avg data for _,avg_over in pairs(config.stats.rolling_avg) do - local avg = Rockets.get_rolling_average(force_name,avg_over) - create_label_value_pair_time(element,'avg-launch-n',avg,true,avg_over) - end + local avg = Rockets.get_rolling_average(force_name,avg_over) + table.insert(stats_data,{ + name = 'avg-launch-n', + subname = avg_over, + value = time_formats.caption(avg), + tooltip = time_formats.tooltip(avg) + }) + end + -- Return formated data + return stats_data end ---- Creates the list of milestones -local function generate_milestones(player,frame) - if not config.milestones.show_milestones then return end - local element = frame.container.milestones.table - local force_name = player.force.name - local force_rockets = Rockets.get_rocket_count(force_name) +--- Gets the label data for the milestones +local function get_milestone_data(force_name) + local force_rockets = Rockets.get_rocket_count(force_name) + local milestone_data = {} - for _,milestone in ipairs(config.milestones) do + for _,milestone in ipairs(config.milestones) do if milestone <= force_rockets then - local time = Rockets.get_rocket_time(force_name,milestone) - create_label_value_pair_time(element,'milestone-n',time,false,milestone) - else - create_label_value_pair_time(element,'milestone-n',0,false,milestone) + local time = Rockets.get_rocket_time(force_name,milestone) + table.insert(milestone_data,{ + name = 'milestone-n', + subname = milestone, + value = time_formats.caption_hours(time), + tooltip = time_formats.tooltip_hours(time) + }) + else + table.insert(milestone_data,{ + name = 'milestone-n', + subname = milestone, + value = {'rocket-info.data-caption-milestone-next'}, + tooltip = {'rocket-info.data-tooltip-milestone-next'} + }) break end - end + end + + return milestone_data end ---- Creats the different buttons used with the rocket silos -local function generate_progress_buttons(player,element,silo_data) - local silo_name = silo_data.name - local rocket_silo = silo_data.entity - local status = rocket_silo.status == defines.entity_status.waiting_to_launch_rocket - local active = rocket_silo.auto_launch +-- Button to toggle a section dropdown +-- @element toggle_section +local toggle_section = +Gui.element{ + type = 'sprite-button', + sprite = 'utility/expand_dark', + hovered_sprite = 'utility/expand', + tooltip = {'rocket-info.toggle-section-tooltip'} +} +:style(Gui.sprite_style(20)) +:on_click(function(_,element,_) + local header_flow = element.parent + local flow_name = header_flow.caption + local flow = header_flow.parent.parent[flow_name] + if Gui.toggle_visible_state(flow) then + element.sprite = 'utility/collapse_dark' + element.hovered_sprite = 'utility/collapse' + element.tooltip = {'rocket-info.toggle-section-collapse-tooltip'} + else + element.sprite = 'utility/expand_dark' + element.hovered_sprite = 'utility/expand' + element.tooltip = {'rocket-info.toggle-section-tooltip'} + end +end) - if player_allowed(player,'toggle_active') then - local button_element = element['toggle-'..silo_name] +-- Draw a section header and main scroll +-- @element rocket_list_container +local section = +Gui.element(function(_,parent,section_name,table_size) + -- Draw the header for the section + local header = Gui.header( + parent, + {'rocket-info.section-caption-'..section_name}, + {'rocket-info.section-tooltip-'..section_name}, + true, + section_name..'-header' + ) - if button_element then - button_element = button_element[toggle_rocket.name] - else - button_element = toggle_rocket(element,silo_name) - end + -- Right aligned button to toggle the section + header.caption = section_name + toggle_section(header) - if active then - button_element.tooltip = {'rocket-info.toggle-rocket-tooltip'} - button_element.sprite = 'utility/stop' - else - button_element.tooltip = {'rocket-info.toggle-rocket-tooltip-disabled'} - button_element.sprite = 'utility/play' - end - end + -- Table used to store the data + local scroll_table = Gui.scroll_table(parent,215,table_size,section_name) + scroll_table.parent.visible = false - if player_allowed(player,'remote_launch') then - local button_element = element['launch-'..silo_name] + -- Return the flow table + return scroll_table +end) - if button_element then - button_element = button_element[launch_rocket.name] - else - button_element = launch_rocket(element,silo_name) - end +--- Main gui container for the left flow +-- @element rocket_list_container +local rocket_list_container = +Gui.element(function(event_trigger,parent) + -- Draw the internal container + local container = Gui.container(parent,event_trigger,200) - if silo_data.awaiting_reset then - button_element.enabled = false - else - button_element.enabled = status - end - end + -- Set the container style + local style = container.style + style.padding = 0 + local player = Gui.get_player_from_element(parent) + local force_name = player.force.name + -- Draw stats section + if config.stats.show_stats then + update_data_labels(section(container,'stats',2),get_stats_data(force_name)) + end + + -- Draw milestones section + if config.milestones.show_milestones then + update_data_labels(section(container,'milestones',2),get_milestone_data(force_name)) + end + + -- Draw build progress list + if config.progress.show_progress then + local col_count = 3 + if check_player_permissions(player,'remote_launch') then col_count = col_count+1 end + if check_player_permissions(player,'toggle_active') then col_count = col_count+1 end + local progress = section(container,'progress',col_count) + -- Label used when there are no active silos + local no_silos = progress.add{ + type = 'label', + name = 'no_silos', + caption = {'rocket-info.progress-no-silos'} + } + no_silos.style.padding = {1,2} + update_build_progress(progress,get_progress_data(force_name)) + end + + -- Return the exteral container + return container.parent +end) +:add_to_left_flow(function(player) + return player.force.rockets_launched > 0 and Roles.player_allowed(player,'gui/rocket-info') +end) + +--- Button on the top flow used to toggle the container +-- @element toggle_left_element +Gui.left_toolbar_button('entity/rocket-silo', {'rocket-info.main-tooltip'}, rocket_list_container, function(player) + return Roles.player_allowed(player,'gui/rocket-info') +end) + +--- Update the gui for all players on a force +local function update_rocket_gui_all(force_name) + local stats = get_stats_data(force_name) + local milestones = get_milestone_data(force_name) + local progress = get_progress_data(force_name) + for _,player in pairs(game.forces[force_name].players) do + local frame = Gui.get_left_element(player,rocket_list_container) + local container = frame.container + update_data_labels(container.stats.table,stats) + update_data_labels(container.milestones.table,milestones) + update_build_progress(container.progress.table,progress) + end end ---[[ Creates build progress section - element - > toggle-"silo_name" (generate_progress_buttons) - > launch-"silo_name" (generate_progress_buttons) - > label-x-"silo_name" - >> "silo_name" - > label-y-"silo_name" - >> "silo_name" - > "silo_name" - >> label -]] -local function generate_progress(player,frame) - if not config.progress.show_progress then return end - local element = frame.container.progress.table - local force = player.force - local force_name = force.name - local force_silos = Rockets.get_silos(force_name) - - if not force_silos or table.size(force_silos) == 0 then - element.parent.no_silos.visible = true - - else - element.parent.no_silos.visible = false - - for _,silo_data in pairs(force_silos) do - local silo_name = silo_data.name - if not silo_data.entity or not silo_data.entity.valid then - force_silos[silo_name] = nil - Gui.destroy_if_valid(element['toggle-'..silo_name]) - Gui.destroy_if_valid(element['launch-'..silo_name]) - Gui.destroy_if_valid(element['label-x-'..silo_name]) - Gui.destroy_if_valid(element['label-y-'..silo_name]) - Gui.destroy_if_valid(element[silo_name]) - - elseif not element[silo_name] then - local entity = silo_data.entity - local progress = entity.rocket_parts - local pos = { - x=entity.position.x, - y=entity.position.y - } - - generate_progress_buttons(player,element,silo_data) - - --- Creates two flows and two labels for the X and Y position - local name = config.progress.allow_zoom_to_map and zoom_to_map_name or nil - local tooltip = config.progress.allow_zoom_to_map and {'rocket-info.progress-label-tooltip'} or nil - local flow_x = element.add{ - type='flow', - name='label-x-'..silo_name, - caption=silo_name - } - Gui.set_padding(flow_x,0,0,1,2) - flow_x.add{ - type='label', - name=name, - caption={'rocket-info.progress-x-pos',pos.x}, - tooltip=tooltip - } - - local flow_y = element.add{ - type='flow', - name='label-y-'..silo_name, - caption=silo_name - } - Gui.set_padding(flow_y,0,0,1,2) - flow_y.add{ - type='label', - name=name, - caption={'rocket-info.progress-y-pos',pos.y}, - tooltip=tooltip - } - - --- Creates the progress value which is right aligned - local right_flow = Gui.create_alignment(element,silo_name) - right_flow.add{ - type='label', - name='label', - caption={'rocket-info.progress-caption',progress}, - tooltip={'rocket-info.progress-tooltip',silo_data.launched or 0} - } - - else - local entity = silo_data.entity - local progress = entity.rocket_parts - local status = entity.status == 21 - - local label = element[silo_name].label - label.caption = {'rocket-info.progress-caption',progress} - label.tooltip = {'rocket-info.progress-tooltip',silo_data.launched or 0} - - if status and silo_data.awaiting_reset then - label.caption = {'rocket-info.progress-launched'} - label.style.font_color = Colors.green - elseif status then - label.caption = {'rocket-info.progress-caption',100} - label.style.font_color = Colors.cyan - else - silo_data.awaiting_reset = false - label.style.font_color = Colors.white - end - - generate_progress_buttons(player,element,silo_data) - - end - end - - end -end - ---- Registers the rocket info --- @element rocket_info -local rocket_info = -Gui.new_left_frame('gui/rocket-info') -:set_sprites('entity/rocket-silo') -:set_post_authenticator(function(player,define_name) - return player.force.rockets_launched > 0 and Gui.classes.toolbar.allowed(player,define_name) -end) -:set_open_by_default(function(player,define_name) - return player.force.rockets_launched > 0 -end) -:set_direction('vertical') -:on_creation(function(player,element) - generate_container(player,element) - generate_stats(player,element) - generate_milestones(player,element) - generate_progress(player,element) -end) -:on_update(function(player,element) - generate_stats(player,element) - generate_milestones(player,element) - generate_progress(player,element) -end) - ---- Event used to update the stats and the hui when a rocket is launched +--- Event used to update the stats when a rocket is launched Event.add(defines.events.on_rocket_launched,function(event) local force = event.rocket_silo.force - local rockets_launched = force.rockets_launched - local first_rocket = rockets_launched == 1 + update_rocket_gui_all(force.name) + if force.rockets_launched == 1 then + for _,player in pairs(force.players) do + Gui.update_top_flow(player) + end + end +end) - --- Updates all the guis (and toolbar since the button may now be visible) - for _,player in pairs(force.players) do - rocket_info:update(player) - if first_rocket then - Gui.update_toolbar(player) - rocket_info:toggle(player) - end - end +--- Update only the progress gui for a force +local function update_rocket_gui_progress(force_name) + local progress = get_progress_data(force_name) + for _,player in pairs(game.forces[force_name].players) do + local frame = Gui.get_left_element(player,rocket_list_container) + local container = frame.container + update_build_progress(container.progress.table,progress) + end +end + +--- Event used to set a rocket silo to be awaiting reset +Event.add(defines.events.on_rocket_launch_ordered,function(event) + local silo = event.rocket_silo + local silo_data = Rockets.get_silo_data(silo) + silo_data.awaiting_reset = true + update_rocket_gui_progress(silo.force.name) +end) + +Event.on_nth_tick(150,function() + for _,force in pairs(game.forces) do + if #Rockets.get_silos(force.name) > 0 then + update_rocket_gui_progress(force.name) + end + end end) --- Adds a silo to the list when it is built local function on_built(event) local entity = event.created_entity if entity.valid and entity.name == 'rocket-silo' then - local force = entity.force - - for _,player in pairs(force.players) do - local frame = rocket_info:get_frame(player) - generate_progress(player,frame) - end + update_rocket_gui_progress(entity.force.name) end end Event.add(defines.events.on_built_entity,on_built) Event.add(defines.events.on_robot_built_entity,on_built) ---- Optimised update for only the build progress -Event.on_nth_tick(150,function() - for _,force in pairs(game.forces) do - local silos = Rockets.get_silos(force.name) - if #silos > 0 then - for _,player in pairs(force.connected_players) do - local frame = rocket_info:get_frame(player) - generate_progress(player,frame) - end - end - end -end) +--- Redraw the progress section on role change +local function role_update_event(event) + local player = game.players[event.player_index] + local container = Gui.get_left_element(player,rocket_list_container).container + local progress = container.progress + if config.progress.show_progress then + progress.destroy() + local col_count = 3 + if check_player_permissions(player,'remote_launch') then col_count = col_count+1 end + if check_player_permissions(player,'toggle_active') then col_count = col_count+1 end + progress = section(container,'progress',col_count) + -- Label used when there are no active silos + progress.add{ + type = 'label', + name = 'no_silos', + caption = {'rocket-info.progress-no-silos'} + } + update_build_progress(progress,get_progress_data(player.force.name)) + end +end ---- Makes sure the right buttons are present when role changes -Event.add(Roles.events.on_role_assigned,rocket_info 'redraw') -Event.add(Roles.events.on_role_unassigned,rocket_info 'redraw') +Event.add(Roles.events.on_role_assigned,role_update_event) +Event.add(Roles.events.on_role_unassigned,role_update_event) -return rocket_info \ No newline at end of file +return rocket_list_container \ No newline at end of file diff --git a/modules/gui/science-info.lua b/modules/gui/science-info.lua index 9ecce6e2..da43c749 100644 --- a/modules/gui/science-info.lua +++ b/modules/gui/science-info.lua @@ -5,283 +5,369 @@ ]] local Gui = require 'expcore.gui' --- @dep expcore.gui +local Roles = require 'expcore.roles' --- @dep expcore.gui local Event = require 'utils.event' --- @dep utils.event -local format_time = ext_require('expcore.common','format_time') --- @dep expcore.common -local config = require 'config.science' --- @dep config.science +local config = require 'config.gui.science' --- @dep config.gui.science local Production = require 'modules.control.production' --- @dep modules.control.production +local format_time = _C.format_time --- @dep expcore.common local null_time_short = {'science-info.eta-time',format_time(0,{hours=true,minutes=true,seconds=true,time=true,null=true})} local null_time_long = format_time(0,{hours=true,minutes=true,seconds=true,long=true,null=true}) ---[[ Generates the main structure for the gui - element - > container - >> header - >> scroll - >>> non_made - >>> table - >> footer (when eta is enabled) - >>> eta-label - >>> eta - >>>> label -]] -local function generate_container(element) - Gui.set_padding(element,1,2,2,2) - element.style.minimal_width = 200 +--- Data label that contains the value and the surfix +-- @element production_label +local production_label = +Gui.element(function(_,parent,production_label_data) + local name = production_label_data.name + local tooltip = production_label_data.tooltip + local color = production_label_data.color - -- main container which contains the other elements - local container = - element.add{ - name='container', - type='frame', - direction='vertical', - style='window_content_frame_packed' + -- Add an alignment for the number + local alignment = Gui.alignment(parent,name) + + -- Add the main value label + local element = + alignment.add{ + name = 'label', + type = 'label', + caption = production_label_data.caption, + tooltip = tooltip } - Gui.set_padding(container) - -- main header for the gui - Gui.create_header( - container, - {'science-info.main-caption'}, - {'science-info.main-tooltip'} - ) + -- Change the style + element.style.font_color = color - -- 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_table.parent.add{ - name='non_made', - type='label', - caption={'science-info.no-packs'} + -- Add the surfix label + local surfix_element = + parent.add{ + name = 'surfix-'..name, + type = 'label', + caption = {'science-info.unit',production_label_data.surfix}, + tooltip = tooltip } - non_made.style.width = 200 - non_made.style.single_line = false - local eta - if config.show_eta then - -- footer used to store the eta - local footer = - container.add{ - name='footer', - type='frame', - style='subheader_frame' - } - Gui.set_padding(footer,2,2,4,4) - footer.style.horizontally_stretchable = true + -- Change the style + local surfix_element_style = surfix_element.style + surfix_element_style.font_color = color + surfix_element_style.right_margin = 1 - -- label for the footer - footer.add{ - name='eta-label', - type='label', - caption={'science-info.eta-caption'}, - tooltip={'science-info.eta-tooltip'}, - style='heading_1_label' - } + -- Return the value label + return element +end) - -- data for the footer - local right_align = Gui.create_alignment(footer,'eta') - eta = - right_align.add{ - name='label', - type='label', - caption=null_time_short, - tooltip=null_time_long, - style='heading_1_label' - } - end - - return flow_table, eta -end - ---[[ Adds two labels where one is right aligned and the other is a unit - element - > "name" - >> label - > spm-"name" -]] -local function add_data_label(element,name,value,secondary,tooltip) +-- Get the data that is used with the production label +local function get_production_label_data(name,tooltip,value,secondary) local data_colour = Production.get_color(config.color_clamp, value, secondary) local surfix,caption = Production.format_number(value) - if element[name] then - local data = element[name].label - data.caption = caption - data.tooltip = tooltip - data.style.font_color = data_colour - local label = element['spm-'..name] - label.caption = {'science-info.unit',surfix} - label.tooltip = tooltip - label.style.font_color = data_colour - - else - -- right aligned number - local right_align = Gui.create_alignment(element,name) - local data = - right_align.add{ - name='label', - type='label', - caption=caption, - tooltip=tooltip - } - data.style.font_color = data_colour - - -- adds the unit onto the end - local label = - element.add{ - name='spm-'..name, - type='label', - caption={'science-info.unit',surfix}, - tooltip=tooltip - } - label.style.font_color = data_colour - end + return { + name = name, + caption = caption, + surfix = surfix, + tooltip = tooltip, + color = data_colour + } end ---[[ Adds a science pack to the list - element - > icon-"science_pack" - > delta-"science_pack" - >> table - >>> pos-"science_pack" (add_data_label) - >>> neg-"science_pack" (add_data_label) - > net-"science_pack" (add_data_label) -]] -local function generate_science_pack(player,element,science_pack) - local total = Production.get_production_total(player.force, science_pack) - local minute = Production.get_production(player.force, science_pack, defines.flow_precision_index.one_minute) - if total.made > 0 then - element.parent.non_made.visible = false +-- Updates a prodution label to match the current data +local function update_production_label(parent,production_label_data) + local name = production_label_data.name + local tooltip = production_label_data.tooltip + local color = production_label_data.color - local icon_style = 'quick_bar_slot_button' - local flux = Production.get_fluctuations(player.force, science_pack, defines.flow_precision_index.one_minute) - if flux.net > -config.color_flux/2 then - icon_style = 'green_slot_button' - elseif flux.net < -config.color_flux then - icon_style = 'red_slot_button' - elseif minute.made > 0 then - icon_style = 'selected_slot_button' - end + -- Update the production label + local production_label_element = parent[name] and parent[name].label or production_label(parent,production_label_data) + production_label_element.caption = production_label_data.caption + production_label_element.tooltip = production_label_data.tooltip + production_label_element.style.font_color = color - local icon = element['icon-'..science_pack] + -- Update the surfix label + local surfix_element = parent['surfix-'..name] + surfix_element.caption = {'science-info.unit',production_label_data.surfix} + surfix_element.tooltip = tooltip + surfix_element.style.font_color = color - if icon then - icon.style = icon_style - icon.style.height = 55 - if icon_style == 'quick_bar_slot_button' then - icon.style.width = 36 - Gui.set_padding(icon,0,0,-2,-2) - end - - else - icon = - element.add{ - name='icon-'..science_pack, - type='sprite-button', - sprite='item/'..science_pack, - tooltip={'item-name.'..science_pack}, - style=icon_style - } - icon.style.height = 55 - if icon_style == 'quick_bar_slot_button' then - icon.style.width = 36 - Gui.set_padding(icon,0,0,-2,-2) - end - - end - - local delta = element['delta-'..science_pack] - - if not delta then - delta = - element.add{ - name='delta-'..science_pack, - type='frame', - style='bordered_frame' - } - Gui.set_padding(delta,0,0,3,3) - - local delta_table = - delta.add{ - name='table', - type='table', - column_count=2 - } - Gui.set_padding(delta_table) - end - - add_data_label(delta.table,'pos-'..science_pack,minute.made,nil,{'science-info.pos-tooltip',total.made}) - add_data_label(delta.table,'neg-'..science_pack,-minute.used,nil,{'science-info.neg-tooltip',total.used}) - add_data_label(element,'net-'..science_pack,minute.net,minute.made+minute.used,{'science-info.net-tooltip',total.net}) - end end ---- Updates the eta label that was created with generate_container -local function update_eta(player,element) - if not config.show_eta then return end +--- Adds 4 elements that show the data for a science pack +-- @element science_pack_base +local science_pack_base = +Gui.element(function(_,parent,science_pack_data) + local science_pack = science_pack_data.science_pack + + -- Draw the icon for the science pack + local icon_style = science_pack_data.icon_style + local pack_icon = + parent.add{ + name = 'icon-'..science_pack, + type = 'sprite-button', + sprite = 'item/'..science_pack, + tooltip = {'item-name.'..science_pack}, + style = icon_style + } + + -- Change the style of the icon + local pack_icon_style = pack_icon.style + pack_icon_style.height = 55 + if icon_style == 'quick_bar_slot_button' then + pack_icon_style.padding = {0,-2} + pack_icon_style.width = 36 + end + + -- Draw the delta flow + local delta_flow = + parent.add{ + name = 'delta-'..science_pack, + type = 'frame', + style = 'bordered_frame' + } + delta_flow.style.padding = {0,3} + + -- Draw the delta flow table + local delta_table = + delta_flow.add{ + name = 'table', + type = 'table', + column_count = 2 + } + delta_table.style.padding = 0 + + -- Draw the production labels + update_production_label(delta_table,science_pack_data.positive) + update_production_label(delta_table,science_pack_data.negative) + update_production_label(parent,science_pack_data.net) + + -- Return the pack icon + return pack_icon +end) + +local function get_science_pack_data(player,science_pack) local force = player.force + + -- Check that some packs have been made + local total = Production.get_production_total(force, science_pack) + local minute = Production.get_production(force, science_pack, defines.flow_precision_index.one_minute) + if total.made == 0 then + return + end + + -- Get the icon style + local icon_style = 'quick_bar_slot_button' + local flux = Production.get_fluctuations(force, science_pack, defines.flow_precision_index.one_minute) + if minute.net > 0 and flux.net > -config.color_flux/2 then + icon_style = 'green_slot_button' + elseif flux.net < -config.color_flux then + icon_style = 'red_slot_button' + elseif minute.made > 0 then + icon_style = 'selected_slot_button' + end + + -- Return the pack data + return { + science_pack = science_pack, + icon_style = icon_style, + positive = get_production_label_data( + 'pos-'..science_pack, + {'science-info.pos-tooltip', total.made}, + minute.made + ), + negative = get_production_label_data( + 'neg-'..science_pack, + {'science-info.neg-tooltip', total.used}, + -minute.used + ), + net = get_production_label_data( + 'net-'..science_pack, + {'science-info.net-tooltip', total.net}, + minute.net, + minute.made+minute.used + ) + } + +end + +local function update_science_pack(pack_table,science_pack_data) + if not science_pack_data then return end + local science_pack = science_pack_data.science_pack + pack_table.parent.non_made.visible = false + + -- Update the icon + local pack_icon = pack_table['icon-'..science_pack] or science_pack_base(pack_table,science_pack_data) + local icon_style = science_pack_data.icon_style + pack_icon.style = icon_style + + local pack_icon_style = pack_icon.style + pack_icon_style.height = 55 + if icon_style == 'quick_bar_slot_button' then + pack_icon_style.padding = {0,-2} + pack_icon_style.width = 36 + end + + -- Update the production labels + local delta_table = pack_table['delta-'..science_pack].table + update_production_label(delta_table,science_pack_data.positive) + update_production_label(delta_table,science_pack_data.negative) + update_production_label(pack_table,science_pack_data.net) + +end + +--- Gets the data that is used with the eta label +local function get_eta_label_data(player) + local force = player.force + + -- If there is no current research then return no research local research = force.current_research if not research then - element.caption = null_time_short - element.tooltip = null_time_long + return { research = false } + end - else - local progress = force.research_progress - local remaining = research.research_unit_count*(1-progress) - local limit - - local stats = player.force.item_production_statistics - for _,ingredient in pairs(research.research_unit_ingredients) do - local pack_name = ingredient.name - local required = ingredient.amount * remaining - local time = Production.get_consumsion_eta(force, pack_name, defines.flow_precision_index.one_minute, required) - if not limit or limit < time then - limit = time - end - end - - if not limit or limit == -1 then - element.caption = null_time_short - element.tooltip = null_time_long - - else - element.caption = {'science-info.eta-time',format_time(limit,{hours=true,minutes=true,seconds=true,time=true})} - element.tooltip = format_time(limit,{hours=true,minutes=true,seconds=true,long=true}) + local limit + local progress = force.research_progress + local remaining = research.research_unit_count*(1-progress) + -- Check for the limiting science pack + for _,ingredient in pairs(research.research_unit_ingredients) do + local pack_name = ingredient.name + local required = ingredient.amount * remaining + local time = Production.get_consumsion_eta(force, pack_name, defines.flow_precision_index.one_minute, required) + if not limit or limit < time then + limit = time end end + + -- Return the caption and tooltip + return limit and limit > 0 and { + research = true, + caption = format_time(limit,{hours=true,minutes=true,seconds=true,time=true}), + tooltip = format_time(limit,{hours=true,minutes=true,seconds=true,long=true}) + } or { research = false } + end ---- Registers the science info --- @element science_info -local science_info = -Gui.new_left_frame('gui/science-info') -:set_sprites('entity/lab') -:set_direction('vertical') -:set_tooltip{'science-info.main-tooltip'} -:on_creation(function(player,element) - local table, eta = generate_container(element) - - for _,science_pack in ipairs(config) do - generate_science_pack(player,table,science_pack) +-- Updates the eta label +local function update_eta_label(element,eta_label_data) + -- If no research selected show null + if not eta_label_data.research then + element.caption = null_time_short + element.tooltip = null_time_long + return end - update_eta(player,eta) + -- Update the element + element.caption = {'science-info.eta-time',eta_label_data.caption} + element.tooltip = eta_label_data.tooltip +end + +--- Main task list container for the left flow +-- @element task_list_container +local science_info_container = +Gui.element(function(event_trigger,parent) + local player = Gui.get_player_from_element(parent) + + -- Draw the internal container + local container = Gui.container(parent,event_trigger,200) + + -- Draw the header + Gui.header(container, {'science-info.main-caption'}, {'science-info.main-tooltip'}) + + -- Draw the scroll table for the tasks + local scroll_table = Gui.scroll_table(container,178,4) + + -- Draw the no packs label + local no_packs_label = + scroll_table.parent.add{ + name = 'non_made', + type = 'label', + caption = {'science-info.no-packs'} + } + + -- Change the style of the no packs label + local no_packs_style = no_packs_label.style + no_packs_style.padding = {2,4} + no_packs_style.single_line = false + no_packs_style.width = 200 + + -- Add the footer and eta + if config.show_eta then + -- Draw the footer + local footer = Gui.footer(container, {'science-info.eta-caption'}, {'science-info.eta-tooltip'}, true) + + -- Draw the eta label + local eta_label = + footer.add{ + name = 'label', + type = 'label', + caption = null_time_short, + tooltip = null_time_long, + style = 'heading_1_label' + } + + -- Update the eta + update_eta_label(eta_label,get_eta_label_data(player)) + + end + + -- Add packs which have been made + for _,science_pack in ipairs(config) do + update_science_pack(scroll_table,get_science_pack_data(player,science_pack)) + end + + -- Return the exteral container + return container.parent end) -:on_update(function(player,element) - local container = element.container - local table = container.scroll.table - local eta = container.footer.eta.label +:add_to_left_flow() - for _,science_pack in ipairs(config) do - generate_science_pack(player,table,science_pack) - end - - update_eta(player,eta) +--- Button on the top flow used to toggle the task list container +-- @element toggle_left_element +Gui.left_toolbar_button('entity/lab', {'science-info.main-tooltip'}, science_info_container, function(player) + return Roles.player_allowed(player,'gui/science-info') end) --- Updates the gui every 1 second -Event.on_nth_tick(60,science_info 'update_all') +Event.on_nth_tick(60,function() + local force_pack_data = {} + local force_eta_data = {} + for _,player in pairs(game.connected_players) do + local force_name = player.force.name + local frame = Gui.get_left_element(player,science_info_container) + local container = frame.container -return science_info \ No newline at end of file + -- Update the science packs + local scroll_table = container.scroll.table + local pack_data = force_pack_data[force_name] + if not pack_data then + -- No data in chache so it needs to be generated + pack_data = {} + force_pack_data[force_name] = pack_data + for _,science_pack in ipairs(config) do + local next_data = get_science_pack_data(player,science_pack) + pack_data[science_pack] = next_data + update_science_pack(scroll_table,next_data) + end + + else + -- Data found in chache is no need to generate it + for _,next_data in ipairs(pack_data) do + update_science_pack(scroll_table,next_data) + end + + end + + -- Update the eta times + if not config.show_eta then return end + local eta_label = container.footer.alignment.label + local eta_data = force_eta_data[force_name] + if not eta_data then + -- No data in chache so it needs to be generated + eta_data = get_eta_label_data(player) + force_eta_data[force_name] = eta_data + update_eta_label(eta_label,eta_data) + + else + -- Data found in chache is no need to generate it + update_eta_label(eta_label,eta_data) + + end + + end +end) \ No newline at end of file diff --git a/modules/gui/server-ups.lua b/modules/gui/server-ups.lua new file mode 100644 index 00000000..29ca6542 --- /dev/null +++ b/modules/gui/server-ups.lua @@ -0,0 +1,64 @@ +--[[-- Gui Module - Server UPS + - Adds a server ups counter in the top right and a command to toggle is + @gui server-ups + @alias server_ups +]] + +local Gui = require 'expcore.gui' --- @dep expcore.gui +local Event = require 'utils.event' --- @dep utils.event +local Commands = require 'expcore.commands' --- @dep expcore.commands + +--- Label to show the server ups +-- @element server_ups +local server_ups = +Gui.element{ + type = 'label', + caption = 'SUPS = 60.0' +} +:style{ + font = 'default-game' +} + +--- Toggles if the server ups is visbile +-- @command server-ups +Commands.new_command('server-ups','Toggle the server ups display') +:add_alias('sups','ups') +:register(function(player) + local label = player.gui.screen[server_ups.name] + if not global.ext or not global.ext.server_ups then + return Commands.error{'expcom-server-ups.no-ext'} + end + label.visible = not label.visible +end) + +-- Set the location of the label +-- 1920x1080: x=1455, y=30 (ui scale 100%) +local function set_location(event) + local player = game.players[event.player_index] + local label = player.gui.screen[server_ups.name] + local res = player.display_resolution + local uis = player.display_scale + label.location = { x=res.width-423*uis, y=30*uis } +end + +-- Draw the label when the player joins +Event.add(defines.events.on_player_created,function(event) + local player = game.players[event.player_index] + local label = server_ups(player.gui.screen) + label.visible = false + set_location(event) +end) + +-- Update the caption for all online players +Event.on_nth_tick(60,function() + if global.ext and global.ext.server_ups then + local caption = 'SUPS = '..global.ext.server_ups + for _,player in pairs(game.connected_players) do + player.gui.screen[server_ups.name].caption = caption + end + end +end) + +-- Update when res or ui scale changes +Event.add(defines.events.on_player_display_resolution_changed,set_location) +Event.add(defines.events.on_player_display_scale_changed,set_location) \ No newline at end of file diff --git a/modules/gui/task-list.lua b/modules/gui/task-list.lua index d82a3a77..20f3f189 100644 --- a/modules/gui/task-list.lua +++ b/modules/gui/task-list.lua @@ -1,5 +1,5 @@ --[[-- Gui Module - Task List - - Adds a task list to the game which players can add remove and edit items on + - Adds a task list to the game which players can add, remove and edit items on @gui Task-List @alias task_list ]] @@ -7,342 +7,410 @@ local Gui = require 'expcore.gui' --- @dep expcore.gui local Event = require 'utils.event' --- @dep utils.event local Roles = require 'expcore.roles' --- @dep expcore.roles -local config = require 'config.tasks' --- @dep config.tasks -local format_time,table_keys = ext_require('expcore.common','format_time','table_keys') --- @dep expcore.common +local config = require 'config.gui.tasks' --- @dep config.gui.tasks local Tasks = require 'modules.control.tasks' --- @dep modules.control.tasks +local format_time = _C.format_time --- @dep expcore.common + +-- Styles used for sprite buttons +local Styles = { + sprite20 = Gui.sprite_style(20), + sprite22 = Gui.sprite_style(20, nil, { right_margin = -3 }) +} --- If a player is allowed to use the edit buttons -local function player_allowed_edit(player,task) +local function check_player_permissions(player,task) if task then + -- When a task is given check if the player can edit it + local allow_edit_task = config.allow_edit_task + + -- Check if the player being the last to edit will override existing permisisons if config.user_can_edit_own_tasks and task.last_edit_name == player.name then return true end - else - if config.any_user_can_add_new_task then + + -- Check player has permisison based on value in the config + if allow_edit_task == 'all' then return true + elseif allow_edit_task == 'admin' then + return player.admin + elseif allow_edit_task == 'expcore.roles' then + return Roles.player_allowed(player,config.edit_tasks_role_permission) end - end - if config.only_admins_can_edit and not player.admin then + -- Return false as all other condidtions have not been met + return false + else + -- When a task is not given check if the player can add a new task + local allow_add_task = config.allow_add_task + + -- Check player has permisison based on value in the config + if allow_add_task == 'all' then + return true + elseif allow_add_task == 'admin' then + return player.admin + elseif allow_add_task == 'expcore.roles' then + return Roles.player_allowed(player,config.expcore_roles_add_permission) + end + + -- Return false as all other condidtions have not been met return false end - - if config.edit_tasks_role_permission and not Roles.player_allowed(player,config.edit_tasks_role_permission) then - return false - end - - return true end ---- Button in the header to add a new task +--- Button displayed in the ehader bar, used to add a new task -- @element add_new_task local add_new_task = -Gui.new_button() -:set_sprites('utility/add') -:set_tooltip{'task-list.add-tooltip'} -:set_style('tool_button',function(style) - Gui.set_padding_style(style,-2,-2,-2,-2) - style.height = 20 - style.width = 20 -end) -:on_click(function(player,element) +Gui.element{ + type = 'sprite-button', + sprite = 'utility/add', + tooltip = {'task-list.add-tooltip'}, + style = 'tool_button' +} +:style(Styles.sprite20) +:on_click(function(player,_,_) Tasks.add_task(player.force.name,nil,player.name) end) ---- Used to save changes to a task --- @element confirm_edit -local confirm_edit = -Gui.new_button() -:set_sprites('utility/downloaded') -:set_tooltip{'task-list.confirm-tooltip'} -:set_style('tool_button',function(style) - Gui.set_padding_style(style,-2,-2,-2,-2) - style.height = 20 - style.width = 20 +--- Button displayed next to tasks which the user is can edit, used to start editing a task +-- @element edit_task +local edit_task = +Gui.element{ + type = 'sprite-button', + sprite = 'utility/rename_icon_normal', + tooltip = {'task-list.edit-tooltip-none'}, + style = 'tool_button' +} +:style(Styles.sprite20) +:on_click(function(player,element,_) + local task_id = element.parent.name:sub(6) + Tasks.set_editing(task_id,player.name,true) end) -:on_click(function(player,element) + +--- Button displayed next to tasks which the user is can edit, used to delete a task from the list +-- @element discard_task +local discard_task = +Gui.element{ + type = 'sprite-button', + sprite = 'utility/trash', + tooltip = {'task-list.discard-tooltip'}, + style = 'tool_button' +} +:style(Styles.sprite20) +:on_click(function(_,element,_) + local task_id = element.parent.name:sub(6) + Tasks.remove_task(task_id) +end) + +--- Set of three elements which make up each row of the task table +-- @element add_task_base +local add_task_base = +Gui.element(function(_,parent,task_id) + -- Add the task number label + local task_number = parent.add{ + name = 'count-'..task_id, + type = 'label', + caption = '0)' + } + task_number.style.left_margin = 1 + + -- Add a flow which will contain the task message and edit buttons + local task_flow = parent.add{ name = task_id, type = 'flow', } + task_flow.style.padding = 0 + + -- Add the two edit buttons outside the task flow + local edit_flow = Gui.alignment(parent,'edit-'..task_id) + edit_task(edit_flow) + discard_task(edit_flow) + + -- Return the task flow as the main element + return task_flow +end) + +-- Removes the three elements that are added as part of the task base +local function remove_task_base(parent,task_id) + Gui.destroy_if_valid(parent['count-'..task_id]) + Gui.destroy_if_valid(parent['edit-'..task_id]) + Gui.destroy_if_valid(parent[task_id]) +end + +--- Button displayed next to tasks which the user is currently editing, used to save changes +-- @element confirm_edit +local task_editing +local confirm_edit = +Gui.element{ + type = 'sprite-button', + sprite = 'utility/downloaded', + tooltip = {'task-list.confirm-tooltip'}, + style = 'shortcut_bar_button_green' +} +:style(Styles.sprite22) +:on_click(function(player,element,_) local task_id = element.parent.name - local new_message = element.parent.task.text + local new_message = element.parent[task_editing.name].text Tasks.set_editing(task_id,player.name) Tasks.update_task(task_id,new_message,player.name) end) ---- Used to cancel any changes you made to a task +--- Button displayed next to tasks which the user is currently editing, used to discard changes -- @element cancel_edit local cancel_edit = -Gui.new_button() -:set_sprites('utility/close_black') -:set_tooltip{'task-list.cancel-tooltip'} -:set_style('tool_button',function(style) - Gui.set_padding_style(style,-2,-2,-2,-2) - style.height = 20 - style.width = 20 -end) -:on_click(function(player,element) +Gui.element{ + type = 'sprite-button', + sprite = 'utility/close_black', + tooltip = {'task-list.cancel-tooltip'}, + style = 'shortcut_bar_button_red' +} +:style(Styles.sprite22) +:on_click(function(player,element,_) local task_id = element.parent.name Tasks.set_editing(task_id,player.name) end) ---- Removes the task from the list --- @element discard_task -local discard_task = -Gui.new_button() -:set_sprites('utility/trash') -:set_tooltip{'task-list.discard-tooltip'} -:set_style('tool_button',function(style) - Gui.set_padding_style(style,-2,-2,-2,-2) - style.height = 20 - style.width = 20 +--- Editing state for a task, contrins a text field and the two edit buttons +-- @element task_editing +task_editing = +Gui.element(function(event_trigger,parent,task) + local message = task.message + + -- Draw the element + local element = + parent.add{ + name = event_trigger, + type = 'textfield', + text = message, + clear_and_focus_on_right_click = true + } + + -- Add the edit buttons + cancel_edit(parent) + confirm_edit(parent) + + -- Return the element + return element end) -:on_click(function(player,element) +:style{ + maximal_width = 110, + height = 20 +} +:on_confirmed(function(player,element,_) local task_id = element.parent.name - Tasks.remove_task(task_id) + local new_message = element.text + Tasks.set_editing(task_id,player.name) + Tasks.update_task(task_id,new_message,player.name) end) ---- Opens edit mode for the task --- @element edit_task -local edit_task = -Gui.new_button() -:set_sprites('utility/rename_icon_normal') -:set_tooltip{'task-list.edit-tooltip-none'} -:set_style('tool_button',function(style) - Gui.set_padding_style(style,-2,-2,-2,-2) - style.height = 20 - style.width = 20 -end) -:on_click(function(player,element) - local task_id = element.parent.name - Tasks.set_editing(task_id,player.name,true) +--- Default state for a task, contains only a label with the task message +-- @element task_label +local task_label = +Gui.element(function(_,parent,task) + local message = task.message + local last_edit_name = task.last_edit_name + local last_edit_time = task.last_edit_time + -- Draw the element + return parent.add{ + name = task_editing.name, + type = 'label', + caption = message, + tooltip = {'task-list.last-edit', last_edit_name, format_time(last_edit_time)} + } end) +:style{ + single_line = false, + maximal_width = 150 +} ---[[ Generates each task, handles both view and edit mode - element - > count-"task_id" - >> label - > "task_id" - >> task - >> cancel_edit (edit mode) - >> confirm_edit (edit mode) - > edit-"task_id" - >> edit_task - >> discard_task -]] -local function generate_task(player,element,task_id) +--- Updates a task for a player +local function update_task(player,task_table,task_id) local task = Tasks.get_task(task_id) local task_ids = Tasks.get_force_task_ids(player.force.name) - local task_number = table.index_of(task_ids, task_id) + local task_number = table.get_index(task_ids, task_id) + -- Task no longer exists so should be removed from the list if not task then - -- task is nil so remove it from the list - element.parent.no_tasks.visible = #task_ids == 1 - Gui.destroy_if_valid(element['count-'..task_id]) - Gui.destroy_if_valid(element['edit-'..task_id]) - Gui.destroy_if_valid(element[task_id]) - - else - local message = task.message - local editing = task.curently_editing[player.name] - local last_edit_name = task.last_edit_name - local last_edit_time = task.last_edit_time - - element.parent.no_tasks.visible = false - -- if it is not already present then add it now - local task_area = element[task_id] - if not task_area then - -- label to show the task number - element.add{ - name='count-'..task_id, - type='label', - caption=task_number..')' - } - - -- area which stores the task and buttons - task_area = - element.add{ - name=task_id, - type='flow', - } - Gui.set_padding(task_area) - - -- if the player can edit then it adds the edit and delete button - local flow = Gui.create_alignment(element,'edit-'..task_id) - local sub_flow = flow.add{type='flow',name=task_id} - - edit_task(sub_flow) - discard_task(sub_flow) - - end - - -- update the number indexes and the current editing players - element['count-'..task_id].caption = task_number..')' - - local edit_area = element['edit-'..task_id][task_id] - local players = table_keys(task.editing) - local allowed = player_allowed_edit(player,task) - - edit_area.visible = allowed - - if #players > 0 then - edit_area[edit_task.name].tooltip = {'task-list.edit-tooltip',table.concat(players,', ')} - else - edit_area[edit_task.name].tooltip = {'task-list.edit-tooltip-none'} - end - - -- draws/updates the task area - local element_type = task_area.task and task_area.task.type or nil - if not editing and element_type == 'label' then - -- update the label already present - task_area.task.caption = message - task_area.task.tooltip = {'task-list.last-edit',last_edit_name,format_time(last_edit_time)} - - elseif not editing then - -- create the label, view mode - if edit_area then - edit_area[edit_task.name].enabled = true - end - - task_area.clear() - - local label = - task_area.add{ - name='task', - type='label', - caption=message, - tooltip={'task-list.last-edit',last_edit_name,format_time(last_edit_time)} - } - label.style.single_line = false - label.style.maximal_width = 150 - - elseif editing and element_type ~= 'textfield' then - -- create the text field, edit mode, update it omitted as value is being edited - if edit_area then - edit_area[edit_task.name].enabled = false - end - - task_area.clear() - - local entry = - task_area.add{ - name='task', - type='textfield', - text=message - } - entry.style.maximal_width = 150 - entry.style.height = 20 - - cancel_edit(task_area) - confirm_edit(task_area) - - end - + task_table.parent.no_tasks.visible = #task_ids == 0 + remove_task_base(task_table,task_id) + return end + -- Get the task flow for this task + local task_flow = task_table[task_id] or add_task_base(task_table,task_id) + task_table.parent.no_tasks.visible = false + task_table['count-'..task_id].caption = task_number..')' + + -- Update the edit flow + local edit_flow = task_table['edit-'..task_id] + local player_allowed_edit = check_player_permissions(player,task) + local players_editing = table.get_keys(task.curently_editing) + local edit_task_element = edit_flow[edit_task.name] + local discard_task_element = edit_flow[discard_task.name] + + edit_task_element.visible = player_allowed_edit + discard_task_element.visible = player_allowed_edit + if #players_editing > 0 then + edit_task_element.hovered_sprite = 'utility/warning_icon' + edit_task_element.tooltip = {'task-list.edit-tooltip',table.concat(players_editing,', ')} + else + edit_task_element.hovered_sprite = edit_task_element.sprite + edit_task_element.tooltip = {'task-list.edit-tooltip-none'} + end + + -- Check if the player is was editing and/or currently editing + local task_entry = task_flow[task_editing.name] or task_label(task_flow,task) + local player_was_editing = task_entry.type == 'textfield' + local player_is_editing = task.curently_editing[player.name] + + -- Update the task flow + if not player_was_editing and not player_is_editing then + -- Update the task message label + local message = task.message + local last_edit_name = task.last_edit_name + local last_edit_time = task.last_edit_time + task_entry.caption = message + task_entry.tooltip = {'task-list.last-edit', last_edit_name, format_time(last_edit_time)} + + elseif player_was_editing and not player_is_editing then + -- Player was editing but is no longer, remove text field and add label + edit_task_element.enabled = true + task_flow.clear() + task_label(task_flow,task) + + elseif not player_was_editing and player_is_editing then + -- Player was not editing but now is, remove label and add text field + edit_task_element.enabled = false + task_flow.clear() + task_editing(task_flow,task).focus() + task_table.parent.scroll_to_element(task_flow,'top-third') + + end end ---[[ generates the main gui structure - element - > container - >> header - >>> right aligned add_new_task - >> scroll - >>> no_tasks - >>> table -]] -local function generate_container(player,element) - Gui.set_padding(element,2,2,2,2) - element.style.minimal_width = 200 +-- Update all the tasks for a player +local function update_all_tasks(player,scroll_table) + local task_ids = Tasks.get_force_task_ids(player.force.name) + if #task_ids > 0 then + for _,task_id in ipairs(task_ids) do + update_task(player,scroll_table,task_id) + end + end +end - -- main container which contains the other elements - local container = - element.add{ - name='container', - type='frame', - direction='vertical', - style='window_content_frame_packed' - } - Gui.set_padding(container) - container.style.vertically_stretchable = false +--- Main task list container for the left flow +-- @element task_list_container +local task_list_container = +Gui.element(function(event_trigger,parent) + -- Draw the internal container + local container = Gui.container(parent,event_trigger,200) - -- main header for the gui - local header_area = Gui.create_header( + -- Draw the header + local header = Gui.header( container, {'task-list.main-caption'}, {'task-list.sub-tooltip'}, true ) - --- Right aligned button to toggle the section - if player_allowed_edit(player) then - add_new_task(header_area) - end + -- Draw the new task button + local player = Gui.get_player_from_element(parent) + local add_new_task_element = add_new_task(header) + add_new_task_element.visible = check_player_permissions(player) - -- 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 + -- Draw the scroll table for the tasks + local scroll_table = Gui.scroll_table(container,190,3) + scroll_table.draw_horizontal_lines = true + scroll_table.vertical_centering = false - -- message to say that you have no tasks - local non_made = - flow_table.parent.add{ - name='no_tasks', - type='label', - caption={'task-list.no-tasks'} + -- Change the style of the scroll table + local scroll_table_style = scroll_table.style + scroll_table_style.top_cell_padding = 3 + scroll_table_style.bottom_cell_padding = 3 + + -- Draw the no tasks label + local no_tasks_label = + scroll_table.parent.add{ + name = 'no_tasks', + type = 'label', + caption = {'task-list.no-tasks'} } - non_made.style.width = 200 - non_made.style.single_line = false - return flow_table -end + -- Change the style of the no tasks label + local no_tasks_style = no_tasks_label.style + no_tasks_style.padding = {2,4} + no_tasks_style.single_line = false + no_tasks_style.width = 200 ---- Registers the task list --- @element task_list -local task_list = -Gui.new_left_frame('gui/task-list') -:set_sprites('utility/not_enough_repair_packs_icon') -:set_direction('vertical') -:set_tooltip{'task-list.main-tooltip'} -:set_open_by_default() -:on_creation(function(player,element) - local data_table = generate_container(player,element) + -- Add any existing tasks local task_ids = Tasks.get_force_task_ids(player.force.name) - - for _,task_id in pairs(task_ids) do - generate_task(player,data_table,task_id) + if #task_ids > 0 then + no_tasks_label.visible = false + for _,task_id in ipairs(task_ids) do + update_task(player,scroll_table,task_id) + end end + + -- Return the exteral container + return container.parent end) -:on_update(function(player,element) - local data_table = element.container.scroll.table +:add_to_left_flow(function(player) local task_ids = Tasks.get_force_task_ids(player.force.name) + return #task_ids > 0 +end) - for _,task_id in pairs(task_ids) do - generate_task(player,data_table,task_id) - end +--- Button on the top flow used to toggle the task list container +-- @element toggle_left_element +Gui.left_toolbar_button('utility/not_enough_repair_packs_icon', {'task-list.main-tooltip'}, task_list_container, function(player) + return Roles.player_allowed(player,'gui/task-list') end) --- When a new task is added it will udpate the task list for everyone on that force -Tasks.on_update(function(task,task_id) - local players +Tasks.on_update(function(task,task_id,removed_task) + -- Get the force to update, task is nil when removed + local force if task then - local force = game.forces[task.force_name] - players = force.connected_players + force = game.forces[task.force_name] else - players = game.connected_players + force = game.forces[removed_task.force_name] end - for _,player in pairs(players) do - local frame = task_list:get_frame(player) - local element = frame.container.scroll.table - generate_task(player,element,task_id) + -- Update the task for all the players on the force + local task_ids = Tasks.get_force_task_ids(force.name) + for _,player in pairs(force.connected_players) do + local frame = Gui.get_left_element(player,task_list_container) + local scroll_table = frame.container.scroll.table + + -- Update the task that was changed + update_task(player,scroll_table,task_id) + + -- Update the numbering of the other tasks if the task was removed + if not task then + for task_number, next_task_id in pairs(task_ids) do + scroll_table['count-'..next_task_id].caption = task_number..')' + end + end end + end) --- Update the tasks when the player joins -Event.add(defines.events.on_player_joined_game,task_list 'redraw') +Event.add(defines.events.on_player_joined_game,function(event) + local player = game.players[event.player_index] + local frame = Gui.get_left_element(player,task_list_container) + local scroll_table = frame.container.scroll.table + update_all_tasks(player,scroll_table) +end) --- Makes sure the right buttons are present when roles change -Event.add(Roles.events.on_role_assigned,task_list 'redraw') -Event.add(Roles.events.on_role_unassigned,task_list 'redraw') +local function role_update_event(event) + local player = game.players[event.player_index] + local container = Gui.get_left_element(player,task_list_container).container -return task_list \ No newline at end of file + -- Update the tasks, incase the user can now edit them + local scroll_table = container.scroll.table + update_all_tasks(player,scroll_table) + + -- Update the new task button incase the user can now add them + local add_new_task_element = container.header.alignment[add_new_task.name] + add_new_task_element.visible = check_player_permissions(player) +end + +Event.add(Roles.events.on_role_assigned,role_update_event) +Event.add(Roles.events.on_role_unassigned,role_update_event) \ No newline at end of file diff --git a/modules/gui/warp-list.lua b/modules/gui/warp-list.lua index d5d12a4f..6f25fac1 100644 --- a/modules/gui/warp-list.lua +++ b/modules/gui/warp-list.lua @@ -10,147 +10,164 @@ local Global = require 'utils.global' --- @dep utils.global local Event = require 'utils.event' --- @dep utils.event local Game = require 'utils.game' --- @dep utils.game local Roles = require 'expcore.roles' --- @dep expcore.roles -local Colors = require 'resources.color_presets' --- @dep resources.color_presets -local config = require 'config.warps' --- @dep config.warps -local format_time,table_keys = ext_require('expcore.common','format_time','table_keys') --- @dep expcore.common +local Colors = require 'utils.color_presets' --- @dep utils.color_presets +local config = require 'config.gui.warps' --- @dep config.gui.warps local Warps = require 'modules.control.warps' --- @dep modules.control.warps +local format_time = _C.format_time --- @dep expcore.common -- Stores a boolean value indexed by player name local player_in_range_store = Store.register(function(player) return player.name end) +-- Stores the time remaing for a players warp cooldown +local player_warp_cooldown_store = Store.register(function(player) + return player.name +end) + -- Table that stores a boolean value of weather to keep the warp gui open local keep_gui_open = {} Global.register(keep_gui_open,function(tbl) keep_gui_open = tbl end) +-- Styles used for sprite buttons +local Styles = { + sprite20 = Gui.sprite_style(20), + sprite22 = Gui.sprite_style(20, nil, { right_margin = -3 }), + sprite32 = { height = 32, width = 32, left_margin = 1 } +} + --- Returns if a player is allowed to edit the given warp -local function player_allowed_edit(player,warp) - if warp then +--- If a player is allowed to use the edit buttons +local function check_player_permissions(player,action,warp) + -- Check if the action is allow edit and then check bypass settings + if action == 'allow_edit_warp' then + -- Check if the warp is the spawn then it cant be edited local spawn_id = Warps.get_spawn_warp_id(player.force.name) if spawn_id == warp.warp_id then return false end + + -- Check if the player being the last to edit will override existing permisisons if config.user_can_edit_own_warps and warp.last_edit_name == player.name then return true end - else - if config.any_user_can_add_new_warp then - return true - end end - if config.only_admins_can_edit and not player.admin then - return false + -- Check player has permisison based on value in the config + local action_config = config[action] + if action_config == 'all' then + return true + elseif action_config == 'admin' then + return player.admin + elseif action_config == 'expcore.roles' then + return Roles.player_allowed(player,config['expcore_roles_'..action]) end - if config.edit_warps_role_permission and not Roles.player_allowed(player,config.edit_warps_role_permission) then - return false - end - - return true + -- Return false as all other condidtions have not been met + return false end ---- Used on the name label to allow zoom to map --- @element zoom_to_map -local zoom_to_map_name = Gui.uid_name() -Gui.on_click(zoom_to_map_name,function(event) - local warp_id = event.element.parent.name - local warp = Warps.get_warp(warp_id) - local position = warp.position - event.player.zoom_to_world(position,1.5) -end) - - ---- This timer controls when a player is able to warp, eg every 60 seconds --- @element warp_timer -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_smoothing)) -:add_store(Gui.categorize_by_player) -:set_style(nil,function(style) - style.horizontally_stretchable = true - style.color = Colors.light_blue -end) -:on_store_complete(function(player_name,reset) - Store.trigger(player_in_range_store,player_name) -end) - ---- When the button is clicked it will teleport the player --- @element goto_warp -local goto_warp = -Gui.new_button() -:set_sprites('item/'..config.default_icon) -:set_tooltip{'warp-list.goto-tooltip',0,0} -:set_style('quick_bar_slot_button',function(style) - style.height = 32 - style.width = 32 -end) -:on_click(function(player,element) - local warp_id = element.parent.caption - Warps.teleport_player(warp_id,player) - - -- Reset the warp cooldown if the player does not have unlimited warps - if config.bypass_warp_limits_permission and not Roles.player_allowed(player,config.bypass_warp_limits_permission) then - warp_timer:set_store(player.name,0) - Store.trigger(player_in_range_store,player) - end -end) - --- Will add a new warp to the list, checks if the player is too close to an existing one -- @element add_new_warp local add_new_warp = -Gui.new_button() -:set_sprites('utility/add') -:set_tooltip{'warp-list.add-tooltip'} -:set_style('tool_button',function(style) - Gui.set_padding_style(style,-2,-2,-2,-2) - style.height = 20 - style.width = 20 -end) -:on_click(function(player,element) +Gui.element{ + type = 'sprite-button', + sprite = 'utility/add', + tooltip = {'warp-list.add-tooltip'}, + style = 'tool_button' +} +:style(Styles.sprite20) +:on_click(function(player,_) + -- Add the new warp local force_name = player.force.name local surface = player.surface local position = player.position - local px = position.x - local py = position.y - local dist2 = config.minimum_distance^2 - - -- Check the distance to all existing warps - local warp_ids = Warps.get_force_warp_ids(force_name) - for _,warp_id in pairs(warp_ids) do - local warp = Warps.get_warp(warp_id) - local pos = warp.position - if surface == warp.surface and (px-pos.x)^2+(py-pos.y)^2 < dist2 then - player.print{'warp-list.too-close',warp.name} - return - end - end - - -- Add the new warp local warp_id = Warps.add_warp(force_name,surface,position,player.name) Warps.make_warp_tag(warp_id) Warps.make_warp_area(warp_id) end) +--- Removes a warp from the list, including the physical area and map tag +-- @element discard_warp +local discard_warp = +Gui.element{ + type = 'sprite-button', + sprite = 'utility/trash', + tooltip = {'warp-list.discard-tooltip'}, + style = 'tool_button' +} +:style(Styles.sprite20) +:on_click(function(_,element) + local warp_id = element.parent.name:sub(6) + Warps.remove_warp(warp_id) +end) + +--- Opens edit mode for the warp +-- @element edit_warp +local edit_warp = +Gui.element{ + type = 'sprite-button', + sprite = 'utility/rename_icon_normal', + tooltip = {'warp-list.edit-tooltip-none'}, + style = 'tool_button' +} +:style(Styles.sprite20) +:on_click(function(player,element) + local warp_id = element.parent.name:sub(6) + Warps.set_editing(warp_id,player.name,true) +end) + +--- Set of three elements which make up each row of the warp table +-- @element add_warp_base +local add_warp_base = +Gui.element(function(_,parent,warp_id) + -- Add the icon flow + local icon_flow = + parent.add{ + name = 'icon-'..warp_id, + type = 'flow', + caption = warp_id + } + icon_flow.style.padding = 0 + + -- Add a flow which will contain the warp name and edit buttons + local warp_flow = parent.add{ type = 'flow', name = warp_id } + warp_flow.style.padding = 0 + + -- Add the two edit buttons outside the warp flow + local edit_flow = Gui.alignment(parent,'edit-'..warp_id) + edit_warp(edit_flow) + discard_warp(edit_flow) + + -- Return the warp flow as the main element + return warp_flow +end) + +-- Removes the three elements that are added as part of the warp base +local function remove_warp_base(parent,warp_id) + Gui.destroy_if_valid(parent['icon-'..warp_id]) + Gui.destroy_if_valid(parent['edit-'..warp_id]) + Gui.destroy_if_valid(parent[warp_id]) +end + --- Confirms the edit to name or icon of the warp -- @element confirm_edit +local warp_editing +local warp_icon_button local confirm_edit = -Gui.new_button() -:set_sprites('utility/downloaded') -:set_tooltip{'warp-list.confirm-tooltip'} -:set_style('tool_button',function(style) - Gui.set_padding_style(style,-2,-2,-2,-2) - style.height = 20 - style.width = 20 -end) +Gui.element{ + type = 'sprite-button', + sprite = 'utility/downloaded', + tooltip = {'warp-list.confirm-tooltip'}, + style = 'shortcut_bar_button_green' +} +:style(Styles.sprite22) :on_click(function(player,element) local warp_id = element.parent.name - local warp_name = element.parent.warp.text - local warp_icon = element.parent.parent['icon-'..warp_id].icon.elem_value + local warp_name = element.parent[warp_editing.name].text + local warp_icon = element.parent.parent['icon-'..warp_id][warp_icon_button.name].elem_value Warps.set_editing(warp_id,player.name) Warps.update_warp(warp_id,warp_name,warp_icon,player.name) end) @@ -158,360 +175,396 @@ end) --- Cancels the editing changes of the selected warp name or icon -- @element cancel_edit local cancel_edit = -Gui.new_button() -:set_sprites('utility/close_black') -:set_tooltip{'warp-list.cancel-tooltip'} -:set_style('tool_button',function(style) - Gui.set_padding_style(style,-2,-2,-2,-2) - style.height = 20 - style.width = 20 -end) +Gui.element{ + type = 'sprite-button', + sprite = 'utility/close_black', + tooltip = {'warp-list.cancel-tooltip'}, + style = 'shortcut_bar_button_red' +} +:style(Styles.sprite22) :on_click(function(player,element) local warp_id = element.parent.name Warps.set_editing(warp_id,player.name) end) ---- Removes a warp from the list, including the physical area and map tag --- @element discard_warp -local discard_warp = -Gui.new_button() -:set_sprites('utility/trash') -:set_tooltip{'warp-list.discard-tooltip'} -:set_style('tool_button',function(style) - Gui.set_padding_style(style,-2,-2,-2,-2) - style.height = 20 - style.width = 20 +--- Editing state for a warp, contrins a text field and the two edit buttons +-- @element warp_editing +warp_editing = +Gui.element(function(event_trigger,parent,warp) + local name = warp.name + + -- Draw the element + local element = + parent.add{ + name = event_trigger, + type = 'textfield', + text = name, + clear_and_focus_on_right_click = true + } + + -- Add the edit buttons + cancel_edit(parent) + confirm_edit(parent) + + -- Return the element + return element end) -:on_click(function(player,element) +:style{ + maximal_width = 110, + height = 20 +} +:on_confirmed(function(player,element,_) local warp_id = element.parent.name - Warps.remove_warp(warp_id) + local warp_name = element.text + local warp_icon = element.parent.parent['icon-'..warp_id][warp_icon_button.name].elem_value + Warps.set_editing(warp_id,player.name) + Warps.update_warp(warp_id,warp_name,warp_icon,player.name) end) ---- Opens edit mode for the warp --- @element edit_warp -local edit_warp = -Gui.new_button() -:set_sprites('utility/rename_icon_normal') -:set_tooltip{'warp-list.edit-tooltip-none'} -:set_style('tool_button',function(style) - Gui.set_padding_style(style,-2,-2,-2,-2) - style.height = 20 - style.width = 20 +--- Default state for a warp, contains only a label with the warp name +-- @element warp_label +local warp_label = +Gui.element(function(event_trigger,parent,warp) + local last_edit_name = warp.last_edit_name + local last_edit_time = warp.last_edit_time + -- Draw the element + return parent.add{ + name = event_trigger, + type = 'label', + caption = warp.name, + tooltip = {'warp-list.last-edit',last_edit_name,format_time(last_edit_time)} + } end) -:on_click(function(player,element) +:style{ + single_line = false, + maximal_width = 150 +} +:on_click(function(player,element,_) local warp_id = element.parent.name - Warps.set_editing(warp_id,player.name,true) -end) - ---[[ Generates each warp, handles both view and edit mode - element - > icon-"warp_id" - >> goto_warp or icon - > "warp_id" - >> warp - >> cancel_edit (edit mode) - >> confirm_edit (edit mode) - > edit-"warp_id" - >> "warp_id" - >>> edit_warp - >>> discard_warp -]] -local function generate_warp(player,element,warp_id) local warp = Warps.get_warp(warp_id) + local position = warp.position + player.zoom_to_world(position,1.5) +end) + + +--- Default state for the warp icon, when pressed teleports the player +-- @element warp_icon_button +warp_icon_button = +Gui.element(function(event_trigger,parent,warp) + local warp_position = warp.position + -- Draw the element + return parent.add{ + name = event_trigger, + type = 'sprite-button', + sprite = 'item/'..warp.icon, + tooltip = {'warp-list.goto-tooltip',warp_position.x,warp_position.y}, + style = 'quick_bar_slot_button' + } +end) +:style(Styles.sprite32) +:on_click(function(player,element,_) + if element.type == 'choose-elem-button' then return end + local warp_id = element.parent.caption + Warps.teleport_player(warp_id,player) + + -- Reset the warp cooldown if the player does not have unlimited warps + if not check_player_permissions(player,'bypass_warp_cooldown') then + Store.set(player_warp_cooldown_store,player,config.cooldown_duraction) + Store.trigger(player_in_range_store,player) + end +end) + +--- Editing state for the warp icon, chose elem used to chosse icon +-- @element warp_icon_editing +local warp_icon_editing = +Gui.element(function(_,parent,warp) + return parent.add{ + name = warp_icon_button.name, + type = 'choose-elem-button', + elem_type = 'item', + item = warp.icon, + tooltip = {'warp-list.goto-edit'}, + } +end) +:style(Styles.sprite32) + +--- This timer controls when a player is able to warp, eg every 60 seconds +-- @element warp_timer +local warp_timer = +Gui.element{ + type = 'progressbar', + tooltip = {'warp-list.timer-tooltip',config.cooldown_duraction}, + minimum_value = 0, + maximum_value = config.cooldown_duraction*config.update_smoothing +} +:style{ + horizontally_stretchable = true, + color = Colors.light_blue +} + +--- Updates a warp for a player +local function update_warp(player,warp_table,warp_id) + local warp = Warps.get_warp(warp_id) + + -- Warp no longer exists so should be removed from the list if not warp then - -- warp is nil so remove it from the list - Gui.destroy_if_valid(element['icon-'..warp_id]) - Gui.destroy_if_valid(element['edit-'..warp_id]) - Gui.destroy_if_valid(element[warp_id]) - - else - local warp_name = warp.name - local warp_icon = warp.icon - local editing = warp.currently_editing[player.name] - local last_edit_name = warp.last_edit_name - local last_edit_time = warp.last_edit_time - local position = warp.position - - -- if it is not already present then add it now - local warp_area = element[warp_id] - local icon_area = element['icon-'..warp_id] - if not warp_area then - -- area to store the warp icon - icon_area = - element.add{ - name='icon-'..warp_id, - type='flow', - caption=warp_id - } - Gui.set_padding(icon_area) - - -- area which stores the warp and buttons - warp_area = - element.add{ - name=warp_id, - type='flow', - } - Gui.set_padding(warp_area) - - -- if the player can edit then it adds the edit and delete button - local flow = Gui.create_alignment(element,'edit-'..warp_id) - local sub_flow = flow.add{type='flow',name=warp_id} - - edit_warp(sub_flow) - discard_warp(sub_flow) - - end - - local edit_area = element['edit-'..warp_id][warp_id] - local players = warp.currently_editing and table_keys(warp.currently_editing) or {} - local allowed = player_allowed_edit(player,warp) - - edit_area.visible = allowed - - if #players > 0 then - edit_area[edit_warp.name].tooltip = {'warp-list.edit-tooltip',table.concat(players,', ')} - else - edit_area[edit_warp.name].tooltip = {'warp-list.edit-tooltip-none'} - end - - -- draws/updates the warp area - local label_element = warp_area.warp or warp_area[zoom_to_map_name] or nil - local element_type = label_element and label_element.type or nil - if not editing and element_type == 'label' then - -- update the label already present - label_element.caption = warp_name - label_element.tooltip = {'warp-list.last-edit',last_edit_name,format_time(last_edit_time)} - icon_area[goto_warp.name].sprite = 'item/'..warp_icon - - elseif not editing then - -- create the label, view mode - if edit_area then - edit_area[edit_warp.name].enabled = true - end - - -- redraws the icon for the warp - icon_area.clear() - - local btn = goto_warp(icon_area) - btn.sprite = 'item/'..warp_icon - btn.tooltip = {'warp-list.goto-tooltip',position.x,position.y} - - local timer = warp_timer:get_store(player.name) - local enabled = not timer and Store.get(player_in_range_store,player) - or Roles.player_allowed(player,config.bypass_warp_limits_permission) - if not enabled then - btn.enabled = false - btn.tooltip = {'warp-list.goto-disabled'} - end - - -- redraws the label for the warp name - warp_area.clear() - - local label = - warp_area.add{ - name=zoom_to_map_name, - type='label', - caption=warp_name, - tooltip={'warp-list.last-edit',last_edit_name,format_time(last_edit_time)} - } - label.style.single_line = false - label.style.maximal_width = 150 - - elseif editing and element_type ~= 'textfield' then - -- create the text field, edit mode, update it omitted as value is being edited - if edit_area then - edit_area[edit_warp.name].enabled = false - end - - -- redraws the icon for the warp and allows selection - icon_area.clear() - - local btn = - icon_area.add{ - name='icon', - type='choose-elem-button', - elem_type='item', - item=warp_icon, - tooltip={'warp-list.goto-edit'}, - } - btn.style.height = 32 - btn.style.width = 32 - - -- redraws the label for the warp name and allows editing - warp_area.clear() - - local entry = - warp_area.add{ - name='warp', - type='textfield', - text=warp_name - } - entry.style.maximal_width = 150 - entry.style.height = 20 - - cancel_edit(warp_area) - confirm_edit(warp_area) - - end - + remove_warp_base(warp_table,warp_id) + return end + -- Get the warp flow for this warp + local warp_flow = warp_table[warp_id] or add_warp_base(warp_table,warp_id) + local icon_flow = warp_table['icon-'..warp_id] + + -- Update the edit flow + local edit_flow = warp_table['edit-'..warp_id] + local player_allowed_edit = check_player_permissions(player,'allow_edit_warp',warp) + local players_editing = table.get_keys(warp.currently_editing) + local edit_warp_element = edit_flow[edit_warp.name] + local discard_warp_element = edit_flow[discard_warp.name] + + edit_warp_element.visible = player_allowed_edit + discard_warp_element.visible = player_allowed_edit + if #players_editing > 0 then + edit_warp_element.hovered_sprite = 'utility/warning_icon' + edit_warp_element.tooltip = {'warp-list.edit-tooltip',table.concat(players_editing,', ')} + else + edit_warp_element.hovered_sprite = edit_warp_element.sprite + edit_warp_element.tooltip = {'warp-list.edit-tooltip-none'} + end + + -- Check if the player is was editing and/or currently editing + local warp_label_element = warp_flow[warp_label.name] or warp_label(warp_flow,warp) + local icon_entry = icon_flow[warp_icon_button.name] or warp_icon_button(icon_flow,warp) + local player_was_editing = icon_entry.type == 'choose-elem-button' + local player_is_editing = warp.currently_editing[player.name] + + -- Update the warp and icon flow + if not player_was_editing and not player_is_editing then + -- Update the warp name label and icon + local warp_name = warp.name + local warp_icon = warp.icon + local last_edit_name = warp.last_edit_name + local last_edit_time = warp.last_edit_time + warp_label_element.caption = warp_name + warp_label_element.tooltip = {'warp-list.last-edit',last_edit_name,format_time(last_edit_time)} + icon_entry.sprite = 'item/'..warp_icon + + elseif player_was_editing and not player_is_editing then + -- Player was editing but is no longer, remove text field and add label + edit_warp_element.enabled = true + warp_flow.clear() + warp_label(warp_flow,warp) + + icon_flow.clear() + local warp_icon_element = warp_icon_button(icon_flow,warp) + local timer = Store.get(player_warp_cooldown_store,player) + local in_range = Store.get(player_in_range_store,player) + local apply_proximity = not check_player_permissions(player,'bypass_warp_proximity') + if (timer and timer > 0) or (apply_proximity and not in_range) then + warp_icon_element.enabled = false + warp_icon_element.tooltip = {'warp-list.goto-disabled'} + end + + elseif not player_was_editing and player_is_editing then + -- Player was not editing but now is, remove label and add text field + edit_warp_element.enabled = false + warp_flow.clear() + warp_editing(warp_flow,warp).focus() + warp_table.parent.scroll_to_element(warp_flow,'top-third') + icon_flow.clear() + warp_icon_editing(icon_flow,warp) + + end end ---[[ generates the main gui structure - element - > container - >> header - >>> right aligned add_new_warp - >> scroll - >>> table - >> warp_timer -]] -local function generate_container(player,element) - Gui.set_padding(element,2,2,2,2) - element.style.minimal_width = 200 +-- Update all the warps for a player +local function update_all_warps(player,warp_table) + local warp_ids = Warps.get_force_warp_ids(player.force.name) + if #warp_ids > 0 then + for _,warp_id in ipairs(warp_ids) do + update_warp(player,warp_table,warp_id) + end + end +end - -- main container which contains the other elements - local container = - element.add{ - name='container', - type='frame', - direction='vertical', - style='window_content_frame_packed' - } - Gui.set_padding(container) - container.style.vertically_stretchable = false +--- Main warp list container for the left flow +-- @element warp_list_container +local warp_list_container = +Gui.element(function(event_trigger,parent) + -- Draw the internal container + local container = Gui.container(parent,event_trigger,200) - -- main header for the gui - local header_area = Gui.create_header( + -- Draw the header + local header = Gui.header( container, {'warp-list.main-caption'}, - {'warp-list.sub-tooltip',config.recharge_time,config.activation_range}, + {'warp-list.sub-tooltip', config.cooldown_duraction, config.standard_proximity_radius}, true ) - --- Right aligned button to toggle the section - if player_allowed_edit(player) then - add_new_warp(header_area) + -- Draw the new warp button + local player = Gui.get_player_from_element(parent) + local add_new_warp_element = add_new_warp(header) + add_new_warp_element.visible = check_player_permissions(player,'allow_add_warp') + + -- Draw the scroll table for the warps + local scroll_table = Gui.scroll_table(container,250,3) + + -- Change the style of the scroll table + local scroll_table_style = scroll_table.style + scroll_table_style.top_cell_padding = 3 + scroll_table_style.bottom_cell_padding = 3 + + -- Draw the warp cooldown progress bar + local warp_timer_element = warp_timer(container) + + -- Change the progress of the warp timer + local progress = 1 + local timer = Store.get(player_warp_cooldown_store,player) + if timer and timer > 0 then + progress = 1 - (timer/config.cooldown_duraction) end + warp_timer_element.value = progress - -- table that stores all the data - local flow_table = Gui.create_scroll_table(container,3,258) - flow_table.style.top_cell_padding = 3 - flow_table.style.bottom_cell_padding = 3 + -- Add any existing warps + update_all_warps(player,scroll_table) - warp_timer(container) - - return flow_table -end - ---- Registers the warp list --- @element warp_list -local warp_list = -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_creation(function(player,element) - local data_table = generate_container(player,element) - local warp_ids = Warps.get_force_warp_ids(player.force.name) - - for _,warp_id in ipairs(warp_ids) do - generate_warp(player,data_table,warp_id) - end + -- Return the exteral container + return container.parent end) -:on_update(function(player,element) - local data_table = element.container.scroll.table - local warp_ids = Warps.get_force_warp_ids(player.force.name) +:add_to_left_flow() - data_table.clear() - for _,warp_id in ipairs(warp_ids) do - generate_warp(player,data_table,warp_id) - end +--- Button on the top flow used to toggle the warp list container +-- @element warp_list_toggle +Gui.left_toolbar_button('item/'..config.default_icon,{'warp-list.main-tooltip',config.standard_proximity_radius},warp_list_container, function(player) + return Roles.player_allowed(player,'gui/warp-list') end) -:on_player_toggle(function(player,element,visible) - keep_gui_open[player.name] = visible +:on_custom_event(Gui.events.on_visibility_changed_by_click, function(player,_,event) + -- Set gui keep open state for player that clicked the button: true if visible, false if invisible + keep_gui_open[player.name] = event.state end) --- When the name of a warp is updated this is triggered -Warps.on_update(function(warp) - local players - local force_name +Warps.on_update(function(warp,_,removed_warp) + -- Get the force to update, warp is nil when removed + local force if warp then - local force = game.forces[warp.force_name] - players = force.connected_players - force_name = warp.force_name + force = game.forces[warp.force_name] else - players = game.connected_players + force = game.forces[removed_warp.force_name] end -- Update the gui for selected players - local force_warps = {} - for _,player in pairs(players) do - local frame = warp_list:get_frame(player) - local element = frame.container.scroll.table - - -- Get the warp ids for the players force - force_name = force_name or player.force.name - local warp_ids = force_warps[force_name] - if not warp_ids then - warp_ids = Warps.get_force_warp_ids(force_name) - force_warps[force_name] = warp_ids - end + local warp_ids = Warps.get_force_warp_ids(force.name) + for _,player in pairs(force.connected_players) do + local frame = Gui.get_left_element(player,warp_list_container) + local scroll_table = frame.container.scroll.table -- Update the gui - element.clear() - for _,warp_id in ipairs(warp_ids) do - generate_warp(player,element,warp_id) + scroll_table.clear() + for _,next_warp_id in ipairs(warp_ids) do + update_warp(player,scroll_table,next_warp_id) end end end) --- Update the warps when the player joins -Event.add(defines.events.on_player_joined_game,warp_list 'redraw') -Event.add(Roles.events.on_role_assigned,warp_list 'redraw') -Event.add(Roles.events.on_role_unassigned,warp_list 'redraw') +Event.add(defines.events.on_player_joined_game,function(event) + local player = game.players[event.player_index] + local frame = Gui.get_left_element(player,warp_list_container) + local scroll_table = frame.container.scroll.table + update_all_warps(player,scroll_table) +end) + +--- Makes sure the right buttons are present when roles change +local function role_update_event(event) + local player = game.players[event.player_index] + local container = Gui.get_left_element(player,warp_list_container).container + + -- Update the warps, incase the user can now edit them + local scroll_table = container.scroll.table + update_all_warps(player,scroll_table) + + -- Update the new warp button incase the user can now add them + local add_new_warp_element = container.header.alignment[add_new_warp.name] + add_new_warp_element.visible = check_player_permissions(player,'allow_add_warp') +end + +Event.add(Roles.events.on_role_assigned,role_update_event) +Event.add(Roles.events.on_role_unassigned,role_update_event) --- When the player leaves or enters range of a warp this is triggered Store.watch(player_in_range_store,function(value,player_name) local player = game.players[player_name] local force = player.force - local frame = warp_list:get_frame(player_name) - local table_area = frame.container.scroll.table - local timer = warp_timer:get_store(player_name) - local state = not timer and value + -- Change if the frame is visible based on if the player is in range if not keep_gui_open[player.name] then - Gui.toggle_left_frame(warp_list.name,player,value) + Gui.toggle_left_element(player,warp_list_container,value) end - if Roles.player_allowed(player,config.bypass_warp_limits_permission) then + -- Check if the player requires proximity + if check_player_permissions(player,'bypass_warp_proximity') then return end + -- Get the warp table + local frame = Gui.get_left_element(player,warp_list_container) + local scroll_table = frame.container.scroll.table + + -- Check if the buttons should be active + local timer = Store.get(player_warp_cooldown_store,player) + local button_disabled = timer and timer > 0 or not value + + -- Change the enabled state of the warp buttons local warp_ids = Warps.get_force_warp_ids(force.name) for _,warp_id in pairs(warp_ids) do - local element = table_area['icon-'..warp_id][goto_warp.name] + local element = scroll_table['icon-'..warp_id][warp_icon_button.name] if element and element.valid then - element.enabled = state - if state then + element.enabled = not button_disabled + if button_disabled then + element.tooltip = {'warp-list.goto-disabled'} + else local position = Warps.get_warp(warp_id).position element.tooltip = {'warp-list.goto-tooltip',position.x,position.y} - else - element.tooltip = {'warp-list.goto-disabled'} end end end end) ---- Handles updating the timer and checking distance from a warp -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(warp_timer.store) or {} - for category,_ in pairs(categories) do - warp_timer:increment(1,category) +--- Update the warp cooldown progress bars to match the store +Store.watch(player_warp_cooldown_store,function(value,player_name,old_value) + if value == old_value then return end + -- Get the progress bar element + local player = game.players[player_name] + local frame = Gui.get_left_element(player,warp_list_container) + local warp_timer_element = frame.container[warp_timer.name] + + -- Set the progress + local progress = 1 + local timer = Store.get(player_warp_cooldown_store,player) + if timer and timer > 0 then + progress = 1 - (timer/config.cooldown_duraction) end + warp_timer_element.value = progress + + -- Trigger update of buttons if cooldown is now 0 + if value == 0 then + Store.trigger(player_in_range_store,player_name) + end +end) + +--- Handles updating the timer and checking distance from a warp +local r2 = config.standard_proximity_radius^2 +local rs2 = config.spawn_proximity_radius^2 +local mr2 = config.minimum_distance^2 +Event.on_nth_tick(math.floor(60/config.update_smoothing),function() + Store.map(player_warp_cooldown_store,function(value) + if value > 0 then + return value - 1 + end + end) local force_warps = {} local warps = {} @@ -527,6 +580,8 @@ Event.on_nth_tick(math.floor(60/config.update_smoothing),function() end -- Check if the force has any warps + local closest_warp + local closest_distance if #warp_ids > 0 then local surface = player.surface local pos = player.position @@ -545,20 +600,34 @@ Event.on_nth_tick(math.floor(60/config.update_smoothing),function() local warp_pos = warp.position if warp.surface == surface then local dx, dy = px-warp_pos.x, py-warp_pos.y - if (warp_id == warp_ids.spawn and (dx*dx)+(dy*dy) < rs2) or (dx*dx)+(dy*dy) < r2 then - -- Set in range to true if the player was preiovusly out of range - if not was_in_range then - Store.set(player_in_range_store,player,true) - end - was_in_range = false -- stops setting back to false below - break + local dist = (dx*dx)+(dy*dy) + if closest_distance == nil or dist < closest_distance then + closest_warp = warp + closest_distance = dist + if dist < r2 then break end end end end - -- Set in range to false if the player was preiovusly in range - if was_in_range then + -- Check the dist to the closest warp + local in_range = closest_warp.warp_id == warp_ids.spawn and closest_distance < rs2 or closest_distance < r2 + if was_in_range and not in_range then Store.set(player_in_range_store,player,false) + elseif not was_in_range and in_range then + Store.set(player_in_range_store,player,true) + end + + -- Change the enabled state of the add warp button + local frame = Gui.get_left_element(player,warp_list_container) + local add_warp_element = frame.container.header.alignment[add_new_warp.name] + local was_able_to_make_warp = add_warp_element.enabled + local can_make_warp = closest_distance > mr2 + if can_make_warp and not was_able_to_make_warp then + add_warp_element.enabled = true + add_warp_element.tooltip = {'warp-list.add-tooltip'} + elseif not can_make_warp and was_able_to_make_warp then + add_warp_element.enabled = false + add_warp_element.tooltip = {'warp-list.too-close',closest_warp.name} end end @@ -567,18 +636,10 @@ Event.on_nth_tick(math.floor(60/config.update_smoothing),function() end) ---- When a player is created it will set them being in range to false to stop warping on join +--- When a player is created make sure that there is a spawn warp created Event.add(defines.events.on_player_created,function(event) - local player = Game.get_player_by_index(event.player_index) - - -- Check if a player is allowed unlimited warps - local allowed = config.bypass_warp_limits_permission and Roles.player_allowed(player,config.bypass_warp_limits_permission) or false - Store.set(player_in_range_store,player,allowed) - if allowed then - warp_timer:set_store(player.name,1) - end - -- If the force has no spawn then make a spawn warp + local player = Game.get_player_by_index(event.player_index) local force = player.force local spawn_id = Warps.get_spawn_warp_id(force.name) if not spawn_id then @@ -590,6 +651,7 @@ Event.add(defines.events.on_player_created,function(event) end end) +--- When a chart tag is removed or edited make sure it is not one that belongs to a warp local function maintain_tag(event) if not event.player_index then return end local tag = event.tag @@ -608,6 +670,4 @@ local function maintain_tag(event) 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 +Event.add(defines.events.on_chart_tag_removed,maintain_tag) \ No newline at end of file diff --git a/utils/debug.lua b/overrides/debug.lua similarity index 99% rename from utils/debug.lua rename to overrides/debug.lua index 98f85a28..20be17a8 100644 --- a/utils/debug.lua +++ b/overrides/debug.lua @@ -161,4 +161,4 @@ function Debug.is_closure(func) end end -return Debug +return Debug \ No newline at end of file diff --git a/utils/inspect.lua b/overrides/inspect.lua similarity index 99% rename from utils/inspect.lua rename to overrides/inspect.lua index c13a8cd4..76605169 100644 --- a/utils/inspect.lua +++ b/overrides/inspect.lua @@ -338,5 +338,4 @@ end setmetatable(inspect, { __call = function(_, ...) return inspect.inspect(...) end }) -return inspect - +return inspect \ No newline at end of file diff --git a/utils/math.lua b/overrides/math.lua similarity index 99% rename from utils/math.lua rename to overrides/math.lua index 179005c9..a9ba046f 100644 --- a/utils/math.lua +++ b/overrides/math.lua @@ -52,4 +52,4 @@ math.degrees = function(angle) return angle * deg_to_rad end -return math +return math \ No newline at end of file diff --git a/utils/print_override.lua b/overrides/print.lua similarity index 69% rename from utils/print_override.lua rename to overrides/print.lua index 848c91b2..22f3c72a 100644 --- a/utils/print_override.lua +++ b/overrides/print.lua @@ -1,5 +1,4 @@ -local Public = {} - +--luacheck:ignore global print local locale_string = {'', '[PRINT] ', nil} local raw_print = print @@ -8,6 +7,4 @@ function print(str) log(locale_string) end -Public.raw_print = raw_print - -return Public +return raw_print \ No newline at end of file diff --git a/utils/require_override.lua b/overrides/require.lua similarity index 75% rename from utils/require_override.lua rename to overrides/require.lua index 06779e59..36430248 100644 --- a/utils/require_override.lua +++ b/overrides/require.lua @@ -1,4 +1,5 @@ -local loaded = _G.package.loaded +--luacheck:ignore global require +local loaded = package.loaded local raw_require = require function require(path) diff --git a/resources/data_stages.lua b/overrides/stages.lua similarity index 91% rename from resources/data_stages.lua rename to overrides/stages.lua index 516fb321..8a7fb800 100644 --- a/resources/data_stages.lua +++ b/overrides/stages.lua @@ -10,3 +10,5 @@ _STAGE = { --config_change = 7, runtime = 8 } + +_LIFECYCLE = _STAGE.control \ No newline at end of file diff --git a/utils/table.lua b/overrides/table.lua similarity index 55% rename from utils/table.lua rename to overrides/table.lua index 4b1973e2..e3823302 100644 --- a/utils/table.lua +++ b/overrides/table.lua @@ -22,7 +22,7 @@ end -- The catch is that fast_remove doesn't guarantee to maintain the order of items in the array. -- @param tbl arrayed table -- @param index Must be >= 0. The case where index > #tbl is handled. -function table.fast_remove(tbl, index) +function table.remove_index(tbl, index) local count = #tbl if index > count then return @@ -36,7 +36,7 @@ end --- Adds the contents of table t2 to table t1 -- @param t1
    to insert into -- @param t2
    to insert from -function table.add_all(t1, t2) +function table.merge_table(t1, t2) for k, v in pairs(t2) do if tonumber(k) then t1[#t1 + 1] = v @@ -46,11 +46,74 @@ function table.add_all(t1, t2) end 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 +table.array_insert(tbl,500,values) -- around 0.4ms +]] +function table.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 +table.table_insert(tbl,50,tbl2) +]] +function table.table_insert(tbl,start_index,tbl2) + if not tbl2 then + tbl2 = start_index + start_index = nil + end + + table.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 + --- Checks if a table contains an element -- @param t
    -- @param e table element -- @return the index of the element or nil -function table.index_of(t, e) +function table.get_key(t, e) for k, v in pairs(t) do if v == e then return k @@ -63,7 +126,7 @@ end -- @param t
    -- @param e table element -- @return the index of the element or nil -function table.index_of_in_array(t, e) +function table.get_index(t, e) for i = 1, #t do if t[i] == e then return i @@ -72,22 +135,33 @@ function table.index_of_in_array(t, e) return nil end -local index_of = table.index_of --- Checks if a table contains an element -- @param t
    -- @param e table element -- @return indicating success function table.contains(t, e) - return index_of(t, e) and true or false + return table.get_key(t, e) and true or false end -local index_of_in_array = table.index_of_in_array --- Checks if the arrayed portion of a table contains an element -- @param t
    -- @param e table element -- @return indicating success function table.array_contains(t, e) - return index_of_in_array(t, e) and true or false + return table.get_index(t, e) and true or false +end + +--- Extracts certain keys from a table +-- @usage local key_three, key_one = extract({key_one='foo',key_two='bar',key_three=true},'key_three','key_one') +-- @tparam table tbl table the which contains the keys +-- @tparam string ... the names of the keys you want extracted +-- @return the keys in the order given +function table.extract_keys(tbl,...) + local values = {} + for _,key in pairs({...}) do + table.insert(values,tbl[key]) + end + return unpack(values) end --- Adds an element into a specific index position while shuffling the rest down @@ -151,6 +225,21 @@ function table.get_random_weighted(weighted_table, item_index, weight_index) end end +--- Clears all existing entries in a table +-- @param t
    to clear +-- @param array to indicate whether the table is an array or not +function table.clear_table(t, array) + if array then + for i = 1, #t do + t[i] = nil + end + else + for i in pairs(t) do + t[i] = nil + end + end +end + --- Creates a fisher-yates shuffle of a sequential number-indexed table -- because this uses math.random, it cannot be used outside of events if no rng is supplied -- from: http://www.sdknews.com/cross-platform/corona/tutorial-how-to-shuffle-table-items @@ -171,19 +260,102 @@ function table.shuffle_table(t, rng) end end ---- Clears all existing entries in a table --- @param t
    to clear --- @param array to indicate whether the table is an array or not -function table.clear_table(t, array) - if array then - for i = 1, #t do - t[i] = nil +--- Default table comparator sort function. +-- @local +-- @param x one comparator operand +-- @param y the other comparator operand +-- @return true if x logically comes before y in a list, false otherwise +local function sortFunc(x, y) --sorts tables with mixed index types. + local tx = type(x) + local ty = type(y) + if tx == ty then + if type(x) == 'string' then + return string.lower(x) < string.lower(y) + else + return x < y + end + elseif tx == 'number' then + return true --only x is a number and goes first + else + return false --only y is a number and goes first + end +end + +--- Returns a copy of all of the values in the table. +-- @tparam table tbl the to copy the keys from, or an empty table if tbl is nil +-- @tparam[opt] boolean sorted whether to sort the keys (slower) or keep the random order from pairs() +-- @tparam[opt] boolean as_string whether to try and parse the values as strings, or leave them as their existing type +-- @treturn array an array with a copy of all the values in the table +function table.get_values(tbl, sorted, as_string) + if not tbl then return {} end + local valueset = {} + local n = 0 + if as_string then --checking as_string /before/ looping is faster + for _, v in pairs(tbl) do + n = n + 1 + valueset[n] = tostring(v) end else - for i in pairs(t) do - t[i] = nil + for _, v in pairs(tbl) do + n = n + 1 + valueset[n] = v end end + if sorted then + table.sort(valueset,sortFunc) + end + return valueset +end + +--- Returns a copy of all of the keys in the table. +-- @tparam table tbl the to copy the keys from, or an empty table if tbl is nil +-- @tparam[opt] boolean sorted whether to sort the keys (slower) or keep the random order from pairs() +-- @tparam[opt] boolean as_string whether to try and parse the keys as strings, or leave them as their existing type +-- @treturn array an array with a copy of all the keys in the table +function table.get_keys(tbl, sorted, as_string) + if not tbl then return {} end + local keyset = {} + local n = 0 + if as_string then --checking as_string /before/ looping is faster + for k, _ in pairs(tbl) do + n = n + 1 + keyset[n] = tostring(k) + end + else + for k, _ in pairs(tbl) do + n = n + 1 + keyset[n] = k + end + end + if sorted then + table.sort(keyset,sortFunc) + end + return keyset +end + +--- Returns the list is a sorted way that would be expected by people (this is by key) +-- @tparam table tbl the table to be sorted +-- @treturn table the sorted table +function table.alphanumsort(tbl) + local o = table.get_keys(tbl) + local function padnum(d) local dec, n = string.match(d, "(%.?)0*(.+)") + return #dec > 0 and ("%.12f"):format(d) or ("%s%03d%s"):format(dec, #n, n) end + table.sort(o, function(a,b) + return tostring(a):gsub("%.?%d+",padnum)..("%3d"):format(#b) + < tostring(b):gsub("%.?%d+",padnum)..("%3d"):format(#a) end) + local _tbl = {} + for _,k in pairs(o) do _tbl[k] = tbl[k] end + return _tbl +end + +--- Returns the list is a sorted way that would be expected by people (this is by key) (faster alternative than above) +-- @tparam table tbl the table to be sorted +-- @treturn table the sorted table +function table.keysort(tbl) + local o = table.get_keys(tbl,true) + local _tbl = {} + for _,k in pairs(o) do _tbl[k] = tbl[k] end + return _tbl end --[[ @@ -238,7 +410,7 @@ require 'util' -- process is a function which allow altering the passed object before transforming it into a string. -- A typical way to use it would be to remove certain values so that they don't appear at all. -- return the prettied table -table.inspect = require 'utils.inspect' --- @dep utils.inspect +table.inspect = require 'overrides.inspect' --- @dep overrides.inspect --- Takes a table and returns the number of entries in the table. (Slower than #table, faster than iterating via pairs) table.size = table_size @@ -262,4 +434,4 @@ table.merge = util.merge -- @return table.equals = table.compare -return table +return table \ No newline at end of file diff --git a/resources/version.lua b/resources/version.lua deleted file mode 100644 index 98d7ac58..00000000 --- a/resources/version.lua +++ /dev/null @@ -1,2 +0,0 @@ -global.redmew_version = nil -global.expgaming_version = '5.0.0' \ No newline at end of file diff --git a/utils/alien_evolution_progress.lua b/utils/alien_evolution_progress.lua deleted file mode 100644 index 03c97aa0..00000000 --- a/utils/alien_evolution_progress.lua +++ /dev/null @@ -1,179 +0,0 @@ ---[[-- info - Original (javascript) version: https://hastebin.com/udakacavap.js - Can be tested against: https://wiki.factorio.com/Enemies#Spawn_chances_by_evolution_factor -]] - --- dependencies -local Global = require 'utils.global' --- @dep utils.global -local Debug = require 'utils.debug' --- @dep utils.debug -local table = require 'utils.table' --- @dep utils.table - --- localized functions -local get_random_weighted = table.get_random_weighted -local round = math.round -local ceil = math.ceil -local floor = math.floor -local random = math.random -local pairs = pairs -local format = string.format - --- this -local AlienEvolutionProgress = {} - -local memory = { - spawner_specifications = {}, - spawner_specifications_count = 0, - evolution_cache = { - ['biter-spawner'] = { - evolution = -1, - weight_table = {}, - }, - ['spitters-spawner'] = { - evolution = -1, - weight_table = {}, - }, - }, -} - -Global.register_init({ - memory = memory, -}, function(tbl) - for name, prototype in pairs(game.entity_prototypes) do - if prototype.type == 'unit-spawner' and prototype.subgroup.name == 'enemies' then - tbl.memory.spawner_specifications[name] = prototype.result_units - memory.spawner_specifications_count = memory.spawner_specifications_count + 1 - end - end -end, function(tbl) - memory = tbl.memory -end) - -local function lerp(low, high, pos) - local s = high.evolution_factor - low.evolution_factor; - local l = (pos - low.evolution_factor) / s; - return (low.weight * (1 - l)) + (high.weight * l) -end - -local function get_values(map, evolution_factor) - local result = {} - local sum = 0 - - for _, spawner_data in pairs(map) do - local list = spawner_data.spawn_points; - local low = list[1]; - local high = list[#list]; - - for _, val in pairs(list) do - local val_evolution = val.evolution_factor - if val_evolution <= evolution_factor and val_evolution > low.evolution_factor then - low = val; - end - if val_evolution >= evolution_factor and val_evolution < high.evolution_factor then - high = val - end - end - - local val - if evolution_factor <= low.evolution_factor then - val = low.weight - elseif evolution_factor >= high.evolution_factor then - val = high.weight; - else - val = lerp(low, high, evolution_factor) - end - sum = sum + val; - - result[spawner_data.unit] = val; - end - - local weighted_table = {} - local count = 0 - for index, _ in pairs(result) do - count = count + 1 - weighted_table[count] = {index, result[index] / sum} - end - - return weighted_table; -end - -local function get_spawner_values(spawner, evolution) - local spawner_specification = memory.spawner_specifications[spawner] - if not spawner_specification then - Debug.print(format('Spawner "%s" does not exist in the prototype data', spawner)) - return - end - - local cache = memory.evolution_cache[spawner] - - if not cache then - cache = { - evolution = -1, - weight_table = {}, - } - memory.evolution_cache[spawner] = cache - end - - local evolution_value = round(evolution * 100) - if (cache.evolution < evolution_value) then - cache.evolution = evolution_value - cache.weight_table = get_values(spawner_specification, evolution) - end - - return cache.weight_table -end - -local function calculate_total(count, spawner, evolution) - if count == 0 then - return {} - end - - local spawner_values = get_spawner_values(spawner, evolution) - if not spawner_values then - return {} - end - - local aliens = {} - for _ = 1, count do - local name = get_random_weighted(spawner_values) - aliens[name] = (aliens[name] or 0) + 1 - end - - return aliens -end - ----Creates the spawner_request structure required for AlienEvolutionProgress.get_aliens for all ----available spawner's. If dividing the total spawner's by the total aliens causes a fraction, the ----fraction will decide a chance to spawn. 1 alien for 2 spawner's will have 50% on both. ----@param total_aliens table -function AlienEvolutionProgress.create_spawner_request(total_aliens) - local per_spawner = total_aliens / memory.spawner_specifications_count - local fraction = per_spawner % 1 - - local spawner_request = {} - for spawner, _ in pairs(memory.spawner_specifications) do - local count = per_spawner - if fraction > 0 then - if random() > fraction then - count = ceil(count) - else - count = floor(count) - end - end - spawner_request[spawner] = count - end - - return spawner_request -end - -function AlienEvolutionProgress.get_aliens(spawner_requests, evolution) - local aliens = {} - for spawner, count in pairs(spawner_requests) do - for name, amount in pairs(calculate_total(count, spawner, evolution)) do - aliens[name] = (aliens[name] or 0) + amount - end - end - - return aliens -end - -return AlienEvolutionProgress diff --git a/resources/color_presets.lua b/utils/color_presets.lua similarity index 100% rename from resources/color_presets.lua rename to utils/color_presets.lua diff --git a/utils/command.lua b/utils/command.lua deleted file mode 100644 index 692eb285..00000000 --- a/utils/command.lua +++ /dev/null @@ -1,326 +0,0 @@ -local Event = require 'utils.event' --- @dep utils.event -local Game = require 'utils.game' --- @dep utils.game -local Utils = require 'utils.core' --- @dep utils.core -local Timestamp = require 'utils.timestamp' --- @dep utils.timestamp -local Rank = require 'features.rank_system' --- @dep features.rank_system -local Donator = require 'features.donator' --- @dep features.donator -local Server = require 'features.server' --- @dep features.server -local Ranks = require 'resources.ranks' --- @dep resources.ranks - -local insert = table.insert -local format = string.format -local next = next -local serialize = serpent.line -local match = string.match -local gmatch = string.gmatch -local get_rank_name = Rank.get_rank_name - -local Command = {} - -local deprecated_command_alternatives = { - ['silent-command'] = 'sc', - ['tpplayer'] = 'tp ', - ['tppos'] = 'tp', - ['tpmode'] = 'tp mode', - ['color-redmew'] = 'redmew-color' -} - -local notify_on_commands = { - ['version'] = 'RedMew has a version as well, accessible via /redmew-version', - ['color'] = 'RedMew allows color saving and a color randomiser: check out /redmew-color', - ['ban'] = 'In case your forgot: please remember to include a message on how to appeal a ban' -} - -local option_names = { - ['description'] = 'A description of the command', - ['arguments'] = 'A table of arguments, example: {"foo", "bar"} would map the first 2 arguments to foo and bar', - ['default_values'] = 'A default value for a given argument when omitted, example: {bar = false}', - ['required_rank'] = 'Set this to determines what rank is required to execute a command', - ['donator_only'] = 'Set this to true if only donators may execute this command', - ['debug_only'] = 'Set this to true if it should be registered when _DEBUG is true', - ['cheat_only'] = 'Set this to true if it should be registered when _CHEATS is true', - ['allowed_by_server'] = 'Set to true if the server (host) may execute this command', - ['allowed_by_player'] = 'Set to false to disable players from executing this command', - ['log_command'] = 'Set to true to log commands. Always true when admin is required', - ['capture_excess_arguments'] = 'Allows the last argument to be the remaining text in the command', - ['custom_help_text'] = 'Sets a custom help text to override the auto-generated help', -} - ----Validates if there aren't any wrong fields in the options. ----@param command_name string ----@param options table -local function assert_existing_options(command_name, options) - local invalid = {} - for name, _ in pairs(options) do - if not option_names[name] then - insert(invalid, name) - end - end - - if next(invalid) then - error(format("The following options were given to the command '%s' but are invalid: %s", command_name, serialize(invalid))) - end -end - ----Adds a command to be executed. ---- ----Options table accepts the following structure: { ---- description = 'A description of the command', ---- arguments = {'foo', 'bar'}, -- maps arguments to these names in the given sequence ---- default_values = {bar = false}, -- gives a default value to 'bar' when omitted ---- required_rank = Ranks.regular, -- defaults to Ranks.guest ---- donator_only = true, -- defaults to false ---- debug_only = true, -- registers the command if _DEBUG is set to true, defaults to false ---- cheat_only = true, -- registers the command if _CHEATS is set to true, defaults to false ---- allowed_by_server = true, -- lets the server execute this, defaults to false ---- allowed_by_player = false, -- lets players execute this, defaults to true ---- log_command = true, -- defaults to false unless admin only, then always true ---- capture_excess_arguments = true, -- defaults to false, captures excess arguments in the last argument, useful for sentences ----} ---- ----The callback receives the following arguments: ---- - arguments (indexed by name, value is extracted from the parameters) ---- - the LuaPlayer or nil if it doesn't exist (such as the server player) ---- - the game tick in which the command was executed ---- ----@param command_name string ----@param options table ----@param callback function -function Command.add(command_name, options, callback) - local description = options.description or '[Undocumented command]' - local arguments = options.arguments or {} - local default_values = options.default_values or {} - local required_rank = options.required_rank or Ranks.guest - local donator_only = options.donator_only or false - local debug_only = options.debug_only or false - local cheat_only = options.cheat_only or false - local capture_excess_arguments = options.capture_excess_arguments or false - local custom_help_text = options.custom_help_text or false - local allowed_by_server = options.allowed_by_server or false - local allowed_by_player = options.allowed_by_player - local log_command = options.log_command or (required_rank >= Ranks.admin) or false - local argument_list_size = table_size(arguments) - local argument_list = '' - - assert_existing_options(command_name, options) - - if nil == options.allowed_by_player then - allowed_by_player = true - end - - if (not _DEBUG and debug_only) and (not _CHEATS and cheat_only) then - return - end - - if not allowed_by_player and not allowed_by_server then - error(format("The command '%s' is not allowed by the server nor player, please enable at least one of them.", command_name)) - end - - for index, argument_name in pairs(arguments) do - local argument_display = argument_name - for default_value_name, _ in pairs(default_values) do - if default_value_name == argument_name then - argument_display = argument_display .. ':optional' - break - end - end - - if argument_list_size == index and capture_excess_arguments then - argument_display = argument_display .. ':sentence' - end - - argument_list = format('%s<%s> ', argument_list, argument_display) - end - - local extra = '' - - if allowed_by_server and not allowed_by_player then - extra = ' (Server only)' - elseif allowed_by_player and (required_rank > Ranks.guest) then - extra = {'command.required_rank', get_rank_name(required_rank)} - elseif allowed_by_player and donator_only then - extra = ' (Donator only)' - end - - local help_text = {'command.help_text_format',(custom_help_text or argument_list), description, extra} - - commands.add_command(command_name, help_text, function (command) - local print -- custom print reference in case no player is present - local player = game.player - local player_name = player and player.valid and player.name or '' - if not player or not player.valid then - print = log - - if not allowed_by_server then - print(format("The command '%s' is not allowed to be executed by the server.", command_name)) - return - end - else - print = player.print - - if not allowed_by_player then - print(format("The command '%s' is not allowed to be executed by players.", command_name)) - return - end - - if Rank.less_than(player_name, required_rank) then - print({'command.higher_rank_needed', command_name, get_rank_name(required_rank)}) - return - end - - if donator_only and not Donator.is_donator(player_name) then - print(format("The command '%s' is only allowed for donators.", command_name)) - return - end - end - - local named_arguments = {} - local from_command = {} - local raw_parameter_index = 1 - for param in gmatch(command.parameter or '', '%S+') do - if capture_excess_arguments and raw_parameter_index == argument_list_size then - if not from_command[raw_parameter_index] then - from_command[raw_parameter_index] = param - else - from_command[raw_parameter_index] = from_command[raw_parameter_index] .. ' ' .. param - end - else - from_command[raw_parameter_index] = param - raw_parameter_index = raw_parameter_index + 1 - end - end - - local errors = {} - - for index, argument in pairs(arguments) do - local parameter = from_command[index] - - if not parameter then - for default_value_name, default_value in pairs(default_values) do - if default_value_name == argument then - parameter = default_value - break - end - end - end - - if parameter == nil then - insert(errors, format('Argument "%s" from command %s is missing.', argument, command_name)) - else - named_arguments[argument] = parameter - end - end - - local return_early = false - - for _, error in pairs(errors) do - return_early = true - print(error) - end - - if return_early then - return - end - - if log_command then - local tick = 'pre-game' - if game then - tick = Utils.format_time(game.tick) - end - local server_time = Server.get_current_time() - if server_time then - server_time = format('(Server time: %s)', Timestamp.to_string(server_time)) - else - server_time = '' - end - - log(format('%s(Map time: %s) [%s Command] %s, used: %s %s', server_time, tick, (options.required_rank >= Ranks.admin) and 'Admin' or 'Player', player_name, command_name, serialize(named_arguments))) - end - - local success, error = pcall(function () - callback(named_arguments, player, command.tick) - end) - - if not success then - local serialized_arguments = serialize(named_arguments) - if _DEBUG then - print(format("%s triggered an error running a command and has been logged: '%s' with arguments %s", player_name, command_name, serialized_arguments)) - print(error) - return - end - - print(format('There was an error running %s, it has been logged.', command_name)) - log(format("Error while running '%s' with arguments %s: %s", command_name, serialized_arguments, error)) - end - end) -end - -function Command.search(keyword) - local matches = {} - local count = 0 - keyword = keyword:lower() - for name, description in pairs(commands.commands) do - local command = format('%s %s', name, description) - if match(command:lower(), keyword) then - count = count + 1 - matches[count] = command - end - end - - -- built-in commands use LocalisedString, which cannot be translated until player.print is called - for name in pairs(commands.game_commands) do - name = name - if match(name:lower(), keyword) then - count = count + 1 - matches[count] = name - end - end - - return matches -end - ---- Trigger messages on deprecated or defined commands, ignores the server -local function on_command(event) - if not event.player_index then - return - end - - local alternative = deprecated_command_alternatives[event.command] - if alternative then - local player = Game.get_player_by_index(event.player_index) - if player then - player.print(format('Warning! Usage of the command "/%s" is deprecated. Please use "/%s" instead.', event.command, alternative)) - end - end - - local notification = notify_on_commands[event.command] - if notification and event.player_index then - local player = Game.get_player_by_index(event.player_index) - if player then - player.print(notification) - end - end -end - ---- Traps command errors if not in DEBUG. -if not _DEBUG then - local old_add_command = commands.add_command - commands.add_command = - function(name, desc, func) - old_add_command( - name, - desc, - function(cmd) - local success, error = pcall(func, cmd) - if not success then - log(error) - Game.player_print('Sorry there was an error running ' .. cmd.name) - end - end - ) - end -end - -Event.add(defines.events.on_console_command, on_command) - -return Command diff --git a/utils/core.lua b/utils/core.lua deleted file mode 100644 index 744265b7..00000000 --- a/utils/core.lua +++ /dev/null @@ -1,223 +0,0 @@ ---- This file contains core utilities used by the redmew scenario. - --- Dependencies -local Game = require 'utils.game' --- @dep utils.game -local Color = require 'resources.color_presets' --- @dep resources.color_presets - --- localized functions -local random = math.random -local sqrt = math.sqrt -local floor = math.floor -local match = string.match -local insert = table.insert -local concat = table.concat - --- local constants -local prefix = '## - ' -local minutes_to_ticks = 60 * 60 -local hours_to_ticks = 60 * 60 * 60 -local ticks_to_minutes = 1 / minutes_to_ticks -local ticks_to_hours = 1 / hours_to_ticks - --- local variables -local Module = {} - ---- Measures distance between pos1 and pos2 -function Module.distance(pos1, pos2) - local dx = pos2.x - pos1.x - local dy = pos2.y - pos1.y - return sqrt(dx * dx + dy * dy) -end - ---- Takes msg and prints it to all players except provided player --- @param msg table if locale is used --- @param player the player not to send the message to --- @param color
    the color to use for the message, defaults to white -function Module.print_except(msg, player, color) - if not color then - color = Color.white - end - - for _, p in pairs(game.connected_players) do - if p ~= player then - p.print(msg, color) - end - end -end - ---- Prints a message to all online admins --- @param msg table if locale is used --- @param source string must be the name of a player, nil for server. -function Module.print_admins(msg, source) - local source_name - local chat_color - if source then - if type(source) == 'string' then - source_name = source - chat_color = game.players[source].chat_color - else - source_name = source.name - chat_color = source.chat_color - end - else - source_name = 'Server' - chat_color = Color.yellow - end - local formatted_msg = {'utils_core.print_admins',prefix, source_name, msg} - log(formatted_msg) - for _, p in pairs(game.connected_players) do - if p.admin then - p.print(formatted_msg, chat_color) - end - end -end - ---- Returns a valid string with the name of the actor of a command. -function Module.get_actor() - if game.player then - return game.player.name - end - return '' -end - -function Module.cast_bool(var) - if var then - return true - else - return false - end -end - -function Module.find_entities_by_last_user(player, surface, filters) - if type(player) == 'string' or not player then - error("bad argument #1 to '" .. debug.getinfo(1, 'n').name .. "' (number or LuaPlayer expected, got " .. type(player) .. ')', 1) - return - end - if type(surface) ~= 'table' and type(surface) ~= 'number' then - error("bad argument #2 to '" .. debug.getinfo(1, 'n').name .. "' (number or LuaSurface expected, got " .. type(surface) .. ')', 1) - return - end - local entities = {} - local filter = filters or {} - if type(surface) == 'number' then - surface = game.surfaces[surface] - end - if type(player) == 'number' then - player = Game.get_player_by_index(player) - end - filter.force = player.force.name - for _, e in pairs(surface.find_entities_filtered(filter)) do - if e.last_user == player then - insert(entities, e) - end - end - return entities -end - -function Module.ternary(c, t, f) - if c then - return t - else - return f - end -end - ---- Takes a time in ticks and returns a string with the time in format "x hour(s) x minute(s)" -function Module.format_time(ticks) - local result = {} - - local hours = floor(ticks * ticks_to_hours) - if hours > 0 then - ticks = ticks - hours * hours_to_ticks - insert(result, hours) - if hours == 1 then - insert(result, 'hour') - else - insert(result, 'hours') - end - end - - local minutes = floor(ticks * ticks_to_minutes) - insert(result, minutes) - if minutes == 1 then - insert(result, 'minute') - else - insert(result, 'minutes') - end - - return concat(result, ' ') -end - ---- Prints a message letting the player know they cannot run a command --- @param name string name of the command -function Module.cant_run(name) - Game.player_print("Can't run command (" .. name .. ') - insufficient permission.') -end - ---- Logs the use of a command and its user --- @param actor string with the actor's name (usually acquired by calling get_actor) --- @param command the command's name as table element --- @param parameters the command's parameters as a table (optional) -function Module.log_command(actor, command, parameters) - local action = concat {'[Admin-Command] ', actor, ' used: ', command} - if parameters then - action = concat {action, ' ', parameters} - end - log(action) -end - -function Module.comma_value(n) -- credit http://richard.warburton.it - local left, num, right = match(n, '^([^%d]*%d)(%d*)(.-)$') - return left .. (num:reverse():gsub('(%d%d%d)', '%1,'):reverse()) .. right -end - ---- Asserts the argument is one of type arg_types --- @param arg the variable to check --- @param arg_types the type as a table of sings --- @return boolean -function Module.verify_mult_types(arg, arg_types) - for _, arg_type in pairs(arg_types) do - if type(arg) == arg_type then - return true - end - end - return false -end - ---- Returns a random RGB color as a table -function Module.random_RGB() - return {r = random(0, 255), g = random(0, 255), b = random(0, 255)} -end - ---- Sets a table element to value while also returning value. --- @param tbl table to change the element of --- @param key string --- @param value nil|boolean|number|string|table to set the element to --- @return value -function Module.set_and_return(tbl, key, value) - tbl[key] = value - return value -end - --- add utility functions that exist in base factorio/util -require 'util' - ---- Moves a position according to the parameters given --- Notice: only accepts cardinal directions as direction --- @param position
    table containing a map position --- @param direction north, east, south, west --- @param distance --- @return
    modified position -Module.move_position = util.moveposition - ---- Takes a direction and gives you the opposite --- @param direction north, east, south, west, northeast, northwest, southeast, southwest --- @return representing the direction -Module.opposite_direction = util.oppositedirection - ---- Takes the string of a module and returns whether is it available or not --- @param name the name of the module (ex. 'utils.core') --- @return -Module.is_module_available = util.ismoduleavailable - -return Module diff --git a/utils/dump_env.lua b/utils/dump_env.lua deleted file mode 100644 index 97f92ff0..00000000 --- a/utils/dump_env.lua +++ /dev/null @@ -1,32 +0,0 @@ ---- A small debugging tool that writes the contents of _ENV to a file when the game loads. --- Useful for ensuring you get the same information when loading --- the reference and desync levels in desync reports. --- dependencies -local table = require 'utils.table' --- @dep utils.table -local Event = require 'utils.event' --- @dep utils.event - --- localized functions -local inspect = table.inspect - --- local constants -local filename = 'env_dump.lua' - --- Removes metatables and the package table -local filter = function(item, path) - if path[#path] ~= inspect.METATABLE and item ~= 'package' then - return item - end -end - -local function player_joined(event) - local dump_string = inspect(_ENV, {process = filter}) - if dump_string then - local s = string.format('tick on join: %s\n%s', event.tick, dump_string) - game.write_file(filename, s) - game.print('_ENV dumped into ' .. filename) - else - game.print('_ENV not dumped, dump_string was nil') - end -end - -Event.add(defines.events.on_player_joined_game, player_joined) diff --git a/utils/event.lua b/utils/event.lua index d4d3bd85..09673c5d 100644 --- a/utils/event.lua +++ b/utils/event.lua @@ -97,7 +97,7 @@ local EventCore = require 'utils.event_core' --- @dep utils.event_core local Global = require 'utils.global' --- @dep utils.global local Token = require 'utils.token' --- @dep utils.token -local Debug = require 'utils.debug' --- @dep utils.debug +local Debug = require 'overrides.debug' --- @dep overrides.debug local table_remove = table.remove local core_add = EventCore.add diff --git a/utils/game.lua b/utils/game.lua index 946d2420..c5ff5db2 100644 --- a/utils/game.lua +++ b/utils/game.lua @@ -1,5 +1,5 @@ local Global = require 'utils.global' --- @dep utils.global -local Color = require 'resources.color_presets' --- @dep resources.color_presets +local Color = require 'utils.color_presets' --- @dep utils.color_presets local pairs = pairs local Game = {} diff --git a/utils/gui.lua b/utils/gui.lua index 764037e0..36fc1d61 100644 --- a/utils/gui.lua +++ b/utils/gui.lua @@ -1,11 +1,7 @@ -local Token = require 'utils.token' --- @dep utils.token -local Event = require 'utils.event' --- @dep utils.event -local Game = require 'utils.game' --- @dep utils.game local Global = require 'utils.global' --- @dep utils.global -local mod_gui = require 'mod-gui' --- @dep mod-gui +local ExpGui = require 'expcore.gui' --- @dep expcore.gui local Gui = {} - local data = {} Global.register( @@ -15,12 +11,9 @@ Global.register( end ) -local top_elements = {} -local on_visible_handlers = {} -local on_pre_hidden_handlers = {} - function Gui.uid_name() - return tostring(Token.uid()) + local new_element = ExpGui.element() + return new_element.name end -- Associates data with the LuaGuiElement. If data is nil then removes the data @@ -75,219 +68,62 @@ function Gui.clear(element) element.clear() end -local function handler_factory(event_id) - local handlers - - local function on_event(event) - local element = event.element - if not element or not element.valid then - return - end - - local handler = handlers[element.name] - if not handler then - return - end - - local player = Game.get_player_by_index(event.player_index) - if not player or not player.valid then - return - end - event.player = player - - handler(event) - end - +local function handler_factory(event_name) return function(element_name, handler) - if not handlers then - handlers = {} - Event.add(event_id, on_event) - end - - handlers[element_name] = handler + local element = ExpGui.defines[element_name] + if not element then return end + element[event_name](element,function(_,_,event) + handler(event) + end) end end -local function custom_handler_factory(handlers) - return function(element_name, handler) - handlers[element_name] = handler - end -end - -local function custom_raise(handlers, element, player) - local handler = handlers[element.name] - if not handler then - return - end - - handler({element = element, player = player}) -end - -- Register a handler for the on_gui_checked_state_changed event for LuaGuiElements with element_name. -- Can only have one handler per element name. -- Guarantees that the element and the player are valid when calling the handler. -- Adds a player field to the event table. -Gui.on_checked_state_changed = handler_factory(defines.events.on_gui_checked_state_changed) +Gui.on_checked_state_changed = handler_factory('on_checked_changed') -- Register a handler for the on_gui_click event for LuaGuiElements with element_name. -- Can only have one handler per element name. -- Guarantees that the element and the player are valid when calling the handler. -- Adds a player field to the event table. -Gui.on_click = handler_factory(defines.events.on_gui_click) +Gui.on_click = handler_factory('on_click') -- Register a handler for the on_gui_closed event for a custom LuaGuiElements with element_name. -- Can only have one handler per element name. -- Guarantees that the element and the player are valid when calling the handler. -- Adds a player field to the event table. -Gui.on_custom_close = handler_factory(defines.events.on_gui_closed) +Gui.on_custom_close = handler_factory('on_closed') -- Register a handler for the on_gui_elem_changed event for LuaGuiElements with element_name. -- Can only have one handler per element name. -- Guarantees that the element and the player are valid when calling the handler. -- Adds a player field to the event table. -Gui.on_elem_changed = handler_factory(defines.events.on_gui_elem_changed) +Gui.on_elem_changed = handler_factory('on_elem_changed') -- Register a handler for the on_gui_selection_state_changed event for LuaGuiElements with element_name. -- Can only have one handler per element name. -- Guarantees that the element and the player are valid when calling the handler. -- Adds a player field to the event table. -Gui.on_selection_state_changed = handler_factory(defines.events.on_gui_selection_state_changed) +Gui.on_selection_state_changed = handler_factory('on_selection_changed') -- Register a handler for the on_gui_text_changed event for LuaGuiElements with element_name. -- Can only have one handler per element name. -- Guarantees that the element and the player are valid when calling the handler. -- Adds a player field to the event table. -Gui.on_text_changed = handler_factory(defines.events.on_gui_text_changed) +Gui.on_text_changed = handler_factory('on_text_changed') -- Register a handler for the on_gui_value_changed event for LuaGuiElements with element_name. -- Can only have one handler per element name. -- Guarantees that the element and the player are valid when calling the handler. -- Adds a player field to the event table. -Gui.on_value_changed = handler_factory(defines.events.on_gui_value_changed) - --- Register a handler for when the player shows the top LuaGuiElements with element_name. --- Assuming the element_name has been added with Gui.allow_player_to_toggle_top_element_visibility. --- Can only have one handler per element name. --- Guarantees that the element and the player are valid when calling the handler. --- Adds a player field to the event table. -Gui.on_player_show_top = custom_handler_factory(on_visible_handlers) - --- Register a handler for when the player hides the top LuaGuiElements with element_name. --- Assuming the element_name has been added with Gui.allow_player_to_toggle_top_element_visibility. --- Can only have one handler per element name. --- Guarantees that the element and the player are valid when calling the handler. --- Adds a player field to the event table. -Gui.on_pre_player_hide_top = custom_handler_factory(on_pre_hidden_handlers) - ---- Allows the player to show / hide this element. --- The element must be in Gui.get_top_element_flow(player) --- This function must be called in the control stage, i.e not inside an event. --- @param element_name This name must be globally unique. -function Gui.allow_player_to_toggle_top_element_visibility(element_name) - if _LIFECYCLE ~= _STAGE.control then - error('can only be called during the control stage', 2) - end - top_elements[#top_elements + 1] = element_name -end +Gui.on_value_changed = handler_factory('on_value_changed') --- Returns the flow where top elements can be added and will be effected by google visibility -- For the toggle to work it must be registed with Gui.allow_player_to_toggle_top_element_visibility(element_name) -- @tparam LuaPlayer player pointer to the player who has the gui -- @treturn LuaGuiElement the top element flow -function Gui.get_top_element_flow(player) - player = Game.get_player_from_any(player) - return mod_gui.get_button_flow(player) -end - -local toggle_button_name = Gui.uid_name() -Gui.top_toggle_button_name = toggle_button_name - -Event.add( - defines.events.on_player_created, - function(event) - local player = Game.get_player_by_index(event.player_index) - - if not player or not player.valid then - return - end - - local top = Gui.get_top_element_flow(player) - - local b = top.add { - type = 'button', - name = toggle_button_name, - style = mod_gui.button_style, - caption = '<', - tooltip = {'gui_util.button_tooltip'} - } - local style = b.style - style.width = 18 - style.height = 36 - style.left_padding = 0 - style.top_padding = 0 - style.right_padding = 0 - style.bottom_padding = 0 - style.font = 'default-small-bold' - end -) - -Gui.on_click( - toggle_button_name, - function(event) - local button = event.element - local player = event.player - local top = Gui.get_top_element_flow(player) - - if button.caption == '<' then - for i = 1, #top_elements do - local name = top_elements[i] - local ele = top[name] - if ele and ele.valid then - if ele.visible then - custom_raise(on_pre_hidden_handlers, ele, player) - ele.visible = false - end - end - end - - button.caption = '>' - button.style.height = 24 - else - for i = 1, #top_elements do - local name = top_elements[i] - local ele = top[name] - if ele and ele.valid then - if not ele.visible then - ele.visible = true - custom_raise(on_visible_handlers, ele, player) - end - end - end - - button.caption = '<' - button.style.height = 36 - end - end -) - -if _DEBUG then - local concat = table.concat - - local names = {} - Gui.names = names - - function Gui.uid_name() - local info = debug.getinfo(2, 'Sl') - local filepath = info.source:match('^.+/currently%-playing/(.+)$'):sub(1, -5) - local line = info.currentline - - local token = tostring(Token.uid()) - - local name = concat {token, ' - ', filepath, ':line:', line} - names[token] = name - - return token - end -end +Gui.get_top_element_flow = ExpGui.get_top_flow return Gui \ No newline at end of file diff --git a/utils/player_rewards.lua b/utils/player_rewards.lua deleted file mode 100644 index dec49ae7..00000000 --- a/utils/player_rewards.lua +++ /dev/null @@ -1,154 +0,0 @@ -local Global = require 'utils.global' --- @dep utils.global -local Game = require 'utils.game' --- @dep utils.game -local PlayerStats = require 'features.player_stats' --- @dep features.player_stats -local Command = require 'utils.command' --- @dep utils.command -local Ranks = require 'resources.ranks' --- @dep resources.ranks - -local format = string.format -local abs = math.abs -local concat = table.concat - -local Public = {} -local reward_token = {global.config.player_rewards.token} or {global.config.market.currency} or {'coin'} - -Global.register( - { - reward_token = reward_token - }, - function(tbl) - reward_token = tbl.reward_token - end -) - ---- Returns the single or plural form of the token name -local function get_token_plural(quantity) - if quantity and quantity > 1 then - return concat({reward_token[1], 's'}) - else - return reward_token[1] - end -end - ---- Set the item to use for rewards --- @param reward string - item name to use as reward --- @return boolean true - indicating success -Public.set_reward = function(reward) - if global.config.player_rewards.enabled == false then - return false - end - - reward_token[1] = reward - return true -end - ---- Returns the name of the reward item -Public.get_reward = function() - return reward_token[1] -end - ---- Gives reward tokens to the player --- @param player --- @param amount of reward tokens --- @param message an optional message to send to the affected player --- @return indicating how many were inserted or if operation failed -Public.give_reward = function(player, amount, message) - if global.config.player_rewards.enabled == false then - return 0 - end - - local player_index - if type(player) == 'number' then - player_index = player - player = Game.get_player_by_index(player) - else - player_index = player.index - end - local reward = {name = reward_token[1], count = amount} - if not player.can_insert(reward) then - return 0 - end - if message then - player.print(message) - end - local coin_difference = player.insert(reward) - if reward_token[1] == 'coin' then - PlayerStats.change_coin_earned(player_index, coin_difference) - end - return coin_difference -end - ---- Removes reward tokens from the player --- @param player --- @param amount of reward tokens --- @param message an optional message to send to the affected player --- @return indicating how many were removed or if operation failed -Public.remove_reward = function(player, amount, message) - if global.config.player_rewards.enabled == false then - return 0 - end - - local player_index - if type(player) == 'number' then - player_index = player - player = Game.get_player_by_index(player) - else - player_index = player.index - end - local unreward = {name = reward_token[1], count = amount} - if message then - player.print(message) - end - local coin_difference = player.remove_item(unreward) - if reward_token[1] == 'coin' then - PlayerStats.change_coin_earned(player_index, -coin_difference) - end - return coin_difference -end - -Command.add( - 'reward', - { - description = 'Gives a reward to a target player (removes if quantity is negative)', - arguments = {'target', 'quantity', 'reason'}, - default_values = {reason = false}, - required_rank = Ranks.admin, - capture_excess_arguments = true, - allowed_by_server = true, - allowed_by_player = true - }, - function(args, player) - local player_name = 'server' - if player then - player_name = player.name - end - - local target_name = args.target - local target = game.players[target_name] - if not target then - player.print('Target not found.') - return - end - - local quantity = tonumber(args.quantity) - if quantity > 0 then - Public.give_reward(target, quantity) - local string = format('%s has rewarded %s with %s %s', player_name, target_name, quantity, get_token_plural(quantity)) - if args.reason then - string = format('%s for %s', string, args.reason) - end - game.print(string) - elseif quantity < 0 then - quantity = abs(quantity) - Public.remove_reward(target, quantity) - local string = format('%s has punished %s by taking %s %s', player_name, target_name, quantity, get_token_plural(quantity)) - if args.reason then - string = format('%s for %s', string, args.reason) - end - game.print(string) - else - Game.player_print(" A reward of 0 is neither a reward nor a punishment, it's just dumb. Try harder.") - end - end -) - -return Public diff --git a/utils/recipe_locker.lua b/utils/recipe_locker.lua deleted file mode 100644 index 53d6c59c..00000000 --- a/utils/recipe_locker.lua +++ /dev/null @@ -1,58 +0,0 @@ ---- A module to prevent recipes from being unlocked by research. Accessed via the public functions. -local Event = require 'utils.event' --- @dep utils.event -local Global = require 'utils.global' --- @dep utils.global - -local Public = {} - -local recipes = {} - -Global.register( - { - recipes = recipes - }, - function(tbl) - recipes = tbl.recipes - end -) - -Event.add( - defines.events.on_research_finished, - function(event) - local p_force = game.forces.player - local r = event.research - for _, effect in pairs(r.effects) do - local recipe = effect.recipe - if recipe and recipes[recipe] then - p_force.recipes[recipe].enabled = false - end - end - end -) - -Event.on_init( - function() - for recipe in pairs(recipes) do - game.forces.player.recipes[recipe].enabled = false - end - end -) - ---- Locks recipes, preventing them from being enabled by research. --- Does not check if they should be enabled/disabled by existing research. --- @param tbl
    an array of recipe strings -function Public.lock_recipes(tbl) - for i = 1, #tbl do - recipes[tbl[i]] = true - end -end - ---- Unlocks recipes, allowing them to be enabled by research. --- Does not check if they should be enabled/disabled by existing research. --- @param tbl
    an array of recipe strings -function Public.unlock_recipes(tbl) - for i = 1, #tbl do - recipes[tbl[i]] = nil - end -end - -return Public diff --git a/utils/redmew_settings.lua b/utils/redmew_settings.lua deleted file mode 100644 index 2e4b0404..00000000 --- a/utils/redmew_settings.lua +++ /dev/null @@ -1,178 +0,0 @@ -local Global = require 'utils.global' --- @dep utils.global -local type = type -local error = error -local tonumber = tonumber -local tostring = tostring -local pairs = pairs -local format = string.format - ---- Contains a set of callable that will attempt to sanitize and transform the input -local settings_type = { - fraction = function (input) - input = tonumber(input) - - if input == nil then - return false, 'fraction setting type requires the input to be a valid number between 0 and 1.' - end - - if input < 0 then - input = 0 - end - - if input > 1 then - input = 1 - end - - return true, input - end, - string = function (input) - if input == nil then - return true, '' - end - - local input_type = type(input) - if input_type == 'string' then - return true, input - end - - if input_type == 'number' or input_type == 'boolean' then - return true, tostring(input) - end - - return false, 'string setting type requires the input to be either a valid string or something that can be converted to a string.' - end, - boolean = function (input) - local input_type = type(input) - - if input_type == 'boolean' then - return true, input - end - - if input_type == 'string' then - if input == '0' or input == '' or input == 'false' or input == 'no' then - return true, false - end - if input == '1' or input == 'true' or input == 'yes' then - return true, true - end - - return true, tonumber(input) ~= nil - end - - if input_type == 'number' then - return true, input ~= 0 - end - - return false, 'boolean setting type requires the input to be either a boolean, number or string that can be transformed to a boolean.' - end, -} - -local settings = {} -local memory = {} - -Global.register(memory, function (tbl) memory = tbl end) - -local Public = {} - -Public.types = {fraction = 'fraction', string = 'string', boolean = 'boolean'} - ----Register a specific setting with a sensitization setting type. ---- ---- Available setting types: ---- - fraction (number between 0 and 1) in either number or string form ---- - string a string or anything that can be cast to a string ---- - boolean, 1, 0, yes, no, true, false or an empty string for false ---- ---- This function must be called in the control stage, i.e. not inside an event. ---- ----@param name string ----@param setting_type string ----@param default mixed -function Public.register(name, setting_type, default) - if _LIFECYCLE ~= _STAGE.control then - error(format('You can only register setting names in the control stage, i.e. not inside events. Tried setting "%s" with type "%s".', name, setting_type), 2) - end - - if settings[name] then - error(format('Trying to register setting for "%s" while it has already been registered.', name), 2) - end - - local callback = settings_type[setting_type] - if not callback then - error(format('Trying to register setting for "%s" with type "%s" while this type does not exist.', name, setting_type), 2) - end - - local setting = { - default = default, - callback = callback, - } - - settings[name] = setting - - return setting -end - ----Sets a setting to a specific value for a player. ---- ----In order to get a setting value, it has to be registered via the "register" function. ---- ----@param player_index number ----@param name string ----@param value mixed -function Public.set(player_index, name, value) - local setting = settings[name] - if not setting then - return error(format('Setting "%s" does not exist.', name), 2) - end - - local success, sanitized_value = setting.callback(value) - - if not success then - error(format('Setting "%s" failed: %s', name, sanitized_value), 2) - end - - local player_settings = memory[player_index] - if not player_settings then - player_settings = {} - memory[player_index] = player_settings - end - - player_settings[name] = sanitized_value - - return sanitized_value -end - ----Returns the value of a setting for this player. ---- ----In order to set a setting value, it has to be registered via the "register" function. ---- ----@param player_index number ----@param name string -function Public.get(player_index, name) - local setting = settings[name] - if not setting then - return error(format('Setting "%s" does not exist.', name), 2) - end - - local player_settings = memory[player_index] - if not player_settings then - return setting.default - end - - local player_setting = player_settings[name] - return player_setting ~= nil and player_setting or setting.default -end - ----Returns a table of all settings for a given player in a key => value set-up ----@param player_index number -function Public.all(player_index) - local player_settings = memory[player_index] or {} - local output = {} - for name, data in pairs(settings) do - output[name] = player_settings[name] or data.default - end - - return output -end - -return Public diff --git a/utils/state_machine.lua b/utils/state_machine.lua deleted file mode 100644 index 9d298a52..00000000 --- a/utils/state_machine.lua +++ /dev/null @@ -1,119 +0,0 @@ ---- This module provides a classical mealy/moore state machine. --- Each machine in constructed by calling new() --- States and Transitions are lazily added to the machine as transition handlers and state tick handlers are registered. --- However the state machine must be fully defined after init is done. Dynamic machine changes are currently unsupported --- An example usage can be found here: map_gen\combined\tetris\control.lua - -local Module = {} - -local Debug = require 'utils.debug' --- @dep utils.debug - -local in_state_callbacks = {} -local transaction_callbacks = {} -local max_stack_depth = 20 -local machine_count = 0 -local control_stage = _STAGE.control - ---- Transitions the supplied machine into a given state and executes all transaction_callbacks --- @param self StateMachine --- @param new_state number/string The new state to transition to -function Module.transition(self, new_state) - Debug.print(string.format('Transitioning from state %d to state %d.', self.state, new_state)) - local old_state = self.state - - local stack_depth = self.stack_depth - self.stack_depth = stack_depth + 1 - if stack_depth > max_stack_depth then - if _DEBUG then - error('[WARNING] Stack overflow at:' .. debug.traceback()) - else - log('[WARNING] Stack overflow at:' .. debug.traceback()) - end - end - - local exit_callbacks = transaction_callbacks[self.id][old_state] - if exit_callbacks then - local entry_callbacks = exit_callbacks[new_state] - if entry_callbacks then - for i = 1, #entry_callbacks do - local callback = entry_callbacks[i] - if callback then - callback() - end - end - end - end - self.state = new_state -end - ---- Is this machine in this state? --- @param self StateMachine --- @param state number/string --- @return boolean -function Module.in_state(self, state) - return self.state == state -end - ---- Invoke a machine tick. Will execute all in_state_callbacks of the given machine --- @param self StateMachine the machine, whose handlers will be invoked -function Module.machine_tick(self) - local callbacks = in_state_callbacks[self.id][self.state] - if callbacks then - for i=1, #callbacks do - local callback = callbacks[i] - if callback then - callback() - end - end - end - self.stack_depth = 0 -end - ---- Register a handler that will be invoked by StateMachine.machine_tick --- You may register multiple handlers for the same transition --- NOTICE: This function will invoke an error if called after init. Dynamic machine changes are currently unsupported --- @param self StateMachine the machine --- @param state number/string The state, that the machine will be in, when callback is invoked --- @param callback function -function Module.register_state_tick_callback(self, state, callback) - if _LIFECYCLE ~= control_stage then - error('Calling StateMachine.register_state_tick_callback after the control stage is unsupported due to desyncs.', 2) - end - in_state_callbacks[self.id][state] = in_state_callbacks[self.id][state] or {} - table.insert(in_state_callbacks[self.id][state], callback) -end - ---- Register a handler that will be invoked by StateMachine.transition --- You may register multiple handlers for the same transition --- NOTICE: This function will invoke an error if called after init. Dynamic machine changes are currently unsupported --- @param self StateMachine the machine --- @param old number/string exiting state --- @param new number/string entering state --- @param callback function -function Module.register_transition_callback(self, old, new, callback) - if _LIFECYCLE ~= control_stage then - error('Calling StateMachine.register_transition_callback after the control stage is unsupported due to desyncs.', 2) - end - transaction_callbacks[self.id][old] = transaction_callbacks[self.id][old] or {} - transaction_callbacks[self.id][old][new] = transaction_callbacks[self.id][old][new] or {} - table.insert(transaction_callbacks[self.id][old][new], callback) -end - ---- Constructs a new state machine --- @param init_state number/string The starting state of the machine --- @return StateMachine The constructed state machine object -function Module.new(init_state) - if _LIFECYCLE ~= control_stage then - error('Calling StateMachine.new after the control stage is unsupported due to desyncs.', 2) - end - machine_count = machine_count + 1 - in_state_callbacks[machine_count] = {} - transaction_callbacks[machine_count] = {} - return { - state = init_state, - stack_depth = 0, - id = machine_count, - } -end - -return Module diff --git a/utils/timestamp.lua b/utils/timestamp.lua deleted file mode 100644 index 3c2eb73e..00000000 --- a/utils/timestamp.lua +++ /dev/null @@ -1,152 +0,0 @@ ---- source https://github.com/daurnimator/luatz/blob/master/luatz/timetable.lua --- edited down to just what is needed. - -local Public = {} - -local floor = math.floor -local strformat = string.format - -local function borrow(tens, units, base) - local frac = tens % 1 - units = units + frac * base - tens = tens - frac - return tens, units -end - -local function carry(tens, units, base) - if units >= base then - tens = tens + floor(units / base) - units = units % base - elseif units < 0 then - tens = tens + floor(units / base) - units = (base + units) % base - end - return tens, units -end - -local function is_leap(y) - if (y % 4) ~= 0 then - return false - elseif (y % 100) ~= 0 then - return true - else - return (y % 400) == 0 - end -end - -local mon_lengths = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} - --- Number of days in year until start of month; not corrected for leap years -local months_to_days_cumulative = {0} -for i = 2, 12 do - months_to_days_cumulative[i] = months_to_days_cumulative[i - 1] + mon_lengths[i - 1] -end - -local function month_length(m, y) - if m == 2 then - return is_leap(y) and 29 or 28 - else - return mon_lengths[m] - end -end - -local function day_of_year(day, month, year) - local y_day = months_to_days_cumulative[month] - if month > 2 and is_leap(year) then - y_day = y_day + 1 - end - return y_day + day -end - -local function leap_years_since(year) - return floor(year / 4) - floor(year / 100) + floor(year / 400) -end - -local leap_years_since_1970 = leap_years_since(1970) - -local function normalise(year, month, day, hour, min, sec) - -- `month` and `day` start from 1, need -1 and +1 so it works modulo - month, day = month - 1, day - 1 - - -- Convert everything (except seconds) to an integer - -- by propagating fractional components down. - year, month = borrow(year, month, 12) - -- Carry from month to year first, so we get month length correct in next line around leap years - year, month = carry(year, month, 12) - month, day = borrow(month, day, month_length(floor(month + 1), year)) - day, hour = borrow(day, hour, 24) - hour, min = borrow(hour, min, 60) - min, sec = borrow(min, sec, 60) - - -- Propagate out of range values up - -- e.g. if `min` is 70, `hour` increments by 1 and `min` becomes 10 - -- This has to happen for all columns after borrowing, as lower radix's may be pushed out of range - min, sec = carry(min, sec, 60) -- TODO: consider leap seconds? - hour, min = carry(hour, min, 60) - day, hour = carry(day, hour, 24) - -- Ensure `day` is not underflowed - -- Add a whole year of days at a time, this is later resolved by adding months - -- TODO[OPTIMIZE]: This could be slow if `day` is far out of range - while day < 0 do - month = month - 1 - if month < 0 then - year = year - 1 - month = 11 - end - day = day + month_length(month + 1, year) - end - year, month = carry(year, month, 12) - - -- TODO[OPTIMIZE]: This could potentially be slow if `day` is very large - while true do - local i = month_length(month + 1, year) - if day < i then - break - end - day = day - i - month = month + 1 - if month >= 12 then - month = 0 - year = year + 1 - end - end - - -- Now we can place `day` and `month` back in their normal ranges - -- e.g. month as 1-12 instead of 0-11 - month, day = month + 1, day + 1 - - return {year = year, month = month, day = day, hour = hour, min = min, sec = sec} -end - ---- Converts unix epoch timestamp into table {year: number, month: number, day: number, hour: number, min: number, sec: number} --- @param seconds unix epoch timestamp --- @return {year: number, month: number, day: number, hour: number, min: number, sec: number} -function Public.to_timetable(seconds) - return normalise(1970, 1, 1, 0, 0, seconds) -end - ---- Converts timetable into unix epoch timestamp --- @param timetable
    {year: number, month: number, day: number, hour: number, min: number, sec: number} --- @return number -function Public.from_timetable(timetable) - local tt = normalise(timetable.year, timetable.month, timetable.day, timetable.hour, timetable.min, timetable.sec) - - local year, month, day, hour, min, sec = tt.year, tt.month, tt.day, tt.hour, tt.min, tt.sec - - local days_since_epoch = - day_of_year(day, month, year) + 365 * (year - 1970) + -- Each leap year adds one day - (leap_years_since(year - 1) - leap_years_since_1970) - - 1 - - return days_since_epoch * (60 * 60 * 24) + hour * (60 * 60) + min * 60 + sec -end - ---- Converts unix epoch timestamp into human readable string. --- @param seconds unix epoch timestamp --- @return string -function Public.to_string(seconds) - local tt = normalise(1970, 1, 1, 0, 0, seconds) - return strformat('%04u-%02u-%02u %02u:%02u:%02d', tt.year, tt.month, tt.day, tt.hour, tt.min, tt.sec) -end - -return Public