https://github.com/sof3/actionapi
Generalized user interface framework for PocketMine plugins.
https://github.com/sof3/actionapi
Last synced: 8 months ago
JSON representation
Generalized user interface framework for PocketMine plugins.
- Host: GitHub
- URL: https://github.com/sof3/actionapi
- Owner: SOF3
- License: mit
- Created: 2021-04-18T08:30:44.000Z (over 4 years ago)
- Default Branch: master
- Last Pushed: 2021-04-21T06:20:46.000Z (over 4 years ago)
- Last Synced: 2025-05-06T22:02:55.351Z (8 months ago)
- Language: PHP
- Size: 25.4 KB
- Stars: 16
- Watchers: 4
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# ActionApi
Generalized user interface framework for PocketMine plugins.
## How does this work?
ActionApi introduces the following concepts:
### Action
`Action` is an interface implemented by plugins
to represent something that a user can do.
Each action type implements a new subclass of `Action`.
A new instance of `Action` is created for every execution.
An `Action` subclass holds the arguments required for the action.
### Arg
`Arg` is an argument that the user provides to customize the action.
They can be inferred from the `Hook` (action trigger),
or separately requested from the user.
Implementations provided by `ActionApi`:
| Type | Command line support | Form UI support | Inference from `Hook` |
| :---: | :---: | :---: | :---: |
| `StringArg` | Yes (single argument or space implosion) | Yes (`CustomForm` `Input`) | None |
| `StringEnumArg` | Yes (single argument) | Yes (`CustomForm` `Dropdown`, or `CustomForm` `StepSlider`, or `MenuForm`) | None |
| `StringEnumSetArg` | Yes (last argument only, or if delimiter is provided) | Yes (`CustomForm` `Toggle`s) | None |
| `IntArg` | Yes | Yes (`CustomForm` `Slider`, or `CustomForm` `Input`) | None |
| `FloatArg` | Yes | Yes (`CustomForm` `Slider`, or `CustomForm` `Input`) | None |
| `BoolArg` | Yes | Yes (`CustomForm` `Toggle`, or `ModalForm`) | None |
| `GenericListArg` | Yes if element type supports (rearranged as last argument, variadic) | Yes if element type supports (interactive loop) | If element type is inferrable, singleton list |
| `PlayerArg` (online players only) | Yes (by name prefix or full name) | Yes (`CustomForm` `Dropdown`, or `MenuForm`) | If hook is clicking on a player |
| `PlayerSetArg` (online players only) | Yes (comma-separated) | Yes (`CustomForm` `Toggle`s) | None |
| `EntityArg` | No | Yes (click on entity in world) | If hook is clicking on an entity |
| `BlockTypeArg` | Yes (by name, with variant colon-separated) | Yes (interactive selector with search button) | If hook is clicking on a block |
| `ItemArg` | Yes (by name, with damage and count colon-separated) | Yes (interactive selector with search button) | If hook is clicking on air, a block or entity (default value is currently held item) |
| `ItemTypeArg` | Yes (by name, with damage colon-separated) | Yes (interactive selector with search button) | If hook is clicking on air, a block or entity (default value is currently held item) |
| `PositionArg` | Yes (by typing x y z world-name) | Yes (`CustomForm` `Dropdown` to select current position, `CustomForm` `Input`, current crosshair target or next-click position) | If hook is clicking on a block or entity (otherwise) |
| `WorldArg` | Yes (world name) | Yes (`CustomForm` `Dropdown`, or `MenuForm`) | None (default value is player current world) |
| `WorldSetArg` | Yes (last argument only) | Yes (`CustomForm` `Toggle`s) | None |
| `YawArg` | Yes (in degrees, not recommended) | Yes (`CustomForm` `Slider`) | Player current orientation |
| `PitchArg` | Yes (in degrees, not recommended) | Yes (`CustomForm` `Slider`) | Player current orientation |
| `DateTimeArg` | Yes (ISO 8601, or `+` + duration) | Yes (`CustomForm` `Slider`s for YMDhmsZ) | None |
| `DurationArg` | Yes (single argument, e.g. `1w2d3h4m5s`) | Yes (interactive loop with `CustomForm` `Input` + `Dropdown` for unit) | None |
Inference from `Hook` may be suppressed as the default value instead of silently selected
by an extra flag from the constructor call in the `Action` implementation.
### Hook
`Hook` is the method that the user used to trigger the initiation of this action.
It stores data related to the trigger.
Implementations provided by `ActionApi`:
- command
- block click
- air click
- entity click
- item selection
- hotbar switch
- action menu (a navigation index for actions defined in config.yml)
### Example `Action` implementation
```php
final class AddWarpAction implements Action {
private DataProvider $db;
private ?string $name = null;
private ?Position $pos = null;
private ?bool $open = null;
public function __construct(DataProvider $db) {
$this->db = $db;
}
public function isMissingArg() : bool {
return $this->name === null || $this->pos === null || $this->open === null;
}
public function getArguments() : iterable {
yield StringArg::new("Warp name", $this->name);
yield PositionArg::new("Warp position", $this->pos);
yield BoolArg::new("Open to public?", $this->open)->default(true);
}
public function run(CommandSender $sender) : void {
$this->db->addWarp($this->name, $this->pos->getX(), $this->pos->getY(), $this->pos->getZ(),
$this->pos->getWorld()->getFolderName(), $this->open);
$sender->sendMessage("Warp \"$this->name\" created at $this->pos");
}
}
```
### Implementing `Arg` and `Hook`
If the existing arguments are not sufficient, other plugins can implement additional `Arg` types.
Plugins that want to trigger actions from other methods can also implement their own `Hook` types.
Each `Arg` supports command line and form UI interface.
However, if an `Arg` additionally infers arguments from a `Hook`,
the logic is implemented under a separate `Inferrer` interface.
Plugins may register an `Inferrer` instance that supports a specific type of `Arg` and a specific type of `Hook`.
An example implementation for inferring `EntityArg` from an `EntityClickHook`:
```php
final class EntityClickItemInferrer implements Inferrer {
public function infer(Hook $hook) {
assert($hook instanceof EntityClickHook); // this is true if you registered the inferrer for the correct class
return $hook->getClickedEntity();
}
}
```