mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-11 23:04:52 +09:00
When the level of a technology changes either by setting level directly or by setting researched to true, the saved progress of the research is reset only if the technology is not the current research. If during the initial synchronisation with the controller an instance has progressed on a multi level research, it's the current research, and the controller's level of that research is higher, then the level is set to the higher level and the game keeps the progress. This in turn results in all of the progress made on the previous level being added to the higher level. Fix by setting the progress to zero when changing the level or researched status of a technology that's the active research.
228 lines
5.7 KiB
Lua
228 lines
5.7 KiB
Lua
local clusterio_api = require("modules/clusterio/api")
|
|
|
|
local sync = {}
|
|
|
|
|
|
local function get_technology_progress(tech)
|
|
if tech == tech.force.current_research then
|
|
return tech.force.research_progress
|
|
else
|
|
return tech.force.get_saved_technology_progress(tech.name)
|
|
end
|
|
end
|
|
|
|
local function set_technology_progress(tech, progress)
|
|
if tech == tech.force.current_research then
|
|
tech.force.research_progress = progress
|
|
else
|
|
tech.force.set_saved_technology_progress(tech.name, progress)
|
|
end
|
|
end
|
|
|
|
sync.events = {}
|
|
sync.events[clusterio_api.events.on_server_startup] = function(event)
|
|
if not global.research_sync then
|
|
global.research_sync = {
|
|
technologies = {},
|
|
}
|
|
end
|
|
|
|
-- Used when syncing completed technologies from the controller
|
|
global.research_sync.ignore_research_finished = false
|
|
|
|
local force = game.forces["player"]
|
|
for _, tech in pairs(force.technologies) do
|
|
local progress = get_technology_progress(tech)
|
|
global.research_sync.technologies[tech.name] = {
|
|
level = tech.level,
|
|
researched = tech.researched,
|
|
progress = progress,
|
|
}
|
|
end
|
|
end
|
|
|
|
local function get_contribution(tech)
|
|
local progress = get_technology_progress(tech)
|
|
if not progress then
|
|
return 0, nil
|
|
end
|
|
|
|
local prev_tech = global.research_sync.technologies[tech.name]
|
|
if prev_tech.progress and prev_tech.level == tech.level then
|
|
return progress - prev_tech.progress, progress
|
|
else
|
|
return progress, progress
|
|
end
|
|
end
|
|
|
|
local function send_contribution(tech)
|
|
local contribution, progress = get_contribution(tech)
|
|
if contribution ~= 0 then
|
|
clusterio_api.send_json("research_sync:contribution", {
|
|
name = tech.name,
|
|
level = tech.level,
|
|
contribution = contribution,
|
|
})
|
|
global.research_sync.technologies[tech.name].progress = progress
|
|
end
|
|
end
|
|
|
|
sync.events[defines.events.on_research_started] = function(event)
|
|
local tech = event.last_research
|
|
if tech then
|
|
send_contribution(tech)
|
|
end
|
|
end
|
|
|
|
sync.events[defines.events.on_research_finished] = function(event)
|
|
if global.research_sync.ignore_research_finished then
|
|
return
|
|
end
|
|
|
|
local tech = event.research
|
|
global.research_sync.technologies[tech.name] = {
|
|
level = tech.level,
|
|
researched = tech.researched,
|
|
}
|
|
|
|
local level = tech.level
|
|
if not tech.researched then
|
|
level = level - 1
|
|
end
|
|
|
|
clusterio_api.send_json("research_sync:finished", {
|
|
name = tech.name,
|
|
level = level,
|
|
})
|
|
end
|
|
|
|
sync.on_nth_tick = {}
|
|
sync.on_nth_tick[79] = function(event)
|
|
local tech = game.forces["player"].current_research
|
|
if tech then
|
|
send_contribution(tech)
|
|
end
|
|
end
|
|
|
|
research_sync = {}
|
|
function research_sync.dump_technologies()
|
|
local force = game.forces["player"]
|
|
|
|
local techs = {}
|
|
for _, tech in pairs(force.technologies) do
|
|
table.insert(techs, {
|
|
name = tech.name,
|
|
level = tech.level,
|
|
progress = get_technology_progress(tech),
|
|
researched = tech.researched,
|
|
})
|
|
end
|
|
|
|
if #techs == 0 then
|
|
rcon.print("[]")
|
|
else
|
|
rcon.print(game.table_to_json(techs))
|
|
end
|
|
end
|
|
|
|
function research_sync.sync_technologies(data)
|
|
local force = game.forces["player"]
|
|
|
|
local nameIndex = 1
|
|
local levelIndex = 2
|
|
local progressIndex = 3
|
|
local researchedIndex = 4
|
|
|
|
global.research_sync.ignore_research_finished = true
|
|
for _, tech_data in pairs(game.json_to_table(data)) do
|
|
local tech = force.technologies[tech_data[nameIndex]]
|
|
if tech and tech.level <= tech_data[levelIndex] then
|
|
local new_level = math.min(tech_data[levelIndex], tech.prototype.max_level)
|
|
if new_level ~= tech.level then
|
|
-- when the level of the current research changes the
|
|
-- progress is not automatically reset.
|
|
if force.current_research == tech then
|
|
force.research_progress = 0
|
|
end
|
|
tech.level = new_level
|
|
end
|
|
|
|
local progress
|
|
if tech_data[researchedIndex] then
|
|
if force.current_research == tech then
|
|
force.research_progress = 0
|
|
end
|
|
tech.researched = true
|
|
progress = nil
|
|
elseif tech_data[progressIndex] then
|
|
send_contribution(tech)
|
|
progress = tech_data[progressIndex]
|
|
set_technology_progress(tech, progress)
|
|
else
|
|
progress = get_technology_progress(tech)
|
|
end
|
|
|
|
global.research_sync.technologies[tech.name] = {
|
|
level = tech.level,
|
|
researched = tech.researched,
|
|
progress = progress,
|
|
}
|
|
end
|
|
end
|
|
global.research_sync.ignore_research_finished = false
|
|
end
|
|
|
|
function research_sync.update_progress(data)
|
|
local techs = game.json_to_table(data)
|
|
local force = game.forces["player"]
|
|
|
|
for _, controllerTech in ipairs(techs) do
|
|
local tech = force.technologies[controllerTech.name]
|
|
if tech and tech.level == controllerTech.level then
|
|
send_contribution(tech)
|
|
set_technology_progress(tech, controllerTech.progress)
|
|
global.research_sync.technologies[tech.name] = {
|
|
level = tech.level,
|
|
progress = controllerTech.progress
|
|
}
|
|
end
|
|
end
|
|
end
|
|
|
|
function research_sync.research_technology(name, level)
|
|
local force = game.forces["player"]
|
|
local tech = force.technologies[name]
|
|
if not tech or tech.level > level then
|
|
return
|
|
end
|
|
|
|
if level > tech.prototype.max_level then
|
|
level = tech.prototype.max_level
|
|
end
|
|
|
|
global.research_sync.ignore_research_finished = true
|
|
if tech == force.current_research and tech.level == level then
|
|
force.research_progress = 1
|
|
|
|
elseif tech.level < level or tech.level == level and not tech.researched then
|
|
tech.level = level
|
|
tech.researched = true
|
|
|
|
if tech.name:find("-%d+$") then
|
|
game.print {"", "Researched ", {"technology-name." .. tech.name:gsub("-%d+$", "")}, " ", level}
|
|
else
|
|
game.print {"", "Researched ", {"technology-name." .. tech.name}}
|
|
end
|
|
game.play_sound { path = "utility/research_completed" }
|
|
end
|
|
global.research_sync.ignore_research_finished = false
|
|
|
|
global.research_sync.technologies[tech.name] = {
|
|
level = tech.level,
|
|
researched = tech.researched,
|
|
}
|
|
end
|
|
|
|
|
|
return sync
|