Skip to content

Text and messages

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"))));

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.

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.

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}.");
};

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]) { ... }

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.