UNPKG

@clusterio/plugin-subspace_storage

Version:

Clusterio plugin for sharing storage between Factorio servers

147 lines 6.68 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.InstancePlugin = void 0; const lib = __importStar(require("@clusterio/lib")); const host_1 = require("@clusterio/host"); const messages_1 = require("./messages"); class InstancePlugin extends host_1.BaseInstancePlugin { pendingTasks; pingId; timeUpdateId; cachedInventoryItems = []; unexpectedError(err) { this.logger.error(`Unexpected error:\n${err.stack}`); } async init() { if (!this.instance.config.get("factorio.enable_script_commands")) { throw new Error("subspace_storage plugin requires script commands."); } this.pendingTasks = new Set(); this.instance.server.on("ipc-subspace_storage:output", (output) => { this.logger.info("Received output items:"); this.logger.info(JSON.stringify(output)); this.provideItems(output).catch(err => this.unexpectedError(err)); }); this.instance.server.on("ipc-subspace_storage:orders", (orders) => { if (this.instance.status !== "running" || !this.host.connected) { return; } let task = this.requestItems(orders).catch(err => this.unexpectedError(err)); this.pendingTasks.add(task); task.finally(() => { this.pendingTasks.delete(task); }); }); this.instance.handle(messages_1.UpdateStorageEvent, this.handleUpdateStorageEvent.bind(this)); } async onStart() { this.pingId = setInterval(() => { if (!this.host.connected) { return; // Only ping if we are actually connected to the controller. } this.sendRcon("/sc __subspace_storage__ global.ticksSinceMasterPinged = 0", true).catch(err => this.unexpectedError(err)); }, 5000); let items = await this.instance.sendTo("controller", new messages_1.GetStorageRequest()); // Cache items for periodic time updates this.cachedInventoryItems = items; // Ensure a payload with updated time is sent every second this.timeUpdateId = setInterval(() => { if (this.instance.status !== "running") { return; } const payloadItems = [ ...this.cachedInventoryItems, new messages_1.Item("signal-unixtime", Math.floor(Date.now() / 1000), "normal"), ]; const payloadJson = lib.escapeString(JSON.stringify(payloadItems)); const task = this.sendRcon(`/sc __subspace_storage__ UpdateInvData("${payloadJson}")`, true) .catch(err => this.unexpectedError(err)); this.pendingTasks.add(task); task.finally(() => { this.pendingTasks.delete(task); }); }, 1000); } async onStop() { clearInterval(this.pingId); clearInterval(this.timeUpdateId); await Promise.all(this.pendingTasks); } onExit() { clearInterval(this.pingId); clearInterval(this.timeUpdateId); } // provide items -------------------------------------------------------------- async provideItems(items) { if (!this.host.connector.hasSession) { // For now the items are voided if the controller connection is // down, which is no different from the previous behaviour. if (this.instance.config.get("subspace_storage.log_item_transfers")) { this.logger.verbose("Voided the following items:"); this.logger.verbose(JSON.stringify(items)); } return; } const fromIpcItems = items.map(item => new messages_1.Item(item[0], item[1], item[2])); this.instance.sendTo("controller", new messages_1.PlaceEvent(fromIpcItems)); if (this.instance.config.get("subspace_storage.log_item_transfers")) { this.logger.verbose("Exported the following to controller:"); this.logger.verbose(JSON.stringify(items)); } } // request items -------------------------------------------------------------- async requestItems(requestItems) { this.logger.info(`Requesting items: ${JSON.stringify(requestItems)}`); // Request the items all at once const fromIpcItems = requestItems.map(item => new messages_1.Item(item[0], item[1], item[2])); let items = await this.instance.sendTo("controller", new messages_1.RemoveRequest(fromIpcItems)); if (!items.length) { return; } if (this.instance.config.get("subspace_storage.log_item_transfers")) { this.logger.verbose("Imported following from controller:"); this.logger.verbose(JSON.stringify(items)); } let itemsJson = lib.escapeString(JSON.stringify(items)); await this.sendRcon(`/sc __subspace_storage__ Import("${itemsJson}")`, true); } // combinator signals --------------------------------------------------------- async handleUpdateStorageEvent(event) { if (this.instance.status !== "running") { return; } // Cache latest inventory from controller this.cachedInventoryItems = event.items; } } exports.InstancePlugin = InstancePlugin; //# sourceMappingURL=instance.js.map