Expand compat to 0.17 (#711)

This commit is contained in:
Cooldude2606 authored and GitHub committed 2024-12-13 13:48:52 +00:00
1 parent 87746edbf5
commit ff9ba0271f
8 files changed
+138 -89

No files matched your search

@@ -12,9 +12,8 @@ local MyModule = {
-- If you use any of these events and access globalData then make sure to call this function first
local script_data = {}
local function setup_script_data()
local _script_data = compat.script_data()
if _script_data["__plugin_name__"] == nil then
_script_data["__plugin_name__"] = {
if compat.script_data["__plugin_name__"] == nil then
compat.script_data["__plugin_name__"] = {
-- starting values go here
}
end
@@ -24,8 +23,7 @@ end
--- The on_load function is called independently for each client when they first load the map
-- It should be used to restore global aliases and metatables not registered with script.register_metatable
function MyModule.on_load()
local _script_data = compat.script_data()
script_data = _script_data["__plugin_name__"]
script_data = compat.script_data["__plugin_name__"]
end
--- Public methods should be available though your top level module table
+3 -3
View File
@@ -10,11 +10,11 @@ api.events = {
}
function api.get_instance_name()
return compat.script_data().clusterio.instance_name
return compat.script_data.clusterio.instance_name
end
function api.get_instance_id()
return compat.script_data().clusterio.instance_id
return compat.script_data.clusterio.instance_id
end
function api.send_json(channel, data)
@@ -33,7 +33,7 @@ function api.send_json(channel, data)
if #data < 4000 then
print("\f$ipc:" .. channel .. "?j" .. data)
else
local script_data = compat.script_data()
local script_data = compat.script_data
script_data.clusterio_file_no = (script_data.clusterio_file_no or 0) + 1
local file_name = "clst_" .. script_data.clusterio_file_no .. ".json"
compat.write_file(file_name, data, false, 0)
+115 -63
View File
@@ -1,14 +1,30 @@
--[[
Adds various functions used to ensure compatibly between version including some polyfills
Adds various functions used to ensure compatibly between version including some polyfills.
Implementation Guidelines
- If a function is only available at runtime in one version, then all versions must be made to error.
- Where possible, directly assign the function / table to the member of compat.
- When not possible, then it should replace itself with a direct assignment asap.
- Versions are handled in ascending order covering all supported versions and ending with an error.
]]
local json = require("json")
local lib_json = require("json")
--- @diagnostic disable: deprecated
--- @class LibCompat
--- @field script_data table
--- @field prototypes LuaPrototypes
--- @field active_mods table<string, string>
--- @field write_file fun(filename: string, data: LocalisedString, append: boolean?, for_player: uint?)
--- @field table_to_json fun(data: table): string
--- @field json_to_table fun(json: string): AnyBasic?
local compat = {}
--- @class LibCompatMt
--- @package
local compat_mt = {}
--- @alias VersionTable { [1]: number, [2]: number, [3]: number }
--- Concert a version string into a version table
@@ -37,12 +53,6 @@ do
end
end
--- Raise an error because the current version is unsupported
--- @return any
local function unsupported_version()
error("Unsupported version: " .. current_version_str, 3)
end
--- Returns true if the current version is equal to the provided version
--- @param version string Version to compare against
--- @return boolean # True if versions are equal
@@ -86,85 +96,127 @@ function compat.version_le(version)
return true
end
--- The major versions of factorio we support
local major_v2 = compat.version_ge("2.0.0")
local major_v1_1 = not major_v2 and compat.version_ge("1.1.0")
-- local major_v1 = not major_v1_1 and compat.version_ge("1.0.0")
--- The versions of factorio we support
local v2_0 = compat.version_ge("2.0")
local v1_1 = not v2_0 and compat.version_ge("1.1")
local v1_0 = not v1_1 and compat.version_ge("1.0")
local v0_18 = not v1_0 and compat.version_ge("0.18")
local v0_17 = not v0_18 and compat.version_ge("0.17")
--- Returns the table reference used to store script data
--- @return table script_data
function compat.script_data()
if major_v1_1 then
--- @diagnostic disable-next-line
return global
elseif major_v2 then
return storage
end
return unsupported_version()
local v2 = compat.version_ge("2.0")
local v1 = not v2 and compat.version_ge("1.0")
local v0 = not v1 and compat.version_ge("0.17")
--- Raise an error because the current version is unsupported
local function unsupported_version()
error("Unsupported version: " .. current_version_str, 3)
end
--- Returns the table reference used to store prototypes
--- @param category string Category of prototype to access, eg "item", "fluid", "recipe"
--- @return table # Table of prototype data
function compat.prototype_data(category)
if major_v1_1 then
return game[category .. "_prototypes"]
elseif major_v2 then
return prototypes[category]
end
return unsupported_version()
--- Raise an error because the function is only available at runtime
local function runtime_only()
error("To maintain compatibly, this value can only be used during runtime.", 3)
end
--- Returns the table reference used to list active mods
--- @return table # Table of active mods
function compat.active_mods()
if major_v1_1 or major_v2 then
--- Keys of this table will raise an unsupported error when accessed
local unsupported_properties = {}
--- Keys of this table can only be accessed at runtime
--- The value is a function which returns the real value
local runtime_properties = {}
--- Handles the indexing of the tables above
function compat_mt:__index(key)
if unsupported_properties[key] then
return unsupported_version()
elseif runtime_properties[key] then
if game == nil then
return runtime_only()
end
local value = runtime_properties[key]()
if value == nil then
return unsupported_version()
end
rawset(self, key, value)
return value
end
end
--- Prototype data contains all the definitions for the game, it is only available during runtime
function runtime_properties.prototypes()
if v0 or v1 then
--- Lazy loading of prototype data
return setmetatable({}, {
-- Prevent iteration due to lazy loading, its a really rare use case
__pairs = function() error("Pairs not supported in " .. current_version_str, 2) end,
__ipairs = function() error("IPairs not supported in " .. current_version_str, 2) end,
__index = function(self, key)
local value = game[key .. "_prototypes"]
rawset(self, key, value)
return value
end
})
elseif v2 then
return prototypes
end
end
--- List of all active mods
function runtime_properties.active_mods()
if v0_17 then
return game.active_mods
elseif v0 or v1 or v2 then
return script.active_mods
end
return unsupported_version()
end
--- @param tbl table
--- @return string
function compat.table_to_json(tbl)
return unsupported_version()
--- Writes a string to file
function runtime_properties.write_file()
if v0 or v1 then
return game.write_file
elseif v2 then
return helpers.write_file
end
end
--- @param json string
--- @return table
function compat.json_to_table(json)
return unsupported_version()
end
--- @param filename string
--- @param data LocalisedString
--- @param append boolean?
--- @param for_player uint?
function compat.write_file(filename, data, append, for_player)
unsupported_version()
end
--- Select the appropriate polyfill implementation
if major_v1_1 then
--- Convert tables to and from json, we have backported this to work before runtime
if v0 or v1 then
compat.table_to_json = function(tbl)
if game then
compat.table_to_json = game.table_to_json
return game.table_to_json(tbl)
end
return json.encode(tbl)
return lib_json.encode(tbl)
end
compat.json_to_table = function(json)
if game then
compat.json_to_table = game.json_to_table
return game.json_to_table(json)
end
return json.decode(json)
return lib_json.decode(json)
end
compat.write_file = function(filename, data, append, for_player) return game.write_file(filename, data, append, for_player) end
elseif major_v2 then
elseif v2 then
compat.table_to_json = helpers.table_to_json
compat.json_to_table = helpers.json_to_table
compat.write_file = helpers.write_file
else
unsupported_properties.table_to_json = true
unsupported_properties.json_to_table = true
end
return compat
--- Script data refers to lua data which is persisted between loads
--- This is called immediately, during init and during load
local function set_script_data()
if v0 or v1 then
--- @diagnostic disable-next-line
compat.script_data = global
elseif v2 then
compat.script_data = storage
else
unsupported_properties.script_data = true
end
end
set_script_data()
compat.on_init = set_script_data --- @package
compat.on_load = set_script_data --- @package
return setmetatable(compat, compat_mt)
+8 -10
View File
@@ -4,9 +4,8 @@ local compat = require("modules/clusterio/compat")
--- @class (exact) EventData.on_server_startup:EventData
local function check_patch()
local script_data = compat.script_data()
if script_data.clusterio_patch_number ~= clusterio_patch_number then
script_data.clusterio_patch_number = clusterio_patch_number
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
})
@@ -19,9 +18,8 @@ impl.events = {}
impl.events[defines.events.on_tick] = check_patch
impl.events[api.events.on_server_startup] = function()
local script_data = compat.script_data()
if not script_data.clusterio then
script_data.clusterio = {
if not compat.script_data.clusterio then
compat.script_data.clusterio = {
instance_id = nil,
instance_name = nil,
}
@@ -55,8 +53,8 @@ end
-- Internal API
clusterio_private = {}
function clusterio_private.update_instance(new_id, new_name)
local script_data = compat.script_data()
check_patch()
local script_data = compat.script_data
script_data.clusterio.instance_id = new_id
script_data.clusterio.instance_name = new_name
script.raise_event(api.events.on_instance_updated, {
@@ -78,15 +76,15 @@ remote.add_interface('clusterio_api', {
end,
get_instance_id = function()
return compat.script_data().clusterio.instance_id
return compat.script_data.clusterio.instance_id
end,
get_instance_name = function()
return compat.script_data().clusterio.instance_name
return compat.script_data.clusterio.instance_name
end,
get_file_no = function()
local script_data = compat.script_data()
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,
+4 -1
View File
@@ -2,5 +2,8 @@
"name": "clusterio",
"version": "0.0.0",
"dependencies": {},
"load": ["impl.lua"]
"load": [
"impl.lua",
"compat.lua"
]
}
@@ -2,8 +2,7 @@ local compat = require("modules/clusterio/compat")
--- @param no_early_return boolean? True to always setup data
return function(no_early_return)
local script_data = compat.script_data()
local inventory_sync = script_data.inventory_sync
local inventory_sync = compat.script_data.inventory_sync
if inventory_sync and not no_early_return then
return inventory_sync
end
@@ -17,6 +16,6 @@ return function(no_early_return)
inventory_sync.finished_downloads = inventory_sync.finished_downloads or {}
inventory_sync.active_uploads = inventory_sync.active_uploads or {}
script_data.inventory_sync = inventory_sync
compat.script_data.inventory_sync = inventory_sync
return inventory_sync
end
@@ -360,7 +360,7 @@ end
-- Upload inventory when a player leaves the game. Triggers on restart after crash if player was online during crash.
inventory_sync.events[defines.events.on_pre_player_left_game] = function(event)
-- for some reason, on_pre_player_left_game gets called before on_server_startup so script_data isn't ready yet
if not compat.script_data().inventory_sync then
if not compat.script_data.inventory_sync then
log("ERROR: script data for inventory sync is not defined")
return
end
+2 -3
View File
@@ -33,8 +33,7 @@ end
--- @param no_early_return boolean?
--- @return table
local function get_script_data(no_early_return)
local script_data = compat.script_data()
local research_sync = script_data.research_sync
local research_sync = compat.script_data.research_sync
if research_sync and not no_early_return then
return research_sync
end
@@ -56,7 +55,7 @@ local function get_script_data(no_early_return)
}
end
script_data.research_sync = research_sync
compat.script_data.research_sync = research_sync
return research_sync
end