Skip to content

Commit

Permalink
feat(package): addCommand (#482)
Browse files Browse the repository at this point in the history
  • Loading branch information
ESK0 authored Jan 15, 2024
1 parent 5dfd14d commit 37a3599
Show file tree
Hide file tree
Showing 2 changed files with 141 additions and 0 deletions.
140 changes: 140 additions & 0 deletions package/server/resource/addCommand/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import { addAce } from '../acl';

type OxCommandArguments = Record<string | number, string | number | boolean>;

interface OxCommandParams {
name: string;
help?: string;
paramType?: 'number' | 'playerId' | 'string';
optional?: boolean;
}

interface OxCommandProperties {
name?: string;
help?: string;
params?: OxCommandParams[];
restricted?: boolean | string | string[];
}

const registeredCommmands: OxCommandProperties[] = [];
let shouldSendCommands = false;

setTimeout(() => {
shouldSendCommands = true;
emitNet('chat:addSuggestions', -1, registeredCommmands);
}, 1000);

on('playerJoining', (source: number) => {
emitNet('chat:addSuggestions', source, registeredCommmands);
});

function parseArguments(
source: number,
args: OxCommandArguments,
raw: string,
params?: OxCommandParams[]
): OxCommandArguments | undefined {
if (!params) { return args; }

const result = params.every((param, index) => {
const arg = args[index];
let value;

switch (param.paramType) {
case 'number':
value = +arg;
break;

case 'string':
value = !Number(arg) ? arg : false;
break;

case 'playerId':
value = arg === 'me' ? source : +arg;
if (!value || !GetPlayerGuid(value.toString())) {
value = false;
}
break;

default:
value = arg;
break;
}

if (!value && (!param.optional || (param.optional && arg))) {
return Citizen.trace(
`^1command '${raw.split(' ') || raw}' received an invalid ${param.paramType} for argument ${index} (${
param.name
}), received '${arg}'^0`
);
}

args[param.name] = value;
delete args[index];

return true;
});

return result ? args : undefined;
}

export function addCommand(
commandName: string | string[],
cb: (source: number, args: object, raw: string) => any,
properties?: OxCommandProperties
) {
const restricted = properties?.restricted;
const params = properties?.params;

if (params) {
params.forEach((param) => {
if (param.paramType) {
param.help = param.help ? `${param.help} (type: ${param.paramType})` : `(type: ${param.paramType})`;
}
});
}

const commands = typeof commandName !== 'object' ? [commandName] : commandName;
const numCommands = commands.length;

const commandHandler = (source: number, args: OxCommandArguments, raw: string) => {
const parsed = parseArguments(source, args, raw, params);
if (!parsed) { return; }

cb(source, parsed, raw);
};

commands.forEach((commandName, index) => {
RegisterCommand(commandName, commandHandler, restricted ? true : false);

if (restricted) {
const ace = `command.${commandName}`;
const restrictedType = typeof restricted;

if (restrictedType === 'string' && !IsPrincipalAceAllowed(restricted as string, ace)) {
addAce(restricted as string, ace, true);
} else if (restrictedType === 'object') {
const _restricted = restricted as string[];
_restricted.forEach((principal) => {
if (!IsPrincipalAceAllowed(principal, ace)) {
addAce(principal as string, ace, true);
}
});
}
}

if (properties) {
properties.name = `/${commandName}`;
delete properties.restricted;
registeredCommmands.push(properties);

if (index !== numCommands && numCommands !== 1) {
properties = { ...properties };
}

if (shouldSendCommands) {
emitNet('chat:addSuggestions', -1, properties);
}
}
});
}
1 change: 1 addition & 0 deletions package/server/resource/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from './acl';
export * from './locale';
export * from './callback';
export * from './version';
export * from './addCommand';

0 comments on commit 37a3599

Please sign in to comment.