feat(cli): add Command pipeline base classes
The Command base class, Commands registry, FeedbackMessageType enum, and four CommandOrigin subclasses (Player/Entity/Block/Server) that every CLI command in this branch depends on. Without these files the new commands fail to resolve imports at module load. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
import { CommandOrigin } from "./CommandOrigin";
|
||||
import { FeedbackMessageType } from "./FeedbackMessageType";
|
||||
|
||||
export class BlockCommandOrigin extends CommandOrigin {
|
||||
getSource() {
|
||||
return this.source.sourceBlock;
|
||||
}
|
||||
|
||||
sendMessage() {
|
||||
return FeedbackMessageType.None;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
import { CustomCommandSource, CustomCommandStatus, Player, system } from "@minecraft/server";
|
||||
import { Commands } from "./Commands.js";
|
||||
import { BlockCommandOrigin } from "./BlockCommandOrigin";
|
||||
import { EntityCommandOrigin } from "./EntityCommandOrigin";
|
||||
import { ServerCommandOrigin } from "./ServerCommandOrigin";
|
||||
import { PlayerCommandOrigin } from "./PlayerCommandOrigin";
|
||||
import { PACK_IDENTIFIER } from "../../consts.js";
|
||||
|
||||
export class Command {
|
||||
customCommand;
|
||||
|
||||
static resolveCommandOrigin(origin) {
|
||||
switch (origin.sourceType) {
|
||||
case CustomCommandSource.Block:
|
||||
return new BlockCommandOrigin(origin);
|
||||
case CustomCommandSource.Entity:
|
||||
if (origin.sourceEntity instanceof Player)
|
||||
return new PlayerCommandOrigin(origin);
|
||||
return new EntityCommandOrigin(origin);
|
||||
case CustomCommandSource.Server:
|
||||
return new ServerCommandOrigin(origin);
|
||||
default:
|
||||
throw new Error("Unknown command source: " + origin?.sourceType);
|
||||
}
|
||||
}
|
||||
|
||||
constructor(customCommand) {
|
||||
this.customCommand = customCommand;
|
||||
this.#setDefaultArgs();
|
||||
Commands.register(this);
|
||||
system.beforeEvents.startup.subscribe(this.setupForRegistry.bind(this));
|
||||
}
|
||||
|
||||
getName() {
|
||||
return this.customCommand.name.replace(/^[^:]+:/, '');
|
||||
}
|
||||
|
||||
isCheatsRequired() {
|
||||
return this.customCommand.cheatsRequired;
|
||||
}
|
||||
|
||||
setupForRegistry(startupEvent) {
|
||||
this.#registerCommand(startupEvent.customCommandRegistry);
|
||||
system.beforeEvents.startup.unsubscribe(this.setupForRegistry.bind(this));
|
||||
}
|
||||
|
||||
#registerCommand(customCommandRegistry) {
|
||||
this.#addPreCallback();
|
||||
this.#registerEnums(customCommandRegistry);
|
||||
this.#registerSingleCommand(customCommandRegistry);
|
||||
this.#registerAliasCommands(customCommandRegistry);
|
||||
}
|
||||
|
||||
#setDefaultArgs() {
|
||||
if (this.customCommand.cheatsRequired === void 0)
|
||||
this.customCommand.cheatsRequired = false;
|
||||
}
|
||||
|
||||
#addPreCallback() {
|
||||
this.callback = (origin, ...args) => {
|
||||
const source = Command.resolveCommandOrigin(origin);
|
||||
if (this.#commandSourceIsNotAllowed(source))
|
||||
return { status: CustomCommandStatus.Failure, message: 'commands.generic.invalidsource' };
|
||||
return this.customCommand.callback(source, ...args);
|
||||
}
|
||||
}
|
||||
|
||||
#registerEnums(customCommandRegistry) {
|
||||
if (this.customCommand.enums) {
|
||||
for (const customEnum of this.customCommand.enums)
|
||||
customCommandRegistry.registerEnum(`${PACK_IDENTIFIER}:${customEnum.name}`, customEnum.values);
|
||||
}
|
||||
}
|
||||
|
||||
#registerSingleCommand(customCommandRegistry, name = this.customCommand.name) {
|
||||
customCommandRegistry.registerCommand({
|
||||
name: `${PACK_IDENTIFIER}:${name}`,
|
||||
description: this.customCommand.description,
|
||||
permissionLevel: this.customCommand.permissionLevel,
|
||||
mandatoryParameters: this.#prepParameters(this.customCommand.mandatoryParameters),
|
||||
optionalParameters: this.#prepParameters(this.customCommand.optionalParameters),
|
||||
cheatsRequired: this.customCommand.cheatsRequired
|
||||
}, this.callback);
|
||||
}
|
||||
|
||||
#prepParameters(parameters) {
|
||||
if (!parameters)
|
||||
return [];
|
||||
for (const parameter of parameters) {
|
||||
if (parameter.name)
|
||||
parameter.name = `${PACK_IDENTIFIER}:${parameter.name}`;
|
||||
}
|
||||
return parameters;
|
||||
}
|
||||
|
||||
#registerAliasCommands(customCommandRegistry) {
|
||||
if (this.customCommand.aliases) {
|
||||
for (const alias of this.customCommand.aliases)
|
||||
this.#registerSingleCommand(customCommandRegistry, alias);
|
||||
}
|
||||
}
|
||||
|
||||
#commandSourceIsNotAllowed(source) {
|
||||
if (!this.customCommand.allowedSources)
|
||||
return false;
|
||||
return !this.customCommand.allowedSources.includes(source.constructor);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import { FeedbackMessageType } from "./FeedbackMessageType";
|
||||
|
||||
export class CommandOrigin {
|
||||
constructor(source) {
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
getType() {
|
||||
return this.source.sourceType;
|
||||
}
|
||||
|
||||
getSource() {
|
||||
throw new Error("getSource() not implemented");
|
||||
}
|
||||
|
||||
sendMessage(message) {
|
||||
console.error(`Unknown source type: ${this.source.sourceType}`, message);
|
||||
return FeedbackMessageType.ConsoleError;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
export class Commands {
|
||||
static #commands = [];
|
||||
|
||||
static register(command) {
|
||||
this.#commands.push(command);
|
||||
}
|
||||
|
||||
static getAll() {
|
||||
return [...this.#commands];
|
||||
}
|
||||
|
||||
static clear() {
|
||||
this.#commands = [];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import { CommandOrigin } from "./CommandOrigin";
|
||||
import { FeedbackMessageType } from "./FeedbackMessageType";
|
||||
|
||||
export class EntityCommandOrigin extends CommandOrigin {
|
||||
getSource() {
|
||||
return this.source.sourceEntity;
|
||||
}
|
||||
|
||||
sendMessage(message) {
|
||||
this.getSource().sendMessage(message);
|
||||
return FeedbackMessageType.ChatMessage;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
export const FeedbackMessageType = Object.freeze({
|
||||
None: "none",
|
||||
ConsoleInfo: "info",
|
||||
ConsoleWarn: "warn",
|
||||
ConsoleError: "error",
|
||||
ChatMessage: "message"
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
import { CommandOrigin } from "./CommandOrigin";
|
||||
import { FeedbackMessageType } from "./FeedbackMessageType";
|
||||
|
||||
export class PlayerCommandOrigin extends CommandOrigin {
|
||||
getType() {
|
||||
return "Player";
|
||||
}
|
||||
|
||||
getSource() {
|
||||
return this.source.sourceEntity;
|
||||
}
|
||||
|
||||
sendMessage(message) {
|
||||
this.getSource().sendMessage(message);
|
||||
return FeedbackMessageType.ChatMessage;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import { CommandOrigin } from "./CommandOrigin";
|
||||
import { FeedbackMessageType } from "./FeedbackMessageType";
|
||||
|
||||
export class ServerCommandOrigin extends CommandOrigin {
|
||||
getSource() {
|
||||
return this.source.sourceType;
|
||||
}
|
||||
|
||||
sendMessage(message) {
|
||||
console.log(message);
|
||||
return FeedbackMessageType.ConsoleInfo;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user