mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-12 07:04:52 +09:00
162 lines
6.6 KiB
JavaScript
162 lines
6.6 KiB
JavaScript
import assert from "node:assert/strict";
|
|
|
|
import {
|
|
components, enabledComponents, mergePlayerData, stripPlayerData, scenarioComponents,
|
|
} from "../dist/node/components.js";
|
|
|
|
const allComponents = Object.keys(components);
|
|
|
|
function configWith(disabled = []) {
|
|
return { get: name => !disabled.includes(name.replace("player_sync.sync_", "")) };
|
|
}
|
|
|
|
const character = { inventories: { main: [] } };
|
|
const stored = {
|
|
generation: 1,
|
|
name: "test",
|
|
controller: "god",
|
|
cheat_mode: true,
|
|
force: "player",
|
|
color: [1, 0, 0],
|
|
chat_color: [1, 0, 0],
|
|
tag: "stored",
|
|
inventories: { main: ["stored god item"] },
|
|
quick_bar: ["stored-item"],
|
|
recipe_notifications: "stored",
|
|
};
|
|
const uploaded = {
|
|
generation: 2,
|
|
name: "test",
|
|
controller: "character",
|
|
cheat_mode: false,
|
|
force: "enemy",
|
|
color: [0, 1, 0],
|
|
chat_color: [0, 1, 0],
|
|
tag: "uploaded",
|
|
character,
|
|
crafting_queue: [],
|
|
personal_logistic_slots: [],
|
|
quick_bar: ["uploaded-item"],
|
|
recipe_notifications: "uploaded",
|
|
};
|
|
|
|
describe("player_sync components", function() {
|
|
describe("enabledComponents()", function() {
|
|
it("should enable every component by default", function() {
|
|
assert.deepEqual([...enabledComponents(configWith())], allComponents);
|
|
});
|
|
it("should leave out disabled components", function() {
|
|
const enabled = enabledComponents(configWith(["force", "quick_bar"]));
|
|
assert.equal(enabled.has("force"), false);
|
|
assert.equal(enabled.has("quick_bar"), false);
|
|
assert.equal(enabled.size, allComponents.length - 2);
|
|
});
|
|
it("should sync the controller without the inventories", function() {
|
|
const enabled = enabledComponents(configWith(["inventories"]));
|
|
assert.equal(enabled.has("controller"), true);
|
|
});
|
|
});
|
|
|
|
describe("stripPlayerData()", function() {
|
|
it("should keep everything when all components are synced", function() {
|
|
const playerData = structuredClone(uploaded);
|
|
stripPlayerData(playerData, new Set(allComponents));
|
|
assert.deepEqual(playerData, uploaded);
|
|
});
|
|
it("should remove the fields of disabled components", function() {
|
|
const playerData = structuredClone(uploaded);
|
|
stripPlayerData(playerData, new Set(allComponents.filter(c => !["appearance", "inventories"].includes(c))));
|
|
for (const key of ["color", "chat_color", "tag", "character", "crafting_queue"]) {
|
|
assert.equal(key in playerData, false, key);
|
|
}
|
|
assert.equal(playerData.force, "enemy");
|
|
});
|
|
it("should remove the god inventory with the inventories", function() {
|
|
const playerData = structuredClone(stored);
|
|
stripPlayerData(playerData, new Set(allComponents.filter(c => c !== "inventories")));
|
|
assert.equal("inventories" in playerData, false);
|
|
assert.equal(playerData.controller, "god");
|
|
});
|
|
});
|
|
|
|
describe("scenarioComponents()", function() {
|
|
it("should sync everything when no components are sent", function() {
|
|
assert.deepEqual([...scenarioComponents(undefined)], allComponents);
|
|
});
|
|
it("should sync the components marked true", function() {
|
|
const enabled = scenarioComponents({ force: true, quick_bar: true, settings: false });
|
|
assert.deepEqual([...enabled], ["force", "quick_bar"]);
|
|
});
|
|
it("should sync nothing for an empty table encoded as an array", function() {
|
|
assert.equal(scenarioComponents([]).size, 0);
|
|
});
|
|
it("should sync the controller without the inventories", function() {
|
|
assert.deepEqual([...scenarioComponents({ controller: true })], ["controller"]);
|
|
});
|
|
});
|
|
|
|
describe("mergePlayerData()", function() {
|
|
function withComponents(data, disabled) {
|
|
const enabled = allComponents.filter(c => !disabled.includes(c));
|
|
return { ...data, components: Object.fromEntries(enabled.map(c => [c, true])) };
|
|
}
|
|
|
|
it("should store the upload as is when it has no components", function() {
|
|
assert.deepEqual(mergePlayerData(stored, uploaded), uploaded);
|
|
});
|
|
it("should not store the components of the upload", function() {
|
|
assert.deepEqual(mergePlayerData(stored, withComponents(uploaded, [])), uploaded);
|
|
});
|
|
it("should keep the stored fields of disabled components", function() {
|
|
const merged = mergePlayerData(stored, withComponents(uploaded, ["force", "appearance"]));
|
|
assert.equal(merged.force, "player");
|
|
assert.deepEqual(merged.color, [1, 0, 0]);
|
|
assert.equal(merged.tag, "stored");
|
|
assert.deepEqual(merged.quick_bar, ["uploaded-item"]);
|
|
assert.equal(merged.generation, 2);
|
|
});
|
|
it("should drop disabled components without stored data", function() {
|
|
const merged = mergePlayerData(undefined, withComponents(uploaded, ["force"]));
|
|
assert.equal("force" in merged, false);
|
|
assert.equal(merged.tag, "uploaded");
|
|
});
|
|
it("should take the items but not the controller when the controller is not synced", function() {
|
|
const merged = mergePlayerData(stored, withComponents(uploaded, ["controller"]));
|
|
assert.equal(merged.controller, "god");
|
|
assert.equal(merged.cheat_mode, true);
|
|
assert.equal(merged.character, character);
|
|
assert.equal("inventories" in merged, false, "the god inventory moved to the character");
|
|
});
|
|
it("should take the items of a player without a character", function() {
|
|
const storedCharacter = {
|
|
...stored, character, crafting_queue: ["stored"], personal_logistic_slots: [{ name: "stored" }],
|
|
};
|
|
const god = { ...uploaded, controller: "god", inventories: { main: ["new god item"] } };
|
|
delete god.character;
|
|
delete god.crafting_queue;
|
|
delete god.personal_logistic_slots;
|
|
const merged = mergePlayerData(storedCharacter, withComponents(god, ["controller"]));
|
|
assert.equal("character" in merged, false);
|
|
assert.equal("crafting_queue" in merged, false);
|
|
assert.deepEqual(merged.inventories, { main: ["new god item"] });
|
|
assert.deepEqual(merged.personal_logistic_slots, [{ name: "stored" }], "nowhere to hold logistics");
|
|
});
|
|
it("should drop logistic requests a character uploaded without", function() {
|
|
const storedSlots = { ...stored, personal_logistic_slots: [{ name: "stored" }] };
|
|
const noSlots = { ...uploaded };
|
|
delete noSlots.personal_logistic_slots;
|
|
const merged = mergePlayerData(storedSlots, withComponents(noSlots, []));
|
|
assert.equal("personal_logistic_slots" in merged, false);
|
|
});
|
|
it("should take cleared logistic requests from an upload without inventories", function() {
|
|
const storedSlots = { ...stored, personal_logistic_slots: [{ name: "stored" }] };
|
|
// Factorio 1.1 serializes a character without requests as an empty table
|
|
const cleared = { ...uploaded, personal_logistic_slots: {} };
|
|
delete cleared.character;
|
|
delete cleared.crafting_queue;
|
|
const merged = mergePlayerData(storedSlots, withComponents(cleared, ["inventories"]));
|
|
assert.deepEqual(merged.personal_logistic_slots, {});
|
|
});
|
|
});
|
|
});
|