mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-11 23:04:52 +09:00
send_udp and get_host_udp_port indexed script data that is only created on the first tick after patching, so calling them from on_init stopped the server. They now return nothing until then. Received packets were only polled once the host port was known, which needs script commands. Poll whenever recv_udp exists instead, it does nothing when the server runs without --enable-lua-udp. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
135 lines
3.9 KiB
Lua
135 lines
3.9 KiB
Lua
local api = require('modules/clusterio/api')
|
|
local compat = require("modules/clusterio/compat")
|
|
|
|
--- @class (exact) EventData.on_server_startup:EventData
|
|
|
|
local function check_patch()
|
|
if compat.script_data.clusterio_patch_number ~= clusterio_patch_number then
|
|
compat.script_data.clusterio_patch_number = clusterio_patch_number
|
|
script.raise_event(api.events.on_server_startup, {
|
|
name = api.events.on_server_startup, tick = game.tick
|
|
})
|
|
end
|
|
end
|
|
|
|
-- Added in Factorio 2.0.59, indexing a missing key on a LuaObject errors
|
|
local has_recv_udp = helpers ~= nil and pcall(function() return helpers.recv_udp end)
|
|
|
|
local impl = {}
|
|
impl.events = {}
|
|
|
|
impl.events[defines.events.on_tick] = function()
|
|
check_patch()
|
|
-- Dispatch on_udp_packet_received for packets sent by the host, this is
|
|
-- a no-op when the server was started without --enable-lua-udp
|
|
if has_recv_udp then
|
|
helpers.recv_udp(0)
|
|
end
|
|
end
|
|
|
|
impl.events[api.events.on_server_startup] = function()
|
|
if not compat.script_data.clusterio then
|
|
compat.script_data.clusterio = {
|
|
instance_id = nil,
|
|
instance_name = nil,
|
|
host_udp_port = nil,
|
|
}
|
|
end
|
|
|
|
-- Replay will just desync after the save is patched
|
|
game.disable_replay()
|
|
end
|
|
|
|
impl.events[defines.events.on_player_joined_game] = function(event)
|
|
local player = game.players[event.player_index]
|
|
api.send_json("player_event", { type = "join", name = player.name })
|
|
end
|
|
|
|
local disconnect_reason_name = {}
|
|
if defines.disconnect_reason then
|
|
for name, i in pairs(defines.disconnect_reason) do
|
|
disconnect_reason_name[i] = name
|
|
end
|
|
end
|
|
|
|
impl.events[defines.events.on_player_left_game] = function(event)
|
|
local player = game.players[event.player_index]
|
|
api.send_json("player_event", {
|
|
type = "leave",
|
|
name = player.name,
|
|
reason = disconnect_reason_name[event.reason] or "quit",
|
|
})
|
|
end
|
|
|
|
impl.events[defines.events.on_player_banned] = function(event)
|
|
api.send_json("player_event", {
|
|
type = "BAN",
|
|
name = event.player_name,
|
|
reason = event.reason,
|
|
})
|
|
end
|
|
|
|
impl.events[defines.events.on_player_unbanned] = function(event)
|
|
api.send_json("player_event", { type = "UNBANNED", name = event.player_name })
|
|
end
|
|
|
|
impl.events[defines.events.on_player_promoted] = function(event)
|
|
local player = game.players[event.player_index]
|
|
api.send_json("player_event", { type = "PROMOTE", name = player.name })
|
|
end
|
|
|
|
impl.events[defines.events.on_player_demoted] = function(event)
|
|
local player = game.players[event.player_index]
|
|
api.send_json("player_event", { type = "DEMOTE", name = player.name })
|
|
end
|
|
|
|
-- Internal API
|
|
clusterio_private = {}
|
|
function clusterio_private.update_instance(new_id, new_name, host_udp_port)
|
|
check_patch()
|
|
local script_data = compat.script_data
|
|
script_data.clusterio.instance_id = new_id
|
|
script_data.clusterio.instance_name = new_name
|
|
script_data.clusterio.host_udp_port = host_udp_port
|
|
script.raise_event(api.events.on_instance_updated, {
|
|
instance_id = new_id,
|
|
instance_name = new_name,
|
|
})
|
|
end
|
|
|
|
|
|
-- This is not part of the add_remote_interface callback to ensure it is
|
|
-- available when the clusterio_lib mod is loaded. The reason this is
|
|
-- neccessary is that on_init for newly added mods happen before on_load
|
|
-- for existing mods, and the add_remote_interface callback is done in
|
|
-- on_load. See https://forums.factorio.com/viewtopic.php?f=25&t=81552 for
|
|
-- more details.
|
|
remote.add_interface('clusterio_api', {
|
|
get_events = function()
|
|
return api.events
|
|
end,
|
|
|
|
get_instance_id = function()
|
|
return compat.script_data.clusterio.instance_id
|
|
end,
|
|
|
|
get_instance_name = function()
|
|
return compat.script_data.clusterio.instance_name
|
|
end,
|
|
|
|
get_host_udp_port = function()
|
|
-- Not initialised until the first tick after the save is patched
|
|
local clusterio = compat.script_data.clusterio
|
|
return clusterio and clusterio.host_udp_port
|
|
end,
|
|
|
|
get_file_no = function()
|
|
local script_data = compat.script_data
|
|
script_data.clusterio_file_no = (script_data.clusterio_file_no or 0) + 1
|
|
return script_data.clusterio_file_no
|
|
end,
|
|
})
|
|
|
|
|
|
return impl
|