mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-11 15:04:52 +09:00
Reimplement core method for crafting_queue sync
* New method avoids all dataloss and prefectly replicates the queue * Made proper description in readme * Added packages to make lerna build happy * Added reference to main readme
This commit is contained in:
1 parent
87218e4803
commit
a4a667ef06
7 files changed
+91
-43
No files matched your search
@@ -72,6 +72,7 @@ These are the plugins supported and maintained by the Clusterio developers:
|
||||
- [Statistics Exporter](/plugins/statistics_exporter/README.md): collect in-game statistics from all the servers and makes it available to the Prometheus endpoint on the master server.
|
||||
- [Subspace Storage](https://github.com/clusterio/subspace_storage): Provide shared storage that can transport items between servers via teleport chests.
|
||||
- [Player Auth](/plugins/player_auth/README.md): Provides authentication to the cluster via logging into a Factorio server.
|
||||
- [Inventory Sync](/plugins/inventory_sync/README.md): Synchronizes your inventory between servers.
|
||||
|
||||
There's also plugins developed and maintained by the community:
|
||||
|
||||
|
||||
@@ -2,6 +2,12 @@
|
||||
|
||||
Carry over player inventory between servers
|
||||
|
||||
As a player, it mostly just works. Most important to know is that factorio data transfer is slow, which means if you have "big" items (blueprints mostly) in your inventory it will take a long time to transfer when joining servers. For this reason it is recommended to keep blueprints in the blueprint library.
|
||||
|
||||
A note on crashing servers:
|
||||
|
||||
When a server crashes while you are online there won't be time to immediately upload the inventory. Instead, the inventory is uploaded as soon as the server restarts. This means if you have been playing on a different server from the one that crashed and gathered/consumed items but are offline at the time of the first server coming online again your inventory will reset to the autosave.
|
||||
|
||||
## Installation
|
||||
|
||||
Run the following commands in the folder Clusterio is installed to:
|
||||
@@ -9,11 +15,11 @@ Run the following commands in the folder Clusterio is installed to:
|
||||
npm install @clusterio/plugin-inventory_sync
|
||||
npx clusteriomaster plugin add @clusterio/plugin-inventory_sync
|
||||
|
||||
Substitute clusteriomaster with clusterioslave or clusterioctl if this a dedicate slave or ctl installation respectively.
|
||||
Substitute clusteriomaster with clusterioslave or clusterioctl if this a dedicated slave or ctl installation respectively.
|
||||
|
||||
## Method of operation
|
||||
|
||||
This plugin does even based synchronization of inventories. The data flow is as follows:
|
||||
This plugin does event based synchronization of inventories. The data flow is as follows:
|
||||
|
||||
1. Player joins server, gets put in spectator mode
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ inventory_sync.events[defines.events.on_player_joined_game] = function(event)
|
||||
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_player_left_game] = function(event)
|
||||
inventory_sync.events[defines.events.on_pre_player_left_game] = function(event)
|
||||
local playerIndex = event.player_index
|
||||
inventory_sync.uploadInventory(playerIndex)
|
||||
global.download_cache[playerIndex] = "" -- Clear cache to avoid leaking memory to people quitting during download
|
||||
|
||||
@@ -3,33 +3,28 @@ function load_crafting_queue(crafting_queue, player)
|
||||
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 + 100
|
||||
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
|
||||
|
||||
-- Load crafting queue
|
||||
for _, queueItem in pairs(crafting_queue) do
|
||||
for _, queueItem in pairs(crafting_queue.crafting_queue) do
|
||||
local recipe = game.recipe_prototypes[queueItem.recipe]
|
||||
game.print("Crafting "..queueItem.recipe)
|
||||
-- Add items to inventory
|
||||
for _, item in pairs(recipe.ingredients) do
|
||||
local count = math.floor(item.amount * queueItem.count / math.max(recipe.main_product.amount, 1))
|
||||
if count > 0 then
|
||||
inventory.insert({
|
||||
name = item.name,
|
||||
count = count,
|
||||
})
|
||||
end
|
||||
end
|
||||
-- game.print("Crafting "..queueItem.recipe)
|
||||
|
||||
-- Start crafting (consume items)
|
||||
player.begin_crafting {
|
||||
count = queueItem.count,
|
||||
recipe = queueItem.recipe,
|
||||
silent = true, -- Fail silently if items are missing
|
||||
-- silent = true, -- Fail silently if items are missing
|
||||
}
|
||||
end
|
||||
|
||||
-- Remove extra inventory slots
|
||||
player.character_inventory_slots_bonus = player.character_inventory_slots_bonus - 100
|
||||
player.character_inventory_slots_bonus = player.character_inventory_slots_bonus - 1000
|
||||
end
|
||||
|
||||
return load_crafting_queue
|
||||
@@ -9,46 +9,87 @@ function save_crafts(event)
|
||||
return
|
||||
end
|
||||
|
||||
-- Serialize crafting queue
|
||||
if player.crafting_queue == nil then
|
||||
player.print("You can't save nothing, you silly goose")
|
||||
return
|
||||
end
|
||||
for _, queueItem in pairs(player.crafting_queue) do
|
||||
crafting_queue[queueItem.index] = {
|
||||
count = queueItem.count,
|
||||
recipe = queueItem.recipe,
|
||||
}
|
||||
end
|
||||
|
||||
-- Give player some more inventory space to avoid duplicating items
|
||||
player.character_inventory_slots_bonus = player.character_inventory_slots_bonus + 100
|
||||
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()
|
||||
|
||||
-- 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]
|
||||
local recipe = game.recipe_prototypes[queueItem.recipe]
|
||||
|
||||
|
||||
-- Cancel craft
|
||||
player.cancel_crafting {
|
||||
index = 1,
|
||||
count = 1,
|
||||
}
|
||||
|
||||
-- Remove ingredients from inventory
|
||||
for _, item in pairs(recipe.ingredients) do
|
||||
local inventory = player.get_main_inventory()
|
||||
inventory.remove({
|
||||
name = item.name,
|
||||
count = item.amount,
|
||||
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
|
||||
|
||||
-- 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("Canceled craft "..recipe.name)
|
||||
-- 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 - 100
|
||||
player.character_inventory_slots_bonus = player.character_inventory_slots_bonus - 1000
|
||||
|
||||
global["saved_crafting_queue_"..player.name] = crafting_queue
|
||||
global["saved_crafting_queue_"..player.name] = {
|
||||
crafting_queue = crafting_queue,
|
||||
ingredients = difference,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
local clusterio_api = require("modules/clusterio/api")
|
||||
local serialize = require("modules/clusterio/serialize")
|
||||
local inventories = require("modules/inventory_sync/define_player_inventories")
|
||||
local save_crafts = require("modules/inventory_sync/save_crafts")
|
||||
|
||||
function upload_inventory(playerIndex)
|
||||
local player = game.players[playerIndex]
|
||||
@@ -68,7 +69,8 @@ function upload_inventory(playerIndex)
|
||||
end
|
||||
end
|
||||
|
||||
-- Serialize crafting queue saved by /csc or /save-crafts
|
||||
-- Serialize crafting queue saved by /csc or /save-crafts OR automatically
|
||||
save_crafts({player_index = player.name})
|
||||
serialized_player.crafting_queue = global["saved_crafting_queue_"..player.name]
|
||||
if serialized_player.crafting_queue == nil then
|
||||
serialized_player.crafting_queue = {}
|
||||
|
||||
@@ -22,6 +22,9 @@
|
||||
"devDependencies": {
|
||||
"@clusterio/lib": "^2.0.0-alpha.6",
|
||||
"@clusterio/web_ui": "^2.0.0-alpha.6",
|
||||
"antd": "^4.16.0",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"webpack": "^5.36.2",
|
||||
"webpack-cli": "^4.7.0",
|
||||
"webpack-merge": "^5.2.0"
|
||||
|
||||
Reference in new issue
Block a user