Afforess / Factorio-Stdlib

Factorio Standard Library Project
ISC License
162 stars 45 forks source link

Issues with custom events #133

Closed linaori closed 5 years ago

linaori commented 5 years ago

I'm trying to convert my very small scenario to use this stdlib, but I'm having some issues with the events. I started by downloading the latest release, but soon found out that it was behind the master by far. I hoped that updating to the master would fix my problem, but it didn't.

I'm trying to achieve a system where I can fire my own custom events, to make the features in the scenario pluggable and the code more structured. I've followed the docs on both the latest release and the master, but I fail registering a custom event.

local Event = require 'stdlib/event/event'

Event.register('test', function (event)
    Game.print_all(event.name)
end)

Gives the following error:

6034.279 Error AppManager.cpp:514: ...Data/Roaming/Factorio/temp/currently-playing/control.lua:2: Unknown custom-input name: test
stack traceback:
    ...g/Factorio/temp/currently-playing/stdlib/event/event.lua:93: in function 'register'
    ...Factorio/temp/currently-playing/Diggy/Initialization.lua:23: in main chunk
    [C]: in function 'require'
    ...Data/Roaming/Factorio/temp/currently-playing/control.lua:2: in main chunk

I've also tried the following from the documentation examples:

Event.register("stdlib-test-hotkey-1", function() game.print("Test key 1") end)
Event.register("stdlib-test-hotkey-1", function() game.print("Test key 1 #2") end)
Event.register("stdlib-test-hotkey-2", function() game.print("Test key 2") end)

But this doesn't work either. Please note that I'm working on a Scenario and not a mod.

Nexela commented 5 years ago

The "release" version does fall behind greatly Current master is stable and a great option for a release however with .17 on the horizon I see no reason to do so as A LOT will change with .17 The latest and greatest is available on the data-library branch, This branch is pretty stable also

PS it it working correctly currently-playing/control.lua:2: Unknown custom-input name: test

You just didn't add any custom-inputs in the data stage

linaori commented 5 years ago

Did I miss something in the documentation or is that missing?

Nexela commented 5 years ago

Scenarios can't have prototype changes (data.lua stuff) and a custom input requires a prototype change, I will keep this issue open as a reminder to update the examples.

Kovus commented 5 years ago

You can create custom events, but you'll need to create the event and register your listener after creating the event entry.

See script.generate_event_name() from Factorio.

For example, in your on-init, you could script.generate_event_name(), store it's value, then register your event listener(s). Elsewhere in your code, you would then dispatch that event using the stored value.


My solution to this for using it with Event from this library was to add a function called Event.def(name) which would take a string name and return the existing value, or create a new value for that name.

--[[
    Returns a UINT based on the name passed, for use in event operations.
    If the name is not already registered, then a new UINT value is generated
--]]
function Event.def(name)
    if not Event._name_registry then
        Event._name_registry = {}
    end
    local reg = Event._name_registry
    if not reg[name] then
        local val = script.generate_event_name()
        reg[name] = val
    end
    return reg[name]
end

Then elsewhere in my code, I can easily do:

Event.dispatch({ name = Event.def("perms.group_change"), tick=game.tick, player_index=pindex, group=group.name})
Event.register(Event.def("perms.group_change"), function(event)
-- do stuff
end)
Nexela commented 5 years ago

From the data_library branch(es) which will be available with .17 Event.generate_event_name(string) This is similar to what Kovus posted

--- Retrieve or Generate an event_name and store it in Event.custom_events
-- @tparam string event_name the custom name for your event.
-- @treturn int the id associated with the event.
-- @usage
-- Event.register(Event.generate_event_name("my_custom_event"), handler)
function Event.generate_event_name(event_name)
    Is.Assert.String(event_name, 'event_name must be a string.')

    local id
    if Is.Number(Event.custom_events[event_name]) then
        id = Event.custom_events[event_name]
    else
        id = script.generate_event_name()
        Event.custom_events[event_name] = id
    end
    return id
end

Closed with 53ceb27c5b803201d0e7e42fbf2768ab6e1e6af9