diff --git a/src/entity/commands/dispatcher.ts b/src/entity/commands/dispatcher.ts index e57fec7..59cdfb4 100644 --- a/src/entity/commands/dispatcher.ts +++ b/src/entity/commands/dispatcher.ts @@ -31,6 +31,7 @@ import GeneralKillCommand from "./general/general _kill"; import GeneralSendCommand from "./general/general _command"; import GeneralRestartCommand from "./general/general _restart"; import DockerStartCommand from "./docker/docker _start"; +import DockerResizeCommand from "./docker/docker _resize"; import GeneralInputCommand from "./general/general _input"; import TimeCheck from "./task/time"; import MinecraftBedrockGetPlayersCommand from "../minecraft/mc_getplayer_bedrock"; @@ -66,6 +67,7 @@ export default class FuntionDispatcher extends InstanceCommand { instance.setPreset("stop", new GeneralStopCommand()); instance.setPreset("kill", new GeneralKillCommand()); instance.setPreset("restart", new GeneralRestartCommand()); + instance.setPreset("resize", new DockerResizeCommand()) } // 根据不同类型设置不同预设功能与作用 diff --git a/src/entity/commands/docker/docker _resize.ts b/src/entity/commands/docker/docker _resize.ts new file mode 100644 index 0000000..9c98330 --- /dev/null +++ b/src/entity/commands/docker/docker _resize.ts @@ -0,0 +1,51 @@ +/* + Copyright (C) 2022 RimuruChan + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + According to the AGPL, it is forbidden to delete all copyright notices, + and if you modify the source code, you must open source the + modified source code. + + 版权所有 (C) 2022 RimuruChan + + 该程序是免费软件,您可以重新分发和/或修改据 GNU Affero 通用公共许可证的条款, + 由自由软件基金会,许可证的第 3 版,或(由您选择)任何更高版本。 + + 根据 AGPL 与用户协议,您必须保留所有版权声明,如果修改源代码则必须开源修改后的源代码。 + 可以前往 https://mcsmanager.com/ 阅读用户协议,申请闭源开发授权等。 +*/ + +import Instance from "../../instance/instance"; +import InstanceCommand from "../base/command"; +import { DockerProcessAdapter } from "./docker _start"; + +export interface IResizeOptions { + h: number, + w: number, +} + +export default class DockerResizeCommand extends InstanceCommand { + constructor() { + super("ResizeTTY"); + } + + async exec(instance: Instance, size?: IResizeOptions): Promise { + // 关服命令需要发送命令,但关服命令执行前会设置状态为关闭中状态。 + // 所以这里只能通过进程是否存在来执行命令 + if (!instance.process) { + instance.failure(new Error("命令执行失败,因为实例实际进程不存在.")); + } + if (!(instance.process instanceof DockerProcessAdapter)) { + instance.failure(new Error("重设TTY大小失败,因为实例不是Docker容器.")); + } + let dockerProcess = instance.process; + await dockerProcess.container.resize({ + h: size.h, + w: size.w + }); + } +} diff --git a/src/entity/commands/docker/docker _start.ts b/src/entity/commands/docker/docker _start.ts index ce98aa7..e1c82eb 100644 --- a/src/entity/commands/docker/docker _start.ts +++ b/src/entity/commands/docker/docker _start.ts @@ -40,12 +40,12 @@ class StartupDockerProcessError extends Error { } // Docker 进程适配器 -class DockerProcessAdapter extends EventEmitter implements IInstanceProcess { +export class DockerProcessAdapter extends EventEmitter implements IInstanceProcess { pid?: number | string; private stream: NodeJS.ReadWriteStream; - constructor(private container: Docker.Container) { + constructor(public container: Docker.Container) { super(); } diff --git a/src/routers/stream_router.ts b/src/routers/stream_router.ts index a3e0ae5..e24aa8f 100644 --- a/src/routers/stream_router.ts +++ b/src/routers/stream_router.ts @@ -28,6 +28,7 @@ import SendCommand from "../entity/commands/cmd"; import SendInput from "../entity/commands/input"; import ProcessInfo from "../entity/commands/process_info"; import ProcessInfoCommand from "../entity/commands/process_info"; +import { DockerProcessAdapter } from "../entity/commands/docker/docker _start"; // 权限认证中间件 routerApp.use(async (event, ctx, data, next) => { @@ -121,3 +122,15 @@ routerApp.on("stream/input", async (ctx, data) => { protocol.responseError(ctx, error); } }); + +// 处理终端 resize +routerApp.on("stream/resize", async (ctx, data) => { + try { + const instanceUuid = ctx.session.stream.instanceUuid; + const instance = InstanceSubsystem.getInstance(instanceUuid); + if (instance.process instanceof DockerProcessAdapter) + await instance.execPreset("resize", data); + } catch (error) { + protocol.responseError(ctx, error); + } +});