This is a PocketMine-MP 5.0 form library with PHP 8.0 support and high quality code
This API is a spoon of Frago's forms library and also includes a ServerSettingsForm which is inspired of skymin's ServerSettingsForm virion and a Image loading fix which is inspired by Muqsit's FormImagesFix plugin.
In order to use the ServerSettingsForms, ImageFix and the auto-back feature you first need to register the packet handler by doing
protected function onEnable(): void{
\Jibix\Forms\Forms::register($this);
}
Note: You only need to do this if you use this plugin as a virion, otherwise it's handled by the Main class
Auto-back is a feature that sends the previous opened form to the player once they close a form or click on a back button. It also overwrites back buttons in a MenuForm with close buttons if there's no form to go back to If you want to use the auto-back feature, you just need to do
\Jibix\Forms\Forms::setAutoBack(true);
Image fix is a workaround for a MCPE MenuForm bug, where url button images take ages to load To make this work you only need to do the registration
The ServerSettingsForm is similar to a CustomForm and has the same elements, but will be displayed in the player's game-settings ui Once you have registered the packet handler, you can just use the ServerSettingsFormEvent
public function onServerSettingsForm(ServerSettingsFormEvent $event): void{
$player = $event->getPlayer();
if (!$player->hasPermission(DefaultPermissions::ROOT_OPERATOR)) return; //Not an operator
(new ServerSettingsForm(
"§bServer settings",
[
new Label("Want to adjust some server settings? Just do it!"),
new Input("Motd", "§cBest Server!", Server::getInstance()->getNetwork()->getName(), function (Player $player, Input $input): void{
Server::getInstance()->getNetwork()->setName($input->getName());
}),
],
function (Player $player, CustomFormResponse $response): void{
$player->sendMessage("Done! You successfully adjusted the server settings.");
},
Image::path("textures/items/diamond") //Set the icon of the form
))->send($player);
}
Using ModalForm to represent "yes" / "no" button clicks as bool
in closure
$player->sendForm(new ModalForm("A small question", "Is our server cool?",
//result of pressing the "yes" / "no" button is written to a variable $choice
function (Player $player, bool $choice): void{
$player->sendMessage($choice ? "Thank you" : "We will try to become better");
}
));
Short version of ModalForm to confirm any action
$player->sendForm(ModalForm::confirm("Teleport request", "Do you want to accept it?",
//called only when the player selects the "yes" button
function (Player $player): void{
$player->sendMessage("*teleporting*");
}
));
Using MenuForm to display buttons with icons from URL and path
$player->sendForm(new MenuForm("Select server", "Choose server", [
//buttons without icon
new Button("SkyWars #1"),
//URL and path are supported for image
new Button("SkyWars #2", null, Image::url("https://static.wikia.nocookie.net/minecraft_gamepedia/images/f/f0/Melon_JE2_BE2.png")),
new Button("SkyWars #3", null, Image::path("textures/items/apple.png")),
//If you have some dynamic images you can use Image::detect
new Button("SkyWars #4", null, Image::detect($image)),
new BackButton(), //Dynamic back button
], function (Player $player, Button $selected): void{
$player->sendMessage("You selected: " . $selected->getText());
$player->sendMessage("Index of button: " . $selected->getValue());
}, function (Player $player): void{
$player->sendMessage("You closed the server selector!");
}));
Shorther/simpler MenuForm, you can directly set the button's onSubmit callback, which can be useful if you have object foreaches
foreach ($objectArray as $key => $object) {
$buttons[] = new Button("Key #$key", function (Player $player, Button $selected) use ($key, $object): void{
$player->sendMessage("You have selected the key #$key");
//Do something with $object
})
}
$buttons[] = new BackButton(); //Dynamic back button
$player->sendForm(new MenuForm("Select key", "Choose key", $buttons));
Using CustomForm with strict-typed API
$player->sendForm(new CustomForm("Enter data", [
new Dropdown("Select product", ["beer", "cheese", "cola"]),
new Input("Enter your name", "Bob"),
new Label("I am label!"), //Note: get<BaseElement>() does not work with label
new Slider("Select count", 0.0, 100.0, 1.0, 50.0),
new StepSlider("Select product", ["beer", "cheese", "cola"]),
new Toggle("Creative", $player->isCreative()),
], function (Player $player, CustomFormResponse $response): void{
$dropdown = $response->getDropdown();
$player->sendMessage("You selected: " . $dropdown->getSelectedOption());
$input = $response->getInput();
$player->sendMessage("Your name is " . $input->getValue());
$slider = $response->getSlider();
$player->sendMessage("Count: " . $slider->getValue());
$stepSlider = $response->getStepSlider();
$player->sendMessage("You selected: " . $stepSlider->getSelectedOption());
$toggle = $response->getToggle();
$player->setGamemode($toggle->getValue() ? GameMode::CREATIVE() : GameMode::SURVIVAL());
}));
Using CustomForm with less strict-typed API
$player->sendForm(new CustomForm("Enter data", [
new Dropdown("Select product", ["beer", "cheese", "cola"]),
new Input("Enter your name", "Bob"),
new Label("I am label!"), //Note: get<BaseElement>() does not work with label
new Slider("Select count", 0.0, 100.0, 1.0, 50.0),
new StepSlider("Select product", ["beer", "cheese", "cola"]),
new Toggle("Creative", $player->isCreative()),
], function (Player $player, CustomFormResponse $response): void{
[$product1, $username, $count, $product2, $enableCreative] = $response->getValues();
$player->sendMessage("You selected: $product1");
$player->sendMessage("Your name is $username");
$player->sendMessage("Count: $count");
$player->sendMessage("You selected: $product2");
$player->setGamemode($enableCreative ? GameMode::CREATIVE() : GameMode::SURVIVAL());
}));
Using CustomForms elements with directly setting their onSubmit callback
$player->sendForm(new CustomForm("Enter data", [
new Dropdown("Select product #1", ["beer", "cheese", "cola"], "", function (Player $player, Dropdown $dropdown): void{
$player->sendMessage("Your first product is {$dropdown->getSelectedOption()}");
}),
new Input("Enter your name", "Bob", "", function (Player $player, Input $input): void{
$player->sendMessage("You entered the name: {$input->getValue()}!");
}),
new Label("I am label!"),
new Slider("Select count", 0.0, 100.0, 1.0, 50.0, function (Player $player, Slider $slider): void{
$player->sendMessgae("You selected a count of {$slider->getValue()}");
}),
new StepSlider("Select product #2", ["beef", "fanta", "chips"], "", function (Player $player, StepSlider $slider): void{
$player->sendMessage("Your second product is {$slider->getSelectedOption()}");
}),
new Toggle("Creative", $player->isCreative(), function (Player $player, Toggle $toggle): void{
$player->setGamemode($toggle->getValue() ? GameMode::CREATIVE() : GameMode::SURVIVAL());
}),
]));
From/to Data CustomForm. This can be useful if you want to send the same ui again, but with some changes, such as an error message label
public function sendCustomForm(Player $player, array $data = [], ?string $message = null){
$player->sendForm(new CustomForm(
"Enter rank data",
CustomForm::fromData([
new Label($message ?? "Enter the ranks data!")
new Input("Name", "Owner"),
new Slider("Price", 0, 100, 1)
], $data),
function (Player $player, CustomFormResponse $response): void{
$data = $response->__toData();
[$name, $price] = $response->getElements();
$error = match (true) {
strlen($name) < 4 => "§cThe name must be at least 4 chars!",
strlen($name) > 20 => "§cThe name must be shorter than 20 chars!",
//other checks
default => null
};
if ($error !== null) {
$this->sendCustomForm($player, $data, $error);
return;
}
//Do something with the rank data
}
));
}
An uncloseable form can be useful if you permanently want to display something to the player
$player->sendForm(new MenuForm(
"§cMaintenance",
"Hello {$player->getName()}! Unfortunately we are currently in maintenance to update some server features!\nPlease come back once we announce that we're done with the update.",
[],
null,
Form::uncloseable()
));