diff --git a/.luacheckrc b/.luacheckrc index dc6cd904..6df4be46 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -56,7 +56,7 @@ local STD_BASE_CONTROL = 'lua52c+factorio+factorio_control+factorio_defines+fact --[Assume Factorio Control stage as default]-- ------------------------------------------------------------------------------- std = STD_CONTROL -globals = {'print', '_DEBUG', '_CHEATS', '_DUMP_ENV', 'ServerCommands', 'Debug'} -- RedMew-specific globals +globals = {'print', '_DEBUG', '_CHEATS', '_DUMP_ENV', 'ServerCommands', 'Debug', '_LIFECYCLE'} -- RedMew-specific globals max_line_length = LINE_LENGTH not_globals = NOT_GLOBALS diff --git a/control.lua b/control.lua index 00bcb209..2c02c104 100644 --- a/control.lua +++ b/control.lua @@ -1,3 +1,8 @@ +-- If you're looking to configure anything, you want config.lua. Nearly everything in this file is dictated by the config. + +-- Info on the data lifecycle and how we use it: https://github.com/Refactorio/RedMew/wiki/The-data-lifecycle +_LIFECYCLE = 4 -- Control stage + -- Omitting the math library is a very bad idea require 'utils.math' diff --git a/features/corpse_util.lua b/features/corpse_util.lua index e0543e6d..def39a5c 100644 --- a/features/corpse_util.lua +++ b/features/corpse_util.lua @@ -117,7 +117,7 @@ local function mined_entity(event) local corpse_owner = Game.get_player_by_index(corpse_owner_index) if player and corpse_owner then - local message = table.concat {'## - ', player.name, ' has looted ', corpse_owner.name, "'s corpse"} + local message = table.concat {player.name, ' has looted ', corpse_owner.name, "'s corpse"} Utils.action_warning('[Corpse]', message) end end diff --git a/features/gui/info.lua b/features/gui/info.lua index 679af331..fd4c89be 100644 --- a/features/gui/info.lua +++ b/features/gui/info.lua @@ -816,7 +816,7 @@ function Public.add_map_extra_info(value) create_map_extra_info(value, false) end ---- Overrides all info added via add_map_extra_info. It is an error to call this more than once. +--- Overrides all info added via add_map_extra_info. -- This should only be used in maps, never in features/modules. -- Use case: for maps that know exactly what features they're using and -- want full control over the info presented. diff --git a/features/infinite_storage_chest.lua b/features/infinite_storage_chest.lua index 5566a13a..3496d984 100644 --- a/features/infinite_storage_chest.lua +++ b/features/infinite_storage_chest.lua @@ -26,7 +26,7 @@ local chest_gui_frame_name = Gui.uid_name() local chest_content_table_name = Gui.uid_name() function Module.create_chest(surface, position, storage) - local entity = surface.create_entity{name = 'infinity-chest', position = position, force = 'player'} + local entity = surface.create_entity {name = 'infinity-chest', position = position, force = 'player'} chests[entity.unit_number] = {entity = entity, storage = storage} return entity end @@ -37,6 +37,8 @@ local function built_entity(event) return end + entity.active = false + chests[entity.unit_number] = {entity = entity, storage = {}} end @@ -262,5 +264,12 @@ Gui.on_custom_close( ) local market_items = require 'resources.market_items' -table.insert(market_items, {price = config.cost, name = 'infinity-chest', description = 'Stores unlimited quantity of items for up to 48 different item types'}) +table.insert( + market_items, + { + price = 100, + name = 'infinity-chest', + description = 'Stores unlimited quantity of items for up to 48 different item types' + } +) return Module diff --git a/features/player_create.lua b/features/player_create.lua index 24869d24..6322d5dc 100644 --- a/features/player_create.lua +++ b/features/player_create.lua @@ -62,7 +62,7 @@ local function player_created(event) if _DEBUG and player.admin then UserGroups.add_regular(player.name) - if game.is_multiplayer then + if game.is_multiplayer() then game.print("THIS MULTIPLAYER MAP IS IN DEBUG!!!") else game.print("DON'T LAUNCH THIS MAP! DEBUG MODE IS ENABLED!!!") diff --git a/features/report.lua b/features/report.lua index 8ffc7f07..2ed10bc4 100644 --- a/features/report.lua +++ b/features/report.lua @@ -1,6 +1,8 @@ -local Gui = require('utils.gui') -local Utils = require('utils.core') +local Gui = require 'utils.gui' +local Utils = require 'utils.core' local Game = require 'utils.game' +local Global = require 'utils.global' +local Popup = require 'features.gui.popup' local Color = require 'resources.color_presets' local format = string.format @@ -16,11 +18,24 @@ local prefix = '------------------NOTICE-------------------' local prefix_e = '--------------------------------------------' local Module = {} -global.reports = {} -global.player_report_data = {} + +-- Global registered locals +local report_data = {} +local jail_data = {} + +Global.register( + { + report_data = report_data, + jail_data = jail_data + }, + function(tbl) + report_data = tbl.report_data + jail_data = tbl.jail_data + end +) local function draw_report(parent, report_id) - local report = global.reports[report_id] + local report = report_data[report_id] if report_id == 0 or not report then parent.add {type = 'label', caption = 'No reports yet.'} return @@ -59,7 +74,7 @@ end Module.show_reports = function(player) - local reports = global.reports or {} + local reports = report_data local center = player.gui.center @@ -102,7 +117,7 @@ function Module.report(reporting_player, reported_player, message) player_index = reporting_player.index reporting_player.print('Your report has been sent.') end - table.insert(global.reports, {reporting_player_index = player_index, reported_player_index = reported_player.index, message = message, tick = game.tick}) + table.insert(report_data, {reporting_player_index = player_index, reported_player_index = reported_player.index, message = message, tick = game.tick}) local notified = false for _, p in pairs(game.players) do @@ -141,13 +156,10 @@ end -- @param player the admin as LuaPlayer or server as nil function Module.jail(target_player, player) local print - local jailed_by if player then - jailed_by = 'a server admin' print = player.print else player = {name = 'server'} - jailed_by = 'the server' print = log end @@ -156,6 +168,7 @@ function Module.jail(target_player, player) return end + local target_name = target_player.name local permissions = game.permissions -- Check if the permission group exists, if it doesn't, create it. @@ -169,20 +182,25 @@ function Module.jail(target_player, player) end end - if target_player.permission_group == permission_group then - print(format('Player %s is already in jail.', target_player.name)) + local former_permission_group = target_player.permission_group + if former_permission_group == permission_group then + print(format('Player %s is already in jail.', target_name)) return end - -- Enable writing to console to allow a person to speak + -- Enable writing to console to allow a person to speak, and allow them to edit permission group so that an admin can unjail themselves permission_group.set_allows_action(defines.input_action.write_to_console, true) permission_group.set_allows_action(defines.input_action.edit_permission_group, true) -- Add player to jail group permission_group.add_player(target_player) - -- Kick player out of vehicle - target_player.driving = false + -- If in vehicle, kick them out and set the speed to 0. + local vehicle = target_player.vehicle + if vehicle then + vehicle.speed = 0 + target_player.driving = false + end -- If a player is shooting when they're jailed they can't stop shooting, so we change their shooting state if target_player.shooting_state.state ~= 0 then @@ -194,18 +212,34 @@ function Module.jail(target_player, player) target_player.walking_state = {walking = false, direction = defines.direction.north} end - -- Check that it worked + -- Check they're in jail if target_player.permission_group == permission_group then -- Let admin know it worked, let target know what's going on. - target_player.print(prefix) - target_player.print('You have been placed in jail by ' .. jailed_by .. '. The only action avaliable to you is chatting.') - target_player.print('Please respond to inquiries from the admins.', Color.yellow) - target_player.print(prefix_e) - Utils.print_admins(format('%s has been jailed by %s', target_player.name, player.name)) - Utils.log_command(Utils.get_actor(), 'jail', target_player.name) + target_player.clear_console() + Popup.player(target_player, 'You have been jailed.\nRespond to queries from the mod team.') + Utils.print_admins(format('%s has been jailed by %s', target_name, player.name)) + Utils.log_command(Utils.get_actor(), 'jail', target_name) + + local character = target_player.character + local former_char_dest + if character and character.valid then + former_char_dest = character.destructible + character.destructible = false + end + + jail_data[target_player.index] = { + name = target_name, + perm_group = former_permission_group, + char_dest = former_char_dest, + color = target_player.color, + chat_color = target_player.chat_color + } + + target_player.color = Color.white + target_player.chat_color = Color.white else -- Let admin know it didn't work. - print(format('Something went wrong in the jailing of %s. You can still change their group via /permissions.',target_player.name)) + print(format('Something went wrong in the jailing of %s. You can still change their group via /permissions.', target_name)) end end @@ -227,10 +261,12 @@ function Module.unjail(target_player, player) end local target_name = target_player.name + local target_index = target_player.index local permissions = game.permissions + local target_jail_data = jail_data[target_index] -- Check if the permission group exists, if it doesn't, create it. - local permission_group = permissions.get_group(default_group) + local permission_group = target_jail_data.perm_group or permissions.get_group(default_group) if not permission_group then permission_group = permissions.create_group(default_group) end @@ -246,15 +282,24 @@ function Module.unjail(target_player, player) -- Set player to a non-shooting state (solves a niche case where players jailed while shooting will be locked into a shooting state) target_player.shooting_state.state = 0 + -- Restore player's state from stored data + local character = target_player.character + if character and character.valid then + character.destructible = target_jail_data.char_dest + end + target_player.color = target_jail_data.color + target_player.chat_color = target_jail_data.chat_color + jail_data[target_index] = nil + -- Check that it worked if target_player.permission_group == permission_group then -- Let admin know it worked, let target know what's going on. Game.player_print(target_name .. ' has been returned to the default group. They have been advised of this.') target_player.print(prefix) - target_player.print('Your ability to perform actions has been restored', Color.green) + target_player.print('Your ability to perform actions has been restored', Color.light_green) target_player.print(prefix_e) - Utils.print_admins(format('%s has been released from jail by %s', target_player.name, player.name)) - Utils.log_command(Utils.get_actor(), 'unjail', target_player.name) + Utils.print_admins(format('%s has been released from jail by %s', target_name, player.name)) + Utils.log_command(Utils.get_actor(), 'unjail', target_name) else -- Let admin know it didn't work. Game.player_print(format('Something went wrong in the unjailing of %s. You can still change their group via /permissions and inform them.', target_name)) diff --git a/map_gen/shared/chunklist.lua b/map_gen/shared/chunklist.lua index 3265487f..a93173b2 100644 --- a/map_gen/shared/chunklist.lua +++ b/map_gen/shared/chunklist.lua @@ -24,7 +24,7 @@ local Public = { tick :: uint: Tick the event was generated. area :: BoundingBox: Area of the chunk surface :: LuaSurface: The surface the chunk is on - chunk_index :: the index of the chunk in the table + chunk_index :: the index of the chunk in Chunklist's table ]] on_chunk_registered = script.generate_event_name() } @@ -49,11 +49,17 @@ local function on_chunk_generated(event) local chunk_list = Public.chunk_list local new_entry_index = #chunk_list + 1 + local area = event.area - chunk_list[new_entry_index] = event.area.left_top - - event.chunk_index = new_entry_index - raise_event(Public.events.on_chunk_registered, event) + chunk_list[new_entry_index] = area.left_top + raise_event( + Public.events.on_chunk_registered, + { + area = area, + surface = surface, + chunk_index = new_entry_index + } + ) end Event.add(defines.events.on_chunk_generated, on_chunk_generated) diff --git a/utils/event.lua b/utils/event.lua index 27348704..781ee0af 100644 --- a/utils/event.lua +++ b/utils/event.lua @@ -152,7 +152,7 @@ end -- @param event_name -- @param handler function Event.add(event_name, handler) - if EventCore.runtime then + if _LIFECYCLE == 8 then error('Calling Event.add after on_init() or on_load() has run is a desync risk.', 2) end @@ -164,7 +164,7 @@ end -- See documentation at top of file for details on using events. -- @param handler function Event.on_init(handler) - if EventCore.runtime then + if _LIFECYCLE == 8 then error('Calling Event.on_init after on_init() or on_load() has run is a desync risk.', 2) end @@ -176,7 +176,7 @@ end -- See documentation at top of file for details on using events. -- @param handler function Event.on_load(handler) - if EventCore.runtime then + if _LIFECYCLE == 8 then error('Calling Event.on_load after on_init() or on_load() has run is a desync risk.', 2) end @@ -189,7 +189,7 @@ end -- @param tick The handler will be called every nth tick -- @param handler function Event.on_nth_tick(tick, handler) - if EventCore.runtime then + if _LIFECYCLE == 8 then error('Calling Event.on_nth_tick after on_init() or on_load() has run is a desync risk.', 2) end diff --git a/utils/event_core.lua b/utils/event_core.lua index b9747446..2f1c0213 100644 --- a/utils/event_core.lua +++ b/utils/event_core.lua @@ -6,8 +6,6 @@ local Public = {} local init_event_name = -1 local load_event_name = -2 -Public.runtime = false -- Set to true after on_init or on_load has finished. - -- map of event_name to handlers[] local event_handlers = {} -- map of nth_tick to handlers[] @@ -34,23 +32,25 @@ local function on_event(event) end local function on_init() + _LIFECYCLE = 5 -- on_init local handlers = event_handlers[init_event_name] call_handlers(handlers) event_handlers[init_event_name] = nil event_handlers[load_event_name] = nil - Public.runtime = true + _LIFECYCLE = 8 -- Runtime end local function on_load() + _LIFECYCLE = 6 -- on_load local handlers = event_handlers[load_event_name] call_handlers(handlers) event_handlers[init_event_name] = nil event_handlers[load_event_name] = nil - Public.runtime = true + _LIFECYCLE = 8 -- Runtime end local function on_nth_tick_event(event) diff --git a/utils/player_rewards.lua b/utils/player_rewards.lua index a94a86dd..a4152ee2 100644 --- a/utils/player_rewards.lua +++ b/utils/player_rewards.lua @@ -131,7 +131,7 @@ Command.add( 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, get_token_plural(quantity), reward_token[1]) + 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 diff --git a/utils/task.lua b/utils/task.lua index 01d05054..63a5aefb 100644 --- a/utils/task.lua +++ b/utils/task.lua @@ -72,6 +72,7 @@ local function on_tick() end --- Allows you to set a timer (in ticks) after which the tokened function will be run with params given as an argument +-- Cannot be called before init -- @param ticks -- @param func_token a token for a function store via the token system -- @param params the argument to send to the tokened function @@ -82,6 +83,7 @@ function Task.set_timeout_in_ticks(ticks, func_token, params) end --- Allows you to set a timer (in seconds) after which the tokened function will be run with params given as an argument +-- Cannot be called before init -- @param sec -- @param func_token a token for a function store via the token system -- @param params the argument to send to the tokened function diff --git a/utils/token.lua b/utils/token.lua index e0566ce0..f9d511b7 100644 --- a/utils/token.lua +++ b/utils/token.lua @@ -1,5 +1,3 @@ -local EventCore = require 'utils.event_core' - local Token = {} local tokens = {} @@ -13,7 +11,7 @@ local counter = 0 -- @param var -- @return number the unique token for the variable. function Token.register(var) - if EventCore.runtime then + if _LIFECYCLE == 8 then error('Calling Token.register after on_init() or on_load() has run is a desync risk.', 2) end