Adds some additional commands to denerys cli.

This commit is contained in:
Vassyli
2021-01-19 17:26:31 +01:00
committed by Basilius Sauter
parent a576bfd2a0
commit 29ad369c88
10 changed files with 367 additions and 26 deletions
@@ -30,8 +30,10 @@ class CharacterListCommand extends BaseCommand
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
$em = $this->game->getEntityManager();
$io = new SymfonyStyle($input, $output);
$characters = $this->game->getEntityManager()->getRepository(Character::class)->findAll();
$characters = $em->getRepository(Character::class)->findAll();
$table = [["id", "name", "level"], []];
foreach ($characters as $character) {
@@ -6,6 +6,7 @@ namespace LotGD\Core\Console\Command\Character;
use LotGD\Core\Console\Command\BaseCommand;
use LotGD\Core\Models\Character;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
@@ -26,7 +27,7 @@ class CharacterResetViewpointCommand extends BaseCommand
->setDescription('Resets the viewpoint of a given character.')
->setDefinition(
new InputDefinition([
new InputOption('id', null, InputOption::VALUE_REQUIRED),
new InputArgument("id", InputArgument::REQUIRED, "ID of the character"),
])
)
;
@@ -37,21 +38,24 @@ class CharacterResetViewpointCommand extends BaseCommand
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
$id = $input->getOption("id");
$em = $this->game->getEntityManager();
/* @var $character \LotGD\Core\Models\Character */
$character = $this->game->getEntityManager()->getRepository(Character::class)->find($id);
$io = new SymfonyStyle($input, $output);
$id = $input->getArgument("id");
/* @var $character Character */
$character = $em->getRepository(Character::class)->find($id);
if ($character === null) {
$io->error("Character not found.");
return Command::FAILURE;
}
$this->game->getEntityManager()->remove($character->getViewpoint());
$em->remove($character->getViewpoint());
$character->setViewpoint(null);
$this->game->getEntityManager()->flush();
# Save
$em->flush();
return Command::SUCCESS;
}
@@ -3,9 +3,12 @@ declare(strict_types=1);
namespace LotGD\Core\Console\Command\Module;
use Exception;
use LotGD\Core\Console\Command\BaseCommand;
use LotGD\Core\Exceptions\ClassNotFoundException;
use LotGD\Core\Exceptions\InvalidConfigurationException;
use LotGD\Core\Exceptions\ModuleAlreadyExistsException;
use LotGD\Core\Exceptions\WrongTypeException;
use LotGD\Core\LibraryConfiguration;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
@@ -35,9 +38,17 @@ class ModuleRegisterCommand extends BaseCommand
$io = new SymfonyStyle($input, $output);
$modules = $this->game->getComposerManager()->getModulePackages();
$globalFlawless = true;
$registered = [];
foreach ($modules as $p) {
$this->registerModule($p->getName(), $io, $registered);
$flawless = $this->registerModule($p->getName(), $io, $registered);
$globalFlawless &= $flawless;
}
if (!$globalFlawless) {
$io->warning("Some module were not registered properly.");
return Command::FAILURE;
}
return Command::SUCCESS;
@@ -46,34 +57,55 @@ class ModuleRegisterCommand extends BaseCommand
/**
* Register a given package as a module if it is of type lotdg-module. Resolves dependencies and skips already registered packages.
* @param string $packageName
* @param OutputInterface $output
* @param SymfonyStyle $io
* @param array $registered
* @throws \LotGD\Core\Exceptions\InvalidConfigurationException
* @throws \LotGD\Core\Exceptions\WrongTypeException
* @return bool True if registering was flawless
* @throws InvalidConfigurationException
* @throws WrongTypeException
* @throws Exception
*/
protected function registerModule(
string $packageName,
SymfonyStyle $io,
array &$registered
) {
): bool {
$composerRepository = $this->game->getComposerManager()->getComposer()
->getRepositoryManager()->getLocalRepository();
$package = $composerRepository->findPackage($packageName, "*");
# Skip if not a lotgd-module
if ($package->getType() !== "lotgd-module") {
return;
return true;
}
# Skip if already registered
if (!empty($registered[$packageName])) {
return;
return true;
}
$io->text("Reading module {$packageName} {$package->getPrettyVersion()}");
$library = new LibraryConfiguration($this->game->getComposerManager(), $package, $this->game->getCWD());
# Try to load module configuration ($moduleRoot/lotgd.yml)
try {
$library = new LibraryConfiguration($this->game->getComposerManager(), $package, $this->game->getCWD());
} catch (InvalidConfigurationException) {
$io->error("\tModule {$packageName} does not have a valid lotgd.yml in its root.");
return false;
}
# Register dependencies first.
$dependencyFlawless = true;
$dependencies = $package->getRequires();
foreach ($dependencies as $dependency) {
$this->registerModule($dependency->getTarget(), $io, $registered);
$dependencyFlawless &= $this->registerModule($dependency->getTarget(), $io, $registered);
}
# If $dependencyFlawless is not true anymore (as true & false == 0), we should abort as a dependency was not met.
if (!$dependencyFlawless) {
$io->warning("\t{$packageName} was not completely installed, as one of its dependencies had an "
."error during registration.");
return false;
}
try {
@@ -83,8 +115,11 @@ class ModuleRegisterCommand extends BaseCommand
$io->note("\tSkipping already registered module {$packageName}");
} catch (ClassNotFoundException $e) {
$io->error("\tError installing module {$packageName}: {$e->getMessage()}");
return false;
}
$registered[$packageName] = true;
return true;
}
}
@@ -34,7 +34,8 @@ class ModuleValidateCommand extends BaseCommand
foreach ($results as $r) {
$output->writeln($r);
}
return 1;
return Command::FAILURE;
}
$output->writeln("<info>LotGD modules validated</info>");
@@ -0,0 +1,92 @@
<?php
declare(strict_types=1);
namespace LotGD\Core\Console\Command\Scene;
use LotGD\Core\Console\Command\BaseCommand;
use LotGD\Core\Models\Character;
use LotGD\Core\Models\Scene;
use LotGD\Core\Models\SceneConnectable;
use LotGD\Core\Models\SceneConnection;
use LotGD\Core\Models\SceneConnectionGroup;
use LotGD\Core\Models\SceneTemplate;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
/**
* Resets the viewpoint of a given character.
*/
class SceneAddCommand extends BaseCommand
{
/**
* @inheritDoc
*/
protected function configure()
{
$this->setName('scene:add')
->setDescription('Add a scene.')
->setDefinition(
new InputDefinition([
new InputArgument(
"title",
mode: InputArgument::REQUIRED,
description: "Scene title",
),
new InputArgument(
"description",
mode: InputArgument::OPTIONAL,
description: "Scene description",
default: "",
),
new InputOption(
"template",
mode: InputOption::VALUE_OPTIONAL,
description: "A valid, user-assignable scene template. Check sceneTemplate:list to get all available scenes.",
default: null,
)
])
)
;
}
/**
* @inheritDoc
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
$em = $this->game->getEntityManager();
$io = new SymfonyStyle($input, $output);
$title = $input->getArgument("title");
$description = $input->getArgument("description");
$templateClass = $input->getArgument("template");
/* @var $template SceneTemplate */
if ($templateClass) {
$template = $em->getRepository(SceneTemplate::class)->find($templateClass);
if (!$template) {
$io->warning("Template '$template' has not been found. Set to NULL instead.")
}
} else {
$template = $templateClass;
}
$scene = Scene::create([
"title" => $title,
"description" => $description,
"template" => $template,
]);
$em->persist($scene);
$em->flush();
return Command::SUCCESS;
}
}
@@ -0,0 +1,49 @@
<?php
declare(strict_types=1);
namespace LotGD\Core\Console\Command\Scene;
use LotGD\Core\Console\Command\BaseCommand;
use LotGD\Core\Models\Scene;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
class SceneListCommand extends BaseCommand
{
/**
* @inheritDoc
*/
protected function configure()
{
$this->setName('scene:list')
->setDescription('Lists all scenes')
;
}
/**
* @inheritDoc
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
$em = $this->game->getEntityManager();
$io = new SymfonyStyle($input, $output);
/** @var Scene[] $scenes */
$scenes = $em->getRepository(Scene::class)->findAll();
$table = [["id", "title", "connections"], []];
foreach ($scenes as $scene) {
$table[1][] = [
$scene->getId(),
$scene->getTitle(),
count($scene->getConnectedScenes()),
];
}
$io->table(...$table);
return Command::SUCCESS;
}
}
@@ -0,0 +1,105 @@
<?php
declare(strict_types=1);
namespace LotGD\Core\Console\Command\Scene;
use LotGD\Core\Console\Command\BaseCommand;
use LotGD\Core\Models\Character;
use LotGD\Core\Models\Scene;
use LotGD\Core\Models\SceneConnectable;
use LotGD\Core\Models\SceneConnection;
use LotGD\Core\Models\SceneConnectionGroup;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
/**
* Resets the viewpoint of a given character.
*/
class SceneShowCommand extends BaseCommand
{
/**
* @inheritDoc
*/
protected function configure()
{
$this->setName('scene:show')
->setDescription('Show details about a specific scene.')
->setDefinition(
new InputDefinition([
new InputArgument("id", InputArgument::REQUIRED, "ID of the scene"),
])
)
;
}
/**
* @inheritDoc
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
$em = $this->game->getEntityManager();
$io = new SymfonyStyle($input, $output);
$id = $input->getArgument("id");
/* @var $scene Scene */
$scene = $em->getRepository(Scene::class)->find($id);
if ($scene === null) {
$io->error("Scene not found.");
return Command::FAILURE;
}
$io->title("About scene '{$scene->getTitle()}'");
$io->listing([
"ID: {$scene->getId()}",
"Title: {$scene->getTitle()}",
"Template: {$scene->getTemplate()->getClass()}",
]);
$io->text($scene->getDescription());
$io->section("Connection groups");
/** @var SceneConnectionGroup[] $connectionGroups */
$connectionGroups = $scene->getConnectionGroups();
$list = [];
foreach ($connectionGroups as $connectionGroup) {
$list[] = "{$connectionGroup->getTitle()} (id={$connectionGroup->getName()})";
}
$io->listing($list);
$io->section("Connected Scenes");
/** @var SceneConnection[] $connections */
$connections = $scene->getConnections();
$list = [];
foreach ($connections as $connection) {
if ($connection->getOutgoingScene() === $scene) {
$other = $connection->getIncomingScene();
if ($connection->isDirectionality(SceneConnectable::Bidirectional)) {
$list[] = "this <=> {$other->getTitle()} (id={$other->getId()})";
} else {
$list[] = "this => {$other->getTitle()} (id={$other->getId()})";
}
} else {
$other = $connection->getOutgoingScene();
if ($connection->isDirectionality(SceneConnectable::Bidirectional)) {
$list[] = "this <=> {$other->getTitle()} (id={$other->getId()})";
} else {
$list[] = "this <= {$other->getTitle()} (id={$other->getId()})";
}
}
}
$io->listing($list);
return Command::SUCCESS;
}
}
@@ -0,0 +1,48 @@
<?php
declare(strict_types=1);
namespace LotGD\Core\Console\Command\SceneTemplates;
use LotGD\Core\Console\Command\BaseCommand;
use LotGD\Core\Models\Scene;
use LotGD\Core\Models\SceneTemplate;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
class SceneTemplateListCommand extends BaseCommand
{
/**
* @inheritDoc
*/
protected function configure()
{
$this->setName('sceneTemplate:list')
->setDescription('Lists all registered scene templates')
;
}
/**
* @inheritDoc
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
$em = $this->game->getEntityManager();
$io = new SymfonyStyle($input, $output);
/** @var SceneTemplate[] $templates */
$templates = $em->getRepository(SceneTemplate::class)->findAll();
$table = [["class"], []];
foreach ($templates as $template) {
$table[1][] = [
$template->getClass(),
];
}
$io->table(...$table);
return Command::SUCCESS;
}
}
+6
View File
@@ -12,6 +12,9 @@ use LotGD\Core\Console\Command\Database\DatabaseInitCommand;
use LotGD\Core\Console\Command\Database\DatabaseSchemaUpdateCommand;
use LotGD\Core\Console\Command\Module\ModuleRegisterCommand;
use LotGD\Core\Console\Command\Module\ModuleValidateCommand;
use LotGD\Core\Console\Command\Scene\SceneListCommand;
use LotGD\Core\Console\Command\Scene\SceneAddCommand;
use LotGD\Core\Console\Command\SceneTemplates\SceneTemplateListCommand;
use LotGD\Core\Game;
use Symfony\Component\Console\Application;
@@ -47,6 +50,9 @@ class Main
$this->application->add(new ConsoleCommand($this->game));
$this->application->add(new CharacterListCommand($this->game));
$this->application->add(new CharacterResetViewpointCommand($this->game));
$this->application->add(new SceneListCommand($this->game));
$this->application->add(new SceneAddCommand($this->game));
$this->application->add(new SceneTemplateListCommand($this->game));
// Add additional ones
$this->bootstrap->addDaenerysCommands($this->application);
+7 -8
View File
@@ -53,7 +53,7 @@ class Scene implements CreateableInterface, SceneConnectable
private $properties;
// required for PropertyManager to now which class the properties belong to.
private $propertyClass = SceneProperty::class;
private string $propertyClass = SceneProperty::class;
/**
* @var array
@@ -64,8 +64,7 @@ class Scene implements CreateableInterface, SceneConnectable
"template",
];
/* @var ?ArrayCollection */
private $connectedScenes = null;
private ?Collection $connectedScenes = null;
/**
* Constructor for a scene.
@@ -110,13 +109,13 @@ class Scene implements CreateableInterface, SceneConnectable
*/
public function hasConnectionGroup(string $name): bool
{
return \count($this->filterConnectionGroupCollectionByName($name)) === 1 ? true : false;
return \count($this->filterConnectionGroupCollectionByName($name)) === 1;
}
/**
* Returns a connection group entity associated with this scene by a given name.
* @param string $name
* @return \LotGD\Core\Models\SceneConnectionGroup
* @return SceneConnectionGroup
*/
public function getConnectionGroup(string $name): SceneConnectionGroup
{
@@ -125,7 +124,7 @@ class Scene implements CreateableInterface, SceneConnectable
/**
* Returns all connection groups associated with this scene.
* @return Collection
* @return Collection<SceneConnectionGroup>
*/
public function getConnectionGroups(): Collection
{
@@ -199,9 +198,9 @@ class Scene implements CreateableInterface, SceneConnectable
* This procedure can get slow, especially if there are a lot of scenes connected
* to one. Use this method only for the installation and removal of modules,
* or for administrative purposes (like a scene graph).
* @return ArrayCollection
* @return Collection
*/
public function getConnectedScenes(): ArrayCollection
public function getConnectedScenes(): Collection
{
$this->loadConnectedScenes();
return $this->connectedScenes;