mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-13 07:04:53 +09:00
Merge pull request #519 from Hornwitser/small-things-11
Small things 11
This commit is contained in:
12 files changed
+55
-29
No files matched your search
@@ -72,6 +72,8 @@ The documentation uses the binaries provided by the packages, but for the develo
|
||||
npx clusteriohost -> node packages/host
|
||||
npx clusterioctl -> node packages/ctl
|
||||
|
||||
By default node does not enable source maps, to get stack traces pointing to the `.ts` files you will need to pass `--enable-source-maps` to `node` or set the environment variable `NODE_OPTIONS=--enable-source-maps`.
|
||||
|
||||
Note that to use `clusterioctl` you will have to create a control config first:
|
||||
|
||||
node packages/controller bootstrap create-ctl-config [admin-user]
|
||||
|
||||
@@ -260,6 +260,7 @@ async function initialize(): Promise<InitializeParameters> {
|
||||
levels,
|
||||
});
|
||||
clusterLogger.add(new DailyRotateFile({
|
||||
format: winston.format.json(),
|
||||
filename: "cluster-%DATE%.log",
|
||||
utc: true,
|
||||
dirname: path.join(args.logDirectory, "cluster"),
|
||||
@@ -269,6 +270,7 @@ async function initialize(): Promise<InitializeParameters> {
|
||||
logger.add(new DailyRotateFile({
|
||||
format: winston.format.json(),
|
||||
filename: "controller-%DATE%.log",
|
||||
utc: true,
|
||||
dirname: path.join(args.logDirectory, "controller"),
|
||||
}));
|
||||
logger.add(new winston.transports.Stream({
|
||||
|
||||
@@ -265,7 +265,7 @@ export default class Controller {
|
||||
|
||||
if (args.dev) {
|
||||
// eslint-disable-next-line node/no-missing-require
|
||||
webpackConfigs.push(require("../../../webpack.config")({})); // Path outside of build
|
||||
webpackConfigs.push(require("../../webpack.config")({})); // Path outside of build
|
||||
}
|
||||
if (args.devPlugin) {
|
||||
let devPlugins = new Map();
|
||||
|
||||
@@ -375,17 +375,26 @@ async function writeScripts(mode) {
|
||||
if (process.platform === "win32") {
|
||||
await safeOutputFile(
|
||||
"run-controller.cmd",
|
||||
"@echo off\n.\\node_modules\\.bin\\clusteriocontroller.cmd run\n"
|
||||
`\
|
||||
@echo off.
|
||||
set "NODE_OPTIONS=--enable-source-maps %NODE_OPTIONS%"
|
||||
\\node_modules\\.bin\\clusteriocontroller.cmd run
|
||||
`
|
||||
);
|
||||
} else {
|
||||
await safeOutputFile(
|
||||
"run-controller.sh",
|
||||
"#!/bin/sh\nexec ./node_modules/.bin/clusteriocontroller run\n",
|
||||
`\
|
||||
#!/bin/sh
|
||||
export "NODE_OPTIONS=--enable-source-maps $NODE_OPTIONS"
|
||||
exec ./node_modules/.bin/clusteriocontroller run
|
||||
`,
|
||||
{ mode: 0o755 },
|
||||
);
|
||||
await safeOutputFile(
|
||||
"systemd/clusteriocontroller.service",
|
||||
`[Unit]
|
||||
`\
|
||||
[Unit]
|
||||
Description=Clusterio Controller
|
||||
|
||||
[Service]
|
||||
@@ -394,6 +403,7 @@ Group=${await groupIdToName(os.userInfo().gid)}
|
||||
WorkingDirectory=${process.cwd()}
|
||||
KillMode=mixed
|
||||
KillSignal=SIGINT
|
||||
Environment=NODE_OPTIONS=--enable-source-maps
|
||||
ExecStart=${process.cwd()}/node_modules/.bin/clusteriocontroller run --log-level=warn
|
||||
|
||||
[Install]
|
||||
|
||||
@@ -214,6 +214,9 @@ class HostRouter {
|
||||
);
|
||||
}
|
||||
logger.warn(`Failed to deliver ${(message as any).name || "message"} (${message.type}): ${err.message}`);
|
||||
if (err instanceof lib.InvalidMessage && err.errors) {
|
||||
logger.warn(JSON.stringify(err.errors, null, 4));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -470,7 +473,7 @@ export default class Host extends lib.Link {
|
||||
let instanceConnection = this.instanceConnections.get(instanceId);
|
||||
this.send(
|
||||
new lib.InstanceStatusChangedEvent(
|
||||
instanceId, instanceConnection ? instanceConnection.status : "stopped", undefined
|
||||
instanceId, instanceConnection ? instanceConnection.instance.status : "stopped", undefined
|
||||
)
|
||||
);
|
||||
|
||||
@@ -490,7 +493,7 @@ export default class Host extends lib.Link {
|
||||
let instanceInfo = this.instanceInfos.get(instanceId);
|
||||
if (instanceInfo) {
|
||||
let instanceConnection = this.instanceConnections.get(instanceId);
|
||||
if (instanceConnection && ["starting", "running"].includes(instanceConnection.status)) {
|
||||
if (instanceConnection && ["starting", "running"].includes(instanceConnection.instance.status)) {
|
||||
await instanceConnection.send(new lib.InstanceStopRequest());
|
||||
}
|
||||
|
||||
@@ -530,10 +533,10 @@ export default class Host extends lib.Link {
|
||||
let hostAddress = new lib.Address(lib.Address.host, this.config.get("host.id"));
|
||||
let instanceAddress = new lib.Address(lib.Address.instance, instanceId);
|
||||
let [connectionClient, connectionServer] = lib.VirtualConnector.makePair(instanceAddress, hostAddress);
|
||||
let instanceConnection = new InstanceConnection(connectionServer, this, instanceId);
|
||||
let instance = new Instance(
|
||||
this, connectionClient, instanceInfo.path, this.config.get("host.factorio_directory"), instanceInfo.config
|
||||
);
|
||||
let instanceConnection = new InstanceConnection(connectionServer, this, instance);
|
||||
|
||||
this.instanceConnections.set(instanceId, instanceConnection);
|
||||
await instance.init(this.pluginInfos);
|
||||
@@ -750,13 +753,6 @@ export default class Host extends lib.Link {
|
||||
});
|
||||
}
|
||||
|
||||
async stopInstance(instanceId: number) {
|
||||
let instanceConnection = this.instanceConnections.get(instanceId);
|
||||
if (instanceConnection) {
|
||||
await instanceConnection.send(new lib.InstanceStopRequest());
|
||||
}
|
||||
}
|
||||
|
||||
async handleInstanceDeleteInternalRequest(request: lib.InstanceDeleteInternalRequest) {
|
||||
let instanceId = request.instanceId;
|
||||
if (this.instanceConnections.has(instanceId)) {
|
||||
@@ -786,7 +782,7 @@ export default class Host extends lib.Link {
|
||||
let instanceConnection = this.instanceConnections.get(instanceId);
|
||||
list.push(new lib.RawInstanceInfo(
|
||||
instanceInfo.config.serialize("controller"),
|
||||
instanceConnection ? instanceConnection.status : "stopped",
|
||||
instanceConnection ? instanceConnection.instance.status : "stopped",
|
||||
));
|
||||
}
|
||||
await this.send(new lib.InstancesUpdateRequest(list));
|
||||
@@ -828,9 +824,9 @@ export default class Host extends lib.Link {
|
||||
}
|
||||
this._shuttingDown = true;
|
||||
|
||||
for (let instanceId of this.instanceConnections.keys()) {
|
||||
for (let instanceConnection of this.instanceConnections.values()) {
|
||||
try {
|
||||
await this.stopInstance(instanceId);
|
||||
await instanceConnection.instance.stop();
|
||||
} catch (err: any) {
|
||||
logger.error(`Unexpected error stopping instance:\n${err.stack}`);
|
||||
}
|
||||
|
||||
@@ -592,7 +592,11 @@ rcon.print(game.table_to_json(players))`.replace(/\r?\n/g, " ");
|
||||
* factorio_settings config entry.
|
||||
*/
|
||||
async writeServerSettings() {
|
||||
let serverSettings = await this.resolveServerSettings(this.config.get("factorio.settings"));
|
||||
const warning = "Changes to this file will be overwitten by the factorio.settings config on the instance.";
|
||||
const serverSettings = {
|
||||
"_comment_warning": warning,
|
||||
...await this.resolveServerSettings(this.config.get("factorio.settings")),
|
||||
};
|
||||
await lib.safeOutputFile(
|
||||
this.server.writePath("server-settings.json"),
|
||||
JSON.stringify(serverSettings, null, 4)
|
||||
|
||||
@@ -5,12 +5,11 @@ import type Instance from "./Instance";
|
||||
|
||||
export default class InstanceConnection extends lib.Link {
|
||||
plugins = new Map<string, string>();
|
||||
status: Instance["status"] = "stopped";
|
||||
|
||||
constructor(
|
||||
connector: lib.VirtualConnector,
|
||||
public host: Host,
|
||||
public instanceId: number
|
||||
public instance: Instance,
|
||||
) {
|
||||
super(connector);
|
||||
this.router = this.host.router;
|
||||
@@ -24,9 +23,8 @@ export default class InstanceConnection extends lib.Link {
|
||||
}
|
||||
|
||||
async snoopInstanceStatusChangedEvent(event: lib.InstanceStatusChangedEvent) {
|
||||
this.status = event.status as Instance["status"];
|
||||
if (this.status === "stopped") {
|
||||
this.host.instanceConnections.delete(this.instanceId);
|
||||
if (this.instance.status === "stopped") {
|
||||
this.host.instanceConnections.delete(this.instance.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,11 @@
|
||||
* @returns sections parsed from the ini file.
|
||||
*/
|
||||
export function parse(input: string) {
|
||||
// Ignore BOM at the start of the file
|
||||
if (input[0] === "\uFEFF") {
|
||||
input = input.slice(1);
|
||||
}
|
||||
|
||||
const sections: Record<string, string | Record<string, string>> = {};
|
||||
let currentSection: Record<string, string> = sections as Record<string, string>;
|
||||
const lines = input.split(/\r\n|\n/);
|
||||
|
||||
@@ -11,8 +11,8 @@ import type { User } from "../users";
|
||||
import type { AddressType, JSONDeserialisable, MessageRoutable, MessageRequest, MessageEvent } from "../data";
|
||||
|
||||
export interface Request<Req, Res> {
|
||||
constructor: Partial<JSONDeserialisable<Request<Req, Res>>> & {
|
||||
new (...args: any): Request<Req, Res>,
|
||||
constructor: Partial<JSONDeserialisable<Req & Request<Req, Res>>> & {
|
||||
new (...args: any): Req & Request<Req, Res>,
|
||||
name: string,
|
||||
type: "request";
|
||||
src: AddressType | readonly AddressType[];
|
||||
@@ -25,8 +25,8 @@ export interface Request<Req, Res> {
|
||||
export type RequestClass<Req, Res> = Request<Req, Res>["constructor"];
|
||||
|
||||
export interface Event<T> {
|
||||
constructor: Partial<JSONDeserialisable<Event<T>>> & {
|
||||
new (...args: any): Event<T>,
|
||||
constructor: Partial<JSONDeserialisable<T & Event<T>>> & {
|
||||
new (...args: any): T & Event<T>,
|
||||
name: string,
|
||||
type: "event";
|
||||
src: AddressType | readonly AddressType[];
|
||||
|
||||
@@ -215,7 +215,7 @@ export class SubscriptionController {
|
||||
* Channels are an optional feature which can be implemented to only get notifications of reliant updates
|
||||
* Multiple handlers can be subscribed at the same time, on the same or different channels
|
||||
*/
|
||||
export class EventSubscriber<T, V=T> {
|
||||
export class EventSubscriber<T extends Event<T>, V=T> {
|
||||
_callbacks = new Array<EventSubscriberCallback<V>>();
|
||||
_channelCallbacks = new Map<string | number, Array<EventSubscriberCallback<V>>>();
|
||||
lastResponse: Event<T> | null = null;
|
||||
@@ -365,7 +365,7 @@ export class EventSubscriber<T, V=T> {
|
||||
));
|
||||
|
||||
if (response.eventReplay) {
|
||||
await this._handle(response.eventReplay);
|
||||
await this._handle(response.eventReplay as any);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
[spam]
|
||||
foo=bar
|
||||
@@ -1,5 +1,6 @@
|
||||
"use strict";
|
||||
const assert = require("assert").strict;
|
||||
const fs = require("fs-extra");
|
||||
const lib = require("@clusterio/lib");
|
||||
|
||||
describe("lib/ini", function() {
|
||||
@@ -58,6 +59,12 @@ describe("lib/ini", function() {
|
||||
new Error("Duplicated key key on line 2")
|
||||
);
|
||||
});
|
||||
it("should parse a file with BOM", async function() {
|
||||
assert.deepEqual(
|
||||
lib.parse(await fs.readFile("test/file/bom.cfg", "utf8")),
|
||||
{ spam: { foo: "bar" }},
|
||||
);
|
||||
});
|
||||
});
|
||||
describe("stringify()", function() {
|
||||
it("should serialize to reference output", function() {
|
||||
|
||||
Reference in new issue
Block a user