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