This PR started out as an effort to decouple Command and CommandMap, but it's turned into a bit more than that.
A summary of changes:
## UX
- Added `cmdalias create`, `cmdalias delete` and `cmdalias list` commands
- `/help` now shows prefixed names such as `pocketmine:help`
- Prefixed command name (e.g. `pocketmine:help`) are now visible to Minecraft clients
- Permission denied messages are now able to show more useful context when e.g. checking subcommand permissions
- Multiple commands claiming an alias make the alias unusable (an error will be shown when used telling the user to pick from the namespaced names), instead of whichever plugin loaded last getting lucky
## API
- Added `CommandAliasMap`, which handles mapping of aliases to namespaced command IDs
- Added `CommandSender->getCommandAliasMap()` for user-specific aliases
- Added `CommandMap->getAliasMap()` for global fallback aliases
- `Command` no longer tracks its own registered aliases (now the job of `CommandMap`), breaking circular dependency
- Aliases must now be provided to `CommandMap->register()`
- Aliases can now be individually registered and unregistered without re-registering/unregistering the whole command using `CommandAliasMap` APIs
- Aliases are no longer namespaced, only the main command name (e.g. `pocketmine:?` is now gone while `pocketmine:help` still exists)
- `Command` now requires a `$namespace` parameter, which replaces the old `$fallbackPrefix` parameter of `register()`. It should be set to the name of the plugin.
Relevant issues
- #6508
- #3371 - this PR doesn't implement storage, but allows configuration of per-user aliases during server runtime
This has several advantages:
Easier to implement new blocks (one less file to modify)
Easier to adjust serialization of existing blocks
Guaranteed consistency between serializers and deserializers
Potentially, exposes more metadata for programmatic analysis, instead of having everything baked inside opaque Closures
There are some exceptions which still use the old approach: big dripleaf, cauldrons, mushroom stems, and pitcher crops. These all have multiple PM block types for a single ID, with relatively complex logic to select which to use. These weren't worth the effort to unify due to their small number. I may revisit this in the future, but I already spent a lot of brainpower on it.
- `AsyncGeneratorExecutor` class added that encapsulates the logic of generating chunks using async tasks as previously
- `GeneratorExecutor` interface added that can be implemented to provide chunks in other ways
- `SyncGeneratorExecutor` which invokes the generator directly on the main thread, useful for simple generators like `Flat` where async tasks are not needed
- Some redundant APIs were removed from `World` (these will probably come back as deprecated stubs for the remainder of 5.x, but I was having too much fun deleting code)
- Removed internal `World->registerGeneratorToWorker()` (no longer useful)
- `World` now invokes generator executor instead of posting AsyncTasks directly
- Some internal classes moved to `pocketmine\world\generator\executor` (PopulationTask excluded because plugins use it in lieu of being able to regenerate chunks
- Generators can opt into main-thread execution by setting the `$fast` parameter to `true` in `GeneratorManager::register()`
we can safely assume this for blocks (though the type info doesn't reflect it) but this is not safe to assume for random APIs that might be used by plugins.
until now, any thread crash would show as a generic crash since we aren't able to get the trace from the crashed thread directly. This uses some dirty tricks to export a partially serialized stack trace to the main thread, where it can be written into a crashdump.
This enables us to see proper crash information for async tasks in the crash archive (finally!!!) as well as being able to capture RakLib errors properly.