Text and messages
Text and translations
Section titled “Text and translations”Every piece of text is either a literal or a key into your own translation tables:
plugin.Translations.Add("en", new Dictionary<string, string>{ ["greet"] = "Greet {name}",});
menu.AddButton(Text.Key("greet", ("name", Text.Literal("world"))));plugin.Translations:Add('en', { greet = 'Greet {name}',})
menu:AddButton(vMenu.Text.Key('greet', { name = 'world' }))plugin.translations.add('en', { greet: 'Greet {name}',});
menu.addButton(vMenu.Text.key('greet', { name: 'world' }));import { Text } from '@vespura/vmenu-plugin/client';
plugin.translations.add('en', { greet: 'Greet {name}',});
menu.addButton(Text.key('greet', { name: 'world' }));A plain string is a literal, so translating is always deliberate. Keys are looked up in the player’s current vMenu language and then in your English table, which is why an en table is required as soon as you provide any. Your keys are yours alone, so they never collide with vMenu’s or another plugin’s. When the player changes language, your menu follows.
Talking to the player
Section titled “Talking to the player”plugin.Notify(NotifyStyle.Success, "That worked.");plugin:Notify('success', 'That worked.')plugin.notify('success', 'That worked.');plugin.notify(NotifyStyle.Success, 'That worked.');Notifications appear in vMenu’s notification area, credited to your plugin. The style is info, success, warning or error, or NotifyStyle.Success and so on in TypeScript, and an optional third argument sets how long it stays, in milliseconds.
Asking the player for text
Section titled “Asking the player for text”GetText opens vMenu’s input box and gives back what the player typed, or nothing when they cancel. Call it from a row’s handler:
var rename = menu.AddButton("Rename vehicle");
rename.Selected += async () =>{ var name = await plugin.GetTextAsync( "New name", maxLength: 32, initialValue: "My car", suggestions: [new PromptSuggestion("Daily driver"), new PromptSuggestion("Race car", "For the track")]);
if (name is null) { return; // cancelled }
plugin.Notify(NotifyStyle.Success, $"Renamed to {name}.");};local rename = menu:AddButton('Rename vehicle')
rename:OnSelected(function() local name = plugin:GetText('New name', { MaxLength = 32, InitialValue = 'My car', Suggestions = { { Value = 'Daily driver' }, { Value = 'Race car', Description = 'For the track' } }, })
if not name then return -- cancelled end
plugin:Notify('success', ('Renamed to %s.'):format(name))end)const rename = menu.addButton('Rename vehicle');
rename.onSelected(async () => { const name = await plugin.getText('New name', { maxLength: 32, initialValue: 'My car', suggestions: [{ value: 'Daily driver' }, { value: 'Race car', description: 'For the track' }], });
if (name === null) { return; // cancelled }
plugin.notify('success', `Renamed to ${name}.`);});const rename = menu.addButton('Rename vehicle');
rename.onSelected(async () => { const name = await plugin.getText('New name', { maxLength: 32, initialValue: 'My car', suggestions: [{ value: 'Daily driver' }, { value: 'Race car', description: 'For the track' }], });
if (name === null) { return; // cancelled }
plugin.notify(NotifyStyle.Success, `Renamed to ${name}.`);});All options are optional. maxLength defaults to 60 and vMenu caps it at 500. Suggestions show as a list while the player types, and picking one fills in its value.
To ask several questions in a row, pass them all at once. You get every answer back in order, or nothing if the player cancelled any of them:
var answers = await plugin.GetTextAsync( new PluginPrompt("First name", maxLength: 20), new PluginPrompt("Last name", maxLength: 20));
if (answers is [var first, var last]) { ... }local answers = plugin:GetTexts({ { Title = 'First name', MaxLength = 20 }, { Title = 'Last name', MaxLength = 20 },})
if answers then local first, last = answers[1], answers[2]endconst answers = await plugin.getTexts([ { title: 'First name', maxLength: 20 }, { title: 'Last name', maxLength: 20 },]);
if (answers !== null) { const [first, last] = answers;}const answers = await plugin.getTexts([ { title: 'First name', maxLength: 20 }, { title: 'Last name', maxLength: 20 },]);
if (answers !== null) { const [first, last] = answers;}The box refuses, and you get nothing back, when something else is already using it. In Lua these calls wait for the answer, so call them from a menu event handler or a CreateThread, or pass a callback as the last argument.
