From d2a5813a7bf5e0613a39ee5caf3384ba631f9360 Mon Sep 17 00:00:00 2001 From: Lex Lim Date: Mon, 19 Aug 2024 14:57:32 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=B8=80=E9=94=AE=E5=BC=80?= =?UTF-8?q?=E7=81=AB=E6=8C=87=E5=AE=9A=E6=B3=A2=E5=BD=A2=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sdk/auto_hot_key.ahk | 69 +++++++++++++++++++ server/src/controllers/game/CoyoteLiveGame.ts | 15 +++- server/src/controllers/http/GameApi.ts | 25 +++++-- 3 files changed, 101 insertions(+), 8 deletions(-) create mode 100644 sdk/auto_hot_key.ahk diff --git a/sdk/auto_hot_key.ahk b/sdk/auto_hot_key.ahk new file mode 100644 index 0000000..180378b --- /dev/null +++ b/sdk/auto_hot_key.ahk @@ -0,0 +1,69 @@ +; ============================================================================= +; AutoHotKey functions for Coyote Game Hub +; ============================================================================= + +global CoyoteControllerURL := "http://127.0.0.1:8920" +global CoyoteTargetClientId := "all" + +HttpPost(url, body) { + ; https://learn.microsoft.com/en-us/windows/win32/winhttp/winhttprequest + web := ComObject('WinHttp.WinHttpRequest.5.1') + web.Open("POST", url, false) + web.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded") + web.Send(body) + return web.ResponseText +} + +CoyoteUpdateGameConfig(paramStr) +{ + global CoyoteControllerURL, CoyoteTargetClientId + + url := CoyoteControllerURL . "/api/game/" . CoyoteTargetClientId . "/strength_config" + return HttpPost(url, paramStr) +} + +CoyoteAddStrength(value) +{ + return CoyoteUpdateGameConfig("strength.add=" . value) +} + +CoyoteSubStrength(value) +{ + return CoyoteUpdateGameConfig("strength.sub=" . value) +} + +CoyoteSetStrength(value) +{ + return CoyoteUpdateGameConfig("strength.set=" . value) +} + +CoyoteAddRandomStrength(value) +{ + return CoyoteUpdateGameConfig("randomStrength.add=" . value) +} + +CoyoteSubRandomStrength(value) +{ + return CoyoteUpdateGameConfig("randomStrength.sub=" . value) +} + +CoyoteSetRandomStrength(value) +{ + return CoyoteUpdateGameConfig("randomStrength.set=" . value) +} + +CoyoteFire(strength, time) +{ + global CoyoteControllerURL, CoyoteTargetClientId + + timeMs := time * 1000 + url := CoyoteControllerURL . "/api/game/" . CoyoteTargetClientId . "/fire" + return HttpPost(url, "strength=" . strength . "&time=" . timeMs) +} + +; Example usage: +; F1:: +; { +; CoyoteAddStrength(1) +; return +; } \ No newline at end of file diff --git a/server/src/controllers/game/CoyoteLiveGame.ts b/server/src/controllers/game/CoyoteLiveGame.ts index df5ce9a..82c37b8 100644 --- a/server/src/controllers/game/CoyoteLiveGame.ts +++ b/server/src/controllers/game/CoyoteLiveGame.ts @@ -41,6 +41,9 @@ export class CoyoteLiveGame { /** 一键开火结束时间 */ public fireEndTimestamp: number = 0; + /** 一键开火波形 */ + public firePulseId: string = ''; + public currentPulseId: string = ''; private eventStore: EventStore = new EventStore(); @@ -174,11 +177,13 @@ export class CoyoteLiveGame { * 一键开火 * @param strength 强度 * @param duration 持续时间(毫秒) + * @param pulseId 一键开火使用的脉冲ID(可选) */ - public async fire(strength: number, duration: number) { + public async fire(strength: number, duration: number, pulseId?: string): Promise { if (!this.fireStrength) { this.fireStrength = strength; this.fireEndTimestamp = Date.now() + duration; + this.firePulseId = pulseId || ''; // 通知强度变化 this.events.emit('strengthChanged', this.gameStrength); @@ -190,6 +195,7 @@ export class CoyoteLiveGame { // 已经在一键开火状态,使用最大的强度,持续时间增加 this.fireStrength = Math.max(this.fireStrength, strength); this.fireEndTimestamp += duration; + this.firePulseId = pulseId || ''; } } @@ -218,6 +224,7 @@ export class CoyoteLiveGame { private async runGameTask(ab: AbortController, harvest: () => void): Promise { let outputTime = 0; + let pulseId = this.currentPulseId; if (this.fireStrength) { if (Date.now() > this.fireEndTimestamp) { // 一键开火结束 this.fireStrength = 0; @@ -225,12 +232,16 @@ export class CoyoteLiveGame { } else { outputTime = Math.min(this.fireEndTimestamp - Date.now(), 30000); // 单次最多输出30秒 } + + if (this.firePulseId) { + pulseId = this.firePulseId; + } } else { // 随机强度 outputTime = randomInt(this.strengthConfig.minInterval, this.strengthConfig.maxInterval) * 1000; } // 输出脉冲,直到下次随机强度时间 - await this.client.outputPulse(this.currentPulseId, outputTime, { + await this.client.outputPulse(pulseId, outputTime, { abortController: ab, bChannel: !!(this.strengthConfig && this.strengthConfig.bChannelMultiplier), onTimeEnd: () => { diff --git a/server/src/controllers/http/GameApi.ts b/server/src/controllers/http/GameApi.ts index 98e71dd..ebc2499 100644 --- a/server/src/controllers/http/GameApi.ts +++ b/server/src/controllers/http/GameApi.ts @@ -28,6 +28,7 @@ export type SetStrengthConfigRequest = { export type FireRequest = { strength: number; time?: number; + pulseId?: string; }; export class GameApiController { @@ -322,12 +323,22 @@ export class GameApiController { }; return; } + + // 是否获取完整的波形信息 + let isFullMode = ctx.request.query?.type === 'full'; // 暂且只从配置文件中获取脉冲列表 - const pulseList = DGLabPulseService.instance.pulseList.map((pulse) => ({ - id: pulse.id, - name: pulse.name, - })); + let pulseList: any[] = []; + + if (isFullMode) { + pulseList = DGLabPulseService.instance.pulseList; + } else { + // 只返回基本信息 + DGLabPulseService.instance.pulseList.map((pulse) => ({ + id: pulse.id, + name: pulse.name, + })); + } ctx.body = { status: 1, @@ -358,7 +369,7 @@ export class GameApiController { // fix for x-www-form-urlencoded const postBody = ctx.request.body; for (const key in postBody) { - if (postBody[key]) { + if (['strength', 'time'].includes(key) && postBody[key]) { postBody[key] = parseInt(postBody[key]); } } @@ -394,6 +405,8 @@ export class GameApiController { return; } + const pulseId = req.pulseId ?? undefined; + let gameList: Iterable = []; if (ctx.params.id === 'all') { // 广播模式,设置所有游戏的强度配置 if (!MainConfig.value.allowBroadcastToClients) { @@ -422,7 +435,7 @@ export class GameApiController { let successClientIds = new Set(); for (const game of gameList) { - game.fire(req.strength, fireTime); + game.fire(req.strength, fireTime, pulseId); successClientIds.add(game.clientId); }