/Jibix-Forms

A very advanced PocketMine-MP form library

Primary LanguagePHP

Forms

php api

This is a PocketMine-MP 5.0 form library with PHP 8.0 support and high quality code

Credits

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.

Code samples

Registration

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

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

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

ServerSettingsForm

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

ModalForm

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

MenuForm

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

CustomForm

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

Uncloseable form

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