Tutorial:Script interfaces: Difference between revisions

From Official Factorio Wiki
Jump to navigation Jump to search
m (Bilka moved page Script interfaces to Tutorial:Script interfaces: this page is a tutorial)
(removed outdated/wrong info, expanded info on how the custom input works)
Line 23: Line 23:


The interface functions cannot take function pointers or function closures. Primitive types, LuaObjects and tables work just fine.
The interface functions cannot take function pointers or function closures. Primitive types, LuaObjects and tables work just fine.
The interfaces are not serialised. Therefore it is a good idea to put them into the global scope of the script. In that way they are run everytime the script file is loaded (no matter whether it is the first run or game being loaded).
At the moment the interface is identified solely by its name. There is no vesion mechanism yet. It is a good idea to prefix the name of the interface with the name of the mod / map where it is defined.


=== Calling interface functions ===
=== Calling interface functions ===
Line 36: Line 32:
   -- calls the my_interface.my_getter from the script above and prints the returning value
   -- calls the my_interface.my_getter from the script above and prints the returning value
   print(remote.call("my_interface", "my_getter"))
   print(remote.call("my_interface", "my_getter"))
This remote.call can be used in the global scope as well. However then the script in which it is called has to be invoked after the script which defined the interface. The ordering of the scripts is: first the map script and then the mod scripts in order defined by the mod ordering.
  -- set values in the other script
   -- remote call takes the name of the interface, name of the function and then variable amount of parameters
   -- remote call takes the name of the interface, name of the function and then variable amount of parameters
   remote.call("my_interface', "my_setter", 5, {bar=baz})
   remote.call("my_interface', "my_setter", 5, {bar=baz})
Line 56: Line 48:
=== Custom input ===
=== Custom input ===


data.lua
Keybindings can also be created. First the keybinding has to be defined in the data stage:
 
  local button={
  local button={
   type = "custom-input",
   type = "custom-input",
Line 65: Line 58:
  data:extend{button}
  data:extend{button}


And then it can be used runtime by subscribing to the event of the name of the custom input:


control.lua
  script.on_event("open-proxy-gui",proxy_gui.on_E_button)
  script.on_event("open-proxy-gui",proxy_gui.on_E_button)
 
Proxy in control.lua:
  proxy_gui={
  proxy_gui={
   on_E_button=function(event)
   on_E_button=function(event)
Line 80: Line 72:
       end
       end
   end
   end
}

Revision as of 13:04, 22 August 2017

Script interfaces allow direct communication between simultaneously running scripts. This is done in form of defining a public interface with given functions. All the code regarding the interfaces communication is in the remote namespace.

Defining interfaces

The interface is defined as follows:

 -- assuming name and table_of_functions are defined elsewhere
 remote.add_interface(interface_name, table_of_functions)
 -- It is possible to define the name and table inside the call
 remote.add_interface("my_interface", {
   my_getter = function()
     -- you can return 1 or more variables from the script
     return "foo"
   end,
 
   -- the values can be only primitive type or (nested) tables
   my_setter = function(foo, bar)
     global.foo = foo
     global.bar = bar
   end
 })

The interface functions cannot take function pointers or function closures. Primitive types, LuaObjects and tables work just fine.

Calling interface functions

The interface can be used for calling functions from a different script.

Example (in the different script than the one above):

 -- calls the my_interface.my_getter from the script above and prints the returning value
 print(remote.call("my_interface", "my_getter"))
 -- remote call takes the name of the interface, name of the function and then variable amount of parameters
 remote.call("my_interface', "my_setter", 5, {bar=baz})

Discovering interfaces

The script can check for expected interfaces and its functions via the remote.interfaces table. This is a table indexed by interface names where the values are set of functions for particular interfaces.

Example:

 -- check whether there is the "my_interface" interface and whether it contains the "my_getter" function
 if remote.interfaces.my_interface and remote.interfaces.my_interface.my_getter then
   -- the remote call for the function is safe to use
 end

Custom input

Keybindings can also be created. First the keybinding has to be defined in the data stage:

local button={
  type = "custom-input",
  name = "open-proxy-gui",
  key_sequence = "SHIFT + E",
  consuming = "none"
}
data:extend{button}

And then it can be used runtime by subscribing to the event of the name of the custom input:

script.on_event("open-proxy-gui",proxy_gui.on_E_button)

proxy_gui={
  on_E_button=function(event)
     local pindex=event.player_index
     local p=game.players[pindex]
     local e=game.players[pindex].selected
     
     if e and e.name=='proxy-chest' and p.force==e.force then
        proxy_gui.open(pindex,e)
     end
  end
}