From 845271b80b14e69153732210a6a2c041933785ea Mon Sep 17 00:00:00 2001 From: Syca <64587684+Sycamore0@users.noreply.github.com> Date: Sat, 5 Oct 2024 20:43:52 +0800 Subject: [PATCH] Add `/dungeon` command(also GMTalk) --- .../commands/worldCommands/dungeonCommand.ts | 57 +++++++++++++++++++ src/cli/commands/worldCommands/index.ts | 4 +- .../game/gameData/data/DungeonData.ts | 4 ++ src/kcpServer/packets/GmTalk.ts | 30 ++++++++-- src/translate/data/en-us.json | 14 +++++ src/translate/data/zh-cn.json | 16 +++++- src/translate/data/zh-tw.json | 20 ++++++- 7 files changed, 135 insertions(+), 10 deletions(-) create mode 100644 src/cli/commands/worldCommands/dungeonCommand.ts diff --git a/src/cli/commands/worldCommands/dungeonCommand.ts b/src/cli/commands/worldCommands/dungeonCommand.ts new file mode 100644 index 00000000..decaa9fa --- /dev/null +++ b/src/cli/commands/worldCommands/dungeonCommand.ts @@ -0,0 +1,57 @@ +import SceneData from '$/gameData/data/SceneData' +import DungeonData from '$/gameData/data/DungeonData' +import Vector from '$/utils/vector' +import translate from '@/translate' +import { SceneEnterReasonEnum, SceneEnterTypeEnum } from '@/types/proto/enum' +import { CommandDefinition } from '..' + +const dungeonCommand: CommandDefinition = { + name: 'dungeon', + usage: 2, + args: [ + { name: 'id', type: 'int' }, + { name: 'uidInput', type: 'str', optional: true } + ], + allowPlayer: true, + exec: async (cmdInfo) => { + const { args, sender, cli, kcpServer } = cmdInfo + const { print, printError } = cli + const [id, uidInput] = args + + let uid; + if (uidInput === '@s' || uidInput === undefined) { + uid = sender?.uid; + } else if (!isNaN(parseInt(uidInput))) { + uid = parseInt(uidInput); + } else { + return printError(translate('generic.invalidTarget')); + } + + const player = kcpServer.game.getPlayerByUid(uid || sender?.uid) + if (!player) return printError(translate('generic.playerNotFound')) + + const { currentWorld, currentScene, context } = player + if (!currentWorld) return printError(translate('generic.notInWorld')) + + const sceneId = await DungeonData.getSceneByDungeon(id) + + const scene = await currentWorld.getScene(sceneId) + const sceneData = await SceneData.getScene(sceneId) + if (!scene || !sceneData) return printError(translate('cli.commands.dungeon.error.sceneNotFound')) + if (currentScene === scene) return printError(translate('cli.commands.dungeon.error.sameScene')) + + print(translate('cli.commands.dungeon.info.changeScene', id, scene.id)) + + const { BornPos, BornRot } = sceneData + + const pos = new Vector() + const rot = new Vector() + + pos.setData(BornPos) + rot.setData(BornRot) + + scene.join(context, pos, rot, SceneEnterTypeEnum.ENTER_DUNGEON, SceneEnterReasonEnum.DUNGEON_ENTER) + } +} + +export default dungeonCommand \ No newline at end of file diff --git a/src/cli/commands/worldCommands/index.ts b/src/cli/commands/worldCommands/index.ts index 78327be8..8d1bee78 100644 --- a/src/cli/commands/worldCommands/index.ts +++ b/src/cli/commands/worldCommands/index.ts @@ -1,5 +1,6 @@ import { CommandDefinition } from '..' import coopCommand from './coopCommand' +import dungeonCommand from './dungeonCommand' import posCommand from './posCommand' import sceneCommand from './sceneCommand' import tpCommand from './tpCommand' @@ -8,7 +9,8 @@ const worldCommands: CommandDefinition[] = [ posCommand, sceneCommand, tpCommand, - coopCommand + coopCommand, + dungeonCommand ] export default worldCommands \ No newline at end of file diff --git a/src/kcpServer/game/gameData/data/DungeonData.ts b/src/kcpServer/game/gameData/data/DungeonData.ts index e656a78d..f4ee0c2e 100644 --- a/src/kcpServer/game/gameData/data/DungeonData.ts +++ b/src/kcpServer/game/gameData/data/DungeonData.ts @@ -20,6 +20,10 @@ class DungeonDataLoader extends Loader { return (await this.getDungeonList()).find(data => data.SceneId === sceneId) } + async getSceneByDungeon(id: number): Promise { + return (await this.getDungeon(id))?.SceneId + } + async getDungeonList(): Promise { return (await this.getData())?.Dungeon || [] } diff --git a/src/kcpServer/packets/GmTalk.ts b/src/kcpServer/packets/GmTalk.ts index fb8ab5e6..9f9f2a6f 100644 --- a/src/kcpServer/packets/GmTalk.ts +++ b/src/kcpServer/packets/GmTalk.ts @@ -6,6 +6,7 @@ import { ChangeHpReasonEnum, PlayerDieTypeEnum, ProtEntityTypeEnum, RetcodeEnum, import Logger from '@/logger' import Gadget from '$/entity/gadget' import SceneData from '$/gameData/data/SceneData' +import DungeonData from '$/gameData/data/DungeonData' const logger = new Logger('GMTALK') export interface GmTalkReq { @@ -108,11 +109,8 @@ class GmTalkPacket extends Packet implements PacketInterface { await player.currentScene.entityManager.add(gadget) } - private async gmtJump(context: PacketContext, id: number) { - const { player } = context - - const scene = await player.currentWorld.getScene(id) - const sceneData = await SceneData.getScene(id) + private async getSceneData(sceneId: number) { + const sceneData = await SceneData.getScene(sceneId) const { BornPos, BornRot } = sceneData const pos = new Vector() @@ -120,9 +118,28 @@ class GmTalkPacket extends Packet implements PacketInterface { pos.setData(BornPos) rot.setData(BornRot) + return { pos, rot } + } + + private async gmtJump(context: PacketContext, id: number) { + const { player } = context + + const scene = await player.currentWorld.getScene(id) + const { pos, rot } = await this.getSceneData(id) + scene.join(context, pos, rot, SceneEnterTypeEnum.ENTER_JUMP, SceneEnterReasonEnum.TRANS_POINT) } + private async gmtDungeon(context: PacketContext, id: number) { + const { player } = context + const sceneId = await DungeonData.getSceneByDungeon(id) + + const scene = await player.currentWorld.getScene(sceneId) + const { pos, rot } = await this.getSceneData(sceneId) + + scene.join(context, pos, rot, SceneEnterTypeEnum.ENTER_DUNGEON, SceneEnterReasonEnum.DUNGEON_ENTER) + } + async request(context: PacketContext, data: GmTalkReq): Promise { const { msg } = data const cmd = msg?.split(' ')?.[0]?.toLowerCase() @@ -155,6 +172,9 @@ class GmTalkPacket extends Packet implements PacketInterface { case 'jump': await this.gmtJump(context, Number(args[0])) break + case 'dungeon': + await this.gmtDungeon(context, Number(args[0])) + break default: logger.warn(`Unsupported GM command: ${msg}`) await this.response(context, { retcode: RetcodeEnum.RET_UNKNOWN_ERROR }) diff --git a/src/translate/data/en-us.json b/src/translate/data/en-us.json index 6027c21f..ac68eef4 100644 --- a/src/translate/data/en-us.json +++ b/src/translate/data/en-us.json @@ -586,6 +586,20 @@ "sameScene": "Same scene." } }, + "dungeon": { + "desc": "Enter dungeon", + "usage": { + "0": "dungeon - Enter dungeon for player", + "1": "dungeon - (In game) Enter dungeon for yourself" + }, + "info": { + "changeScene": "Enter dungeon: %0(Scene: %1)" + }, + "error": { + "sceneNotFound": "Scene not found.", + "sameScene": "Same scene." + } + }, "tp": { "desc": "Teleport to location", "usage": { diff --git a/src/translate/data/zh-cn.json b/src/translate/data/zh-cn.json index 2dce79a8..89bb2129 100644 --- a/src/translate/data/zh-cn.json +++ b/src/translate/data/zh-cn.json @@ -572,7 +572,7 @@ } }, "scene": { - "desc": "改变场景", + "desc": "进入场景", "usage": { "0": "scene - 将该玩家传送到该场景", "1": "scene - (游戏中)改变自己所在的场景" @@ -585,6 +585,20 @@ "sameScene": "处于同一场景中." } }, + "dungeon": { + "desc": "进入秘境", + "usage": { + "0": "dungeon - 将该玩家传送到该秘境", + "1": "dungeon - (游戏中)改变自己所在的秘境" + }, + "info": { + "changeScene": "传送到秘境: %0(场景: %1)" + }, + "error": { + "sceneNotFound": "该场景未找到.", + "sameScene": "处于同一场景中." + } + }, "tp": { "desc": "传送到某位置", "usage": { diff --git a/src/translate/data/zh-tw.json b/src/translate/data/zh-tw.json index 8de759d6..97dd05a1 100644 --- a/src/translate/data/zh-tw.json +++ b/src/translate/data/zh-tw.json @@ -572,17 +572,31 @@ } }, "scene": { - "desc": "場景改變", + "desc": "進入場景", "usage": { "0": "scene - 將該玩家傳送到該場景", - "1": "scene - (遊戲中)為自己改變場景" + "1": "scene - (遊戲中)改變自己所在的場景" }, "info": { "changeScene": "修改場景到: %0" }, "error": { "sceneNotFound": "該場景未找到.", - "sameScene": "相同的場景." + "sameScene": "處於同一場景中." + } + }, + "dungeon": { + "desc": "進入秘境", + "usage": { + "0": "dungeon - 將該玩家傳送到該秘境", + "1": "dungeon - (遊戲中)改變自己所在的秘境" + }, + "info": { + "changeScene": "傳送到秘境: %0(場景: %1)" + }, + "error": { + "sceneNotFound": "該場景未找到.", + "sameScene": "處於同一場景中." } }, "tp": {