Forms & UI¶
Bedrokia features a modern, ultra-optimized (.NET 10, zero reflection) and secure system for Bedrock Forms and Data-Driven UI (DDUI / DataStore), built upon the strict server-authoritative security model of Dragonfly (df-mc/dragonfly).
1. SimpleForm (Button Menu)¶
A standard menu containing a title, optional body text, and a list of clickable buttons (with optional local texture path or URL icon).
using Bedrokia.Server.Game.Ui.Forms;
var form = new SimpleForm("Shop")
.Content("Select an item to purchase:")
.Button("Diamond Sword", "textures/items/diamond_sword", FormButtonImageType.Path, player =>
{
player.SendMessage("§aYou bought a Diamond Sword!");
})
.Button("Golden Apple", "textures/items/apple_golden", FormButtonImageType.Path, player =>
{
player.SendMessage("§eYou bought a Golden Apple!");
})
.OnClose((player, reason) =>
{
if (reason == FormCancelReason.UserClosed)
player.SendMessage("§7Shop closed.");
});
player.SendForm(form);
2. ModalForm (Yes / No Confirmation)¶
A binary modal dialog asking for confirmation (true or false).
var confirm = new ModalForm("Teleport", "Do you want to teleport to the world spawn?")
.ConfirmText("Yes, Teleport")
.CancelText("Cancel")
.OnSubmit((player, accepted) =>
{
if (accepted)
{
var (x, y, z) = server.World.Spawn;
player.Teleport(x + 0.5f, y, z + 0.5f);
player.SendMessage("§aTeleported!");
}
else
{
player.SendMessage("§cTeleportation cancelled.");
}
});
player.SendForm(confirm);
3. CustomForm (Interactive Form)¶
Supports labels, headers, dividers, text inputs, toggles, sliders, step sliders, and dropdown menus.
var custom = new CustomForm("Player Preferences")
.Label("Customize your in-game preferences below:")
.Input("Display Name", placeholder: "e.g. Steve", defaultValue: player.Name, maxLength: 16)
.Toggle("Allow Private Messages", defaultValue: true)
.Slider("Music Volume", min: 0.0, max: 100.0, step: 5.0, defaultValue: 50.0)
.StepSlider("Difficulty Level", ["Easy", "Normal", "Hard"], defaultIndex: 1)
.Dropdown("Language", ["English", "Français", "Español"], defaultIndex: 0)
.OnSubmit((player, result) =>
{
string nickname = result.GetString(1);
bool pmsEnabled = result.GetBool(2);
double volume = result.GetDouble(3);
string difficulty = result.GetSelectedOption(4) ?? "Normal";
string language = result.GetSelectedOption(5) ?? "English";
player.SendMessage($"§aSettings saved! Language: §e{language}§a, Difficulty: §e{difficulty}");
})
.OnClose((player, reason) =>
{
if (reason == FormCancelReason.InvalidResponse)
player.SendMessage("§cInvalid data received from client.");
});
player.SendForm(custom);
4. Dragonfly-Grade Security & Anti-DoS Protection¶
The Bedrokia server enforces Absolute Server Authority over all client form interactions:
- Anti-Replay Protection: Each form has an incremental, unique
FormId. Upon receiving a response, the form record is immediately removed before executing callbacks (preventing double-click and retransmission exploits). - Bounded Form Queue: Maximum 3 pending forms per player. Stale or overflowing forms are cleanly closed with
UserBusy. - Strict Anti-DoS Limits: Payloads exceeding 16 KB or JSON depth greater than 2 are instantly rejected.
- Server-Side Element Validation:
Input: bounded length (maxLength, default 256) and illegal control characters are automatically stripped.Slider: rejectsNaNand infinite values, enforces strict[min, max]bounds.Dropdown&StepSlider: selection indices are strictly validated against the server-defined option list.- Automatic Lifecycle Cleanup: Active forms and DDUI sessions are cleaned up when a player disconnects, dies, or after a timeout period (5 minutes).
5. Data-Driven UI (DDUI) & DataStore¶
Supports custom screens backed by client-side data stores:
using Bedrokia.Server.Game.Ui.Ddui;
// 1. Define a DataStore with schema validation
var store = new DduiDataStore("MyHudStore")
.DefineProperty("coins", typeof(double), clientWritable: false) // Server-only
.DefineProperty("sound_mute", typeof(bool), clientWritable: true); // Client-editable
store.Set("coins", 1500.0);
store.Set("sound_mute", false);
// 2. Open DDUI screen for player
player.ShowDduiScreen("custom_hud_screen", store);
// 3. Reactively update property on client
player.SendDataStoreUpdate("MyHudStore", "coins", "1750");