@haelp/teto
Version:
A typescript-based controllable TETR.IO client.
143 lines (142 loc) • 4.13 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "AdapterIO", {
enumerable: true,
get: function() {
return AdapterIO;
}
});
const _ = require("..");
const _core = require("./core");
const _chalk = /*#__PURE__*/ _interop_require_default(require("chalk"));
const _child_process = require("child_process");
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
class AdapterIO extends _core.Adapter {
static defaultConfig = {
name: "AdapterIO",
verbose: false,
env: {},
args: []
};
log(msg, { force = false, level = "info" } = {
force: false,
level: "info"
}) {
if (!this.cfg.verbose && !force) return;
const func = level === "info" ? _chalk.default.blue : level === "warning" ? _chalk.default.yellow : _chalk.default.red;
console[level === "error" ? "error" : "log"](`${func(`[${this.cfg.name}]`)} ${msg}`);
}
cfg;
events = new _.EventEmitter();
dead = false;
#dataBuffer = "";
process;
constructor(config){
super();
if (!config.path) {
throw new Error("AdapterIO requires a path to the binary executable.");
}
this.cfg = {
...AdapterIO.defaultConfig,
...config
};
}
#start() {
this.process = (0, _child_process.spawn)(this.cfg.path, this.cfg.args, {
env: this.cfg.env,
stdio: [
"pipe",
"pipe",
"pipe"
]
});
this.process.stderr.on("data", (data)=>{
this.log("Error: " + data.toString(), {
level: "error",
force: true
});
});
this.process.stdout.on("data", (message)=>this.#handle(message));
}
initialize() {
return new Promise((resolve)=>{
this.events.once("info", (info)=>{
this.log("READY");
resolve(info);
});
this.#start();
});
}
send(message) {
if (this.dead) return;
this.process.stdin.write(JSON.stringify(message) + "\n");
this.log("OUTGOING:\n" + JSON.stringify(message, null, 2));
}
#handle(message) {
const text = message.toString();
this.#dataBuffer += text;
let newlineIndex;
while((newlineIndex = this.#dataBuffer.indexOf("\n")) >= 0){
const line = this.#dataBuffer.slice(0, newlineIndex);
this.#dataBuffer = this.#dataBuffer.slice(newlineIndex + 1);
if (line === "") continue;
try {
const message = JSON.parse(line.trim());
this.log("INCOMING:\n" + JSON.stringify(message, null, 2));
this.events.emit(message.type, message);
} catch {
this.log(line);
}
}
}
config(engine, data) {
this.send({
type: "config",
...this.configFromEngine(engine),
data
});
}
update(engine, data) {
this.send({
type: "state",
...this.stateFromEngine(engine),
data
});
}
addPieces(pieces, data) {
this.send({
type: "pieces",
pieces,
data
});
}
play(engine, data) {
this.send({
type: "play",
...this.playFromEngine(engine),
data
});
return new Promise((resolve)=>{
this.events.once("move", (move)=>{
resolve(move);
});
});
}
stop() {
this.process.kill("SIGINT");
this.events.removeAllListeners();
this.process.removeAllListeners();
this.process.stdout.removeAllListeners();
this.process.stderr.removeAllListeners();
this.process.stdin.removeAllListeners();
this.process.unref();
this.dead = true;
}
}
//# sourceMappingURL=adapter-io.js.map