1
0
mirror of https://github.com/Refactorio/RedMew.git synced 2024-12-12 10:04:40 +02:00

Merge pull request #742 from plague006/apply_lifecycle

Apply lifecycle
This commit is contained in:
Matthew 2019-02-19 14:13:28 -05:00 committed by GitHub
commit 16fe4a7345
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 100 additions and 24 deletions

View File

@ -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', '_LIFECYCLE'} -- RedMew-specific globals
globals = {'print', '_DEBUG', '_CHEATS', '_DUMP_ENV', 'ServerCommands', 'Debug', '_LIFECYCLE', '_STAGE'} -- RedMew-specific globals
max_line_length = LINE_LENGTH
not_globals = NOT_GLOBALS

View File

@ -1,7 +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
require 'resources.data_stages'
_LIFECYCLE = _STAGE.control -- Control stage
-- Overrides the _G.print function
require 'utils.print_override'

View File

@ -76,7 +76,7 @@ end
---@param callback function function(number level_reached, LuaForce force)
---@param lua_force_name string|nil only register for this force (optional)
function ForceControlBuilder.register(level_matches, callback, lua_force_name)
if game then
if _LIFECYCLE > _STAGE.control then
error('You can only register level up callbacks before the game is initialized')
end
assert_type('function', level_matches, 'level_matches of function ForceControl.register_reward')

View File

@ -332,6 +332,9 @@ end
-- end
-- )
function Public.on_data_set_changed(data_set, handler)
if _LIFECYCLE == _STAGE.runtime then
error('cannot call during runtime', 2)
end
if type(data_set) ~= 'string' then
error('data_set must be a string', 2)
end

View File

@ -128,7 +128,7 @@ local spawn_callback =
)
local function init()
local on_init = game ~= nil
local on_init = (_LIFECYCLE == _STAGE.init)
local outpost_random = Random.new(outpost_seed, outpost_seed * 2)

View File

@ -55,7 +55,7 @@ Event.on_init(init)
-- Public functions
--- Sets the day/night cycle according to the table it is given.
-- Can only be used during or after init.
-- Can only be called during or after init.
-- @param day_night_cycle <table> containing specific, required keys: ticks_per_day, dusk, evening, morning, dawn
-- @param surface <LuaSurface> to set the day/night cycle of
-- @returns <boolean> true if set properly, nil if not
@ -86,7 +86,7 @@ function Public.set_cycle(day_night_cycle, surface)
end
--- Sets the brightness to a fixed level
-- Can only be used during or after init.
-- Can only be called during or after init.
-- @param daylight <number> between 0.15 and 1 representing the percentage of daylight (0.15 brightness is the darkest available)
-- @param surface <LuaSurface> to set the day/night cycle of
-- @return <boolean> true if time is set properly, nil if not
@ -121,6 +121,7 @@ function Public.set_fixed_brightness(daylight, surface)
end
--- Unfreezes daytime (usually frozen by set_fixed_brightness)
-- Can only be called during or after init.
-- @param surface <LuaSurface> to unfreeze the day/night cycle of
-- @return <boolean> true if daytime unfrozen, nil if not
function Public.unfreeze_daytime(surface)

View File

@ -231,6 +231,8 @@ end
local map_gen_action_token = Token.register(map_gen_action)
--- Adds generation of a Chunk of the map to the queue
-- @param event <table> the event table from on_chunk_generated
function Public.schedule_chunk(event)
local surface = event.surface
local shape = surfaces[surface.name]
@ -257,6 +259,8 @@ function Public.schedule_chunk(event)
Task.queue_task(map_gen_action_token, data, total_calls)
end
--- Generates a Chunk of map when called
-- @param event <table> the event table from on_chunk_generated
function Public.do_chunk(event)
local surface = event.surface
local shape = surfaces[surface.name]
@ -288,6 +292,8 @@ function Public.do_chunk(event)
do_place_decoratives(data)
end
--- Sets the variables for the generate functions, should only be called from map_loader
-- @param args <table>
function Public.init(args)
tiles_per_tick = args.tiles_per_tick or 32
regen_decoratives = args.regen_decoratives or false
@ -307,6 +313,7 @@ local function on_chunk(event)
end
end
--- Registers the event to generate our map when Chunks are generated, should only be called from map_loader
function Public.register()
if not Public.enable_register_events then
return
@ -319,6 +326,8 @@ function Public.register()
end
end
--- Returns the surfaces that the generate functions will act on
-- @return dictionary of surface_name -> shape function
function Public.get_surfaces()
return surfaces
end

