Expanded give command logic (!283)
This change was originally made in master branch, between the time v3.7.6 and v3.8.0 were released. Due to the way that v3.8.0 was merged into master, and the fact that this change was never merged into v3.8.0, it had to be cherry-picked and have some conflicts resolved. I gave it my best and I would love some help testing it before it's merged for v3.8.1.
Conflicts:
- project/package.json
- project/src/helpers/Dialogue/Commando/SptCommands/GiveSptCommand.ts
Resolved by Refringe <me@refringe.com>
Original PR: https://dev.sp-tarkov.com/SPT-AKI/Server/pulls/182
Original Commit: 9846adc68b
Original Message:
- Added give by name
- Refactored Commando so its abstracted, that way modders can use it too! :)
Co-authored-by: clodan <clodan@clodan.com>
Reviewed-on: https://dev.sp-tarkov.com/SPT-AKI/Server/pulls/182
Co-authored-by: Alex <clodan@noreply.dev.sp-tarkov.com>
Co-committed-by: Alex <clodan@noreply.dev.sp-tarkov.com>
Co-authored-by: Alex <clodan@noreply.dev.sp-tarkov.com>
Co-authored-by: chomp <chomp@noreply.dev.sp-tarkov.com>
Reviewed-on: https://dev.sp-tarkov.com/SPT-AKI/Server/pulls/283
Co-authored-by: Refringe <refringe@noreply.dev.sp-tarkov.com>
Co-committed-by: Refringe <refringe@noreply.dev.sp-tarkov.com>
This commit is contained in:
parent
8342edf55f
commit
834a2e3ef5
@ -33,6 +33,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"atomically": "~1.7",
|
"atomically": "~1.7",
|
||||||
"buffer-crc32": "^1.0.0",
|
"buffer-crc32": "^1.0.0",
|
||||||
|
"closest-match": "~1.3",
|
||||||
"date-fns": "~2.30",
|
"date-fns": "~2.30",
|
||||||
"date-fns-tz": "~2.0",
|
"date-fns-tz": "~2.0",
|
||||||
"i18n": "~0.15",
|
"i18n": "~0.15",
|
||||||
|
@ -596,7 +596,7 @@ export class Container
|
|||||||
lifecycle: Lifecycle.Singleton,
|
lifecycle: Lifecycle.Singleton,
|
||||||
});
|
});
|
||||||
// SptCommands
|
// SptCommands
|
||||||
depContainer.register<GiveSptCommand>("GiveSptCommand", GiveSptCommand);
|
depContainer.register<GiveSptCommand>("GiveSptCommand", GiveSptCommand, { lifecycle: Lifecycle.Singleton });
|
||||||
}
|
}
|
||||||
|
|
||||||
private static registerLoaders(depContainer: DependencyContainer): void
|
private static registerLoaders(depContainer: DependencyContainer): void
|
||||||
|
75
project/src/helpers/Dialogue/AbstractDialogueChatBot.ts
Normal file
75
project/src/helpers/Dialogue/AbstractDialogueChatBot.ts
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
import { IChatCommand, ICommandoCommand } from "@spt-aki/helpers/Dialogue/Commando/IChatCommand";
|
||||||
|
import { IDialogueChatBot } from "@spt-aki/helpers/Dialogue/IDialogueChatBot";
|
||||||
|
import { ISendMessageRequest } from "@spt-aki/models/eft/dialog/ISendMessageRequest";
|
||||||
|
import { IUserDialogInfo } from "@spt-aki/models/eft/profile/IAkiProfile";
|
||||||
|
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
||||||
|
import { MailSendService } from "@spt-aki/services/MailSendService";
|
||||||
|
|
||||||
|
export abstract class AbstractDialogueChatBot implements IDialogueChatBot
|
||||||
|
{
|
||||||
|
public constructor(
|
||||||
|
protected logger: ILogger,
|
||||||
|
protected mailSendService: MailSendService,
|
||||||
|
protected chatCommands: IChatCommand[] | ICommandoCommand[],
|
||||||
|
)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated As of v3.7.6. Use registerChatCommand.
|
||||||
|
*/
|
||||||
|
// TODO: v3.9.0 - Remove registerCommandoCommand method.
|
||||||
|
public registerCommandoCommand(chatCommand: IChatCommand | ICommandoCommand): void
|
||||||
|
{
|
||||||
|
this.registerChatCommand(chatCommand);
|
||||||
|
}
|
||||||
|
|
||||||
|
public registerChatCommand(chatCommand: IChatCommand | ICommandoCommand): void
|
||||||
|
{
|
||||||
|
if (this.chatCommands.some((cc) => cc.getCommandPrefix() === chatCommand.getCommandPrefix()))
|
||||||
|
{
|
||||||
|
throw new Error(
|
||||||
|
`The command "${chatCommand.getCommandPrefix()}" attempting to be registered already exists.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
this.chatCommands.push(chatCommand);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract getChatBot(): IUserDialogInfo;
|
||||||
|
|
||||||
|
protected abstract getUnrecognizedCommandMessage(): string;
|
||||||
|
|
||||||
|
public handleMessage(sessionId: string, request: ISendMessageRequest): string
|
||||||
|
{
|
||||||
|
if ((request.text ?? "").length === 0)
|
||||||
|
{
|
||||||
|
this.logger.error("Command came in as empty text! Invalid data!");
|
||||||
|
return request.dialogId;
|
||||||
|
}
|
||||||
|
|
||||||
|
const splitCommand = request.text.split(" ");
|
||||||
|
|
||||||
|
const commandos = this.chatCommands.filter((c) => c.getCommandPrefix() === splitCommand[0]);
|
||||||
|
if (commandos[0]?.getCommands().has(splitCommand[1]))
|
||||||
|
{
|
||||||
|
return commandos[0].handle(splitCommand[1], this.getChatBot(), sessionId, request);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (splitCommand[0].toLowerCase() === "help")
|
||||||
|
{
|
||||||
|
const helpMessage = this.chatCommands.map((c) =>
|
||||||
|
`Available commands:\n\n${c.getCommandPrefix()}:\n\n${
|
||||||
|
Array.from(c.getCommands()).map((command) => c.getCommandHelp(command)).join("\n")
|
||||||
|
}`
|
||||||
|
).join("\n");
|
||||||
|
this.mailSendService.sendUserMessageToPlayer(sessionId, this.getChatBot(), helpMessage);
|
||||||
|
return request.dialogId;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.mailSendService.sendUserMessageToPlayer(
|
||||||
|
sessionId,
|
||||||
|
this.getChatBot(),
|
||||||
|
this.getUnrecognizedCommandMessage(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,12 @@
|
|||||||
import { ISendMessageRequest } from "@spt-aki/models/eft/dialog/ISendMessageRequest";
|
import { ISendMessageRequest } from "@spt-aki/models/eft/dialog/ISendMessageRequest";
|
||||||
import { IUserDialogInfo } from "@spt-aki/models/eft/profile/IAkiProfile";
|
import { IUserDialogInfo } from "@spt-aki/models/eft/profile/IAkiProfile";
|
||||||
|
|
||||||
export interface ICommandoCommand
|
/**
|
||||||
|
* @deprecated As of v3.7.6. Use IChatCommand. Will be removed in v3.9.0.
|
||||||
|
*/
|
||||||
|
// TODO: v3.9.0 - Remove ICommandoCommand.
|
||||||
|
export type ICommandoCommand = IChatCommand;
|
||||||
|
export interface IChatCommand
|
||||||
{
|
{
|
||||||
getCommandPrefix(): string;
|
getCommandPrefix(): string;
|
||||||
getCommandHelp(command: string): string;
|
getCommandHelp(command: string): string;
|
@ -1,4 +1,4 @@
|
|||||||
import { ICommandoCommand } from "@spt-aki/helpers/Dialogue/Commando/ICommandoCommand";
|
import { IChatCommand } from "@spt-aki/helpers/Dialogue/Commando/IChatCommand";
|
||||||
import { ISptCommand } from "@spt-aki/helpers/Dialogue/Commando/SptCommands/ISptCommand";
|
import { ISptCommand } from "@spt-aki/helpers/Dialogue/Commando/SptCommands/ISptCommand";
|
||||||
import { ISendMessageRequest } from "@spt-aki/models/eft/dialog/ISendMessageRequest";
|
import { ISendMessageRequest } from "@spt-aki/models/eft/dialog/ISendMessageRequest";
|
||||||
import { IUserDialogInfo } from "@spt-aki/models/eft/profile/IAkiProfile";
|
import { IUserDialogInfo } from "@spt-aki/models/eft/profile/IAkiProfile";
|
||||||
@ -8,7 +8,7 @@ import { ConfigServer } from "@spt-aki/servers/ConfigServer";
|
|||||||
import { inject, injectAll, injectable } from "tsyringe";
|
import { inject, injectAll, injectable } from "tsyringe";
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class SptCommandoCommands implements ICommandoCommand
|
export class SptCommandoCommands implements IChatCommand
|
||||||
{
|
{
|
||||||
constructor(
|
constructor(
|
||||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||||
@ -31,7 +31,7 @@ export class SptCommandoCommands implements ICommandoCommand
|
|||||||
{
|
{
|
||||||
if (this.sptCommands.some((c) => c.getCommand() === command.getCommand()))
|
if (this.sptCommands.some((c) => c.getCommand() === command.getCommand()))
|
||||||
{
|
{
|
||||||
throw new Error(`The command ${command.getCommand()} being registered for SPT Commands already exists!`);
|
throw new Error(`The command "${command.getCommand()}" attempting to be registered already exists.`);
|
||||||
}
|
}
|
||||||
this.sptCommands.push(command);
|
this.sptCommands.push(command);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { ISptCommand } from "@spt-aki/helpers/Dialogue/Commando/SptCommands/ISptCommand";
|
import { ISptCommand } from "@spt-aki/helpers/Dialogue/Commando/SptCommands/ISptCommand";
|
||||||
|
import { SavedCommand } from "@spt-aki/helpers/Dialogue/Commando/SptCommands/SavedCommand";
|
||||||
import { ItemHelper } from "@spt-aki/helpers/ItemHelper";
|
import { ItemHelper } from "@spt-aki/helpers/ItemHelper";
|
||||||
import { PresetHelper } from "@spt-aki/helpers/PresetHelper";
|
import { PresetHelper } from "@spt-aki/helpers/PresetHelper";
|
||||||
import { Item } from "@spt-aki/models/eft/common/tables/IItem";
|
import { Item } from "@spt-aki/models/eft/common/tables/IItem";
|
||||||
@ -6,14 +7,30 @@ import { ISendMessageRequest } from "@spt-aki/models/eft/dialog/ISendMessageRequ
|
|||||||
import { IUserDialogInfo } from "@spt-aki/models/eft/profile/IAkiProfile";
|
import { IUserDialogInfo } from "@spt-aki/models/eft/profile/IAkiProfile";
|
||||||
import { BaseClasses } from "@spt-aki/models/enums/BaseClasses";
|
import { BaseClasses } from "@spt-aki/models/enums/BaseClasses";
|
||||||
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
||||||
|
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
||||||
|
import { LocaleService } from "@spt-aki/services/LocaleService";
|
||||||
import { MailSendService } from "@spt-aki/services/MailSendService";
|
import { MailSendService } from "@spt-aki/services/MailSendService";
|
||||||
import { HashUtil } from "@spt-aki/utils/HashUtil";
|
import { HashUtil } from "@spt-aki/utils/HashUtil";
|
||||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||||
|
import { closestMatch, distance } from "closest-match";
|
||||||
import { inject, injectable } from "tsyringe";
|
import { inject, injectable } from "tsyringe";
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class GiveSptCommand implements ISptCommand
|
export class GiveSptCommand implements ISptCommand
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Regex to account for all these cases:
|
||||||
|
* spt give "item name" 5
|
||||||
|
* spt give templateId 5
|
||||||
|
* spt give en "item name in english" 5
|
||||||
|
* spt give es "nombre en español" 5
|
||||||
|
* spt give 5 <== this is the reply when the algo isn't sure about an item
|
||||||
|
*/
|
||||||
|
private static commandRegex = /^spt give (((([a-z]{2,5}) )?"(.+)"|\w+) )?([0-9]+)$/;
|
||||||
|
private static maxAllowedDistance = 1.5;
|
||||||
|
|
||||||
|
protected savedCommand: SavedCommand;
|
||||||
|
|
||||||
public constructor(
|
public constructor(
|
||||||
@inject("WinstonLogger") protected logger: ILogger,
|
@inject("WinstonLogger") protected logger: ILogger,
|
||||||
@inject("ItemHelper") protected itemHelper: ItemHelper,
|
@inject("ItemHelper") protected itemHelper: ItemHelper,
|
||||||
@ -21,6 +38,8 @@ export class GiveSptCommand implements ISptCommand
|
|||||||
@inject("JsonUtil") protected jsonUtil: JsonUtil,
|
@inject("JsonUtil") protected jsonUtil: JsonUtil,
|
||||||
@inject("PresetHelper") protected presetHelper: PresetHelper,
|
@inject("PresetHelper") protected presetHelper: PresetHelper,
|
||||||
@inject("MailSendService") protected mailSendService: MailSendService,
|
@inject("MailSendService") protected mailSendService: MailSendService,
|
||||||
|
@inject("LocaleService") protected localeService: LocaleService,
|
||||||
|
@inject("DatabaseServer") protected databaseServer: DatabaseServer,
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -32,49 +51,135 @@ export class GiveSptCommand implements ISptCommand
|
|||||||
|
|
||||||
public getCommandHelp(): string
|
public getCommandHelp(): string
|
||||||
{
|
{
|
||||||
return "Usage: spt give tplId quantity";
|
return "spt give\n========\nSends items to the player through the message system.\n\n\tspt give [template ID] [quantity]\n\t\tEx: spt give 544fb25a4bdc2dfb738b4567 2\n\n\tspt give [\"item name\"] [quantity]\n\t\tEx: spt give \"pack of sugar\" 10\n\n\tspt give [locale] [\"item name\"] [quantity]\n\t\tEx: spt give fr \"figurine de chat\" 3";
|
||||||
}
|
}
|
||||||
|
|
||||||
public performAction(commandHandler: IUserDialogInfo, sessionId: string, request: ISendMessageRequest): string
|
public performAction(commandHandler: IUserDialogInfo, sessionId: string, request: ISendMessageRequest): string
|
||||||
{
|
{
|
||||||
const giveCommand = request.text.split(" ");
|
if (!GiveSptCommand.commandRegex.test(request.text))
|
||||||
if (giveCommand[1] !== "give")
|
|
||||||
{
|
|
||||||
this.logger.error("Invalid action received for give command!");
|
|
||||||
return request.dialogId;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!giveCommand[2])
|
|
||||||
{
|
{
|
||||||
this.mailSendService.sendUserMessageToPlayer(
|
this.mailSendService.sendUserMessageToPlayer(
|
||||||
sessionId,
|
sessionId,
|
||||||
commandHandler,
|
commandHandler,
|
||||||
"Invalid use of give command! Template ID is missing. Use \"Help\" for more info",
|
"Invalid use of give command. Use \"help\" for more information.",
|
||||||
);
|
);
|
||||||
return request.dialogId;
|
return request.dialogId;
|
||||||
}
|
}
|
||||||
const tplId = giveCommand[2];
|
|
||||||
|
|
||||||
if (!giveCommand[3])
|
const result = GiveSptCommand.commandRegex.exec(request.text);
|
||||||
|
|
||||||
|
let item: string;
|
||||||
|
let quantity: number;
|
||||||
|
let isItemName: boolean;
|
||||||
|
let locale: string;
|
||||||
|
|
||||||
|
// This is a reply to a give request previously made pending a reply
|
||||||
|
if (result[1] === undefined)
|
||||||
|
{
|
||||||
|
if (this.savedCommand === undefined)
|
||||||
{
|
{
|
||||||
this.mailSendService.sendUserMessageToPlayer(
|
this.mailSendService.sendUserMessageToPlayer(
|
||||||
sessionId,
|
sessionId,
|
||||||
commandHandler,
|
commandHandler,
|
||||||
"Invalid use of give command! Quantity is missing. Use \"Help\" for more info",
|
"Invalid use of give command. Use \"help\" for more information.",
|
||||||
);
|
);
|
||||||
return request.dialogId;
|
return request.dialogId;
|
||||||
}
|
}
|
||||||
const quantity = giveCommand[3];
|
if (+result[6] > this.savedCommand.potentialItemNames.length)
|
||||||
|
|
||||||
if (Number.isNaN(+quantity))
|
|
||||||
{
|
{
|
||||||
this.mailSendService.sendUserMessageToPlayer(
|
this.mailSendService.sendUserMessageToPlayer(
|
||||||
sessionId,
|
sessionId,
|
||||||
commandHandler,
|
commandHandler,
|
||||||
"Invalid use of give command! Quantity is not a valid integer. Use \"Help\" for more info",
|
"Invalid selection. Outside of bounds! Use \"help\" for more information.",
|
||||||
);
|
);
|
||||||
return request.dialogId;
|
return request.dialogId;
|
||||||
}
|
}
|
||||||
|
item = this.savedCommand.potentialItemNames[+result[6] - 1];
|
||||||
|
quantity = this.savedCommand.quantity;
|
||||||
|
locale = this.savedCommand.locale;
|
||||||
|
isItemName = true;
|
||||||
|
this.savedCommand = undefined;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// A new give request was entered, we need to ignore the old saved command
|
||||||
|
this.savedCommand = undefined;
|
||||||
|
isItemName = result[5] !== undefined;
|
||||||
|
item = result[5] ? result[5] : result[2];
|
||||||
|
quantity = +result[6];
|
||||||
|
|
||||||
|
if (isItemName)
|
||||||
|
{
|
||||||
|
locale = result[4] ? result[4] : this.localeService.getDesiredGameLocale();
|
||||||
|
if (!this.localeService.getServerSupportedLocales().includes(locale))
|
||||||
|
{
|
||||||
|
this.mailSendService.sendUserMessageToPlayer(
|
||||||
|
sessionId,
|
||||||
|
commandHandler,
|
||||||
|
`Unknown locale "${locale}". Use \"help\" for more information.`,
|
||||||
|
);
|
||||||
|
return request.dialogId;
|
||||||
|
}
|
||||||
|
|
||||||
|
const localizedGlobal = this.databaseServer.getTables().locales.global[locale];
|
||||||
|
|
||||||
|
const closestItemsMatchedByName = closestMatch(
|
||||||
|
item.toLowerCase(),
|
||||||
|
this.itemHelper.getItems().filter((i) => i._type !== "Node").map((i) =>
|
||||||
|
localizedGlobal[`${i?._id} Name`]?.toLowerCase()
|
||||||
|
).filter((i) => i !== undefined),
|
||||||
|
true,
|
||||||
|
) as string[];
|
||||||
|
|
||||||
|
if (closestItemsMatchedByName === undefined || closestItemsMatchedByName.length === 0)
|
||||||
|
{
|
||||||
|
this.mailSendService.sendUserMessageToPlayer(
|
||||||
|
sessionId,
|
||||||
|
commandHandler,
|
||||||
|
"That item could not be found. Please refine your request and try again.",
|
||||||
|
);
|
||||||
|
return request.dialogId;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (closestItemsMatchedByName.length > 1)
|
||||||
|
{
|
||||||
|
let i = 1;
|
||||||
|
const slicedItems = closestItemsMatchedByName.slice(0, 10);
|
||||||
|
// max 10 item names and map them
|
||||||
|
const itemList = slicedItems.map((itemName) => `${i++}. ${itemName}`).join("\n");
|
||||||
|
this.savedCommand = new SavedCommand(quantity, slicedItems, locale);
|
||||||
|
this.mailSendService.sendUserMessageToPlayer(
|
||||||
|
sessionId,
|
||||||
|
commandHandler,
|
||||||
|
`Could not find exact match. Closest matches are:\n\n${itemList}\n\nUse "spt give [number]" to select one.`,
|
||||||
|
);
|
||||||
|
return request.dialogId;
|
||||||
|
}
|
||||||
|
|
||||||
|
const dist = distance(item, closestItemsMatchedByName[0]);
|
||||||
|
if (dist > GiveSptCommand.maxAllowedDistance)
|
||||||
|
{
|
||||||
|
this.mailSendService.sendUserMessageToPlayer(
|
||||||
|
sessionId,
|
||||||
|
commandHandler,
|
||||||
|
`Found a possible match for "${item}" but uncertain. Match: "${
|
||||||
|
closestItemsMatchedByName[0]
|
||||||
|
}". Please refine your request and try again.`,
|
||||||
|
);
|
||||||
|
return request.dialogId;
|
||||||
|
}
|
||||||
|
// Only one available so we get that entry and use it
|
||||||
|
item = closestItemsMatchedByName[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If item is an item name, we need to search using that item name and the locale which one we want otherwise
|
||||||
|
// item is just the tplId.
|
||||||
|
const tplId = isItemName
|
||||||
|
? this.itemHelper.getItems().find((i) =>
|
||||||
|
this.databaseServer.getTables().locales.global[locale][`${i?._id} Name`]?.toLowerCase() === item
|
||||||
|
)._id
|
||||||
|
: item;
|
||||||
|
|
||||||
const checkedItem = this.itemHelper.getItem(tplId);
|
const checkedItem = this.itemHelper.getItem(tplId);
|
||||||
if (!checkedItem[0])
|
if (!checkedItem[0])
|
||||||
@ -82,21 +187,25 @@ export class GiveSptCommand implements ISptCommand
|
|||||||
this.mailSendService.sendUserMessageToPlayer(
|
this.mailSendService.sendUserMessageToPlayer(
|
||||||
sessionId,
|
sessionId,
|
||||||
commandHandler,
|
commandHandler,
|
||||||
"Invalid template ID requested for give command. The item doesn't exist in the DB.",
|
"That item could not be found. Please refine your request and try again.",
|
||||||
);
|
);
|
||||||
return request.dialogId;
|
return request.dialogId;
|
||||||
}
|
}
|
||||||
|
|
||||||
const itemsToSend: Item[] = [];
|
const itemsToSend: Item[] = [];
|
||||||
|
if (this.itemHelper.isOfBaseclass(checkedItem[1]._id, BaseClasses.WEAPON))
|
||||||
|
{
|
||||||
const preset = this.presetHelper.getDefaultPreset(checkedItem[1]._id);
|
const preset = this.presetHelper.getDefaultPreset(checkedItem[1]._id);
|
||||||
if (preset)
|
if (!preset)
|
||||||
{
|
{
|
||||||
for (let i = 0; i < +quantity; i++)
|
this.mailSendService.sendUserMessageToPlayer(
|
||||||
{
|
sessionId,
|
||||||
// Make sure IDs are unique before adding to array - prevent collisions
|
commandHandler,
|
||||||
const presetToSend = this.itemHelper.replaceIDs(preset._items);
|
"That weapon template ID could not be found. Please refine your request and try again.",
|
||||||
itemsToSend.push(...presetToSend);
|
);
|
||||||
|
return request.dialogId;
|
||||||
}
|
}
|
||||||
|
itemsToSend.push(...this.jsonUtil.clone(preset._items));
|
||||||
}
|
}
|
||||||
else if (this.itemHelper.isOfBaseclass(checkedItem[1]._id, BaseClasses.AMMO_BOX))
|
else if (this.itemHelper.isOfBaseclass(checkedItem[1]._id, BaseClasses.AMMO_BOX))
|
||||||
{
|
{
|
||||||
@ -115,13 +224,25 @@ export class GiveSptCommand implements ISptCommand
|
|||||||
_tpl: checkedItem[1]._id,
|
_tpl: checkedItem[1]._id,
|
||||||
upd: { StackObjectsCount: +quantity, SpawnedInSession: true },
|
upd: { StackObjectsCount: +quantity, SpawnedInSession: true },
|
||||||
};
|
};
|
||||||
|
try
|
||||||
|
{
|
||||||
itemsToSend.push(...this.itemHelper.splitStack(item));
|
itemsToSend.push(...this.itemHelper.splitStack(item));
|
||||||
}
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
this.mailSendService.sendUserMessageToPlayer(
|
||||||
|
sessionId,
|
||||||
|
commandHandler,
|
||||||
|
"Too many items requested. Please lower the amount and try again.",
|
||||||
|
);
|
||||||
|
return request.dialogId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Flag the items as FiR
|
// Flag the items as FiR
|
||||||
this.itemHelper.setFoundInRaid(itemsToSend);
|
this.itemHelper.setFoundInRaid(itemsToSend);
|
||||||
|
|
||||||
this.mailSendService.sendSystemMessageToPlayer(sessionId, "Give command!", itemsToSend);
|
this.mailSendService.sendSystemMessageToPlayer(sessionId, "SPT GIVE", itemsToSend);
|
||||||
return request.dialogId;
|
return request.dialogId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
export class SavedCommand
|
||||||
|
{
|
||||||
|
public constructor(public quantity: number, public potentialItemNames: string[], public locale: string)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -1,33 +1,22 @@
|
|||||||
import { inject, injectAll, injectable } from "tsyringe";
|
import { inject, injectAll, injectable } from "tsyringe";
|
||||||
|
|
||||||
import { ICommandoCommand } from "@spt-aki/helpers/Dialogue/Commando/ICommandoCommand";
|
import { AbstractDialogueChatBot } from "@spt-aki/helpers/Dialogue/AbstractDialogueChatBot";
|
||||||
import { IDialogueChatBot } from "@spt-aki/helpers/Dialogue/IDialogueChatBot";
|
import { IChatCommand } from "@spt-aki/helpers/Dialogue/Commando/IChatCommand";
|
||||||
import { ISendMessageRequest } from "@spt-aki/models/eft/dialog/ISendMessageRequest";
|
|
||||||
import { IUserDialogInfo } from "@spt-aki/models/eft/profile/IAkiProfile";
|
import { IUserDialogInfo } from "@spt-aki/models/eft/profile/IAkiProfile";
|
||||||
import { MemberCategory } from "@spt-aki/models/enums/MemberCategory";
|
import { MemberCategory } from "@spt-aki/models/enums/MemberCategory";
|
||||||
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
||||||
import { MailSendService } from "@spt-aki/services/MailSendService";
|
import { MailSendService } from "@spt-aki/services/MailSendService";
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class CommandoDialogueChatBot implements IDialogueChatBot
|
export class CommandoDialogueChatBot extends AbstractDialogueChatBot
|
||||||
{
|
{
|
||||||
public constructor(
|
public constructor(
|
||||||
@inject("WinstonLogger") protected logger: ILogger,
|
@inject("WinstonLogger") logger: ILogger,
|
||||||
@inject("MailSendService") protected mailSendService: MailSendService,
|
@inject("MailSendService") mailSendService: MailSendService,
|
||||||
@injectAll("CommandoCommand") protected commandoCommands: ICommandoCommand[],
|
@injectAll("CommandoCommand") chatCommands: IChatCommand[],
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
}
|
super(logger, mailSendService, chatCommands);
|
||||||
|
|
||||||
public registerCommandoCommand(commandoCommand: ICommandoCommand): void
|
|
||||||
{
|
|
||||||
if (this.commandoCommands.some((cc) => cc.getCommandPrefix() === commandoCommand.getCommandPrefix()))
|
|
||||||
{
|
|
||||||
throw new Error(
|
|
||||||
`The commando command ${commandoCommand.getCommandPrefix()} being registered already exists!`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
this.commandoCommands.push(commandoCommand);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public getChatBot(): IUserDialogInfo
|
public getChatBot(): IUserDialogInfo
|
||||||
@ -39,37 +28,8 @@ export class CommandoDialogueChatBot implements IDialogueChatBot
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public handleMessage(sessionId: string, request: ISendMessageRequest): string
|
protected getUnrecognizedCommandMessage(): string
|
||||||
{
|
{
|
||||||
if ((request.text ?? "").length === 0)
|
return `I'm sorry soldier, I don't recognize the command you are trying to use! Type "help" to see available commands.`;
|
||||||
{
|
|
||||||
this.logger.error("Commando command came in as empty text! Invalid data!");
|
|
||||||
return request.dialogId;
|
|
||||||
}
|
|
||||||
|
|
||||||
const splitCommand = request.text.split(" ");
|
|
||||||
|
|
||||||
const commandos = this.commandoCommands.filter((c) => c.getCommandPrefix() === splitCommand[0]);
|
|
||||||
if (commandos[0]?.getCommands().has(splitCommand[1]))
|
|
||||||
{
|
|
||||||
return commandos[0].handle(splitCommand[1], this.getChatBot(), sessionId, request);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (splitCommand[0].toLowerCase() === "help")
|
|
||||||
{
|
|
||||||
const helpMessage = this.commandoCommands.map((c) =>
|
|
||||||
`Help for ${c.getCommandPrefix()}:\n${
|
|
||||||
Array.from(c.getCommands()).map((command) => c.getCommandHelp(command)).join("\n")
|
|
||||||
}`
|
|
||||||
).join("\n");
|
|
||||||
this.mailSendService.sendUserMessageToPlayer(sessionId, this.getChatBot(), helpMessage);
|
|
||||||
return request.dialogId;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.mailSendService.sendUserMessageToPlayer(
|
|
||||||
sessionId,
|
|
||||||
this.getChatBot(),
|
|
||||||
`Im sorry soldier, I dont recognize the command you are trying to use! Type "help" to see available commands.`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user