Replace spaces with tabs

This commit is contained in:
Daniel committed 2021-07-29 23:59:37 +02:00
1 parent e63f1246da
commit 2ffb848fe6
15 files changed
+473 -473

No files matched your search

+9 -9
View File
@@ -2,16 +2,16 @@ local save_crafts = require("modules/inventory_sync/save_crafts")
local restore_crafts = require("modules/inventory_sync/restore_crafts")
function add_commands()
--[[
Command to serialize crafting queue for transport.
When serialized, the crafting queue is cleared and stored in global. The items received are cleared as well.
Upon leaving, the value in global is cleared and sent with the inventory to the master.
Upon joining a game the crafting queue is added to the end of the existing crafting queue.
]]
--[[
Command to serialize crafting queue for transport.
When serialized, the crafting queue is cleared and stored in global. The items received are cleared as well.
Upon leaving, the value in global is cleared and sent with the inventory to the master.
Upon joining a game the crafting queue is added to the end of the existing crafting queue.
]]
commands.add_command("save-crafts", "Save crafting queue for transport to a different server", save_crafts)
commands.add_command("csc", "Shorthand for /save-crafts", save_crafts)
commands.add_command("restore-crafts", "Load crafting queue from global", restore_crafts)
commands.add_command("crc", "Shorthand for /restore-crafts", restore_crafts)
commands.add_command("csc", "Shorthand for /save-crafts", save_crafts)
commands.add_command("restore-crafts", "Load crafting queue from global", restore_crafts)
commands.add_command("crc", "Shorthand for /restore-crafts", restore_crafts)
end
return add_commands
@@ -1,10 +1,10 @@
local inventories = {
defines.inventory.character_main,
defines.inventory.character_guns,
defines.inventory.character_ammo,
defines.inventory.character_armor,
defines.inventory.character_vehicle,
defines.inventory.character_trash,
defines.inventory.character_main,
defines.inventory.character_guns,
defines.inventory.character_ammo,
defines.inventory.character_armor,
defines.inventory.character_vehicle,
defines.inventory.character_trash,
}
return inventories
@@ -1,23 +1,23 @@
return {
"character_crafting_speed_modifier",
"character_mining_speed_modifier",
"character_additional_mining_categories",
"character_running_speed_modifier",
"character_build_distance_bonus",
"character_item_drop_distance_bonus",
"character_reach_distance_bonus",
"character_resource_reach_distance_bonus",
"character_item_pickup_distance_bonus",
"character_loot_pickup_distance_bonus",
"character_inventory_slots_bonus",
"character_trash_slot_count_bonus",
"character_maximum_following_robot_count_bonus",
"character_health_bonus",
"character_personal_logistic_requests_enabled",
"build_distance",
"drop_item_distance",
"reach_distance",
"item_pickup_distance",
"loot_pickup_distance",
"resource_reach_distance",
"character_crafting_speed_modifier",
"character_mining_speed_modifier",
"character_additional_mining_categories",
"character_running_speed_modifier",
"character_build_distance_bonus",
"character_item_drop_distance_bonus",
"character_reach_distance_bonus",
"character_resource_reach_distance_bonus",
"character_item_pickup_distance_bonus",
"character_loot_pickup_distance_bonus",
"character_inventory_slots_bonus",
"character_trash_slot_count_bonus",
"character_maximum_following_robot_count_bonus",
"character_health_bonus",
"character_personal_logistic_requests_enabled",
"build_distance",
"drop_item_distance",
"reach_distance",
"item_pickup_distance",
"loot_pickup_distance",
"resource_reach_distance",
}
@@ -6,102 +6,102 @@ local ensure_character = require("modules/inventory_sync/ensure_character")
local player_stat_keys = require("modules/inventory_sync/define_player_stat_keys")
function download_inventory(player_name, data, number, total)
local player = game.get_player(player_name)
if player == nil then
log("Player not found! "..player_name)
return
end
if number then
if global.inventory_sync.download_cache[player_name] == nil then
global.inventory_sync.download_cache[player_name] = ""
end
-- Append data to download cache
global.inventory_sync.download_cache[player_name] = global.inventory_sync.download_cache[player_name] .. data
end
local player = game.get_player(player_name)
if player == nil then
log("Player not found! "..player_name)
return
end
if number then
if global.inventory_sync.download_cache[player_name] == nil then
global.inventory_sync.download_cache[player_name] = ""
end
-- Append data to download cache
global.inventory_sync.download_cache[player_name] = global.inventory_sync.download_cache[player_name] .. data
end
if number ~= total then
-- Show progress in console
-- player.print("Downloaded "..(number + 1).."/"..total.." parts")
-- Show progress in GUI
progress_dialog(player, number+1, total)
if number ~= total then
-- Show progress in console
-- player.print("Downloaded "..(number + 1).."/"..total.." parts")
-- Show progress in GUI
progress_dialog(player, number+1, total)
-- Request next segment
rcon.print("Segment downloaded")
-- Request next segment
rcon.print("Segment downloaded")
-- Reset sync_start_tick to indicate master connection
global.inventory_sync.players[player_name].sync_start_tick = game.tick
else
-- Stop tracking master connection status, sync is complete
global.inventory_sync.players[player_name].sync_start_tick = 0
-- Reset sync_start_tick to indicate master connection
global.inventory_sync.players[player_name].sync_start_tick = game.tick
else
-- Stop tracking master connection status, sync is complete
global.inventory_sync.players[player_name].sync_start_tick = 0
-- Handle dirty inventory
if global.inventory_sync.players[player_name].dirty_inventory then
clean_dirty_inventory(player)
end
-- Handle dirty inventory
if global.inventory_sync.players[player_name].dirty_inventory then
clean_dirty_inventory(player)
end
-- Recreate player character
ensure_character(player)
-- Recreate player character
ensure_character(player)
-- Remove freeplay skip cutscene label
if player.gui.screen.skip_cutscene_label then
player.gui.screen.skip_cutscene_label.destroy()
end
-- Remove freeplay skip cutscene label
if player.gui.screen.skip_cutscene_label then
player.gui.screen.skip_cutscene_label.destroy()
end
local character = player.character or player.cutscene_character
local character = player.character or player.cutscene_character
-- Load downloaded inventory
local serialized_player = game.json_to_table(global.inventory_sync.download_cache[player_name])
global.inventory_sync.download_cache[player_name] = nil -- remove data to lower mapsize
-- Load downloaded inventory
local serialized_player = game.json_to_table(global.inventory_sync.download_cache[player_name])
global.inventory_sync.download_cache[player_name] = nil -- remove data to lower mapsize
-- Load inventories
for _, inv in pairs(inventories) do
local inventory = player.get_inventory(inv)
if inventory ~= nil and serialized_player.inventories[tostring(inv)] ~= nil then
serialize.deserialize_inventory(inventory, serialized_player.inventories[tostring(inv)])
end
end
-- Load inventories
for _, inv in pairs(inventories) do
local inventory = player.get_inventory(inv)
if inventory ~= nil and serialized_player.inventories[tostring(inv)] ~= nil then
serialize.deserialize_inventory(inventory, serialized_player.inventories[tostring(inv)])
end
end
-- Load personal logistics slots
for i = 1, 200 do
local slot = serialized_player.personal_logistic_slots[tostring(i+1)] -- 1 is empty to force array to be spare
if slot ~= nil then
player.set_personal_logistic_slot(i, slot)
end
end
-- Load personal logistics slots
for i = 1, 200 do
local slot = serialized_player.personal_logistic_slots[tostring(i+1)] -- 1 is empty to force array to be spare
if slot ~= nil then
player.set_personal_logistic_slot(i, slot)
end
end
-- Load hotbar, don't overwrite empty slots
for i = 1, 100 do
-- if serialized_player.hotbar[i] ~= nil then
player.set_quick_bar_slot(i, game.item_prototypes[serialized_player.hotbar[i]])
-- end
end
-- Load hotbar, don't overwrite empty slots
for i = 1, 100 do
-- if serialized_player.hotbar[i] ~= nil then
player.set_quick_bar_slot(i, game.item_prototypes[serialized_player.hotbar[i]])
-- end
end
-- Load crafting queue
load_crafting_queue(serialized_player.crafting_queue, player)
-- Load crafting queue
load_crafting_queue(serialized_player.crafting_queue, player)
-- Misc
player.cheat_mode = serialized_player.cheat_mode
player.force = serialized_player.force -- Force by name as string
player.tag = serialized_player.tag
player.color = serialized_player.color
player.chat_color = serialized_player.chat_color
-- Misc
player.cheat_mode = serialized_player.cheat_mode
player.force = serialized_player.force -- Force by name as string
player.tag = serialized_player.tag
player.color = serialized_player.color
player.chat_color = serialized_player.chat_color
-- Player stats
for _,v in pairs(player_stat_keys) do
character[v] = serialized_player[v]
end
-- Player stats
for _,v in pairs(player_stat_keys) do
character[v] = serialized_player[v]
end
if serialized_player.flashlight then
player.enable_flashlight()
else
player.disable_flashlight()
end
if serialized_player.flashlight then
player.enable_flashlight()
else
player.disable_flashlight()
end
local startTick = global.inventory_sync.download_start_tick[player.name]
local log_line = "Imported inventory for "..player_name.." in "..game.tick - startTick.." ticks"
player.print(log_line)
log("[inventory_sync] "..log_line)
end
local startTick = global.inventory_sync.download_start_tick[player.name]
local log_line = "Imported inventory for "..player_name.." in "..game.tick - startTick.." ticks"
player.print(log_line)
log("[inventory_sync] "..log_line)
end
end
return download_inventory
@@ -1,10 +1,10 @@
local function ensure_character(player)
if player.character == nil then
player.set_controller {
type = defines.controllers.god,
}
player.create_character()
end
if player.character == nil then
player.set_controller {
type = defines.controllers.god,
}
player.create_character()
end
end
return ensure_character
@@ -1,31 +1,31 @@
-- Show inventory download progressbar
function dialog_failed_download(player)
if player.gui.screen.dialog_failed_download then
player.gui.screen.dialog_failed_download.destroy()
end
if player.gui.screen.dialog_failed_download then
player.gui.screen.dialog_failed_download.destroy()
end
local frame = player.gui.screen.add {
name = "dialog_failed_download",
type = "frame",
direction = "vertical",
}
local frame = player.gui.screen.add {
name = "dialog_failed_download",
type = "frame",
direction = "vertical",
}
local titlebar = frame.add {
type = "flow",
}
titlebar.drag_target = frame
local titlebar = frame.add {
type = "flow",
}
titlebar.drag_target = frame
local title = titlebar.add {
type = "label",
style = "frame_title",
caption = "Inventory sync download failed",
}
title.drag_target = frame
local title = titlebar.add {
type = "label",
style = "frame_title",
caption = "Inventory sync download failed",
}
title.drag_target = frame
local filler = titlebar.add {
type = "empty-widget",
style = "draggable_space_header",
}
local filler = titlebar.add {
type = "empty-widget",
style = "draggable_space_header",
}
filler.style.horizontally_stretchable = "on"
filler.style.right_margin = 4
filler.style.height = 24
@@ -46,15 +46,15 @@ function dialog_failed_download(player)
p1.style.single_line = false
p1.style.bottom_margin = 8
local abort = content.add {
name = "inventory_sync_failed_download_abort",
type = "button",
caption = "Continue with new inventory",
tooltip = "Create a new empty temporary inventory. Items you pick up will be placed in a chest when the sync completes.",
}
local abort = content.add {
name = "inventory_sync_failed_download_abort",
type = "button",
caption = "Continue with new inventory",
tooltip = "Create a new empty temporary inventory. Items you pick up will be placed in a chest when the sync completes.",
}
frame.force_auto_center()
player.opened = frame
frame.force_auto_center()
player.opened = frame
end
return dialog_failed_download
@@ -2,22 +2,22 @@ local ensure_character = require("modules/inventory_sync/ensure_character")
-- on_gui_click
local handle_gui_events = function(event)
local player = game.get_player(event.player_index)
local element = event.element
if element.name == "inventory_sync_failed_download_abort" then
-- Give the player a new inventory and mark it as dirty
-- Show dirty status and an explanation in a GUI
local player = game.get_player(event.player_index)
local element = event.element
if element.name == "inventory_sync_failed_download_abort" then
-- Give the player a new inventory and mark it as dirty
-- Show dirty status and an explanation in a GUI
-- Remove GUI element
player.gui.screen.dialog_failed_download.destroy()
-- Handle inventory dirtying
if not global.inventory_sync.players[player.name].dirty_inventory then
global.inventory_sync.players[player.name].dirty_inventory = true
-- Restore player character
ensure_character(player)
end
end
-- Remove GUI element
player.gui.screen.dialog_failed_download.destroy()
-- Handle inventory dirtying
if not global.inventory_sync.players[player.name].dirty_inventory then
global.inventory_sync.players[player.name].dirty_inventory = true
-- Restore player character
ensure_character(player)
end
end
end
return handle_gui_events
@@ -1,34 +1,34 @@
-- Show inventory download progressbar
function open_dialog(player, progress, total)
if player.gui.screen.inventory_sync_progress then
player.gui.screen.inventory_sync_progress.destroy()
end
if progress == total then
return -- Hide dialog on completed download
end
if player.gui.screen.inventory_sync_progress then
player.gui.screen.inventory_sync_progress.destroy()
end
if progress == total then
return -- Hide dialog on completed download
end
local frame = player.gui.screen.add {
name = "inventory_sync_progress",
type = "frame",
direction = "vertical",
}
local frame = player.gui.screen.add {
name = "inventory_sync_progress",
type = "frame",
direction = "vertical",
}
local titlebar = frame.add {
type = "flow",
}
titlebar.drag_target = frame
local titlebar = frame.add {
type = "flow",
}
titlebar.drag_target = frame
local title = titlebar.add {
type = "label",
style = "frame_title",
caption = "Inventory sync",
}
title.drag_target = frame
local title = titlebar.add {
type = "label",
style = "frame_title",
caption = "Inventory sync",
}
title.drag_target = frame
local filler = titlebar.add {
type = "empty-widget",
style = "draggable_space_header",
}
local filler = titlebar.add {
type = "empty-widget",
style = "draggable_space_header",
}
filler.style.horizontally_stretchable = "on"
filler.style.right_margin = 4
filler.style.height = 24
@@ -58,14 +58,14 @@ function open_dialog(player, progress, total)
p1.style.single_line = false
p1.style.bottom_margin = 8
local progressbar = content.add {
type = "progressbar",
value = progress / total,
}
progressbar.style.width = 376 -- inside_shallow_frame_with_padding has 12px padding on each side
local progressbar = content.add {
type = "progressbar",
value = progress / total,
}
progressbar.style.width = 376 -- inside_shallow_frame_with_padding has 12px padding on each side
frame.force_auto_center()
player.opened = frame
frame.force_auto_center()
player.opened = frame
end
return open_dialog
@@ -1,9 +1,9 @@
local function welcome_new_player(player_name)
local player = game.get_player(player_name)
if player == nil then return end
player.print("Welcome to the server!")
player.print("Your inventory will be automatically synchronized between servers in this cluster.")
player.print("To improve sync performance, please avoid storing blueprints in your inventory.")
local player = game.get_player(player_name)
if player == nil then return end
player.print("Welcome to the server!")
player.print("Your inventory will be automatically synchronized between servers in this cluster.")
player.print("To improve sync performance, please avoid storing blueprints in your inventory.")
end
return welcome_new_player
@@ -29,124 +29,124 @@ inventory_sync.upload_inventory = upload_inventory
inventory_sync.add_commands = add_commands
inventory_sync.events = {}
inventory_sync.events[clusterio_api.events.on_server_startup] = function(event)
-- set up global table
if not global.inventory_sync then
global.inventory_sync = {
download_start_tick = {},
saved_crafting_queue = {},
download_cache = {},
players_waiting_for_download = {},
players = {},
}
end
-- set up global table
if not global.inventory_sync then
global.inventory_sync = {
download_start_tick = {},
saved_crafting_queue = {},
download_cache = {},
players_waiting_for_download = {},
players = {},
}
end
end
-- Cleanup
inventory_sync.events[defines.events.on_player_removed] = function(event)
local player = game.get_player(event.player_index)
local player = game.get_player(event.player_index)
-- Remove inventory download performance counter
global.inventory_sync.download_start_tick[player.name] = nil
-- Remove stored crafting queue
global.inventory_sync.saved_crafting_queue[player.name] = nil
-- Remove other player data
global.inventory_sync.players[player.name] = nil
-- Remove inventory download performance counter
global.inventory_sync.download_start_tick[player.name] = nil
-- Remove stored crafting queue
global.inventory_sync.saved_crafting_queue[player.name] = nil
-- Remove other player data
global.inventory_sync.players[player.name] = nil
end
inventory_sync.events[defines.events.on_player_created] = function(event)
local player = game.get_player(event.player_index)
global.inventory_sync.players[player.name] = {
dirty_inventory = false, -- Player has a temporary non-synced inventory that should be persisted
sync_start_tick = 0, -- To track download failure timeout
}
local player = game.get_player(event.player_index)
global.inventory_sync.players[player.name] = {
dirty_inventory = false, -- Player has a temporary non-synced inventory that should be persisted
sync_start_tick = 0, -- To track download failure timeout
}
end
inventory_sync.events[defines.events.on_gui_click] = handle_gui_events
-- Download inventory from master
inventory_sync.events[defines.events.on_player_joined_game] = function(event)
-- Add player to download queue. Inventory won't be downloaded before the player has a character
global.inventory_sync.players_waiting_for_download[game.get_player(event.player_index).name] = true
-- Don't wait for on_nth_tick if not required
inventory_sync.check_player_character_before_download()
-- Add player to download queue. Inventory won't be downloaded before the player has a character
global.inventory_sync.players_waiting_for_download[game.get_player(event.player_index).name] = true
-- Don't wait for on_nth_tick if not required
inventory_sync.check_player_character_before_download()
end
inventory_sync.on_nth_tick = {}
inventory_sync.on_nth_tick[33] = function(event)
-- Periodically check if player has a character to download to. False in cutscenes.
inventory_sync.check_player_character_before_download()
-- Periodically check if player has a character to download to. False in cutscenes.
inventory_sync.check_player_character_before_download()
-- Check if download has failed and we should create a dirty inventory
inventory_sync.check_inventory_download_failed()
-- Check if download has failed and we should create a dirty inventory
inventory_sync.check_inventory_download_failed()
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 global isn't ready yet
if not global.inventory_sync then
log("ERROR: Global inventory sync not defined")
return
end
-- for some reason, on_pre_player_left_game gets called before on_server_startup so global isn't ready yet
if not global.inventory_sync then
log("ERROR: Global inventory sync not defined")
return
end
local player_index = event.player_index
local player = game.get_player(player_index)
-- Avoid uploading for unsynced players (due to not having a character, ex during freeplay cutscene)
if global.inventory_sync.players_waiting_for_download[player.name] == nil then
inventory_sync.upload_inventory(player_index)
global.inventory_sync.download_cache[player_index] = "" -- Clear cache to avoid leaking memory to people quitting during download
end
global.inventory_sync.players_waiting_for_download[player.name] = nil
local player_index = event.player_index
local player = game.get_player(player_index)
-- Avoid uploading for unsynced players (due to not having a character, ex during freeplay cutscene)
if global.inventory_sync.players_waiting_for_download[player.name] == nil then
inventory_sync.upload_inventory(player_index)
global.inventory_sync.download_cache[player_index] = "" -- Clear cache to avoid leaking memory to people quitting during download
end
global.inventory_sync.players_waiting_for_download[player.name] = nil
end
function inventory_sync.check_player_character_before_download()
-- Check if players waiting for download have a valid character
-- Check if players waiting for download have a valid character
for name in pairs(global.inventory_sync.players_waiting_for_download) do
local player = game.get_player(name)
if player.character ~= nil then
global.inventory_sync.players_waiting_for_download[name] = nil
inventory_sync.initiate_inventory_download(player)
end
end
local player = game.get_player(name)
if player.character ~= nil then
global.inventory_sync.players_waiting_for_download[name] = nil
inventory_sync.initiate_inventory_download(player)
end
end
end
function inventory_sync.initiate_inventory_download(player)
player.print("Initiating inventory download...")
global.inventory_sync.download_start_tick[player.name] = game.tick
global.inventory_sync.download_cache[player.name] = ""
clusterio_api.send_json("inventory_sync_download", {
player_name = player.name
})
player.print("Initiating inventory download...")
global.inventory_sync.download_start_tick[player.name] = game.tick
global.inventory_sync.download_cache[player.name] = ""
clusterio_api.send_json("inventory_sync_download", {
player_name = player.name
})
-- Handle dirty inventories. A dirty inventory is a temporary inventory that has been used while waiting
-- for sync. It should be taken care of in some way, like putting it in a corpse or a chest.
if global.inventory_sync.players[player.name].dirty_inventory then
clean_dirty_inventory(player)
end
-- Handle dirty inventories. A dirty inventory is a temporary inventory that has been used while waiting
-- for sync. It should be taken care of in some way, like putting it in a corpse or a chest.
if global.inventory_sync.players[player.name].dirty_inventory then
clean_dirty_inventory(player)
end
-- Set player into ghost mode for duration of download
local character = player.character
player.set_controller {
type = defines.controllers.ghost,
}
if character ~= nil then character.destroy() end
-- Set player into ghost mode for duration of download
local character = player.character
player.set_controller {
type = defines.controllers.ghost,
}
if character ~= nil then character.destroy() end
-- Start timeout for detecting master connection failure
global.inventory_sync.players[player.name].sync_start_tick = game.tick
-- Start timeout for detecting master connection failure
global.inventory_sync.players[player.name].sync_start_tick = game.tick
end
function inventory_sync.check_inventory_download_failed()
-- Used for letting the master report the inventory download failing, like when the master is offline or an
-- error occurs somewhere in the server code. The player will be returned to a playable state.
for name, data in pairs(global.inventory_sync.players) do
if data.sync_start_tick ~= 0 and data.sync_start_tick <= game.tick - 600 then
-- Stop refreshing timer
data.sync_start_tick = 0
-- Used for letting the master report the inventory download failing, like when the master is offline or an
-- error occurs somewhere in the server code. The player will be returned to a playable state.
for name, data in pairs(global.inventory_sync.players) do
if data.sync_start_tick ~= 0 and data.sync_start_tick <= game.tick - 600 then
-- Stop refreshing timer
data.sync_start_tick = 0
local player = game.get_player(name)
player.print("Inventory download failed due to master connection")
-- Show GUI with option to retry or abort download
dialog_failed_download(player)
end
end
local player = game.get_player(name)
player.print("Inventory download failed due to master connection")
-- Show GUI with option to retry or abort download
dialog_failed_download(player)
end
end
end
return inventory_sync
@@ -1,27 +1,27 @@
-- Load crafting queue from a table
function load_crafting_queue(crafting_queue, player)
local inventory = player.get_main_inventory()
local inventory = player.get_main_inventory()
-- Give player some more inventory space to avoid duplicating items
player.character_inventory_slots_bonus = player.character_inventory_slots_bonus + 1000
-- Give player some more inventory space to avoid duplicating items
player.character_inventory_slots_bonus = player.character_inventory_slots_bonus + 1000
-- Add items to inventory
for _, item in pairs(crafting_queue.ingredients) do
inventory.insert(item)
end
-- Add items to inventory
for _, item in pairs(crafting_queue.ingredients) do
inventory.insert(item)
end
-- Load crafting queue
for _, queueItem in pairs(crafting_queue.crafting_queue) do
-- Start crafting (consume items)
player.begin_crafting {
count = queueItem.count,
recipe = queueItem.recipe,
-- silent = true, -- Fail silently if items are missing
}
end
-- Load crafting queue
for _, queueItem in pairs(crafting_queue.crafting_queue) do
-- Start crafting (consume items)
player.begin_crafting {
count = queueItem.count,
recipe = queueItem.recipe,
-- silent = true, -- Fail silently if items are missing
}
end
-- Remove extra inventory slots
player.character_inventory_slots_bonus = player.character_inventory_slots_bonus - 1000
-- Remove extra inventory slots
player.character_inventory_slots_bonus = player.character_inventory_slots_bonus - 1000
end
return load_crafting_queue
@@ -1,19 +1,19 @@
local load_crafting_queue = require("modules/inventory_sync/load_crafting_queue")
function restore_crafts(event)
if event.player_index then
local player = game.get_player(event.player_index)
local crafting_queue = global.inventory_sync.saved_crafting_queue[player.name]
if event.player_index then
local player = game.get_player(event.player_index)
local crafting_queue = global.inventory_sync.saved_crafting_queue[player.name]
if crafting_queue == nil then
player.print("No saved crafting queue")
return
end
if crafting_queue == nil then
player.print("No saved crafting queue")
return
end
load_crafting_queue(crafting_queue, player)
load_crafting_queue(crafting_queue, player)
global.inventory_sync.saved_crafting_queue[player.name] = nil
end
global.inventory_sync.saved_crafting_queue[player.name] = nil
end
end
return restore_crafts
+83 -83
View File
@@ -1,96 +1,96 @@
function save_crafts(event)
if event.player_index then
local player = game.get_player(event.player_index)
local crafting_queue = {}
if event.player_index then
local player = game.get_player(event.player_index)
local crafting_queue = {}
-- Avoid overwriting old save
if global.inventory_sync.saved_crafting_queue[player.name] ~= nil then
player.print("You already have a saved crafting queue, restore it with /restore-crafts")
return
end
-- Avoid overwriting old save
if global.inventory_sync.saved_crafting_queue[player.name] ~= nil then
player.print("You already have a saved crafting queue, restore it with /restore-crafts")
return
end
-- Give player some more inventory space to avoid duplicating items
player.character_inventory_slots_bonus = player.character_inventory_slots_bonus + 1000
-- Give player some more inventory space to avoid duplicating items
player.character_inventory_slots_bonus = player.character_inventory_slots_bonus + 1000
-- Save current items
local inventory = player.get_main_inventory()
local old_items = inventory.get_contents()
-- Save current items
local inventory = player.get_main_inventory()
local old_items = inventory.get_contents()
-- Cancel old crafts to get the items back
while player.crafting_queue_size > 0 do
local old_queue = player.crafting_queue
local queueItem = player.crafting_queue[1]
-- Cancel craft
player.cancel_crafting {
index = 1,
count = 1,
}
-- Cancel old crafts to get the items back
while player.crafting_queue_size > 0 do
local old_queue = player.crafting_queue
local queueItem = player.crafting_queue[1]
-- Cancel craft
player.cancel_crafting {
index = 1,
count = 1,
}
local rightmost_right_index = 0 -- 0 indexed since it is subtractive in a 1 indexed language
local new_queue = player.crafting_queue
while
new_queue ~= nil and
new_queue[#new_queue - rightmost_right_index] ~= nil and
new_queue[#new_queue - rightmost_right_index].count >= old_queue[#old_queue - rightmost_right_index].count
do
rightmost_right_index = rightmost_right_index + 1
end
local oldItem = old_queue[#old_queue - rightmost_right_index]
local newItem = nil
if new_queue ~= nil then
newItem = new_queue[#new_queue - rightmost_right_index]
end
local rightmost_right_index = 0 -- 0 indexed since it is subtractive in a 1 indexed language
local new_queue = player.crafting_queue
while
new_queue ~= nil and
new_queue[#new_queue - rightmost_right_index] ~= nil and
new_queue[#new_queue - rightmost_right_index].count >= old_queue[#old_queue - rightmost_right_index].count
do
rightmost_right_index = rightmost_right_index + 1
end
local oldItem = old_queue[#old_queue - rightmost_right_index]
local newItem = nil
if new_queue ~= nil then
newItem = new_queue[#new_queue - rightmost_right_index]
end
-- Figure out how many items to add to queue
local added = oldItem.count
if newItem ~= nil then
added = oldItem.count - newItem.count
if oldItem.recipe ~= newItem.recipe then
log("ERROR: Old item "..oldItem.recipe.." is not equal "..newItem.recipe)
end
end
-- Figure out how many items to add to queue
local added = oldItem.count
if newItem ~= nil then
added = oldItem.count - newItem.count
if oldItem.recipe ~= newItem.recipe then
log("ERROR: Old item "..oldItem.recipe.." is not equal "..newItem.recipe)
end
end
-- If the last item we added was of the same type, merge them in the queue
if #crafting_queue > 0 and crafting_queue[#crafting_queue].recipe == oldItem.recipe then
crafting_queue[#crafting_queue].count = crafting_queue[#crafting_queue].count + added
else
-- If the last item was of a different type, add a new item to the queue
table.insert(crafting_queue, {
recipe = oldItem.recipe,
count = added,
})
end
-- game.print("Saved craft "..oldItem.recipe)
end
-- Find amount of items added and remove from inventory
local new_items = inventory.get_contents()
local difference = {}
for k,v in pairs(new_items) do
local old_count = old_items[k]
local diff = v
if old_count ~= nil then
diff = diff - old_count
end
if diff > 0 then
local ingredient = {
name = k,
count = diff,
}
inventory.remove(ingredient)
table.insert(difference, ingredient)
end
end
-- If the last item we added was of the same type, merge them in the queue
if #crafting_queue > 0 and crafting_queue[#crafting_queue].recipe == oldItem.recipe then
crafting_queue[#crafting_queue].count = crafting_queue[#crafting_queue].count + added
else
-- If the last item was of a different type, add a new item to the queue
table.insert(crafting_queue, {
recipe = oldItem.recipe,
count = added,
})
end
-- game.print("Saved craft "..oldItem.recipe)
end
-- Find amount of items added and remove from inventory
local new_items = inventory.get_contents()
local difference = {}
for k,v in pairs(new_items) do
local old_count = old_items[k]
local diff = v
if old_count ~= nil then
diff = diff - old_count
end
if diff > 0 then
local ingredient = {
name = k,
count = diff,
}
inventory.remove(ingredient)
table.insert(difference, ingredient)
end
end
-- Remove extra inventory slots
player.character_inventory_slots_bonus = player.character_inventory_slots_bonus - 1000
-- Remove extra inventory slots
player.character_inventory_slots_bonus = player.character_inventory_slots_bonus - 1000
global.inventory_sync.saved_crafting_queue[player.name] = {
crafting_queue = crafting_queue,
ingredients = difference,
}
end
global.inventory_sync.saved_crafting_queue[player.name] = {
crafting_queue = crafting_queue,
ingredients = difference,
}
end
end
return save_crafts
@@ -8,22 +8,22 @@ put them in ghost mode and mark the inventory as clean.
]]
function clean_dirty_inventory(player)
global.inventory_sync.players[player.name].dirty_inventory = false
global.inventory_sync.players[player.name].dirty_inventory = false
local surface = player.surface
local position = player.position
local character = player.character
player.disassociate_character(character)
character.die()
player.ticks_to_respawn = nil
player.teleport(position, surface)
local surface = player.surface
local position = player.position
local character = player.character
player.disassociate_character(character)
character.die()
player.ticks_to_respawn = nil
player.teleport(position, surface)
-- Remove player character
local character = player.character
player.set_controller {
type = defines.controllers.ghost,
}
if character ~= nil then character.destroy() end
-- Remove player character
local character = player.character
player.set_controller {
type = defines.controllers.ghost,
}
if character ~= nil then character.destroy() end
end
return clean_dirty_inventory
@@ -5,77 +5,77 @@ local save_crafts = require("modules/inventory_sync/save_crafts")
local player_stat_keys = require("modules/inventory_sync/define_player_stat_keys")
function upload_inventory(playerIndex)
local player = game.get_player(playerIndex)
local player = game.get_player(playerIndex)
if player.character == nil then
-- Panic!
log("ERROR: Player "..player.name.." quit without a character. Inventory not uploaded")
return false
end
if player.character == nil then
-- Panic!
log("ERROR: Player "..player.name.." quit without a character. Inventory not uploaded")
return false
end
local serialized_player = {
name = player.name,
inventories = {},
hotbar = {},
color = player.color,
chat_color = player.chat_color,
tag = player.tag,
-- admin = player.admin, -- This is handled by other parts of clusterio
personal_logistic_slots = {},
force = player.force.name,
cheat_mode = player.cheat_mode,
flashlight = player.is_flashlight_enabled(),
}
local serialized_player = {
name = player.name,
inventories = {},
hotbar = {},
color = player.color,
chat_color = player.chat_color,
tag = player.tag,
-- admin = player.admin, -- This is handled by other parts of clusterio
personal_logistic_slots = {},
force = player.force.name,
cheat_mode = player.cheat_mode,
flashlight = player.is_flashlight_enabled(),
}
-- Transfer player stats
for _,v in pairs(player_stat_keys) do
serialized_player[v] = player[v]
end
-- Transfer player stats
for _,v in pairs(player_stat_keys) do
serialized_player[v] = player[v]
end
-- Serialize hotbar
for i = 1, 100 do
serialized_player.hotbar[i] = {}
local slot = player.get_quick_bar_slot(i)
if slot ~= nil and slot.name ~= nil then
serialized_player.hotbar[i] = slot.name
end
end
-- Serialize hotbar
for i = 1, 100 do
serialized_player.hotbar[i] = {}
local slot = player.get_quick_bar_slot(i)
if slot ~= nil and slot.name ~= nil then
serialized_player.hotbar[i] = slot.name
end
end
-- Serialize personal logistics slots
for i = 1, 200 do -- Nobody will have more than 200 logistics slots, right?
local slot = player.get_personal_logistic_slot(i)
if slot.name ~= nil then
-- We leave [1] empty to force the JSON function to parse it as an object.
-- When its parsed as an array we get inconsistent key datatypes depending
-- on whether or not it is sparse.
serialized_player.personal_logistic_slots[i+1] = {
name = slot.name,
min = slot.min,
max = slot.max,
}
end
end
-- Serialize personal logistics slots
for i = 1, 200 do -- Nobody will have more than 200 logistics slots, right?
local slot = player.get_personal_logistic_slot(i)
if slot.name ~= nil then
-- We leave [1] empty to force the JSON function to parse it as an object.
-- When its parsed as an array we get inconsistent key datatypes depending
-- on whether or not it is sparse.
serialized_player.personal_logistic_slots[i+1] = {
name = slot.name,
min = slot.min,
max = slot.max,
}
end
end
-- Serialize inventories
for _, inv in pairs(inventories) do
local inventory = player.get_inventory(inv)
if inventory ~= nil then
local serialized_inventory = serialize.serialize_inventory(inventory)
serialized_player.inventories[inv] = serialized_inventory
end
end
-- Serialize inventories
for _, inv in pairs(inventories) do
local inventory = player.get_inventory(inv)
if inventory ~= nil then
local serialized_inventory = serialize.serialize_inventory(inventory)
serialized_player.inventories[inv] = serialized_inventory
end
end
-- Serialize crafting queue saved by /csc or /save-crafts OR automatically
save_crafts({player_index = player.name})
serialized_player.crafting_queue = global.inventory_sync.saved_crafting_queue[player.name]
if serialized_player.crafting_queue == nil then
serialized_player.crafting_queue = {}
end
-- Serialize crafting queue saved by /csc or /save-crafts OR automatically
save_crafts({player_index = player.name})
serialized_player.crafting_queue = global.inventory_sync.saved_crafting_queue[player.name]
if serialized_player.crafting_queue == nil then
serialized_player.crafting_queue = {}
end
clusterio_api.send_json("inventory_sync_upload", serialized_player)
-- Clear saved crafting queue
global.inventory_sync.saved_crafting_queue[player.name] = nil
clusterio_api.send_json("inventory_sync_upload", serialized_player)
-- Clear saved crafting queue
global.inventory_sync.saved_crafting_queue[player.name] = nil
end
return upload_inventory