12
resources/data_stages.lua Normal file
View File

@ -0,0 +1,12 @@
-- Info on the data lifecycle and how we use it: https://github.com/Refactorio/RedMew/wiki/The-data-lifecycle
-- Non-applicable stages are commented out.
_STAGE = {
--settings = 1,
--data = 2,
--migration = 3,
control = 4,
init = 5,
load = 6,
--config_change = 7,
runtime = 8
}

View File

@ -62,7 +62,7 @@ function Debug.print(message, trace_levels)
message = format('%s - Traceback%s', message, traceback_string)
end
if game then
if _LIFECYCLE == _STAGE.runtime then
game.print(message)
end
log(message)

View File

@ -104,6 +104,9 @@ local core_add = EventCore.add
local core_on_init = EventCore.on_init
local core_on_load = EventCore.on_load
local core_on_nth_tick = EventCore.on_nth_tick
local stage_load = _STAGE.load
local script_on_event = script.on_event
local script_on_nth_tick = script.on_nth_tick
local Event = {}
@ -205,6 +208,9 @@ function Event.add_removable(event_name, token)
if type(token) ~= 'number' then
error('token must be a number', 2)
end
if _LIFECYCLE == stage_load then
error('cannot call during on_load', 2)
end
local tokens = token_handlers[event_name]
if not tokens then
@ -225,6 +231,9 @@ end
-- @param event_name<number>
-- @param token<number>
function Event.remove_removable(event_name, token)
if _LIFECYCLE == stage_load then
error('cannot call during on_load', 2)
end
local tokens = token_handlers[event_name]
if not tokens then
@ -238,7 +247,7 @@ function Event.remove_removable(event_name, token)
remove(handlers, handler)
if #handlers == 0 then
script.on_event(event_name, nil)
script_on_event(event_name, nil)
end
end
@ -249,6 +258,9 @@ end
-- @param event_name<number>
-- @param func<function>
function Event.add_removable_function(event_name, func)
if _LIFECYCLE == stage_load then
error('cannot call during on_load', 2)
end
if type(func) ~= 'function' then
error('func must be a function', 2)
end
@ -278,6 +290,9 @@ end
-- @param event_name<number>
-- @param func<function>
function Event.remove_removable_function(event_name, func)
if _LIFECYCLE == stage_load then
error('cannot call during on_load', 2)
end
local funcs = function_handlers[event_name]
if not funcs then
@ -290,7 +305,7 @@ function Event.remove_removable_function(event_name, func)
remove(handlers, func)
if #handlers == 0 then
script.on_event(event_name, nil)
script_on_event(event_name, nil)
end
end
@ -300,6 +315,9 @@ end
-- @param tick<number>
-- @param token<number>
function Event.add_removable_nth_tick(tick, token)
if _LIFECYCLE == stage_load then
error('cannot call during on_load', 2)
end
if type(token) ~= 'number' then
error('token must be a number', 2)
end
@ -323,6 +341,9 @@ end
-- @param tick<number>
-- @param token<number>
function Event.remove_removable_nth_tick(tick, token)
if _LIFECYCLE == stage_load then
error('cannot call during on_load', 2)
end
local tokens = token_nth_tick_handlers[tick]
if not tokens then
@ -336,7 +357,7 @@ function Event.remove_removable_nth_tick(tick, token)
remove(handlers, handler)
if #handlers == 0 then
script.on_nth_tick(tick, nil)
script_on_nth_tick(tick, nil)
end
end
@ -347,6 +368,9 @@ end
-- @param tick<number>
-- @param func<function>
function Event.add_removable_nth_tick_function(tick, func)
if _LIFECYCLE == stage_load then
error('cannot call during on_load', 2)
end
if type(func) ~= 'function' then
error('func must be a function', 2)
end
@ -376,6 +400,9 @@ end
-- @param tick<number>
-- @param func<function>
function Event.remove_removable_nth_tick_function(tick, func)
if _LIFECYCLE == stage_load then
error('cannot call during on_load', 2)
end
local funcs = function_nth_tick_handlers[tick]
if not funcs then
@ -388,7 +415,7 @@ function Event.remove_removable_nth_tick_function(tick, func)
remove(handlers, func)
if #handlers == 0 then
script.on_nth_tick(tick, nil)
script_on_nth_tick(tick, nil)
end
end

