mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-11 15:04:52 +09:00
Restore pre-2.0 logistic slots and bound imported stats
Logistic slots saved before 2.0 are keyed by index strings, which json_to_table keeps as strings, so the migration branch never ran and the 2.0 branch failed on the missing sections. Detect the old format by the missing sections and convert the keys to numbers. The import schema now uses the minimums Factorio enforces for character stats, checks the filter value type and the quick bar comparator, and allows filters without quality or comparator. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
c06555c5da
commit
5ca10d579d
3 files changed
+34
-16
No files matched your search
@@ -23,8 +23,8 @@ export type IpcPlayerData = {
|
||||
character?: any,
|
||||
inventories?: any,
|
||||
quick_bar?: any,
|
||||
hotbar?: string[],
|
||||
personal_logistic_slots?: {name:string, min:number, max:number}[],
|
||||
hotbar?: Record<string, string>,
|
||||
personal_logistic_slots?: any,
|
||||
crafting_queue?: any,
|
||||
recipe_notifications?: string,
|
||||
// Components the upload was serialized with, all when missing
|
||||
@@ -54,22 +54,22 @@ const jsonColor = Type.Union([
|
||||
Type.Object({ r: Type.Number(), g: Type.Number(), b: Type.Number(), a: Type.Optional(Type.Number()) }),
|
||||
Type.Array(Type.Number(), { minItems: 3, maxItems: 4 }),
|
||||
]);
|
||||
// module/define_player_stat_keys.lua, missing stats are left as they are
|
||||
// Missing stats are left as they are, the minimums are the ones Factorio enforces
|
||||
const jsonCharacter = Type.Object({
|
||||
character_crafting_speed_modifier: Type.Optional(Type.Number()),
|
||||
character_mining_speed_modifier: Type.Optional(Type.Number()),
|
||||
character_crafting_speed_modifier: Type.Optional(Type.Number({ minimum: -1 })),
|
||||
character_mining_speed_modifier: Type.Optional(Type.Number({ minimum: -1 })),
|
||||
character_additional_mining_categories: Type.Optional(jsonList(Type.String())),
|
||||
character_running_speed_modifier: Type.Optional(Type.Number()),
|
||||
character_running_speed_modifier: Type.Optional(Type.Number({ minimum: -1 })),
|
||||
character_build_distance_bonus: Type.Optional(Type.Number()),
|
||||
character_item_drop_distance_bonus: Type.Optional(Type.Number()),
|
||||
character_reach_distance_bonus: Type.Optional(Type.Number()),
|
||||
character_resource_reach_distance_bonus: Type.Optional(Type.Number()),
|
||||
character_item_pickup_distance_bonus: Type.Optional(Type.Number()),
|
||||
character_loot_pickup_distance_bonus: Type.Optional(Type.Number()),
|
||||
character_inventory_slots_bonus: Type.Optional(Type.Number()),
|
||||
character_trash_slot_count_bonus: Type.Optional(Type.Number()),
|
||||
character_maximum_following_robot_count_bonus: Type.Optional(Type.Number()),
|
||||
character_health_bonus: Type.Optional(Type.Number()),
|
||||
character_inventory_slots_bonus: Type.Optional(Type.Integer({ minimum: 0 })),
|
||||
character_trash_slot_count_bonus: Type.Optional(Type.Integer({ minimum: 0 })),
|
||||
character_maximum_following_robot_count_bonus: Type.Optional(Type.Integer({ minimum: 0 })),
|
||||
character_health_bonus: Type.Optional(Type.Number({ minimum: 0 })),
|
||||
character_personal_logistic_requests_enabled: Type.Optional(Type.Boolean()),
|
||||
allow_dispatching_robots: Type.Optional(Type.Boolean()),
|
||||
inhibit_movement_bonus: Type.Optional(Type.Boolean()),
|
||||
@@ -88,7 +88,7 @@ const jsonPersonalLogisticSlots = Type.Union([
|
||||
group: Type.String(),
|
||||
active: Type.Boolean(),
|
||||
multiplier: Type.Number({ minimum: 0 }),
|
||||
filters: jsonList(Type.Object({})),
|
||||
filters: jsonList(Type.Object({ value: Type.Optional(Type.Object({})) })),
|
||||
})),
|
||||
}),
|
||||
// From before 2.0, slot index to request
|
||||
@@ -98,7 +98,12 @@ const jsonPersonalLogisticSlots = Type.Union([
|
||||
// QuickBarSlotEncoded in module/serialize.lua
|
||||
const jsonQuickBarSlot = Type.Union([
|
||||
Type.String(),
|
||||
Type.Object({ t: Type.Literal("f"), n: Type.String(), q: Type.String(), c: Type.String() }),
|
||||
Type.Object({
|
||||
t: Type.Literal("f"),
|
||||
n: Type.String(),
|
||||
q: Type.Optional(Type.String()),
|
||||
c: Type.Optional(StringEnum(["=", ">", "<", "≥", ">=", "≤", "<=", "≠", "!="])),
|
||||
}),
|
||||
Type.Object({
|
||||
t: Type.Literal("i"),
|
||||
n: Type.String(),
|
||||
|
||||
@@ -346,13 +346,13 @@ function serialize.deserialize_personal_logistic_slots(player, serialized)
|
||||
logistic_point.remove_section(i)
|
||||
end
|
||||
|
||||
-- If this is an array instead of a table, migrate to v2 format
|
||||
-- Data from before 2.0 maps slot indices to requests, migrate it to a section
|
||||
if next(serialized) == nil then
|
||||
return
|
||||
elseif serialized[1] ~= nil then
|
||||
elseif serialized.sections == nil then
|
||||
local section = logistic_point.add_section()
|
||||
for i, slot in pairs(serialized) do
|
||||
section.set_slot(i, {
|
||||
section.set_slot(tonumber(i), {
|
||||
value = {
|
||||
name = slot.name,
|
||||
quality = "normal",
|
||||
|
||||
@@ -75,7 +75,12 @@ describe("player_sync plugin", function() {
|
||||
personal_logistic_slots: {
|
||||
enabled: true,
|
||||
trash_not_requested: false,
|
||||
sections: [{ group: "", active: true, multiplier: 1, filters: [{ index: 1, min: 50 }] }],
|
||||
sections: [{
|
||||
group: "",
|
||||
active: true,
|
||||
multiplier: 1,
|
||||
filters: [{ value: { name: "iron-plate", type: "item" }, min: 3 }],
|
||||
}],
|
||||
},
|
||||
quick_bar: {
|
||||
1: "iron-plate",
|
||||
@@ -118,6 +123,9 @@ describe("player_sync plugin", function() {
|
||||
["character", { inventories: { main: { i: [{ s: 0 }] } } }],
|
||||
["shortcuts", { "toggle-personal-roboport": "yes" }],
|
||||
["character", { character_health_bonus: "100" }],
|
||||
["character", { character_inventory_slots_bonus: -1 }],
|
||||
["character", { character_crafting_speed_modifier: -5 }],
|
||||
["quick_bar", { 1: { t: "f", n: "iron-plate", q: "normal", c: "~" } }],
|
||||
["crafting_queue", {}],
|
||||
["crafting_queue", { crafting_queue: [], crafting_queue_progress: 0 }],
|
||||
["crafting_queue", {
|
||||
@@ -129,6 +137,11 @@ describe("player_sync plugin", function() {
|
||||
["personal_logistic_slots", { enabled: true, sections: [] }],
|
||||
["personal_logistic_slots", { enabled: true, trash_not_requested: false, sections: [{}] }],
|
||||
["personal_logistic_slots", { 1: { min: 50 } }],
|
||||
["personal_logistic_slots", {
|
||||
enabled: true,
|
||||
trash_not_requested: false,
|
||||
sections: [{ group: "", active: true, multiplier: 1, filters: [{ value: 5 }] }],
|
||||
}],
|
||||
]) {
|
||||
assert(!accepts({ ...exported, [field]: value }), `accepted ${field} ${JSON.stringify(value)}`);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user