mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-15 23:24:52 +09:00
Close the remaining ways an accepted import fails to restore
Imports no longer accept the cutscene controller, which needs waypoints to restore. Logistic filters and the basic item stack fields now have the types and limits Factorio enforces, and the inventory summary skips malformed items and counts repeated exported items once instead of expanding them. Lua's JSON loses precision past 2^50, so a generation there could no longer be counted up and uploads were discarded. Imports now start over from generation 1 when the stored or imported generation is at that limit. Instances holding a copy from another epoch take the stored generation instead of keeping their own higher one when there is no data to download. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
9ecd497f1e
commit
39df22be65
6 files changed
+167
-20
No files matched your search
@@ -76,7 +76,15 @@ describe("player_sync plugin", function() {
|
||||
character_additional_mining_categories: {},
|
||||
allow_dispatching_robots: true,
|
||||
inventories: {
|
||||
main: { b: 80, i: [{ n: "iron-plate", c: 100, r: 2 }, { s: 10, f: { name: "coal" } }] },
|
||||
main: { b: 80, i: [
|
||||
{ n: "iron-plate", c: 100, r: 2 },
|
||||
{ s: 10, f: { name: "coal" } },
|
||||
{ f: { quality: "rare", comparator: "=" } },
|
||||
{ f: "stone" },
|
||||
{ n: "firearm-magazine", c: 10, q: "rare", a: 5 },
|
||||
{ n: "automation-science-pack", c: 3, d: 0.5, p: 0.25, h: 0.75 },
|
||||
{ e: "0eNq" },
|
||||
] },
|
||||
armor: { i: {} },
|
||||
},
|
||||
},
|
||||
@@ -87,7 +95,19 @@ describe("player_sync plugin", function() {
|
||||
group: "",
|
||||
active: true,
|
||||
multiplier: 1,
|
||||
filters: [{ value: { name: "iron-plate", type: "item" }, min: 3 }],
|
||||
// Empty slots export as {}
|
||||
filters: [
|
||||
{},
|
||||
{ value: { name: "iron-plate", type: "item" }, min: 3 },
|
||||
{ value: { name: "stone", type: "item" }, min: -5, max: 10 },
|
||||
{
|
||||
value: { name: "coal", type: "item", quality: "normal", comparator: "=" },
|
||||
min: 5,
|
||||
max: 10,
|
||||
minimum_delivery_count: 2,
|
||||
import_from: null,
|
||||
},
|
||||
],
|
||||
}],
|
||||
},
|
||||
quick_bar: {
|
||||
@@ -124,6 +144,7 @@ describe("player_sync plugin", function() {
|
||||
for (const [field, value] of [
|
||||
["controller", "not-a-controller"],
|
||||
["controller", "remote"],
|
||||
["controller", "cutscene"],
|
||||
["deleted", false],
|
||||
["deleted", true],
|
||||
["color", "red"],
|
||||
@@ -131,6 +152,10 @@ describe("player_sync plugin", function() {
|
||||
["ticks_to_respawn", -1],
|
||||
["inventories", { main: { i: "iron-plate" } }],
|
||||
["inventories", { main: [] }],
|
||||
["inventories", { main: { i: [{ e: null }] } }],
|
||||
["inventories", { main: { i: [{ n: 5, c: 1 }] } }],
|
||||
["inventories", { main: { i: [{ n: "wood", c: "many" }] } }],
|
||||
["inventories", { main: { i: [{ n: "wood", c: 0 }] } }],
|
||||
["character", { inventories: { main: { i: [{ s: 0 }] } } }],
|
||||
["shortcuts", { "toggle-personal-roboport": "yes" }],
|
||||
["character", { character_health_bonus: "100" }],
|
||||
@@ -157,6 +182,25 @@ describe("player_sync plugin", function() {
|
||||
]) {
|
||||
assert(!accepts({ ...exported, [field]: value }), `accepted ${field} ${JSON.stringify(value)}`);
|
||||
}
|
||||
for (const filter of [
|
||||
{ value: { name: "iron-plate" }, min: "many" },
|
||||
{ value: { name: "iron-plate" }, min: 2 ** 31 },
|
||||
{ value: { name: "iron-plate" }, max: -1 },
|
||||
{ value: { name: "iron-plate" }, minimum_delivery_count: -1 },
|
||||
{ value: { type: "item" }, min: 1 },
|
||||
{ value: { name: "iron-plate", type: "nope" }, min: 1 },
|
||||
{ value: { name: "iron-plate", comparator: "~" }, min: 1 },
|
||||
{ value: { name: "iron-plate", quality: 5 }, min: 1 },
|
||||
]) {
|
||||
const slots = {
|
||||
enabled: true,
|
||||
trash_not_requested: false,
|
||||
sections: [{ group: "", active: true, multiplier: 1, filters: [filter] }],
|
||||
};
|
||||
assert(
|
||||
!accepts({ ...exported, personal_logistic_slots: slots }), `accepted ${JSON.stringify(filter)}`,
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
it("SetPlayerDataResponse should be round trip json serialisable", function() {
|
||||
@@ -184,10 +228,27 @@ describe("player_sync plugin", function() {
|
||||
] }), [
|
||||
{ name: "iron-plate", quality: undefined, count: 307 },
|
||||
{ name: "iron-plate", quality: "rare", count: 50 },
|
||||
{ name: "exported item", count: 1, exportSize: 4 },
|
||||
{ name: "exported item", count: 1, exportSize: 4 },
|
||||
{ name: "exported item", count: 2, exportSize: 4 },
|
||||
]);
|
||||
});
|
||||
it("should skip malformed entries", function() {
|
||||
assert.deepEqual(summarizeInventory({ i: [
|
||||
{ e: null },
|
||||
null,
|
||||
"wood",
|
||||
{ n: 5, c: 1 },
|
||||
{ n: "wood", c: "many", r: "x" },
|
||||
{ n: "wood", c: 2, r: 1 },
|
||||
{ e: "0eNq", r: 1e9 },
|
||||
] }), [
|
||||
{ name: "wood", quality: undefined, count: 4 },
|
||||
{ name: "exported item", count: 1e9 + 1, exportSize: 4 },
|
||||
]);
|
||||
assert.deepEqual(
|
||||
summarizePlayerInventories(playerData("player", 1, { inventories: { main: null } })),
|
||||
[{ name: "main", items: [] }],
|
||||
);
|
||||
});
|
||||
it("should handle empty inventories", function() {
|
||||
assert.deepEqual(summarizeInventory({}), []);
|
||||
assert.deepEqual(summarizeInventory(JSON.parse('{"i":{}}')), []);
|
||||
|
||||
Reference in new issue
Block a user