View File

@ -11,13 +11,20 @@ local event_handlers = {}
-- map of nth_tick to handlers[]
local on_nth_tick_event_handlers = {}
local pcall = pcall
local log = log
local script_on_event = script.on_event
local script_on_nth_tick = script.on_nth_tick
local function call_handlers(handlers, event)
if _DEBUG then
for _, handler in ipairs(handlers) do
for i = 1, #handlers do
local handler = handlers[i]
handler(event)
end
else
for _, handler in ipairs(handlers) do
for i = 1, #handlers do
local handler = handlers[i]
local success, error = pcall(handler, event)
if not success then
log(error)
@ -63,11 +70,11 @@ function Public.add(event_name, handler)
local handlers = event_handlers[event_name]
if not handlers then
event_handlers[event_name] = {handler}
script.on_event(event_name, on_event)
script_on_event(event_name, on_event)
else
table.insert(handlers, handler)
if #handlers == 1 then
script.on_event(event_name, on_event)
script_on_event(event_name, on_event)
end
end
end
@ -105,11 +112,11 @@ function Public.on_nth_tick(tick, handler)
local handlers = on_nth_tick_event_handlers[tick]
if not handlers then
on_nth_tick_event_handlers[tick] = {handler}
script.on_nth_tick(tick, on_nth_tick_event)
script_on_nth_tick(tick, on_nth_tick_event)
else
table.insert(handlers, handler)
if #handlers == 1 then
script.on_nth_tick(tick, on_nth_tick_event)
script_on_nth_tick(tick, on_nth_tick_event)
end
end
end

View File

@ -4,6 +4,9 @@ local Token = require 'utils.token'
local Global = {}
function Global.register(tbl, callback)
if _LIFECYCLE ~= _STAGE.control then
error('can only be called during the control stage', 2)
end
local token = Token.register_global(tbl)
Event.on_load(
@ -14,6 +17,9 @@ function Global.register(tbl, callback)
end
function Global.register_init(tbl, init_handler, callback)
if _LIFECYCLE ~= _STAGE.control then
error('can only be called during the control stage', 2)
end
local token = Token.register_global(tbl)
Event.on_init(

View File

@ -183,6 +183,9 @@ Gui.on_pre_player_hide_top = custom_handler_factory(on_pre_hidden_handlers)
-- This function must be called in the control stage, i.e not inside an event.
-- @param element_name<string> 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

View File

@ -89,7 +89,7 @@ Public.types = {fraction = 'fraction', string = 'string', boolean = 'boolean'}
---@param setting_type string
---@param default mixed
function Public.register(name, setting_type, default)
if game then
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

View File

@ -12,6 +12,7 @@ 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
@ -75,8 +76,8 @@ end
-- @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 game then
error('StateMachine.register_state_tick_callback after on_init() is unsupported due to desyncs.', 2)
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)
@ -90,8 +91,8 @@ end
-- @param state number/string entering state
-- @param callback function
function Module.register_transition_callback(self, old, new, callback)
if game then
error('StateMachine.register_transition after on_init() is unsupported due to desyncs.', 2)
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 {}
@ -102,8 +103,8 @@ end
-- @param init_state number/string The starting state of the machine
-- @return StateMachine The constructed state machine object
function Module.new(init_state)
if game then
error('StateMachine.register_transition after on_init() is unsupported due to desyncs.', 2)
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] = {}

View File

@ -77,6 +77,9 @@ end
-- @param func_token <number> a token for a function store via the token system
-- @param params <any> the argument to send to the tokened function
function Task.set_timeout_in_ticks(ticks, func_token, params)
if not game then
error('cannot call when game is not available', 2)
end
local time = game.tick + ticks
local callback = {time = time, func_token = func_token, params = params}
PriorityQueue.push(global.callbacks, callback, comp)
@ -88,6 +91,9 @@ end
-- @param func_token <number> a token for a function store via the token system
-- @param params <any> the argument to send to the tokened function
function Task.set_timeout(sec, func_token, params)
if not game then
error('cannot call when game is not available', 2)
end
Task.set_timeout_in_ticks(60 * sec, func_token, params)
end