Compare commits
185 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b1942e675a | |||
| e2455be738 | |||
| ef9c040204 | |||
| 1e900d8ec7 | |||
| 30b9d981fa | |||
| 9019caaafc | |||
| 31eca85df4 | |||
| 8d43b3d2ce | |||
| a9e5647fe0 | |||
| 25ccbd8974 | |||
| 2e9f0dc564 | |||
| 03fde83fc1 | |||
| 669085e65d | |||
| f72adb1a38 | |||
| 0292a66252 | |||
| eea72f848b | |||
| c2a139d192 | |||
| d83e437b4a | |||
| 99d554e5d7 | |||
| 75dd7494c3 | |||
| f7504bbb60 | |||
| 60a3a8bd2b | |||
| 147692d722 | |||
| 454248ed0f | |||
| 27347d0677 | |||
| 69434c7bbf | |||
| 2a3a3e7bc2 | |||
| 47693f6127 | |||
| e3534ea88d | |||
| 5dbe8fdca3 | |||
| 31387c1840 | |||
| dfd39cd1f8 | |||
| f25bab7af8 | |||
| c0ed663ef4 | |||
| b3b1c4af0a | |||
| 2153df5cc8 | |||
| 13dfab2321 | |||
| 29ad369c88 | |||
| a576bfd2a0 | |||
| aa5b32c03d | |||
| c2aaf025f6 | |||
| 9b60cc0ebb | |||
| eca1343b5f | |||
| 1fb2eb023e | |||
| 1a0b6dbe3e | |||
| 96feb12fb5 | |||
| 512d875609 | |||
| 0a2313b5e5 | |||
| c4634b90b7 | |||
| 6325b8bd36 | |||
| dd074a8bea | |||
| fdb53972d2 | |||
| ad3ea14bb2 | |||
| bb1ca987b5 | |||
| 57b8045c1a | |||
| f658b421f6 | |||
| 7ab55c1cb0 | |||
| 05d72a11bb | |||
| d006aa3ded | |||
| 147d449a27 | |||
| c18cdef3ff | |||
| 3eb538145e | |||
| 696a5f3305 | |||
| 765b65a9d2 | |||
| 96afd4b87e | |||
| ea6be63bb3 | |||
| 126fdee80e | |||
| 81c72ca91a | |||
| 29e5ced0f9 | |||
| c7dbf33f6e | |||
| d4124a71ef | |||
| 28c12a47f1 | |||
| 709b96ea52 | |||
| 363c4678d3 | |||
| d8b8fb69d9 | |||
| 0a20c8a968 | |||
| f051d72aea | |||
| af17f434d4 | |||
| 2680a41cee | |||
| c7d91230bd | |||
| 541748a168 | |||
| 42e3f22726 | |||
| 3c64492cde | |||
| 18ec30ede5 | |||
| 4e35fbd6b3 | |||
| 32305238d9 | |||
| 13082f7b9d | |||
| 272910c3a3 | |||
| 33a7812abe | |||
| a086fe4b9b | |||
| 557215bba3 | |||
| 81a6edc074 | |||
| 1cfe1cacba | |||
| f3fee8cc7d | |||
| 90f187dbf2 | |||
| 1a6079b270 | |||
| 17b704bec4 | |||
| f6df590cd6 | |||
| 3338a75f71 | |||
| 7fe81a9c5b | |||
| 3ecb7f8e95 | |||
| 0fcc6dc8b7 | |||
| 2376696101 | |||
| a52de33ed7 | |||
| cf99395ed3 | |||
| 1c53604244 | |||
| c6ecab6ce9 | |||
| ff154ccbd9 | |||
| fc73f86ffa | |||
| a375cb98cd | |||
| e18cdd21cc | |||
| c4ff330928 | |||
| e74dcbdfde | |||
| 8612a53538 | |||
| e8f2ea56bc | |||
| d0b2d48cc1 | |||
| 14d1c9d582 | |||
| 7725c7faed | |||
| 4ca81a3789 | |||
| 353c4251c4 | |||
| 248258a8fe | |||
| 4d1ab9e763 | |||
| d7229858cc | |||
| 14b1db8b82 | |||
| d7100deb0f | |||
| e260a1d661 | |||
| 2ff8d647e8 | |||
| 8d9a186b46 | |||
| 8f69527764 | |||
| 684f86aed6 | |||
| 55481c30b1 | |||
| 6b383be1cd | |||
| d609f981aa | |||
| 4ec84dfec3 | |||
| 049d116028 | |||
| aa63259992 | |||
| a097c29d67 | |||
| bab3e0f236 | |||
| 2f89bbc7e3 | |||
| 6e2ba248c4 | |||
| b398ffae14 | |||
| 90971d152a | |||
| 04b3b6aaf9 | |||
| 0aaba1b94b | |||
| 2affd4803f | |||
| c07f7b3342 | |||
| 8a75e81431 | |||
| ccfb432e4d | |||
| 2a0bf5f038 | |||
| 4248dad033 | |||
| b89f6d7b0c | |||
| 6c4b1e15f4 | |||
| ddb7ae08a6 | |||
| 8ba04dade4 | |||
| 70243f4662 | |||
| 77b33d7385 | |||
| db49e63c99 | |||
| d90e4d0ba9 | |||
| ccbfa0553c | |||
| 04a5b59ea2 | |||
| 846ab6018e | |||
| efb333d08a | |||
| 92c0f71ed6 | |||
| c9e6f679c4 | |||
| 17ebdbdbe5 | |||
| 55b821c8e8 | |||
| 45a785a8f5 | |||
| ff713ac333 | |||
| aba0d53a68 | |||
| 9ddd16b4e8 | |||
| c0edd3ac67 | |||
| 81d773720a | |||
| 5ac7098f35 | |||
| 41db0ddfda | |||
| 003a6517ba | |||
| af6a6cbff0 | |||
| 56c80e3f8d | |||
| 4b82ee4b89 | |||
| 829d63d7f6 | |||
| 94763f8d6e | |||
| a287313f6f | |||
| 51a102f981 | |||
| 9842fa9ace | |||
| adf4eeac5e | |||
| 533378d006 |
@@ -0,0 +1,39 @@
|
|||||||
|
name: Tests
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Validate composer.json and composer.lock
|
||||||
|
run: composer validate
|
||||||
|
|
||||||
|
- name: Cache Composer packages
|
||||||
|
id: composer-cache
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: vendor
|
||||||
|
key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-php-
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
if: steps.composer-cache.outputs.cache-hit != 'true'
|
||||||
|
run: composer install --prefer-dist --no-progress --no-suggest
|
||||||
|
|
||||||
|
- name: Run test suite
|
||||||
|
run: vendor/bin/phpunit --stop-on-failure
|
||||||
|
|
||||||
|
# Add a test script to composer.json, for instance: "test": "vendor/bin/phpunit"
|
||||||
|
# Docs: https://getcomposer.org/doc/articles/scripts.md
|
||||||
|
|
||||||
|
# - name: Run test suite
|
||||||
|
# run: composer run-script test
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
name: Package push
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
release:
|
||||||
|
types: [ created ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Setup PHP with PECL extension
|
||||||
|
uses: shivammathur/setup-php@v2
|
||||||
|
with:
|
||||||
|
php-version: '7.4'
|
||||||
|
|
||||||
|
- name: Set git credentials
|
||||||
|
run: git config --global user.name "Vassyli" && git config --global user.email "basilius.sauter+automated@gmail.com" && git config --global user.password "${{ secrets.GH_TOKEN }}"
|
||||||
|
|
||||||
|
- name: Set composer token
|
||||||
|
run: composer config -g github-oauth.github.com ${{ secrets.GH_TOKEN }}
|
||||||
|
|
||||||
|
- name: "Checkouts satis and packages"
|
||||||
|
run: git clone https://github.com/composer/satis && git clone https://github.com/lotgd/packages
|
||||||
|
|
||||||
|
- name: "Install satis"
|
||||||
|
run: cd satis && composer install && cd ..
|
||||||
|
|
||||||
|
- name: "Build satis"
|
||||||
|
run: satis/bin/satis build packages/satis.json packages/build
|
||||||
|
|
||||||
|
- name: Set git url with credentials for pushing
|
||||||
|
run: cd packages && git config remote.origin.url 'https://Vassyli:${{ secrets.GH_TOKEN }}@github.com/lotgd/packages.git' && cd ..
|
||||||
|
|
||||||
|
- name: "Commit changes and push to origin"
|
||||||
|
run: cd packages && git add build/* && git commit -a -m "Updated packages" && git push origin master && cd ..
|
||||||
@@ -228,3 +228,8 @@ pip-log.txt
|
|||||||
#Mr Developer
|
#Mr Developer
|
||||||
.mr.developer.cfg
|
.mr.developer.cfg
|
||||||
dbconfig.php
|
dbconfig.php
|
||||||
|
composer.phar
|
||||||
|
clover.xml
|
||||||
|
.phpunit.result.cache
|
||||||
|
|
||||||
|
.php_cs.cache
|
||||||
+142
@@ -0,0 +1,142 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return PhpCsFixer\Config::create()
|
||||||
|
->setRiskyAllowed(true)
|
||||||
|
->setRules([
|
||||||
|
'align_multiline_comment' => true,
|
||||||
|
'array_indentation' => true,
|
||||||
|
'array_syntax' => ['syntax' => 'short'],
|
||||||
|
'binary_operator_spaces' => true,
|
||||||
|
'blank_line_after_namespace' => true,
|
||||||
|
'braces' => [
|
||||||
|
'position_after_control_structures' => 'same',
|
||||||
|
'position_after_functions_and_oop_constructs' => 'next',
|
||||||
|
],
|
||||||
|
'cast_spaces' => ['space' => 'none'],
|
||||||
|
'class_definition' => true,
|
||||||
|
'class_keyword_remove' => false,
|
||||||
|
'combine_consecutive_issets' => true,
|
||||||
|
'combine_consecutive_unsets' => true,
|
||||||
|
'compact_nullable_typehint' => true,
|
||||||
|
'declare_strict_types' => true,
|
||||||
|
'declare_equal_normalize' => true,
|
||||||
|
'dir_constant' => true,
|
||||||
|
'doctrine_annotation_array_assignment' => true,
|
||||||
|
'doctrine_annotation_braces' => true,
|
||||||
|
'doctrine_annotation_indentation' => true,
|
||||||
|
'doctrine_annotation_spaces' => [
|
||||||
|
'after_array_assignments_colon' => false,
|
||||||
|
'after_array_assignments_equals' => false,
|
||||||
|
'before_argument_assignments' => false,
|
||||||
|
'before_array_assignments_colon' => false,
|
||||||
|
'before_array_assignments_equals' => false,
|
||||||
|
],
|
||||||
|
'elseif' => true,
|
||||||
|
'encoding' => true,
|
||||||
|
'ereg_to_preg' => true,
|
||||||
|
'escape_implicit_backslashes' => true,
|
||||||
|
'explicit_indirect_variable' => true,
|
||||||
|
'explicit_string_variable' => true,
|
||||||
|
'full_opening_tag' => true,
|
||||||
|
'fully_qualified_strict_types' => true,
|
||||||
|
'function_declaration' => true,
|
||||||
|
'function_typehint_space' => true,
|
||||||
|
'general_phpdoc_annotation_remove' => true,
|
||||||
|
'indentation_type' => true,
|
||||||
|
'line_ending' => true,
|
||||||
|
'linebreak_after_opening_tag' => true,
|
||||||
|
'list_syntax' => ['syntax' => 'short'],
|
||||||
|
'lowercase_cast' => true,
|
||||||
|
'lowercase_constants' => true,
|
||||||
|
'lowercase_static_reference' => true,
|
||||||
|
'magic_constant_casing' => true,
|
||||||
|
'magic_method_casing' => true,
|
||||||
|
'method_argument_space' => true,
|
||||||
|
'method_chaining_indentation' => true,
|
||||||
|
'multiline_comment_opening_closing' => true,
|
||||||
|
'multiline_whitespace_before_semicolons' => ['strategy' => 'new_line_for_chained_calls'],
|
||||||
|
'native_constant_invocation' => true,
|
||||||
|
'native_function_invocation' => true,
|
||||||
|
'native_function_type_declaration_casing' => true,
|
||||||
|
'new_with_braces' => true,
|
||||||
|
'no_alias_functions' => true,
|
||||||
|
'no_alternative_syntax' => true,
|
||||||
|
'no_blank_lines_after_phpdoc' => true,
|
||||||
|
'no_break_comment' => true,
|
||||||
|
'no_closing_tag' => true,
|
||||||
|
'no_empty_comment' => true,
|
||||||
|
'no_empty_phpdoc' => true,
|
||||||
|
'no_empty_statement' => true,
|
||||||
|
'no_extra_blank_lines' => true,
|
||||||
|
'no_homoglyph_names' => true,
|
||||||
|
'no_leading_import_slash' => true,
|
||||||
|
'no_leading_namespace_whitespace' => true,
|
||||||
|
'no_mixed_echo_print' => ["use" => "print"],
|
||||||
|
'no_multiline_whitespace_around_double_arrow' => true,
|
||||||
|
'no_php4_constructor' => true,
|
||||||
|
'no_short_bool_cast' => true,
|
||||||
|
'no_singleline_whitespace_before_semicolons' => true,
|
||||||
|
'no_spaces_after_function_name' => true,
|
||||||
|
'no_spaces_around_offset' => true,
|
||||||
|
'no_spaces_inside_parenthesis' => true,
|
||||||
|
'no_trailing_comma_in_list_call' => true,
|
||||||
|
'no_trailing_comma_in_singleline_array' => true,
|
||||||
|
'no_trailing_whitespace' => true,
|
||||||
|
'no_trailing_whitespace_in_comment' => true,
|
||||||
|
'no_unneeded_control_parentheses' => true,
|
||||||
|
'no_unneeded_curly_braces' => true,
|
||||||
|
'no_unneeded_final_method' => true,
|
||||||
|
'no_unreachable_default_argument_value' => true,
|
||||||
|
'no_unused_imports' => true,
|
||||||
|
'no_useless_else' => true,
|
||||||
|
'no_useless_return' => true,
|
||||||
|
'no_whitespace_before_comma_in_array' => true,
|
||||||
|
'non_printable_character' => true,
|
||||||
|
'normalize_index_brace' => true,
|
||||||
|
'object_operator_without_whitespace' => true,
|
||||||
|
'ordered_imports' => true,
|
||||||
|
'phpdoc_add_missing_param_annotation' => true,
|
||||||
|
'phpdoc_indent' => true,
|
||||||
|
'phpdoc_no_access' => true,
|
||||||
|
'phpdoc_no_alias_tag' => true,
|
||||||
|
'phpdoc_no_empty_return' => true,
|
||||||
|
'phpdoc_no_package' => true,
|
||||||
|
'phpdoc_no_useless_inheritdoc' => true,
|
||||||
|
'phpdoc_order' => true,
|
||||||
|
'phpdoc_scalar' => true,
|
||||||
|
'phpdoc_single_line_var_spacing' => true,
|
||||||
|
'phpdoc_summary' => true,
|
||||||
|
'phpdoc_to_return_type' => true,
|
||||||
|
'phpdoc_trim_consecutive_blank_line_separation' => true,
|
||||||
|
'phpdoc_types' => true,
|
||||||
|
'phpdoc_types_order' => ['null_adjustment' => 'always_last'],
|
||||||
|
'phpdoc_var_annotation_correct_order' => true,
|
||||||
|
'pow_to_exponentiation' => true,
|
||||||
|
'psr4' => true,
|
||||||
|
'random_api_migration' => true,
|
||||||
|
'return_type_declaration' => true,
|
||||||
|
'self_accessor' => true,
|
||||||
|
'semicolon_after_instruction' => true,
|
||||||
|
'set_type_to_cast' => true,
|
||||||
|
'short_scalar_cast' => true,
|
||||||
|
'single_blank_line_at_eof' => true,
|
||||||
|
'single_blank_line_before_namespace' => true,
|
||||||
|
'single_class_element_per_statement' => true,
|
||||||
|
'single_import_per_statement' => true,
|
||||||
|
'single_line_after_imports' => true,
|
||||||
|
'standardize_not_equals' => true,
|
||||||
|
'standardize_increment' => true,
|
||||||
|
'switch_case_semicolon_to_colon' => true,
|
||||||
|
'switch_case_space' => true,
|
||||||
|
'ternary_to_null_coalescing' => true,
|
||||||
|
'trailing_comma_in_multiline_array' => true,
|
||||||
|
'trim_array_spaces' => false,
|
||||||
|
'unary_operator_spaces' => true,
|
||||||
|
'visibility_required' => true,
|
||||||
|
'whitespace_after_comma_in_array' => true,
|
||||||
|
'yoda_style' => false,
|
||||||
|
])
|
||||||
|
->setFinder(
|
||||||
|
PhpCsFixer\Finder::create()
|
||||||
|
->in(__DIR__."/src")
|
||||||
|
);
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
sudo: false
|
|
||||||
language: php
|
|
||||||
php:
|
|
||||||
- '7.1'
|
|
||||||
install:
|
|
||||||
- composer install
|
|
||||||
script:
|
|
||||||
- ./t
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
# Legend of the Green Dragon (Core)
|
# Legend of the Green Dragon (Core)
|
||||||
|
|
||||||
[](https://travis-ci.org/lotgd/core)
|

|
||||||
|
|
||||||
Legend of the Green Dragon is a text-based RPG originally developed by Eric Stevens and JT Traub as a remake of and homage to the classic BBS Door game,
|
Legend of the Green Dragon is a text-based RPG originally developed by Eric Stevens and JT Traub as a remake of and homage to the classic BBS Door game,
|
||||||
Legend of the Red Dragon, by Seth Able Robinson. You can play it at numerous sites, including http://www.lotgd.net/.
|
Legend of the Red Dragon, by Seth Able Robinson. You can play it at numerous sites, including http://www.lotgd.net/.
|
||||||
|
|||||||
+17
-11
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "lotgd/core",
|
"name": "lotgd/core",
|
||||||
"description": "Core functionality for Legend of the Green Dragon, a text-based RPG game.",
|
"description": "Core functionality for Legend of the Green Dragon, a text-based RPG game.",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0-or-later",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"LotGD\\Core\\": "src/",
|
"LotGD\\Core\\": "src/",
|
||||||
@@ -12,13 +12,19 @@
|
|||||||
"bin/daenerys"
|
"bin/daenerys"
|
||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^7.1.0",
|
"php": "^8.0",
|
||||||
"composer/composer": "*",
|
"ext-pdo": "*",
|
||||||
"gedmo/doctrine-extensions": "*",
|
"composer/composer": "^1.10|^2.0",
|
||||||
"doctrine/orm": "^2.5",
|
"gedmo/doctrine-extensions": "^2.3|^3.0",
|
||||||
"monolog/monolog": "^1.12",
|
"doctrine/orm": "^2.8",
|
||||||
"symfony/console": "^3.0",
|
"doctrine/common": "^3.0",
|
||||||
"symfony/yaml": "^3.0",
|
"doctrine/dbal": "^2.12 <2.13",
|
||||||
|
"monolog/monolog": "^2.0",
|
||||||
|
"symfony/console": "^5.0",
|
||||||
|
"symfony/yaml": "^5.0",
|
||||||
|
"twig/twig": "^3.0",
|
||||||
|
"ramsey/uuid-doctrine": "^1.5",
|
||||||
|
"jetbrains/phpstorm-attributes": "^1.0",
|
||||||
"d11wtq/boris": "^1.0"
|
"d11wtq/boris": "^1.0"
|
||||||
},
|
},
|
||||||
"repositories": [
|
"repositories": [
|
||||||
@@ -29,8 +35,8 @@
|
|||||||
|
|
||||||
],
|
],
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpunit/phpunit": "^5.0",
|
"phpunit/phpunit": "*",
|
||||||
"phpunit/dbunit": "^2.0",
|
"phpunit/php-code-coverage": "*",
|
||||||
"block8/php-docblock-checker": "2.0.0"
|
"friendsofphp/php-cs-fixer": "*"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+3956
-911
File diff suppressed because it is too large
Load Diff
@@ -3,6 +3,7 @@ database:
|
|||||||
name: daenerys
|
name: daenerys
|
||||||
user: root
|
user: root
|
||||||
password:
|
password:
|
||||||
|
disableAutoSchemaUpdate: false
|
||||||
game:
|
game:
|
||||||
epoch: 2016-07-01 00:00:00.0 -8
|
epoch: 2016-07-01 00:00:00.0 -8
|
||||||
offsetSeconds: 0
|
offsetSeconds: 0
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<phpunit bootstrap="bootstrap/bootstrap.php">
|
<phpunit bootstrap="bootstrap/bootstrap.php">
|
||||||
<php>
|
<php>
|
||||||
<env name="LOTGD_TESTS_CONFIG_PATH" value="./config/lotgd.yml"/>
|
<env name="LOTGD_TESTS_CONFIG_PATH" value="./config/lotgd.yml"/>
|
||||||
|
<env name="COLUMNS" value="120" />
|
||||||
</php>
|
</php>
|
||||||
<testsuites>
|
<testsuites>
|
||||||
<testsuite name="All">
|
<testsuite name="All">
|
||||||
|
|||||||
+72
-18
@@ -3,29 +3,64 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace LotGD\Core;
|
namespace LotGD\Core;
|
||||||
|
|
||||||
|
use LotGD\Core\Models\Viewpoint;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A representation of an action the user can take to affect the game
|
* A representation of an action the user can take to affect the game
|
||||||
* state. An encapsulation of a navigation menu option.
|
* state. An encapsulation of a navigation menu option.
|
||||||
*/
|
*/
|
||||||
class Action
|
class Action implements \Serializable
|
||||||
{
|
{
|
||||||
protected $id;
|
protected string $id;
|
||||||
protected $destinationSceneId;
|
private ?Viewpoint $viewpoint = null;
|
||||||
protected $title = null;
|
|
||||||
protected $parameters = [];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new action with the specified Scene as its destination.
|
* Construct a new action with the specified Scene as its destination.
|
||||||
* @param int $destinationSceneId
|
* @param string $destinationSceneId
|
||||||
* @param string|null $title
|
* @param string|null $title
|
||||||
* @param array $parameters
|
* @param array $parameters
|
||||||
*/
|
*/
|
||||||
public function __construct(int $destinationSceneId, ?string $title = null, array $parameters = [])
|
public function __construct(
|
||||||
|
protected string $destinationSceneId,
|
||||||
|
protected ?string $title = null,
|
||||||
|
protected array $parameters = []
|
||||||
|
) {
|
||||||
|
$this->id = \bin2hex(\random_bytes(8));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function serialize()
|
||||||
{
|
{
|
||||||
$this->id = bin2hex(random_bytes(8));
|
return serialize([
|
||||||
$this->destinationSceneId = $destinationSceneId;
|
"id" => $this->id,
|
||||||
$this->title = $title;
|
"destinationSceneId" => $this->destinationSceneId,
|
||||||
$this->parameters = $parameters;
|
"title" => $this->title,
|
||||||
|
"parameters" => $this->parameters,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function unserialize($serialized)
|
||||||
|
{
|
||||||
|
$data = unserialize($serialized);
|
||||||
|
$this->id = $data["id"];
|
||||||
|
$this->destinationSceneId = $data["destinationSceneId"];
|
||||||
|
$this->title = $data["title"];
|
||||||
|
$this->parameters = $data["parameters"];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Viewpoint|null $viewpoint
|
||||||
|
*/
|
||||||
|
public function setViewpoint(?Viewpoint $viewpoint)
|
||||||
|
{
|
||||||
|
$this->viewpoint = $viewpoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Viewpoint|null
|
||||||
|
*/
|
||||||
|
public function getViewpoint(): ?Viewpoint
|
||||||
|
{
|
||||||
|
return $this->viewpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -41,15 +76,15 @@ class Action
|
|||||||
/**
|
/**
|
||||||
* Return the database ID of the destination scene, where the user will
|
* Return the database ID of the destination scene, where the user will
|
||||||
* go if they take this action.
|
* go if they take this action.
|
||||||
* @return int
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getDestinationSceneId(): int
|
public function getDestinationSceneId(): string
|
||||||
{
|
{
|
||||||
return $this->destinationSceneId;
|
return $this->destinationSceneId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return null|string
|
* @return string|null
|
||||||
*/
|
*/
|
||||||
public function getTitle(): ?string
|
public function getTitle(): ?string
|
||||||
{
|
{
|
||||||
@@ -57,15 +92,34 @@ class Action
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return null|string
|
* Returns the rendered action title.
|
||||||
|
* @return string|null
|
||||||
|
* @throws Exceptions\InsecureTwigTemplateError
|
||||||
*/
|
*/
|
||||||
public function setTitle(?string $title)
|
public function getRenderedTitle(): ?string
|
||||||
|
{
|
||||||
|
$title = $this->getTitle();
|
||||||
|
$sceneRenderer = $this->getViewpoint()?->getTwigSceneRenderer();
|
||||||
|
|
||||||
|
if (!$title) {
|
||||||
|
return null;
|
||||||
|
} elseif ($sceneRenderer) {
|
||||||
|
return $sceneRenderer->render($title, $this->viewpoint, ignoreErrors: true, templateValues: ["Action" => $this]);
|
||||||
|
} else {
|
||||||
|
return $title;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string|null $title
|
||||||
|
*/
|
||||||
|
public function setTitle(?string $title): void
|
||||||
{
|
{
|
||||||
$this->title = $title;
|
$this->title = $title;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all parameters for this action
|
* Returns all parameters for this action.
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function getParameters(): array
|
public function getParameters(): array
|
||||||
@@ -74,7 +128,7 @@ class Action
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets all parameters for this action
|
* Sets all parameters for this action.
|
||||||
* @param array $parameters
|
* @param array $parameters
|
||||||
*/
|
*/
|
||||||
public function setParameters(array $parameters): void
|
public function setParameters(array $parameters): void
|
||||||
|
|||||||
+86
-13
@@ -1,20 +1,23 @@
|
|||||||
<?php
|
<?php
|
||||||
declare (strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace LotGD\Core;
|
namespace LotGD\Core;
|
||||||
|
|
||||||
|
use LotGD\Core\Models\Viewpoint;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A grouping of navigation actions, like a submenu.
|
* A grouping of navigation actions, like a submenu.
|
||||||
*/
|
*/
|
||||||
class ActionGroup
|
class ActionGroup implements \Countable, \Serializable
|
||||||
{
|
{
|
||||||
const DefaultGroup = 'lotgd/core/default';
|
const DefaultGroup = 'lotgd/core/default';
|
||||||
const HiddenGroup = 'lotgd/core/hidden';
|
const HiddenGroup = 'lotgd/core/hidden';
|
||||||
|
|
||||||
private $id;
|
/**
|
||||||
private $title;
|
* @var Action[]
|
||||||
private $sortKey;
|
*/
|
||||||
private $actions;
|
private array $actions;
|
||||||
|
private ?Viewpoint $viewpoint = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new ActionGroup, starting with an empty set of actions.
|
* Create a new ActionGroup, starting with an empty set of actions.
|
||||||
@@ -22,14 +25,62 @@ class ActionGroup
|
|||||||
* @param string $title Title to display to the end user. Empty string means no title.
|
* @param string $title Title to display to the end user. Empty string means no title.
|
||||||
* @param int $sortKey Navigation menus are displayed in the order sorted by this integer.
|
* @param int $sortKey Navigation menus are displayed in the order sorted by this integer.
|
||||||
*/
|
*/
|
||||||
public function __construct(string $id, string $title, int $sortKey)
|
public function __construct(
|
||||||
{
|
private string $id,
|
||||||
$this->id = $id;
|
private string $title,
|
||||||
$this->title = $title;
|
private int $sortKey
|
||||||
$this->sortKey = $sortKey;
|
) {
|
||||||
$this->actions = [];
|
$this->actions = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function serialize()
|
||||||
|
{
|
||||||
|
return serialize([
|
||||||
|
"id" => $this->id,
|
||||||
|
"title" => $this->title,
|
||||||
|
"actions" => $this->actions,
|
||||||
|
"sortKey" => $this->sortKey,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function unserialize($serialized)
|
||||||
|
{
|
||||||
|
$data = unserialize($serialized);
|
||||||
|
$this->id = $data["id"];
|
||||||
|
$this->title = $data["title"];
|
||||||
|
$this->actions = $data["actions"];
|
||||||
|
$this->sortKey = $data["sortKey"];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Viewpoint|null $viewpoint
|
||||||
|
*/
|
||||||
|
public function setViewpoint(?Viewpoint $viewpoint)
|
||||||
|
{
|
||||||
|
$this->viewpoint = $viewpoint;
|
||||||
|
|
||||||
|
foreach ($this->actions as $action) {
|
||||||
|
$action->setViewpoint($viewpoint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Viewpoint|null
|
||||||
|
*/
|
||||||
|
public function getViewpoint(): ?Viewpoint
|
||||||
|
{
|
||||||
|
return $this->viewpoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of registered Actions for this group.
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function count(): int
|
||||||
|
{
|
||||||
|
return \count($this->actions);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the unique identifier for this group, in the vendor/module/group format.
|
* Returns the unique identifier for this group, in the vendor/module/group format.
|
||||||
* @return string
|
* @return string
|
||||||
@@ -48,6 +99,23 @@ class ActionGroup
|
|||||||
return $this->title;
|
return $this->title;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the rendered title for this group.
|
||||||
|
* @return string
|
||||||
|
* @throws Exceptions\InsecureTwigTemplateError
|
||||||
|
*/
|
||||||
|
public function getRenderedTitle(): string
|
||||||
|
{
|
||||||
|
$title = $this->getTitle();
|
||||||
|
$sceneRenderer = $this->viewpoint?->getTwigSceneRenderer();
|
||||||
|
|
||||||
|
if ($sceneRenderer) {
|
||||||
|
return $sceneRenderer->render($title, $this->viewpoint, ignoreErrors: true);
|
||||||
|
} else {
|
||||||
|
return $title;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the sort key for this group. The ordering of the groups in the
|
* Returns the sort key for this group. The ordering of the groups in the
|
||||||
* final menu displayed to users will be sorted by this key. The default
|
* final menu displayed to users will be sorted by this key. The default
|
||||||
@@ -61,7 +129,7 @@ class ActionGroup
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the ordered array of actions.
|
* Returns the ordered array of actions.
|
||||||
* @return array<Action>
|
* @return Action[]
|
||||||
*/
|
*/
|
||||||
public function getActions(): array
|
public function getActions(): array
|
||||||
{
|
{
|
||||||
@@ -70,10 +138,14 @@ class ActionGroup
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the ordered array of actions.
|
* Sets the ordered array of actions.
|
||||||
* @param array<Action> $actions
|
* @param Action[] $actions
|
||||||
*/
|
*/
|
||||||
public function setActions(array $actions)
|
public function setActions(array $actions)
|
||||||
{
|
{
|
||||||
|
foreach ($actions as $action) {
|
||||||
|
$action->setViewpoint($this->viewpoint);
|
||||||
|
}
|
||||||
|
|
||||||
$this->actions = $actions;
|
$this->actions = $actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,6 +155,7 @@ class ActionGroup
|
|||||||
*/
|
*/
|
||||||
public function addAction(Action $action)
|
public function addAction(Action $action)
|
||||||
{
|
{
|
||||||
|
$action->setViewpoint($this->viewpoint);
|
||||||
$this->actions[] = $action;
|
$this->actions[] = $action;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-17
@@ -3,24 +3,31 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace LotGD\Core;
|
namespace LotGD\Core;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use LotGD\Core\Models\Scene;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An attachment to a scene. This is desigend to be subclasses by modules to
|
* An attachment to a scene. This is desigend to be subclasses by modules to
|
||||||
* provide functinoality like forms or maybe image attachments to go along with a scene.
|
* provide functinoality like forms or maybe image attachments to go along with a scene.
|
||||||
*/
|
*/
|
||||||
abstract class Attachment
|
abstract class Attachment implements AttachmentInterface
|
||||||
{
|
{
|
||||||
protected $id;
|
protected string $id;
|
||||||
protected $type;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new attachment of the given type. Randomly assigns it an ID.
|
* Construct a new attachment of the given type. Randomly assigns it an ID.
|
||||||
* @param string $type Type of this attachment, in the vendor/module/type format.
|
* @param Game $game
|
||||||
* @return Attachment
|
* @param Scene $scene
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public function __construct(string $type)
|
public function __construct(Game $game, Scene $scene)
|
||||||
{
|
{
|
||||||
$this->id = bin2hex(random_bytes(8));
|
$this->id = \bin2hex(\random_bytes(8));
|
||||||
$this->type = $type;
|
}
|
||||||
|
|
||||||
|
public function __toString(): string
|
||||||
|
{
|
||||||
|
return "<Attachment#{$this->id} '{". static::class . "}'>";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -32,13 +39,4 @@ abstract class Attachment
|
|||||||
{
|
{
|
||||||
return $this->id;
|
return $this->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the type of this attachment, in vendor/module/type format.
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getType(): string
|
|
||||||
{
|
|
||||||
return $this->type;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LotGD\Core;
|
||||||
|
|
||||||
|
use LotGD\Core\Models\Scene;
|
||||||
|
|
||||||
|
interface AttachmentInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* AttachmentInterface constructor.
|
||||||
|
* @param Game $g Should not be saved internally.
|
||||||
|
* @param Scene $scene Should not be saved internally.
|
||||||
|
*/
|
||||||
|
public function __construct(Game $g, Scene $scene);
|
||||||
|
public function __toString(): string;
|
||||||
|
public function getId(): string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array with attachment-specific fields.
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getData(): array;
|
||||||
|
}
|
||||||
+105
-97
@@ -3,25 +3,17 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace LotGD\Core;
|
namespace LotGD\Core;
|
||||||
|
|
||||||
use Doctrine\Common\Collections\{
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
ArrayCollection,
|
use Doctrine\Common\Collections\Collection;
|
||||||
Collection
|
|
||||||
};
|
|
||||||
|
|
||||||
use LotGD\Core\{
|
use LotGD\Core\Exceptions\ArgumentException;
|
||||||
DiceBag,
|
use LotGD\Core\Exceptions\BattleIsOverException;
|
||||||
Exceptions\ArgumentException,
|
use LotGD\Core\Exceptions\BattleNotOverException;
|
||||||
Exceptions\BattleIsOverException,
|
use LotGD\Core\Models\BattleEvents\CriticalHitEvent;
|
||||||
Exceptions\BattleNotOverException,
|
use LotGD\Core\Models\BattleEvents\DamageEvent;
|
||||||
Models\FighterInterface
|
use LotGD\Core\Models\BattleEvents\DeathEvent;
|
||||||
};
|
use LotGD\Core\Models\Buff;
|
||||||
use LotGD\Core\Models\{
|
use LotGD\Core\Models\FighterInterface;
|
||||||
Buff,
|
|
||||||
BattleEvents\BuffMessageEvent,
|
|
||||||
BattleEvents\CriticalHitEvent,
|
|
||||||
BattleEvents\DamageEvent,
|
|
||||||
BattleEvents\DeathEvent
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class for managing and running battles between 2 participants.
|
* Class for managing and running battles between 2 participants.
|
||||||
@@ -38,18 +30,10 @@ class Battle
|
|||||||
const RESULT_PLAYERDEATH = 1;
|
const RESULT_PLAYERDEATH = 1;
|
||||||
const RESULT_MONSTERDEATH = 2;
|
const RESULT_MONSTERDEATH = 2;
|
||||||
|
|
||||||
protected $player;
|
protected ArrayCollection $events;
|
||||||
protected $monster;
|
protected int $result = 0;
|
||||||
protected $game;
|
protected int $round = 0;
|
||||||
protected $events;
|
protected array $configuration = [
|
||||||
protected $result = 0;
|
|
||||||
protected $round = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Battle Configuration
|
|
||||||
* @var type
|
|
||||||
*/
|
|
||||||
protected $configuration = [
|
|
||||||
"riposteEnabled" => true,
|
"riposteEnabled" => true,
|
||||||
"levelAdjustementEnabled" => true,
|
"levelAdjustementEnabled" => true,
|
||||||
"criticalHitEnabled" => true,
|
"criticalHitEnabled" => true,
|
||||||
@@ -57,35 +41,54 @@ class Battle
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Takes a game object and two participants (Player and Monster) to fight a battle.
|
* Takes a game object and two participants (Player and Monster) to fight a battle.
|
||||||
* @param \LotGD\Core\Game $game
|
* @param Game $game
|
||||||
* @param FighterInterface $player
|
* @param FighterInterface $player
|
||||||
* @param FighterInterface $monster
|
* @param FighterInterface|null $monster
|
||||||
*/
|
*/
|
||||||
public function __construct(Game $game, FighterInterface $player, FighterInterface $monster)
|
public function __construct(
|
||||||
{
|
protected Game $game,
|
||||||
$this->game = $game;
|
protected FighterInterface $player,
|
||||||
$this->player = $player;
|
protected ?FighterInterface $monster
|
||||||
$this->monster = $monster;
|
) {
|
||||||
$this->events = new ArrayCollection();
|
$this->events = new ArrayCollection();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ToDo Returns at some point battle actions
|
* Returns a string which contains the important fields that must be serialized.
|
||||||
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getActions()
|
public function serialize(): string
|
||||||
{
|
{
|
||||||
|
return \serialize([
|
||||||
|
"monster" => $this->monster,
|
||||||
|
"result" => $this->result,
|
||||||
|
"round" => $this->round,
|
||||||
|
"configuration" => $this->configuration,
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ToDo Do some action
|
* @param Game $game
|
||||||
|
* @param FighterInterface $player
|
||||||
|
* @param string $serialized
|
||||||
|
* @return self
|
||||||
*/
|
*/
|
||||||
public function selectAction()
|
public static function unserialize(Game $game, FighterInterface $player, string $serialized): self
|
||||||
{
|
{
|
||||||
|
$battle = new self($game, $player, null);
|
||||||
|
$unserialized = \unserialize($serialized);
|
||||||
|
|
||||||
|
$battle->monster = $unserialized["monster"];
|
||||||
|
$battle->result = $unserialized["result"];
|
||||||
|
$battle->round = $unserialized["round"];
|
||||||
|
$battle->configuration = $unserialized["configuration"];
|
||||||
|
|
||||||
|
return $battle;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list of all battle events
|
* Returns a list of all battle events.
|
||||||
* @return \LotGD\Core\Collection
|
* @return Collection
|
||||||
*/
|
*/
|
||||||
public function getEvents(): Collection
|
public function getEvents(): Collection
|
||||||
{
|
{
|
||||||
@@ -93,23 +96,23 @@ class Battle
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disables ripostes
|
* Disables ripostes.
|
||||||
*/
|
*/
|
||||||
public function disableRiposte()
|
public function disableRiposte(): void
|
||||||
{
|
{
|
||||||
$this->configuration["riposteEnabled"] = false;
|
$this->configuration["riposteEnabled"] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enables ripostes
|
* Enables ripostes.
|
||||||
*/
|
*/
|
||||||
public function enableRiposte()
|
public function enableRiposte(): void
|
||||||
{
|
{
|
||||||
$this->configuration["riposteEnabled"] = true;
|
$this->configuration["riposteEnabled"] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if ripostes are enabled
|
* Returns true if ripostes are enabled.
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function isRiposteEnabled(): bool
|
public function isRiposteEnabled(): bool
|
||||||
@@ -118,23 +121,23 @@ class Battle
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enables level adjustement
|
* Enables level adjustement.
|
||||||
*/
|
*/
|
||||||
public function enableLevelAdjustement()
|
public function enableLevelAdjustement(): void
|
||||||
{
|
{
|
||||||
$this->configuration["levelAdjustementEnabled"] = true;
|
$this->configuration["levelAdjustementEnabled"] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disables level adjustement
|
* Disables level adjustement.
|
||||||
*/
|
*/
|
||||||
public function disableLevelAdjustement()
|
public function disableLevelAdjustement(): void
|
||||||
{
|
{
|
||||||
$this->configuration["levelAdjustementEnabled"] = false;
|
$this->configuration["levelAdjustementEnabled"] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if level adjustements are enabled
|
* Returns true if level adjustements are enabled.
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function isLevelAdjustementEnabled(): bool
|
public function isLevelAdjustementEnabled(): bool
|
||||||
@@ -143,7 +146,7 @@ class Battle
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if critical hit events are enabled
|
* Returns true if critical hit events are enabled.
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function isCriticalHitEnabled(): bool
|
public function isCriticalHitEnabled(): bool
|
||||||
@@ -152,17 +155,17 @@ class Battle
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disable critical hits
|
* Disable critical hits.
|
||||||
*/
|
*/
|
||||||
public function disableCriticalHit()
|
public function disableCriticalHit(): void
|
||||||
{
|
{
|
||||||
$this->configuration["criticalHitEnabled"] = false;
|
$this->configuration["criticalHitEnabled"] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* enables critical hits
|
* enables critical hits.
|
||||||
*/
|
*/
|
||||||
public function enableCriticalHit()
|
public function enableCriticalHit(): void
|
||||||
{
|
{
|
||||||
$this->configuration["criticalHitEnabled"] = true;
|
$this->configuration["criticalHitEnabled"] = true;
|
||||||
}
|
}
|
||||||
@@ -177,7 +180,7 @@ class Battle
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the player instance
|
* Returns the player instance.
|
||||||
* @return FighterInterface
|
* @return FighterInterface
|
||||||
*/
|
*/
|
||||||
public function getPlayer(): FighterInterface
|
public function getPlayer(): FighterInterface
|
||||||
@@ -186,7 +189,7 @@ class Battle
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the montser instance
|
* Returns the montser instance.
|
||||||
* @return FighterInterface
|
* @return FighterInterface
|
||||||
*/
|
*/
|
||||||
public function getMonster(): FighterInterface
|
public function getMonster(): FighterInterface
|
||||||
@@ -195,7 +198,8 @@ class Battle
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the winner of this fight
|
* Returns the winner of this fight.
|
||||||
|
* @throws BattleNotOverException if battle is not over.
|
||||||
* @return FighterInterface
|
* @return FighterInterface
|
||||||
*/
|
*/
|
||||||
public function getWinner(): FighterInterface
|
public function getWinner(): FighterInterface
|
||||||
@@ -208,7 +212,8 @@ class Battle
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the loser of this fight
|
* Returns the loser of this fight.
|
||||||
|
* @throws BattleNotOverException if battle is not over.
|
||||||
* @return FighterInterface
|
* @return FighterInterface
|
||||||
*/
|
*/
|
||||||
public function getLoser(): FighterInterface
|
public function getLoser(): FighterInterface
|
||||||
@@ -224,7 +229,9 @@ class Battle
|
|||||||
* Fights the number of rounds given by the parameter $n and returns the number
|
* Fights the number of rounds given by the parameter $n and returns the number
|
||||||
* of actual rounds fought.
|
* of actual rounds fought.
|
||||||
* @param int $n
|
* @param int $n
|
||||||
* @param bool $firstDamageRound Which damage rounds are calculated. Cannot be 0.
|
* @param int $firstDamageRound Which damage rounds are calculated. Cannot be 0.
|
||||||
|
* @throws ArgumentException if firstDamageRound is 0.
|
||||||
|
* @throws BattleIsOverException
|
||||||
* @return int Number of fights fought.
|
* @return int Number of fights fought.
|
||||||
*/
|
*/
|
||||||
public function fightNRounds(int $n = 1, int $firstDamageRound = self::DAMAGEROUND_BOTH): int
|
public function fightNRounds(int $n = 1, int $firstDamageRound = self::DAMAGEROUND_BOTH): int
|
||||||
@@ -246,14 +253,14 @@ class Battle
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $count+1;
|
return $count + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fights exactly 1 round
|
* Fights exactly 1 round.
|
||||||
* @param int $firstDamageRound
|
* @param int $firstDamageRound
|
||||||
*/
|
*/
|
||||||
protected function fightOneRound(int $firstDamageRound)
|
protected function fightOneRound(int $firstDamageRound): void
|
||||||
{
|
{
|
||||||
$damageHasBeenDone = false;
|
$damageHasBeenDone = false;
|
||||||
|
|
||||||
@@ -266,7 +273,7 @@ class Battle
|
|||||||
$offenseTurnEvents = $firstDamageRound & self::DAMAGEROUND_PLAYER ? $this->turn($this->player, $this->monster) : new ArrayCollection();
|
$offenseTurnEvents = $firstDamageRound & self::DAMAGEROUND_PLAYER ? $this->turn($this->player, $this->monster) : new ArrayCollection();
|
||||||
$defenseTurnEvents = $firstDamageRound & self::DAMAGEROUND_MONSTER ? $this->turn($this->monster, $this->player) : new ArrayCollection();
|
$defenseTurnEvents = $firstDamageRound & self::DAMAGEROUND_MONSTER ? $this->turn($this->monster, $this->player) : new ArrayCollection();
|
||||||
|
|
||||||
$events = new ArrayCollection(array_merge($offenseTurnEvents->toArray(), $defenseTurnEvents->toArray()));
|
$events = new ArrayCollection([...$offenseTurnEvents->toArray(), ...$defenseTurnEvents->toArray()]);
|
||||||
$eventsToAdd = new ArrayCollection();
|
$eventsToAdd = new ArrayCollection();
|
||||||
|
|
||||||
foreach ($events as $event) {
|
foreach ($events as $event) {
|
||||||
@@ -296,17 +303,17 @@ class Battle
|
|||||||
$monsterBuffExpiringEvents = $this->monster->getBuffs()->expireOneRound();
|
$monsterBuffExpiringEvents = $this->monster->getBuffs()->expireOneRound();
|
||||||
|
|
||||||
$this->events = new ArrayCollection(
|
$this->events = new ArrayCollection(
|
||||||
array_merge(
|
[
|
||||||
$this->events->toArray(),
|
...$this->events->toArray(),
|
||||||
$playerBuffStartEvents->toArray(),
|
...$playerBuffStartEvents->toArray(),
|
||||||
$monsterBuffStartEvents->toArray(),
|
...$monsterBuffStartEvents->toArray(),
|
||||||
$eventsToAdd->toArray(),
|
...$eventsToAdd->toArray(),
|
||||||
$playerBuffEndEvents->toArray(),
|
...$playerBuffEndEvents->toArray(),
|
||||||
$monsterBuffEndEvents->toArray(),
|
...$monsterBuffEndEvents->toArray(),
|
||||||
$playerBuffExpiringEvents->toArray(),
|
...$playerBuffExpiringEvents->toArray(),
|
||||||
$monsterBuffExpiringEvents->toArray(),
|
...$monsterBuffExpiringEvents->toArray(),
|
||||||
isset($deathEvent) ? [$deathEvent] : []
|
...isset($deathEvent) ? [$deathEvent] : [],
|
||||||
)
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -314,6 +321,7 @@ class Battle
|
|||||||
* Runs one turn.
|
* Runs one turn.
|
||||||
* @param FighterInterface $attacker
|
* @param FighterInterface $attacker
|
||||||
* @param FighterInterface $defender
|
* @param FighterInterface $defender
|
||||||
|
* @return ArrayCollection
|
||||||
*/
|
*/
|
||||||
protected function turn(FighterInterface $attacker, FighterInterface $defender): ArrayCollection
|
protected function turn(FighterInterface $attacker, FighterInterface $defender): ArrayCollection
|
||||||
{
|
{
|
||||||
@@ -346,12 +354,12 @@ class Battle
|
|||||||
|
|
||||||
// Apply buff scaling for the attacker's attack - this needs to take into
|
// Apply buff scaling for the attacker's attack - this needs to take into
|
||||||
// account the attacker's goodguyAttackModifier and the defenders badguyAttackModifier
|
// account the attacker's goodguyAttackModifier and the defenders badguyAttackModifier
|
||||||
$attackersAttack = $attacker->getAttack($this->game)
|
$attackersAttack = $attacker->getAttack()
|
||||||
* $attackersBuffs->getGoodguyAttackModifier()
|
* $attackersBuffs->getGoodguyAttackModifier()
|
||||||
* $defendersBuffs->getBadguyAttackModifier();
|
* $defendersBuffs->getBadguyAttackModifier();
|
||||||
// It's the opposite for the defender's defense - it needs to take into account the
|
// It's the opposite for the defender's defense - it needs to take into account the
|
||||||
// defender's goodguyDefenseModifier as well as the attacker's badguyDefenseModifier.
|
// defender's goodguyDefenseModifier as well as the attacker's badguyDefenseModifier.
|
||||||
$defendersDefense = $defender->getDefense($this->game)
|
$defendersDefense = $defender->getDefense()
|
||||||
* $defendersBuffs->getGoodguyDefenseModifier()
|
* $defendersBuffs->getGoodguyDefenseModifier()
|
||||||
* $attackersBuffs->getBadguyDefenseModifier()
|
* $attackersBuffs->getBadguyDefenseModifier()
|
||||||
* $defenseAdjustement;
|
* $defenseAdjustement;
|
||||||
@@ -365,17 +373,17 @@ class Battle
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Conversion from float to int, since the random number generator takes int values.
|
// Conversion from float to int, since the random number generator takes int values.
|
||||||
$attackersAttack = (int) round($attackersAttack, 0);
|
$attackersAttack = (int)\round($attackersAttack, 0);
|
||||||
$defendersDefense = (int) round($defendersDefense, 0);
|
$defendersDefense = (int)\round($defendersDefense, 0);
|
||||||
|
|
||||||
// Lets roll the
|
// Lets roll the
|
||||||
$attackersAtkRoll = $this->game->getDiceBag()->normal(0, $attackersAttack);
|
$attackersAtkRoll = $this->game->getDiceBag()->pseudoBell(0, $attackersAttack);
|
||||||
$defendersDefRoll = $this->game->getDiceBag()->normal(0, $defendersDefense);
|
$defendersDefRoll = $this->game->getDiceBag()->pseudoBell(0, $defendersDefense);
|
||||||
$damage = $attackersAtkRoll - $defendersDefRoll;
|
$damage = $attackersAtkRoll - $defendersDefRoll;
|
||||||
|
|
||||||
// If the attacker's attack after modification is bigger than before,
|
// If the attacker's attack after modification is bigger than before,
|
||||||
// we call it a critical hit and apply the CriticalHitEvent.
|
// we call it a critical hit and apply the CriticalHitEvent.
|
||||||
if ($attackersAttack > $attacker->getAttack($this->game) && $this->isCriticalHitEnabled()) {
|
if ($attackersAttack > $attacker->getAttack() && $this->isCriticalHitEnabled()) {
|
||||||
$events->add(new CriticalHitEvent($attacker, $attackersAttack));
|
$events->add(new CriticalHitEvent($attacker, $attackersAttack));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -394,10 +402,10 @@ class Battle
|
|||||||
$damage = 0;
|
$damage = 0;
|
||||||
} elseif ($attackerIsInvulnurable) {
|
} elseif ($attackerIsInvulnurable) {
|
||||||
// Attaker is invulnurable, damage is always > 0 (there is no riposte)
|
// Attaker is invulnurable, damage is always > 0 (there is no riposte)
|
||||||
$damage = abs($damage);
|
$damage = \abs($damage);
|
||||||
} elseif ($defenderIsInvulnurable) {
|
} elseif ($defenderIsInvulnurable) {
|
||||||
// Defender is invulnurable, damage is always < 0 (defender always ripostes)
|
// Defender is invulnurable, damage is always < 0 (defender always ripostes)
|
||||||
$damage = - abs($damage);
|
$damage = -\abs($damage);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($damage < 0) {
|
if ($damage < 0) {
|
||||||
@@ -419,7 +427,7 @@ class Battle
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Round the damage value and convert to int.
|
// Round the damage value and convert to int.
|
||||||
$damage = (int)round($damage, 0);
|
$damage = (int)\round($damage, 0);
|
||||||
|
|
||||||
// Add the damage event
|
// Add the damage event
|
||||||
$events->add(new DamageEvent($attacker, $defender, $damage));
|
$events->add(new DamageEvent($attacker, $defender, $damage));
|
||||||
@@ -435,15 +443,15 @@ class Battle
|
|||||||
$defendersDamageDependentBuffEvents = $defendersBuffs->processDamageDependentBuffs(Buff::ACTIVATE_DEFENSE, -$damage, $this->game, $defender, $attacker);
|
$defendersDamageDependentBuffEvents = $defendersBuffs->processDamageDependentBuffs(Buff::ACTIVATE_DEFENSE, -$damage, $this->game, $defender, $attacker);
|
||||||
|
|
||||||
return new ArrayCollection(
|
return new ArrayCollection(
|
||||||
array_merge(
|
[
|
||||||
$attackersBuffStartEvents->toArray(),
|
...$attackersBuffStartEvents->toArray(),
|
||||||
$attackersDirectBuffEvents->toArray(),
|
...$attackersDirectBuffEvents->toArray(),
|
||||||
$defendersBuffStartEvents->toArray(),
|
...$defendersBuffStartEvents->toArray(),
|
||||||
$defendersDirectBuffEvents->toArray(),
|
...$defendersDirectBuffEvents->toArray(),
|
||||||
$events->toArray(),
|
...$events->toArray(),
|
||||||
$attackersDamageDependentBuffEvents->toArray(),
|
...$attackersDamageDependentBuffEvents->toArray(),
|
||||||
$defendersDamageDependentBuffEvents->toArray()
|
...$defendersDamageDependentBuffEvents->toArray(),
|
||||||
)
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+77
-46
@@ -3,26 +3,22 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace LotGD\Core;
|
namespace LotGD\Core;
|
||||||
|
|
||||||
use Doctrine\ORM\ {
|
use Doctrine\Common\Annotations\AnnotationRegistry;
|
||||||
EntityManager,
|
use Doctrine\DBAL\DBALException;
|
||||||
EntityManagerInterface,
|
use Doctrine\DBAL\Types\Type;
|
||||||
Mapping\AnsiQuoteStrategy,
|
use Doctrine\ORM\EntityManager;
|
||||||
Tools\Setup,
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
Tools\SchemaTool
|
use Doctrine\ORM\Events as DoctrineEvents;
|
||||||
};
|
use Doctrine\ORM\Tools\SchemaTool;
|
||||||
use Monolog\ {
|
use Doctrine\ORM\Tools\Setup;
|
||||||
Logger,
|
use LotGD\Core\Doctrine\EntityPostLoadEventListener;
|
||||||
Handler\RotatingFileHandler
|
use LotGD\Core\Exceptions\InvalidConfigurationException;
|
||||||
};
|
use Monolog\Handler\RotatingFileHandler;
|
||||||
|
use Monolog\Logger;
|
||||||
|
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
use Symfony\Component\Console\Application;
|
use Symfony\Component\Console\Application;
|
||||||
|
|
||||||
use LotGD\Core\ {
|
|
||||||
ComposerManager,
|
|
||||||
BootstrapInterface,
|
|
||||||
Exceptions\InvalidConfigurationException
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The entry point for constructing a properly configured LotGD Game object.
|
* The entry point for constructing a properly configured LotGD Game object.
|
||||||
*/
|
*/
|
||||||
@@ -30,23 +26,24 @@ class Bootstrap
|
|||||||
{
|
{
|
||||||
private $logger;
|
private $logger;
|
||||||
private $game;
|
private $game;
|
||||||
private $libraryConfigurationManager = [];
|
/** @var LibraryConfigurationManager */
|
||||||
|
private $libraryConfigurationManager;
|
||||||
private $annotationDirectories = [];
|
private $annotationDirectories = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new Game object, with all the necessary configuration.
|
* Create a new Game object, with all the necessary configuration.
|
||||||
* @param string $cwd
|
* @param string|null $cwd
|
||||||
* @return Game The newly created Game object.
|
* @return Game The newly created Game object.
|
||||||
*/
|
*/
|
||||||
public static function createGame(string $cwd = null): Game
|
public static function createGame(string $cwd = null): Game
|
||||||
{
|
{
|
||||||
$game = new self();
|
$game = new self();
|
||||||
$cwd = $cwd ?? getcwd();
|
$cwd = $cwd ?? \getcwd();
|
||||||
return $game->getGame($cwd);
|
return $game->getGame($cwd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts the game kernel with the most important classes and returns the object
|
* Starts the game kernel with the most important classes and returns the object.
|
||||||
* @param string $cwd
|
* @param string $cwd
|
||||||
* @return Game
|
* @return Game
|
||||||
*/
|
*/
|
||||||
@@ -60,25 +57,33 @@ class Bootstrap
|
|||||||
$composer = $this->createComposerManager($cwd);
|
$composer = $this->createComposerManager($cwd);
|
||||||
$this->libraryConfigurationManager = $this->createLibraryConfigurationManager($composer, $cwd);
|
$this->libraryConfigurationManager = $this->createLibraryConfigurationManager($composer, $cwd);
|
||||||
|
|
||||||
list($dsn, $user, $password) = $config->getDatabaseConnectionDetails($cwd);
|
[$dsn, $user, $password] = $config->getDatabaseConnectionDetails($cwd);
|
||||||
$pdo = $this->connectToDatabase($dsn, $user, $password);
|
$pdo = $this->connectToDatabase($dsn, $user, $password);
|
||||||
$entityManager = $this->createEntityManager($pdo);
|
$entityManager = $this->createEntityManager($pdo, $config);
|
||||||
|
|
||||||
$this->game = (new GameBuilder())
|
$this->game = (new GameBuilder())
|
||||||
->withConfiguration($config)
|
->withConfiguration($config)
|
||||||
->withLogger($this->logger)
|
->withLogger($this->logger)
|
||||||
->withEntityManager($entityManager)
|
->withEntityManager($entityManager)
|
||||||
->withCwd($cwd)
|
->withCwd($cwd)
|
||||||
->create();
|
->create()
|
||||||
|
;
|
||||||
|
|
||||||
|
// Add Event listener to entity manager
|
||||||
|
$dem = $entityManager->getEventManager();
|
||||||
|
$dem->addEventListener([DoctrineEvents::postLoad], new EntityPostLoadEventListener($this->game));
|
||||||
|
|
||||||
|
// Run model extender
|
||||||
|
$this->extendModels();
|
||||||
|
|
||||||
return $this->game;
|
return $this->game;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a library configuration manager
|
* Creates a library configuration manager.
|
||||||
* @param ComposerManager $composerManager
|
* @param ComposerManager $composerManager
|
||||||
* @param string $cwd
|
* @param string $cwd
|
||||||
* @return \LotGD\Core\LibraryConfigurationManager
|
* @return LibraryConfigurationManager
|
||||||
*/
|
*/
|
||||||
protected function createLibraryConfigurationManager(
|
protected function createLibraryConfigurationManager(
|
||||||
ComposerManager $composerManager,
|
ComposerManager $composerManager,
|
||||||
@@ -88,8 +93,10 @@ class Bootstrap
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connects to a database using pdo
|
* Connects to a database using pdo.
|
||||||
* @param \LotGD\Core\Configuration $config
|
* @param string $dsn
|
||||||
|
* @param string $user
|
||||||
|
* @param string $password
|
||||||
* @return \PDO
|
* @return \PDO
|
||||||
*/
|
*/
|
||||||
protected function connectToDatabase(string $dsn, string $user, string $password): \PDO
|
protected function connectToDatabase(string $dsn, string $user, string $password): \PDO
|
||||||
@@ -98,7 +105,7 @@ class Bootstrap
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates and returns an instance of ComposerManager
|
* Creates and returns an instance of ComposerManager.
|
||||||
* @param string $cwd
|
* @param string $cwd
|
||||||
* @return ComposerManager
|
* @return ComposerManager
|
||||||
*/
|
*/
|
||||||
@@ -111,16 +118,16 @@ class Bootstrap
|
|||||||
/**
|
/**
|
||||||
* Returns a configuration object reading from the file located at the path stored in $cwd/config/lotgd.yml.
|
* Returns a configuration object reading from the file located at the path stored in $cwd/config/lotgd.yml.
|
||||||
* @param string $cwd
|
* @param string $cwd
|
||||||
* @return \LotGD\Core\Configuration
|
|
||||||
* @throws InvalidConfigurationException
|
* @throws InvalidConfigurationException
|
||||||
|
* @return Configuration
|
||||||
*/
|
*/
|
||||||
protected function createConfiguration(string $cwd): Configuration
|
protected function createConfiguration(string $cwd): Configuration
|
||||||
{
|
{
|
||||||
if (empty($configFilePath)) {
|
if (empty($configFilePath)) {
|
||||||
$configFilePath = implode(DIRECTORY_SEPARATOR, [$cwd, "config", "lotgd.yml"]);
|
$configFilePath = \implode(\DIRECTORY_SEPARATOR, [$cwd, "config", "lotgd.yml"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($configFilePath === false || strlen($configFilePath) == 0 || is_file($configFilePath) === false) {
|
if ($configFilePath === false || \strlen($configFilePath) == 0 || \is_file($configFilePath) === false) {
|
||||||
throw new InvalidConfigurationException("Invalid or missing configuration file: {$configFilePath}.");
|
throw new InvalidConfigurationException("Invalid or missing configuration file: {$configFilePath}.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,7 +136,7 @@ class Bootstrap
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a logger instance
|
* Returns a logger instance.
|
||||||
* @param Configuration $config
|
* @param Configuration $config
|
||||||
* @param string $name
|
* @param string $name
|
||||||
* @return LoggerInterface
|
* @return LoggerInterface
|
||||||
@@ -138,35 +145,41 @@ class Bootstrap
|
|||||||
{
|
{
|
||||||
$logger = new Logger($name);
|
$logger = new Logger($name);
|
||||||
// Add lotgd as the prefix for the log filenames.
|
// Add lotgd as the prefix for the log filenames.
|
||||||
$logger->pushHandler(new RotatingFileHandler($config->getLogPath() . DIRECTORY_SEPARATOR . $name, 14));
|
$logger->pushHandler(new RotatingFileHandler($config->getLogPath() . \DIRECTORY_SEPARATOR . $name, 14));
|
||||||
|
|
||||||
return $logger;
|
return $logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the EntityManager using the pdo connection given in it's argument
|
* Creates the EntityManager using the pdo connection given in it's argument.
|
||||||
* @param \PDO $pdo
|
* @param \PDO $pdo
|
||||||
|
* @param Configuration
|
||||||
* @return EntityManagerInterface
|
* @return EntityManagerInterface
|
||||||
*/
|
*/
|
||||||
protected function createEntityManager(\PDO $pdo): EntityManagerInterface
|
protected function createEntityManager(\PDO $pdo, Configuration $config): EntityManagerInterface
|
||||||
{
|
{
|
||||||
$this->annotationDirectories = $this->generateAnnotationDirectories();
|
$this->annotationDirectories = $this->generateAnnotationDirectories();
|
||||||
$this->logger->addDebug("Adding annotation directories:");
|
$this->logger->debug("Adding annotation directories:");
|
||||||
foreach ($this->annotationDirectories as $d) {
|
foreach ($this->annotationDirectories as $d) {
|
||||||
$this->logger->addDebug(" {$d}");
|
$this->logger->debug(" {$d}");
|
||||||
}
|
}
|
||||||
$configuration = Setup::createAnnotationMetadataConfiguration($this->annotationDirectories, true);
|
$configuration = Setup::createAnnotationMetadataConfiguration($this->annotationDirectories, true);
|
||||||
|
|
||||||
// Set a quote
|
|
||||||
$configuration->setQuoteStrategy(new AnsiQuoteStrategy());
|
|
||||||
|
|
||||||
// Create entity manager
|
// Create entity manager
|
||||||
$entityManager = EntityManager::create(["pdo" => $pdo], $configuration);
|
$entityManager = EntityManager::create(["pdo" => $pdo], $configuration);
|
||||||
|
|
||||||
|
// Register uuid type
|
||||||
|
try {
|
||||||
|
Type::addType('uuid', 'Ramsey\Uuid\Doctrine\UuidType');
|
||||||
|
} catch (DBALException $e) {
|
||||||
|
}
|
||||||
|
|
||||||
// Create Schema and update database if needed
|
// Create Schema and update database if needed
|
||||||
$metaData = $entityManager->getMetadataFactory()->getAllMetadata();
|
if ($config->getDatabaseAutoSchemaUpdate()) {
|
||||||
$schemaTool = new SchemaTool($entityManager);
|
$metaData = $entityManager->getMetadataFactory()->getAllMetadata();
|
||||||
$schemaTool->updateSchema($metaData);
|
$schemaTool = new SchemaTool($entityManager);
|
||||||
|
$schemaTool->updateSchema($metaData);
|
||||||
|
}
|
||||||
|
|
||||||
return $entityManager;
|
return $entityManager;
|
||||||
}
|
}
|
||||||
@@ -178,12 +191,12 @@ class Bootstrap
|
|||||||
protected function generateAnnotationDirectories(): array
|
protected function generateAnnotationDirectories(): array
|
||||||
{
|
{
|
||||||
// Read db annotations from our own model files.
|
// Read db annotations from our own model files.
|
||||||
$directories = [__DIR__ . DIRECTORY_SEPARATOR . 'Models'];
|
$directories = [__DIR__ . \DIRECTORY_SEPARATOR . 'Models'];
|
||||||
|
|
||||||
// Get additional annotation directories from library configs.
|
// Get additional annotation directories from library configs.
|
||||||
$libraryDirectories = $this->libraryConfigurationManager->getEntityDirectories();
|
$libraryDirectories = $this->libraryConfigurationManager->getEntityDirectories();
|
||||||
|
|
||||||
return array_merge($directories, $libraryDirectories);
|
return \array_merge($directories, $libraryDirectories);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -199,4 +212,22 @@ class Bootstrap
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs the code to extend models.
|
||||||
|
*/
|
||||||
|
public function extendModels()
|
||||||
|
{
|
||||||
|
AnnotationRegistry::registerLoader("class_exists");
|
||||||
|
|
||||||
|
$modelExtender = new ModelExtender();
|
||||||
|
|
||||||
|
foreach ($this->libraryConfigurationManager->getConfigurations() as $config) {
|
||||||
|
$modelExtensions = $config->getSubKeyIfItExists(["modelExtensions"]);
|
||||||
|
|
||||||
|
if ($modelExtensions) {
|
||||||
|
$modelExtender->addMore($modelExtensions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+66
-82
@@ -3,73 +3,58 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace LotGD\Core;
|
namespace LotGD\Core;
|
||||||
|
|
||||||
use Doctrine\Common\Collections\{
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
ArrayCollection,
|
use Doctrine\Common\Collections\Collection;
|
||||||
Collection
|
|
||||||
};
|
|
||||||
|
|
||||||
use LotGD\Core\Exceptions\{
|
|
||||||
ArgumentException,
|
|
||||||
BuffListAlreadyActivatedException
|
|
||||||
};
|
|
||||||
use LotGD\Core\Models\{
|
|
||||||
Buff,
|
|
||||||
Character,
|
|
||||||
FighterInterface,
|
|
||||||
BattleEvents\BuffMessageEvent,
|
|
||||||
BattleEvents\DamageLifetapEvent,
|
|
||||||
BattleEvents\DamageReflectionEvent,
|
|
||||||
BattleEvents\RegenerationBuffEvent,
|
|
||||||
BattleEvents\MinionDamageEvent
|
|
||||||
};
|
|
||||||
|
|
||||||
|
use LotGD\Core\Exceptions\ArgumentException;
|
||||||
|
use LotGD\Core\Exceptions\BuffListAlreadyActivatedException;
|
||||||
|
use LotGD\Core\Exceptions\BuffSlotOccupiedException;
|
||||||
|
use LotGD\Core\Models\BattleEvents\BuffMessageEvent;
|
||||||
|
use LotGD\Core\Models\BattleEvents\DamageLifetapEvent;
|
||||||
|
use LotGD\Core\Models\BattleEvents\DamageReflectionEvent;
|
||||||
|
use LotGD\Core\Models\BattleEvents\MinionDamageEvent;
|
||||||
|
use LotGD\Core\Models\BattleEvents\RegenerationBuffEvent;
|
||||||
|
use LotGD\Core\Models\Buff;
|
||||||
|
use LotGD\Core\Models\FighterInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Description of BuffList
|
* Description of BuffList.
|
||||||
*/
|
*/
|
||||||
class BuffList
|
class BuffList
|
||||||
{
|
{
|
||||||
protected $buffs;
|
protected array $buffsBySlot;
|
||||||
protected $buffsBySlot;
|
protected array $activeBuffs = [];
|
||||||
protected $activeBuffs = [];
|
protected ArrayCollection $usedBuffs;
|
||||||
/** @var Doctrine\Common\Collections\ArrayCollection */
|
|
||||||
protected $usedBuffs;
|
|
||||||
|
|
||||||
/** @var boolean True of the modifiers have already been calculated */
|
/** True of the modifiers have already been calculated */
|
||||||
protected $modifiersCalculated = false;
|
protected bool $modifiersCalculated = false;
|
||||||
/** @var boolean True if the badguy is invulnurable */
|
/** True if the badguy is invulnurable */
|
||||||
protected $badguyInvulnurable = false;
|
protected bool $badguyInvulnurable = false;
|
||||||
/** @var float */
|
|
||||||
protected $badguyDamageModifier = 1.;
|
|
||||||
/** @var float */
|
|
||||||
protected $badguyAttackModifier = 1.;
|
|
||||||
/** @var float */
|
|
||||||
protected $badguyDefenseModifier = 1.;
|
|
||||||
/** @var boolean True if the goodguy is invulnurable */
|
|
||||||
protected $goodguyInvulnurable = false;
|
|
||||||
/** @var float */
|
|
||||||
protected $goodguyDamageModifier = 1.;
|
|
||||||
/** @var float */
|
|
||||||
protected $goodguyAttackModifier = 1.;
|
|
||||||
/** @var float */
|
|
||||||
protected $goodguyDefenseModifier = 1.;
|
|
||||||
|
|
||||||
protected $events;
|
protected float $badguyDamageModifier = 1.;
|
||||||
protected $loaded = false;
|
protected float $badguyAttackModifier = 1.;
|
||||||
|
protected float $badguyDefenseModifier = 1.;
|
||||||
|
protected bool $goodguyInvulnurable = false;
|
||||||
|
protected float $goodguyDamageModifier = 1.;
|
||||||
|
protected float $goodguyAttackModifier = 1.;
|
||||||
|
protected float $goodguyDefenseModifier = 1.;
|
||||||
|
|
||||||
|
protected ArrayCollection $events;
|
||||||
|
protected bool $loaded = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initiates some variables
|
* Initiates some variables.
|
||||||
* @param Collection $buffs
|
* @param Collection $buffs
|
||||||
*/
|
*/
|
||||||
public function __construct(Collection $buffs)
|
public function __construct(
|
||||||
{
|
protected Collection $buffs
|
||||||
$this->buffs = $buffs;
|
) {
|
||||||
$this->events = new ArrayCollection();
|
$this->events = new ArrayCollection();
|
||||||
$this->usedBuffs = new ArrayCollection();
|
$this->usedBuffs = new ArrayCollection();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads all buffs (since it's a lazy correlation)
|
* Loads all buffs (since it's a lazy correlation).
|
||||||
*/
|
*/
|
||||||
public function loadBuffs()
|
public function loadBuffs()
|
||||||
{
|
{
|
||||||
@@ -97,7 +82,7 @@ class BuffList
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marks the given buff as used
|
* Marks the given buff as used.
|
||||||
* @param Buff $buff
|
* @param Buff $buff
|
||||||
*/
|
*/
|
||||||
protected function useBuff(Buff $buff)
|
protected function useBuff(Buff $buff)
|
||||||
@@ -106,7 +91,7 @@ class BuffList
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the buff's start or round message
|
* Returns the buff's start or round message.
|
||||||
* @param Buff $buff
|
* @param Buff $buff
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
@@ -125,7 +110,7 @@ class BuffList
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets the buff usage for a new round
|
* Resets the buff usage for a new round.
|
||||||
*/
|
*/
|
||||||
public function resetBuffUsage()
|
public function resetBuffUsage()
|
||||||
{
|
{
|
||||||
@@ -136,22 +121,23 @@ class BuffList
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether any buffs are in use.
|
* Returns whether any buffs are in use.
|
||||||
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function hasBuffsInUse(): bool
|
public function hasBuffsInUse(): bool
|
||||||
{
|
{
|
||||||
return count($this->usedBuffs) > 0 ? true : false;
|
return \count($this->usedBuffs) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Activates all buffs that activate upon the given activation parameter.
|
* Activates all buffs that activate upon the given activation parameter.
|
||||||
* @param int $activation
|
* @param int $activation
|
||||||
* @return Collection
|
|
||||||
* @throws ArgumentException
|
* @throws ArgumentException
|
||||||
* @throws BuffListAlreadyActivatedException
|
* @throws BuffListAlreadyActivatedException
|
||||||
|
* @return Collection
|
||||||
*/
|
*/
|
||||||
public function activate(int $activation): Collection
|
public function activate(int $activation): Collection
|
||||||
{
|
{
|
||||||
if ($activation%2 !== 0 && $activation !== 1) {
|
if ($activation % 2 !== 0 && $activation !== 1) {
|
||||||
throw new ArgumentException("You can only activate one activation type at a time.");
|
throw new ArgumentException("You can only activate one activation type at a time.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,7 +172,7 @@ class BuffList
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decreases the rounds left on all used buffs
|
* Decreases the rounds left on all used buffs.
|
||||||
* @return Collection A Collection containing expire messages (if there are any)
|
* @return Collection A Collection containing expire messages (if there are any)
|
||||||
*/
|
*/
|
||||||
public function expireOneRound(): Collection
|
public function expireOneRound(): Collection
|
||||||
@@ -261,10 +247,9 @@ class BuffList
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates all total modifiers
|
* Calculates all total modifiers.
|
||||||
* @return type
|
|
||||||
*/
|
*/
|
||||||
protected function calculateModifiers()
|
protected function calculateModifiers(): void
|
||||||
{
|
{
|
||||||
if ($this->modifiersCalculated === true) {
|
if ($this->modifiersCalculated === true) {
|
||||||
return;
|
return;
|
||||||
@@ -302,14 +287,13 @@ class BuffList
|
|||||||
// Only look at buffs that are activated in battle.
|
// Only look at buffs that are activated in battle.
|
||||||
if ($buff->getsActivatedAt(Buff::ACTIVATE_NONE)) {
|
if ($buff->getsActivatedAt(Buff::ACTIVATE_NONE)) {
|
||||||
continue;
|
continue;
|
||||||
} else {
|
|
||||||
yield $buff;
|
|
||||||
}
|
}
|
||||||
|
yield $buff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the badguy attack modifier calculated over the whole bufflist
|
* Returns the badguy attack modifier calculated over the whole bufflist.
|
||||||
* @return float
|
* @return float
|
||||||
*/
|
*/
|
||||||
public function getBadguyAttackModifier(): float
|
public function getBadguyAttackModifier(): float
|
||||||
@@ -318,8 +302,8 @@ class BuffList
|
|||||||
return $this->badguyAttackModifier;
|
return $this->badguyAttackModifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the badguy defense modifier calculated over the whole bufflist
|
* Returns the badguy defense modifier calculated over the whole bufflist.
|
||||||
* @return float
|
* @return float
|
||||||
*/
|
*/
|
||||||
public function getBadguyDefenseModifier(): float
|
public function getBadguyDefenseModifier(): float
|
||||||
@@ -329,7 +313,7 @@ class BuffList
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the badguy damage modifier calculated over the whole bufflist
|
* Returns the badguy damage modifier calculated over the whole bufflist.
|
||||||
* @return float
|
* @return float
|
||||||
*/
|
*/
|
||||||
public function getBadguyDamageModifier(): float
|
public function getBadguyDamageModifier(): float
|
||||||
@@ -339,7 +323,7 @@ class BuffList
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the badguy is invulnurable
|
* Returns true if the badguy is invulnurable.
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function badguyIsInvulnurable(): bool
|
public function badguyIsInvulnurable(): bool
|
||||||
@@ -349,7 +333,7 @@ class BuffList
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the badguy attack modifier calculated over the whole bufflist
|
* Returns the badguy attack modifier calculated over the whole bufflist.
|
||||||
* @return float
|
* @return float
|
||||||
*/
|
*/
|
||||||
public function getGoodguyAttackModifier(): float
|
public function getGoodguyAttackModifier(): float
|
||||||
@@ -358,8 +342,8 @@ class BuffList
|
|||||||
return $this->goodguyAttackModifier;
|
return $this->goodguyAttackModifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the badguy defense modifier calculated over the whole bufflist
|
* Returns the badguy defense modifier calculated over the whole bufflist.
|
||||||
* @return float
|
* @return float
|
||||||
*/
|
*/
|
||||||
public function getGoodguyDefenseModifier(): float
|
public function getGoodguyDefenseModifier(): float
|
||||||
@@ -368,8 +352,8 @@ class BuffList
|
|||||||
return $this->goodguyDefenseModifier;
|
return $this->goodguyDefenseModifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the badguy damage modifier calculated over the whole bufflist
|
* Returns the badguy damage modifier calculated over the whole bufflist.
|
||||||
* @return float
|
* @return float
|
||||||
*/
|
*/
|
||||||
public function getGoodguyDamageModifier(): float
|
public function getGoodguyDamageModifier(): float
|
||||||
@@ -379,7 +363,7 @@ class BuffList
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the goodguy is invulnurable
|
* Returns true if the goodguy is invulnurable.
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function goodguyIsInvulnurable(): bool
|
public function goodguyIsInvulnurable(): bool
|
||||||
@@ -389,9 +373,9 @@ class BuffList
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Processes buffs that do direct damage or regeneration
|
* Processes buffs that do direct damage or regeneration.
|
||||||
* @param int $activation
|
* @param int $activation
|
||||||
* @param \LotGD\Core\Game $game
|
* @param Game $game
|
||||||
* @param FighterInterface $goodguy
|
* @param FighterInterface $goodguy
|
||||||
* @param FighterInterface $badguy
|
* @param FighterInterface $badguy
|
||||||
* @return Collection
|
* @return Collection
|
||||||
@@ -477,7 +461,7 @@ class BuffList
|
|||||||
|
|
||||||
$events[] = new MinionDamageEvent(
|
$events[] = new MinionDamageEvent(
|
||||||
$target,
|
$target,
|
||||||
(int)round($damage, 0),
|
(int)\round($damage, 0),
|
||||||
$message
|
$message
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -490,10 +474,10 @@ class BuffList
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Processes buffs that are dependant on the damage done in one round
|
* Processes buffs that are dependant on the damage done in one round.
|
||||||
* @param int $activation
|
* @param int $activation
|
||||||
* @param int $damage Positive damage is applied to the badguy, negative damage is applied to the goodguy
|
* @param int $damage Positive damage is applied to the badguy, negative damage is applied to the goodguy
|
||||||
* @param \LotGD\Core\Game $game
|
* @param Game $game
|
||||||
* @param FighterInterface $goodguy
|
* @param FighterInterface $goodguy
|
||||||
* @param FighterInterface $badguy
|
* @param FighterInterface $badguy
|
||||||
* @return Collection
|
* @return Collection
|
||||||
@@ -518,7 +502,7 @@ class BuffList
|
|||||||
$reflectedDamage = 0;
|
$reflectedDamage = 0;
|
||||||
$message = $buff->getNoEffectMessage();
|
$message = $buff->getNoEffectMessage();
|
||||||
} else {
|
} else {
|
||||||
$reflectedDamage = (int)round($buff->getGoodguyDamageReflection() * $damage * -1, 0);
|
$reflectedDamage = (int)\round($buff->getGoodguyDamageReflection() * $damage * -1, 0);
|
||||||
if ($reflectedDamage === 0) {
|
if ($reflectedDamage === 0) {
|
||||||
$message = $buff->getNoEffectMessage();
|
$message = $buff->getNoEffectMessage();
|
||||||
} else {
|
} else {
|
||||||
@@ -536,7 +520,7 @@ class BuffList
|
|||||||
if ($buff->getBadguyDamageReflection() !== 0.) {
|
if ($buff->getBadguyDamageReflection() !== 0.) {
|
||||||
if ($damage > 0) {
|
if ($damage > 0) {
|
||||||
// Damage is > 0, so badguy takes damage, we can normally reflect
|
// Damage is > 0, so badguy takes damage, we can normally reflect
|
||||||
$reflectedDamage = (int)round($buff->getGoodguyDamageReflection() * $damage, 0);
|
$reflectedDamage = (int)\round($buff->getBadguyDamageReflection() * $damage, 0);
|
||||||
if ($reflectedDamage === 0) {
|
if ($reflectedDamage === 0) {
|
||||||
$message = $buff->getNoEffectMessage();
|
$message = $buff->getNoEffectMessage();
|
||||||
} else {
|
} else {
|
||||||
@@ -565,7 +549,7 @@ class BuffList
|
|||||||
$message = $buff->getEffectFailsMessage();
|
$message = $buff->getEffectFailsMessage();
|
||||||
} elseif ($damage < 0) {
|
} elseif ($damage < 0) {
|
||||||
// Damage is < 0, goodguy takes damage. We act upon this.
|
// Damage is < 0, goodguy takes damage. We act upon this.
|
||||||
$healAmount = (int)round($damage * -$buff->getBadguyLifetap(), 0);
|
$healAmount = (int)\round($damage * -$buff->getBadguyLifetap(), 0);
|
||||||
if ($healAmount === 0) {
|
if ($healAmount === 0) {
|
||||||
$message = $buff->getNoEffectMessage();
|
$message = $buff->getNoEffectMessage();
|
||||||
} else {
|
} else {
|
||||||
@@ -586,7 +570,7 @@ class BuffList
|
|||||||
if ($buff->getBadguyLifetap() !== 0.) {
|
if ($buff->getBadguyLifetap() !== 0.) {
|
||||||
if ($damage > 0) {
|
if ($damage > 0) {
|
||||||
// Damage is > 0, badguy takes damage. We act upon this to heal goodguy.
|
// Damage is > 0, badguy takes damage. We act upon this to heal goodguy.
|
||||||
$healAmount = (int)round($damage * $buff->getBadguyLifetap(), 0);
|
$healAmount = (int)\round($damage * $buff->getBadguyLifetap(), 0);
|
||||||
if ($healAmount === 0) {
|
if ($healAmount === 0) {
|
||||||
$message = $buff->getNoEffectMessage();
|
$message = $buff->getNoEffectMessage();
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+38
-43
@@ -3,36 +3,29 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace LotGD\Core;
|
namespace LotGD\Core;
|
||||||
|
|
||||||
use Composer\{
|
use Composer\Composer;
|
||||||
Composer,
|
use Composer\Factory;
|
||||||
Factory,
|
use Composer\IO\NullIO;
|
||||||
IO\NullIO,
|
use Composer\Package\CompletePackageInterface;
|
||||||
Package\CompletePackageInterface
|
use Composer\Package\PackageInterface;
|
||||||
};
|
use Exception;
|
||||||
use Monolog\Logger;
|
|
||||||
|
|
||||||
use LotGD\Core\{
|
use LotGD\Core\Exceptions\InvalidConfigurationException;
|
||||||
Exceptions\InvalidConfigurationException,
|
use LotGD\Core\Exceptions\LibraryDoesNotExistException;
|
||||||
Exceptions\LibraryDoesNotExistException
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helps perform tasks with the composer configuration.
|
* Helps perform tasks with the composer configuration.
|
||||||
*/
|
*/
|
||||||
class ComposerManager
|
class ComposerManager
|
||||||
{
|
{
|
||||||
private $composer;
|
private ?Composer $composer = null;
|
||||||
private $cwd;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a manager with an optional working directory where composer.json
|
* Construct a manager with an optional working directory where composer.json
|
||||||
* lives.
|
* lives.
|
||||||
* @param string $cwd
|
* @param string $cwd
|
||||||
*/
|
*/
|
||||||
public function __construct(string $cwd)
|
public function __construct(private string $cwd) {}
|
||||||
{
|
|
||||||
$this->cwd = $cwd;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a Composer instance to perform underlying operations on. Be careful.
|
* Returns a Composer instance to perform underlying operations on. Be careful.
|
||||||
@@ -42,8 +35,8 @@ class ComposerManager
|
|||||||
{
|
{
|
||||||
if ($this->composer === null) {
|
if ($this->composer === null) {
|
||||||
// Verify location of composer.json.
|
// Verify location of composer.json.
|
||||||
$composerConfigPath = $this->cwd . DIRECTORY_SEPARATOR . "composer.json";
|
$composerConfigPath = $this->cwd . \DIRECTORY_SEPARATOR . "composer.json";
|
||||||
if (!file_exists($composerConfigPath)) {
|
if (!\file_exists($composerConfigPath)) {
|
||||||
throw new InvalidConfigurationException("composer.json cannot be found at {$composerConfigPath}.");
|
throw new InvalidConfigurationException("composer.json cannot be found at {$composerConfigPath}.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,8 +49,9 @@ class ComposerManager
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the Composer package for the corresponding library, in vendor/module format.
|
* Return the Composer package for the corresponding library, in vendor/module format.
|
||||||
* @return PackageInterface Package corresponding to this library.
|
* @param string $library
|
||||||
* @throws LibraryDoesNotExistException
|
* @throws LibraryDoesNotExistException
|
||||||
|
* @return CompletePackageInterface Package corresponding to this library.
|
||||||
*/
|
*/
|
||||||
public function getPackageForLibrary(string $library): CompletePackageInterface
|
public function getPackageForLibrary(string $library): CompletePackageInterface
|
||||||
{
|
{
|
||||||
@@ -73,27 +67,27 @@ class ComposerManager
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Return all the packages installed in the current setup.
|
* Return all the packages installed in the current setup.
|
||||||
* @return array<Composer\PackageInterface>
|
* @return PackageInterface[]
|
||||||
*/
|
*/
|
||||||
public function getPackages(): array
|
public function getPackages(): array
|
||||||
{
|
{
|
||||||
return array_merge(
|
return [
|
||||||
[$this->getComposer()->getPackage()],
|
$this->getComposer()->getPackage(),
|
||||||
$this->getComposer()->getRepositoryManager()->getLocalRepository()->getPackages()
|
...$this->getComposer()->getRepositoryManager()->getLocalRepository()->getPackages(),
|
||||||
);
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a list of the configured packages which are LotGD modules (type = 'lotgd-module').
|
* Return a list of the configured packages which are LotGD modules (type = 'lotgd-module').
|
||||||
* @return array Array of \Composer\PackageInterface.
|
* @return PackageInterface[]
|
||||||
*/
|
*/
|
||||||
public function getModulePackages(): array
|
public function getModulePackages(): array
|
||||||
{
|
{
|
||||||
$result = array();
|
$result = [];
|
||||||
$packages = $this->getComposer()->getRepositoryManager()->getLocalRepository()->getPackages();
|
$packages = $this->getComposer()->getRepositoryManager()->getLocalRepository()->getPackages();
|
||||||
foreach ($packages as $p) {
|
foreach ($packages as $p) {
|
||||||
if ($p->getType() === 'lotgd-module') {
|
if ($p->getType() === 'lotgd-module') {
|
||||||
array_push($result, $p);
|
\array_push($result, $p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,7 +100,7 @@ class ComposerManager
|
|||||||
* @return string|null Path representing $namespace or null if $namespace
|
* @return string|null Path representing $namespace or null if $namespace
|
||||||
* cannot be found or if the path does not exist.
|
* cannot be found or if the path does not exist.
|
||||||
*/
|
*/
|
||||||
public function translateNamespaceToPath(string $namespace)
|
public function translateNamespaceToPath(string $namespace): ?string
|
||||||
{
|
{
|
||||||
// Find the directory for this namespace by using the autoloader's
|
// Find the directory for this namespace by using the autoloader's
|
||||||
// classmap.
|
// classmap.
|
||||||
@@ -116,32 +110,32 @@ class ComposerManager
|
|||||||
// Standardize the namespace to remove any leading \ and add a trailing \
|
// Standardize the namespace to remove any leading \ and add a trailing \
|
||||||
$n = $namespace;
|
$n = $namespace;
|
||||||
if ('\\' == $n[0]) {
|
if ('\\' == $n[0]) {
|
||||||
$n = substr($n, 1);
|
$n = \substr($n, 1);
|
||||||
}
|
}
|
||||||
if (strlen($n) > 0 && '\\' != $n[strlen($n) - 1]) {
|
if (\strlen($n) > 0 && '\\' != $n[\strlen($n) - 1]) {
|
||||||
$n .= '\\';
|
$n .= '\\';
|
||||||
}
|
}
|
||||||
|
|
||||||
$split = explode('\\', $n);
|
$split = \explode('\\', $n);
|
||||||
$suffix = array_splice($split, -1, 1); // starts with ['']
|
$suffix = \array_splice($split, -1, 1); // starts with ['']
|
||||||
$path = null;
|
$path = null;
|
||||||
while (!empty($split)) {
|
while (!empty($split)) {
|
||||||
$key = implode('\\', $split) . '\\';
|
$key = \implode('\\', $split) . '\\';
|
||||||
$dir = implode(DIRECTORY_SEPARATOR, $suffix);
|
$dir = \implode(\DIRECTORY_SEPARATOR, $suffix);
|
||||||
// Prefix to directory mappings are arrays in Composer's
|
// Prefix to directory mappings are arrays in Composer's
|
||||||
// ClassLoader object. Not sure why. This might break in
|
// ClassLoader object. Not sure why. This might break in
|
||||||
// some unforseen case.
|
// some unforseen case.
|
||||||
if (isset($prefixes[$key]) && is_dir($prefixes[$key][0] . DIRECTORY_SEPARATOR . $dir)) {
|
if (isset($prefixes[$key]) && \is_dir($prefixes[$key][0] . \DIRECTORY_SEPARATOR . $dir)) {
|
||||||
$path = $prefixes[$key][0] . DIRECTORY_SEPARATOR . $dir;
|
$path = $prefixes[$key][0] . \DIRECTORY_SEPARATOR . $dir;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
$suffix = array_merge($suffix, array_splice($split, -1, 1));
|
$suffix = \array_merge($suffix, \array_splice($split, -1, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($path == null) {
|
if ($path == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
$path = realpath($path);
|
$path = \realpath($path);
|
||||||
if ($path == false) {
|
if ($path == false) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -151,19 +145,20 @@ class ComposerManager
|
|||||||
/**
|
/**
|
||||||
* Returns a path (could be relative) to the proper autoload.php file in
|
* Returns a path (could be relative) to the proper autoload.php file in
|
||||||
* the current setup.
|
* the current setup.
|
||||||
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function findAutoloader(): string
|
public function findAutoloader(): string
|
||||||
{
|
{
|
||||||
// Dance to find the autoloader.
|
// Dance to find the autoloader.
|
||||||
// TOOD: change this to open up the Composer config and use $c['config']['vendor-dir'] instead of "vendor"
|
// TOOD: change this to open up the Composer config and use $c['config']['vendor-dir'] instead of "vendor"
|
||||||
$order = [
|
$order = [
|
||||||
implode(DIRECTORY_SEPARATOR, [$this->cwd, "vendor", "autoload.php"]),
|
\implode(\DIRECTORY_SEPARATOR, [$this->cwd, "vendor", "autoload.php"]),
|
||||||
implode(DIRECTORY_SEPARATOR, [__DIR__, "..", "vendor", "autoload.php"]),
|
\implode(\DIRECTORY_SEPARATOR, [__DIR__, "..", "vendor", "autoload.php"]),
|
||||||
implode(DIRECTORY_SEPARATOR, [__DIR__, "..", "autoload.php"]),
|
\implode(\DIRECTORY_SEPARATOR, [__DIR__, "..", "autoload.php"]),
|
||||||
];
|
];
|
||||||
|
|
||||||
foreach ($order as $path) {
|
foreach ($order as $path) {
|
||||||
if (file_exists($path)) {
|
if (\file_exists($path)) {
|
||||||
return $path;
|
return $path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+34
-17
@@ -5,10 +5,10 @@ namespace LotGD\Core;
|
|||||||
|
|
||||||
use DateTime;
|
use DateTime;
|
||||||
|
|
||||||
use Symfony\Component\Yaml\Exception\ParseException;
|
|
||||||
use Symfony\Component\Yaml\Yaml;
|
|
||||||
|
|
||||||
use LotGD\Core\Exceptions\InvalidConfigurationException;
|
use LotGD\Core\Exceptions\InvalidConfigurationException;
|
||||||
|
use Symfony\Component\Yaml\Exception\ParseException;
|
||||||
|
|
||||||
|
use Symfony\Component\Yaml\Yaml;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The configuration information for a LotGD game. Configuration is read from
|
* The configuration information for a LotGD game. Configuration is read from
|
||||||
@@ -16,14 +16,15 @@ use LotGD\Core\Exceptions\InvalidConfigurationException;
|
|||||||
*/
|
*/
|
||||||
class Configuration
|
class Configuration
|
||||||
{
|
{
|
||||||
private $databaseDSN;
|
private string $databaseDSN;
|
||||||
private $databaseName;
|
private string $databaseName;
|
||||||
private $databaseUser;
|
private string $databaseUser;
|
||||||
private $databasePassword;
|
private string $databasePassword;
|
||||||
private $logPath;
|
private bool $databaseAutoSchemaUpdate;
|
||||||
private $gameEpoch;
|
private string $logPath;
|
||||||
private $gameOffsetSeconds;
|
private DateTime $gameEpoch;
|
||||||
private $gameDaysPerDay;
|
private int $gameOffsetSeconds;
|
||||||
|
private int $gameDaysPerDay;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create the configuration object, reading from the specified path.
|
* Create the configuration object, reading from the specified path.
|
||||||
@@ -41,8 +42,8 @@ class Configuration
|
|||||||
|
|
||||||
// Log dir path is relative to config directory.
|
// Log dir path is relative to config directory.
|
||||||
$logPath = $rawConfig['logs']['path'] ?? '';
|
$logPath = $rawConfig['logs']['path'] ?? '';
|
||||||
$realLogPath = dirname($configFilePath) . DIRECTORY_SEPARATOR . $logPath;
|
$realLogPath = \dirname($configFilePath) . \DIRECTORY_SEPARATOR . $logPath;
|
||||||
if ($realLogPath === false || strlen($realLogPath) == 0 || is_dir($realLogPath) === false) {
|
if ($realLogPath === false || \strlen($realLogPath) == 0 || \is_dir($realLogPath) === false) {
|
||||||
throw new InvalidConfigurationException("Invalid or missing log path: {$realLogPath}");
|
throw new InvalidConfigurationException("Invalid or missing log path: {$realLogPath}");
|
||||||
}
|
}
|
||||||
$this->logPath = $realLogPath;
|
$this->logPath = $realLogPath;
|
||||||
@@ -52,10 +53,10 @@ class Configuration
|
|||||||
$passwd = $rawConfig['database']['password'] ?? '';
|
$passwd = $rawConfig['database']['password'] ?? '';
|
||||||
$name = $rawConfig['database']['name'] ?? '';
|
$name = $rawConfig['database']['name'] ?? '';
|
||||||
|
|
||||||
if ($dsn === false || strlen($dsn) == 0) {
|
if ($dsn === false || \strlen($dsn) == 0) {
|
||||||
throw new InvalidConfigurationException("Invalid or missing data source name: {$dsn}");
|
throw new InvalidConfigurationException("Invalid or missing data source name: {$dsn}");
|
||||||
}
|
}
|
||||||
if ($user === false || strlen($user) == 0) {
|
if ($user === false || \strlen($user) == 0) {
|
||||||
throw new InvalidConfigurationException("Invalid or missing database user: {$user}");
|
throw new InvalidConfigurationException("Invalid or missing database user: {$user}");
|
||||||
}
|
}
|
||||||
if ($passwd === false) {
|
if ($passwd === false) {
|
||||||
@@ -70,6 +71,12 @@ class Configuration
|
|||||||
$this->databasePassword = $passwd;
|
$this->databasePassword = $passwd;
|
||||||
$this->databaseName = $name;
|
$this->databaseName = $name;
|
||||||
|
|
||||||
|
if (empty($rawConfig['database']['disableAutoSchemaUpdate'])) {
|
||||||
|
$this->databaseAutoSchemaUpdate = true;
|
||||||
|
} else {
|
||||||
|
$this->databaseAutoSchemaUpdate = false;
|
||||||
|
}
|
||||||
|
|
||||||
$gameEpoch = $rawConfig['game']['epoch'];
|
$gameEpoch = $rawConfig['game']['epoch'];
|
||||||
$gameOffsetSeconds = $rawConfig['game']['offsetSeconds'];
|
$gameOffsetSeconds = $rawConfig['game']['offsetSeconds'];
|
||||||
$gameDaysPerDay = $rawConfig['game']['daysPerDay'];
|
$gameDaysPerDay = $rawConfig['game']['daysPerDay'];
|
||||||
@@ -98,7 +105,7 @@ class Configuration
|
|||||||
*/
|
*/
|
||||||
protected function retrieveRawConfig(string $configFilePath): array
|
protected function retrieveRawConfig(string $configFilePath): array
|
||||||
{
|
{
|
||||||
return Yaml::parse(file_get_contents($configFilePath));
|
return Yaml::parse(\file_get_contents($configFilePath));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -114,7 +121,7 @@ class Configuration
|
|||||||
public function getDatabaseConnectionDetails(string $cwd = ""): array
|
public function getDatabaseConnectionDetails(string $cwd = ""): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
str_replace("%cwd%", $cwd . DIRECTORY_SEPARATOR, $this->getDatabaseDSN()),
|
\str_replace("%cwd%", $cwd . \DIRECTORY_SEPARATOR, $this->getDatabaseDSN()),
|
||||||
$this->getDatabaseUser(),
|
$this->getDatabaseUser(),
|
||||||
$this->getDatabasePassword(),
|
$this->getDatabasePassword(),
|
||||||
];
|
];
|
||||||
@@ -157,6 +164,15 @@ class Configuration
|
|||||||
return $this->databasePassword;
|
return $this->databasePassword;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if doctrine should not auto update.
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function getDatabaseAutoSchemaUpdate(): bool
|
||||||
|
{
|
||||||
|
return $this->databaseAutoSchemaUpdate;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the path to the directory to store log files.
|
* Return the path to the directory to store log files.
|
||||||
* @return string The configured log directory path.
|
* @return string The configured log directory path.
|
||||||
@@ -197,6 +213,7 @@ class Configuration
|
|||||||
/**
|
/**
|
||||||
* Generate a textual representation of the configuration, for debugging
|
* Generate a textual representation of the configuration, for debugging
|
||||||
* purposes.
|
* purposes.
|
||||||
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function __toString(): string
|
public function __toString(): string
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,16 +3,17 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace LotGD\Core\Console\Command;
|
namespace LotGD\Core\Console\Command;
|
||||||
|
|
||||||
use Symfony\Component\Console\Command\Command;
|
|
||||||
|
|
||||||
use LotGD\Core\Game;
|
use LotGD\Core\Game;
|
||||||
|
use Monolog\Logger;
|
||||||
|
use Symfony\Component\Console\Command\Command;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parent class for daenerys tool commands.
|
* Parent class for daenerys tool commands.
|
||||||
*/
|
*/
|
||||||
abstract class BaseCommand extends Command
|
abstract class BaseCommand extends Command
|
||||||
{
|
{
|
||||||
protected $game;
|
protected Game $game;
|
||||||
|
protected ?string $namespace = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct the command, using the provided Game.
|
* Construct the command, using the provided Game.
|
||||||
@@ -23,4 +24,22 @@ abstract class BaseCommand extends Command
|
|||||||
parent::__construct();
|
parent::__construct();
|
||||||
$this->game = $game;
|
$this->game = $game;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a cloned logger with a different context name.
|
||||||
|
* @return Logger
|
||||||
|
*/
|
||||||
|
public function getCliLogger(): Logger
|
||||||
|
{
|
||||||
|
return $this->game->getLogger()->withName("daenerys-cli");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function namespaced(string $command): string
|
||||||
|
{
|
||||||
|
if ($this->namespace) {
|
||||||
|
return "{$this->namespace}:{$command}";
|
||||||
|
} else {
|
||||||
|
return $command;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,105 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LotGD\Core\Console\Command\Character;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
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;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the viewpoint of a given character.
|
||||||
|
*/
|
||||||
|
class CharacterAddCommand extends CharacterBaseCommand
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$this->setName($this->namespaced("add"))
|
||||||
|
->setDescription("Add a character.")
|
||||||
|
->setDefinition(
|
||||||
|
new InputDefinition([
|
||||||
|
new InputArgument(
|
||||||
|
"name",
|
||||||
|
mode: InputArgument::REQUIRED,
|
||||||
|
description: "Character name",
|
||||||
|
),
|
||||||
|
new InputOption(
|
||||||
|
"level",
|
||||||
|
mode: InputOption::VALUE_OPTIONAL,
|
||||||
|
description: "Character level",
|
||||||
|
default: 1,
|
||||||
|
),
|
||||||
|
new InputOption(
|
||||||
|
"maxHealth",
|
||||||
|
mode: InputOption::VALUE_OPTIONAL,
|
||||||
|
description: "Maximum health of the character. 10*level if not given.",
|
||||||
|
default: null,
|
||||||
|
),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
|
{
|
||||||
|
$em = $this->game->getEntityManager();
|
||||||
|
$logger = $this->getCliLogger();
|
||||||
|
$io = new SymfonyStyle($input, $output);
|
||||||
|
|
||||||
|
$name = $input->getArgument("name");
|
||||||
|
$level = intval($input->getOption("level"));
|
||||||
|
$maxHealth = $input->getOption("maxHealth");
|
||||||
|
|
||||||
|
if ($level <= 0) {
|
||||||
|
$io->error("Level must at least be 1.");
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set maxHealth in dependence of the level if not given.
|
||||||
|
if ($maxHealth === null) {
|
||||||
|
$maxHealth = $level*10;
|
||||||
|
} else {
|
||||||
|
$maxHealth = intval($maxHealth);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($maxHealth < 0) {
|
||||||
|
$io->error("Maximum health must be at least 0.");
|
||||||
|
return Command::FAILURE;
|
||||||
|
} elseif ($maxHealth === 0) {
|
||||||
|
$io->warning("The character will have 0 max health and will be permanently dead.");
|
||||||
|
}
|
||||||
|
|
||||||
|
$character = Character::createAtFullHealth([
|
||||||
|
"name" => $name,
|
||||||
|
"level" => $level,
|
||||||
|
"maxHealth" => $maxHealth,
|
||||||
|
]);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$em->persist($character);
|
||||||
|
|
||||||
|
// Commit changes
|
||||||
|
$em->flush();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$io->error("Creating the character was not possible. Reason: {$e->getMessage()}.");
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
$io->success("{$character} was successfully created.");
|
||||||
|
$logger->info("Character was created.", ["character" => $character]);
|
||||||
|
|
||||||
|
return Command::SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LotGD\Core\Console\Command\Character;
|
||||||
|
|
||||||
|
use LotGD\Core\Console\Command\BaseCommand;
|
||||||
|
use LotGD\Core\Models\Character;
|
||||||
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
|
|
||||||
|
class CharacterBaseCommand extends BaseCommand
|
||||||
|
{
|
||||||
|
protected ?string $namespace = "character";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return InputArgument
|
||||||
|
*/
|
||||||
|
protected function getCharacterIdArgumentDefinition(): InputArgument
|
||||||
|
{
|
||||||
|
return new InputArgument(
|
||||||
|
name: "id",
|
||||||
|
mode: InputArgument::REQUIRED,
|
||||||
|
description: "Character ID",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $id
|
||||||
|
* @return Character|null
|
||||||
|
*/
|
||||||
|
protected function getCharacter(string $id): ?Character
|
||||||
|
{
|
||||||
|
/** @var Character|null $character */
|
||||||
|
$character = $this->game->getEntityManager()->getRepository(Character::class)->find($id);
|
||||||
|
return $character;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LotGD\Core\Console\Command\Character;
|
||||||
|
|
||||||
|
use LotGD\Core\Events\EventContextData;
|
||||||
|
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 CharacterConfigListCommand extends CharacterBaseCommand
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$this->setName($this->namespaced("config:list"))
|
||||||
|
->setDescription('List available settings for a character')
|
||||||
|
->setDefinition([
|
||||||
|
$this->getCharacterIdArgumentDefinition(),
|
||||||
|
])
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output)
|
||||||
|
{
|
||||||
|
$io = new SymfonyStyle($input, $output);
|
||||||
|
$character = $this->getCharacter($input->getArgument("id"));
|
||||||
|
|
||||||
|
if (!$character) {
|
||||||
|
$io->error("Character was not found.");
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create hook
|
||||||
|
$context = EventContextData::create([
|
||||||
|
"character" => $character,
|
||||||
|
"io" => $io,
|
||||||
|
"settings" => [],
|
||||||
|
]);
|
||||||
|
$newContext = $this->game->getEventManager()->publish(
|
||||||
|
event: "h/lotgd/core/cli/character-config-list",
|
||||||
|
contextData: $context
|
||||||
|
);
|
||||||
|
$settings = $newContext->get("settings");
|
||||||
|
|
||||||
|
$io->title("Character ".$character->getDisplayName());
|
||||||
|
|
||||||
|
if (count($settings) === 0) {
|
||||||
|
$io->note("There are no character settings available.");
|
||||||
|
} else {
|
||||||
|
$io->table(["setting", "value", "description"], $settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Command::SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LotGD\Core\Console\Command\Character;
|
||||||
|
|
||||||
|
use LotGD\Core\Events\EventContextData;
|
||||||
|
use Symfony\Component\Console\Command\Command;
|
||||||
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||||
|
|
||||||
|
class CharacterConfigResetCommand extends CharacterBaseCommand
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$this->setName($this->namespaced("config:reset"))
|
||||||
|
->setDescription('Reset a character setting')
|
||||||
|
->setDefinition([
|
||||||
|
$this->getCharacterIdArgumentDefinition(),
|
||||||
|
new InputArgument(
|
||||||
|
"setting",
|
||||||
|
mode: InputArgument::REQUIRED,
|
||||||
|
description: "Name of setting, see {$this->namespaced('config:list')}.",
|
||||||
|
),
|
||||||
|
])
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output)
|
||||||
|
{
|
||||||
|
$logger = $this->getCliLogger();
|
||||||
|
$io = new SymfonyStyle($input, $output);
|
||||||
|
$character = $this->getCharacter($input->getArgument("id"));
|
||||||
|
|
||||||
|
if (!$character) {
|
||||||
|
$io->error("Module was not found.");
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
$io->title("Character {$character->getDisplayName()}");
|
||||||
|
|
||||||
|
// Create hook
|
||||||
|
$context = EventContextData::create([
|
||||||
|
"character" => $character,
|
||||||
|
"io" => $io,
|
||||||
|
"setting" => $input->getArgument("setting"),
|
||||||
|
"return" => Command::FAILURE,
|
||||||
|
"reason" => "Setting does not exist.",
|
||||||
|
]);
|
||||||
|
|
||||||
|
$newContext = $this->game->getEventManager()->publish(
|
||||||
|
event: "h/lotgd/core/cli/character-config-reset",
|
||||||
|
contextData: $context
|
||||||
|
);
|
||||||
|
if ($newContext->get("return") != Command::SUCCESS) {
|
||||||
|
$io->error($newContext->get("reason"));
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->game->getEntityManager()->flush();
|
||||||
|
|
||||||
|
return Command::SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LotGD\Core\Console\Command\Character;
|
||||||
|
|
||||||
|
use LotGD\Core\Events\EventContextData;
|
||||||
|
use Symfony\Component\Console\Command\Command;
|
||||||
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||||
|
|
||||||
|
class CharacterConfigSetCommand extends CharacterBaseCommand
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$this->setName($this->namespaced("config:set"))
|
||||||
|
->setDescription('Change a character setting')
|
||||||
|
->setDefinition([
|
||||||
|
$this->getCharacterIdArgumentDefinition(),
|
||||||
|
new InputArgument(
|
||||||
|
"setting",
|
||||||
|
mode: InputArgument::REQUIRED,
|
||||||
|
description: "Name of setting, see {$this->namespaced('config:list')}.",
|
||||||
|
),
|
||||||
|
new InputArgument(
|
||||||
|
"value",
|
||||||
|
InputArgument::REQUIRED,
|
||||||
|
description: "New value for the given setting.",
|
||||||
|
),
|
||||||
|
])
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output)
|
||||||
|
{
|
||||||
|
$logger = $this->getCliLogger();
|
||||||
|
$io = new SymfonyStyle($input, $output);
|
||||||
|
$character = $this->getCharacter($input->getArgument("id"));
|
||||||
|
|
||||||
|
if (!$character) {
|
||||||
|
$io->error("Module was not found.");
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
$io->title("Character {$character->getDisplayName()}");
|
||||||
|
|
||||||
|
// Create hook
|
||||||
|
$context = EventContextData::create([
|
||||||
|
"character" => $character,
|
||||||
|
"io" => $io,
|
||||||
|
"setting" => $input->getArgument("setting"),
|
||||||
|
"value" => $input->getArgument("value"),
|
||||||
|
"return" => Command::FAILURE,
|
||||||
|
"reason" => "Setting does not exist.",
|
||||||
|
]);
|
||||||
|
$newContext = $this->game->getEventManager()->publish(
|
||||||
|
event: "h/lotgd/core/cli/character-config-set",
|
||||||
|
contextData: $context
|
||||||
|
);
|
||||||
|
if ($newContext->get("return") != Command::SUCCESS) {
|
||||||
|
$io->error($newContext->get("reason"));
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->game->getEntityManager()->flush();
|
||||||
|
|
||||||
|
return Command::SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,227 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LotGD\Core\Console\Command\Character;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use Symfony\Component\Console\Command\Command;
|
||||||
|
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 CharacterEditCommand extends CharacterBaseCommand
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$this->setName($this->namespaced("edit"))
|
||||||
|
->setDescription("Edit a given character.")
|
||||||
|
->setDefinition(
|
||||||
|
new InputDefinition([
|
||||||
|
$this->getCharacterIdArgumentDefinition(),
|
||||||
|
new InputOption(
|
||||||
|
"level",
|
||||||
|
mode: InputOption::VALUE_REQUIRED,
|
||||||
|
description: "Changes the level"
|
||||||
|
),
|
||||||
|
new InputOption(
|
||||||
|
"maxHealth",
|
||||||
|
mode: InputOption::VALUE_REQUIRED,
|
||||||
|
description: "Change maximum amount of health points. Health will be adjusted accordingly."
|
||||||
|
),
|
||||||
|
new InputOption(
|
||||||
|
"heal",
|
||||||
|
mode: InputOption::VALUE_NONE,
|
||||||
|
description: "Restores full health"
|
||||||
|
),
|
||||||
|
new InputOption(
|
||||||
|
"revive",
|
||||||
|
mode: InputOption::VALUE_OPTIONAL,
|
||||||
|
description: "Revives at full health. Give a number between 0 and 1 to revive fractionally.",
|
||||||
|
default: false,
|
||||||
|
),
|
||||||
|
new InputOption(
|
||||||
|
"kill",
|
||||||
|
mode: InputOption::VALUE_NONE,
|
||||||
|
description: "Kills"
|
||||||
|
),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
|
{
|
||||||
|
$em = $this->game->getEntityManager();
|
||||||
|
$logger = $this->getCliLogger();
|
||||||
|
$io = new SymfonyStyle($input, $output);
|
||||||
|
|
||||||
|
$id = $input->getArgument("id");
|
||||||
|
$level = $input->getOption("level");
|
||||||
|
$heal = $input->getOption("heal");
|
||||||
|
$revive = $input->getOption("revive");
|
||||||
|
$kill = $input->getOption("kill");
|
||||||
|
$maxHealth = $input->getOption("maxHealth");
|
||||||
|
|
||||||
|
$changed = false;
|
||||||
|
|
||||||
|
// Find character
|
||||||
|
$character = $this->getCharacter($id);
|
||||||
|
|
||||||
|
if (!$character) {
|
||||||
|
$io->error("The character with the id {$id} was not found.");
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change level
|
||||||
|
if ($level !== null) {
|
||||||
|
$level = intval($level);
|
||||||
|
|
||||||
|
if ($level <= 0) {
|
||||||
|
$io->error("Cannot set the level below 1.");
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only change level if necessary
|
||||||
|
if ($character->getLevel() !== $level) {
|
||||||
|
// Log
|
||||||
|
$logger->info("Character level changed", [
|
||||||
|
"for" => $character,
|
||||||
|
"from" => $character->getLevel(),
|
||||||
|
"to" => $level
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Change
|
||||||
|
$character->setLevel($level);
|
||||||
|
$changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Heal
|
||||||
|
if ($heal) {
|
||||||
|
if ($character->getHealth() >= $character->getMaxHealth()) {
|
||||||
|
$io->note("Character is already at full health.");
|
||||||
|
} elseif ($character->isAlive()) {
|
||||||
|
$oldHealth = $character->getHealth();
|
||||||
|
|
||||||
|
// Log
|
||||||
|
$logger->info("Character health changed", [
|
||||||
|
"for" => $character,
|
||||||
|
"from" => $oldHealth,
|
||||||
|
"to" => $character->getMaxHealth()
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Change
|
||||||
|
$character->setHealth($character->getMaxHealth());
|
||||||
|
$io->success("Character was restored to full health ({$oldHealth} to {$character->getMaxHealth()}).");
|
||||||
|
$changed = true;
|
||||||
|
} else {
|
||||||
|
$io->error("Cannot heal a dead character. Use --revive instead.");
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Revive the character
|
||||||
|
if ($revive !== false) {
|
||||||
|
// Make sure we revive between 0 and 1
|
||||||
|
if ($revive === null) {
|
||||||
|
$revive = 1;
|
||||||
|
} elseif (str_ends_with($revive, "%")) {
|
||||||
|
$revive = min(floatval($revive)/100, 1);
|
||||||
|
} else {
|
||||||
|
$revive = min(floatval($revive), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($character->isAlive()) {
|
||||||
|
$io->error("Character is already alive. Use --heal instead.");
|
||||||
|
return Command::FAILURE;
|
||||||
|
} else {
|
||||||
|
// Make sure we heal at least by 1.
|
||||||
|
$reviveAmount = (int)round(max($revive * $character->getMaxHealth(), 1), 0);
|
||||||
|
|
||||||
|
// Log
|
||||||
|
$logger->info("Character was revived", [
|
||||||
|
"for" => $character,
|
||||||
|
"to" => $reviveAmount
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Change
|
||||||
|
$character->setHealth($reviveAmount);
|
||||||
|
$io->success("Character was revived with {$reviveAmount} of health points "
|
||||||
|
."(max: {$character->getMaxHealth()}).");
|
||||||
|
$changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($kill) {
|
||||||
|
if (!$character->isAlive()) {
|
||||||
|
$io->error("What is dead may never die.");
|
||||||
|
return Command::FAILURE;
|
||||||
|
} else {
|
||||||
|
// Log
|
||||||
|
$logger->info("Character was killed", ["for" => $character]);
|
||||||
|
|
||||||
|
// Change
|
||||||
|
$character->setHealth(0);
|
||||||
|
$io->success("Character was killed.");
|
||||||
|
$changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($maxHealth) {
|
||||||
|
$maxHealth = intval($maxHealth);
|
||||||
|
if ($maxHealth < 0) {
|
||||||
|
$io->error("Cannot set maximum health below 0.");
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($character->getMaxHealth() === 0) {
|
||||||
|
$healthProportion = 0;
|
||||||
|
} else {
|
||||||
|
$healthProportion = $character->getHealth() / $character->getMaxHealth();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log
|
||||||
|
$logger->info("Character maxHealth changed", [
|
||||||
|
"for" => $character,
|
||||||
|
"from" => $character->getMaxHealth(),
|
||||||
|
"to" => $maxHealth
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Change
|
||||||
|
$character->setMaxHealth($maxHealth);
|
||||||
|
$character->setHealth((int)round($healthProportion*$maxHealth, 0));
|
||||||
|
$io->success("Character has new maximum health of {$maxHealth} (current health is {$character->getHealth()}).");
|
||||||
|
$changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save changes
|
||||||
|
if ($changed) {
|
||||||
|
try {
|
||||||
|
$em->flush();
|
||||||
|
$io->success("The character was successfully changed.");
|
||||||
|
|
||||||
|
// Log
|
||||||
|
$logger->info("Changed committed.");
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$io->error("Character could not be saved. Reason: {$e}");
|
||||||
|
$logger->error("Changes rolled back.", ["exception" => $e]);
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$io->note("Nothing was changed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Command::SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LotGD\Core\Console\Command\Character;
|
||||||
|
|
||||||
|
use LotGD\Core\Models\Character;
|
||||||
|
use LotGD\Core\Models\Repositories\CharacterRepository;
|
||||||
|
use Symfony\Component\Console\Command\Command;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command to list all characters.
|
||||||
|
*/
|
||||||
|
class CharacterListCommand extends CharacterBaseCommand
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$this->setName($this->namespaced("list"))
|
||||||
|
->setDescription('Lists all characters')
|
||||||
|
->setDefinition(
|
||||||
|
new InputDefinition([
|
||||||
|
new InputOption(
|
||||||
|
"includeSoftDeleted",
|
||||||
|
mode: InputOption::VALUE_NONE,
|
||||||
|
description: "Includes soft-deleted characters",
|
||||||
|
),
|
||||||
|
new InputOption(
|
||||||
|
"onlySoftDeleted",
|
||||||
|
mode: InputOption::VALUE_NONE,
|
||||||
|
description: "Displays only soft-deleted characters",
|
||||||
|
),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
|
{
|
||||||
|
$em = $this->game->getEntityManager();
|
||||||
|
$io = new SymfonyStyle($input, $output);
|
||||||
|
|
||||||
|
/** @var CharacterRepository $repository */
|
||||||
|
$repository = $em->getRepository(Character::class);
|
||||||
|
|
||||||
|
$marker = "";
|
||||||
|
if ($input->getOption("includeSoftDeleted")) {
|
||||||
|
$io->writeln("* marks soft-deleted characters");
|
||||||
|
|
||||||
|
$marker = "*";
|
||||||
|
$characters = $repository->findAll(CharacterRepository::INCLUDE_SOFTDELETED);
|
||||||
|
} elseif ($input->getOption("onlySoftDeleted")) {
|
||||||
|
$io->writeln("Only soft-deleted characters are shown");
|
||||||
|
$characters = $repository->findAll(CharacterRepository::ONLY_SOFTDELETED);
|
||||||
|
} else {
|
||||||
|
$characters = $repository->findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
$table = [["id", "name", "level"], []];
|
||||||
|
foreach ($characters as $character) {
|
||||||
|
$table[1][] = [
|
||||||
|
$character->getId(),
|
||||||
|
$marker.$character->getName(),
|
||||||
|
$character->getLevel(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$io->table(...$table);
|
||||||
|
|
||||||
|
return Command::SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LotGD\Core\Console\Command\Character;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use LotGD\Core\Models\Character;
|
||||||
|
use LotGD\Core\Models\Repositories\CharacterRepository;
|
||||||
|
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 CharacterRemoveCommand extends CharacterBaseCommand
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$this->setName($this->namespaced("remove"))
|
||||||
|
->setDescription("Definitely removes a character (no soft delete).")
|
||||||
|
->setDefinition(
|
||||||
|
new InputDefinition([
|
||||||
|
$this->getCharacterIdArgumentDefinition(),
|
||||||
|
new InputOption(
|
||||||
|
name: "soft",
|
||||||
|
mode: InputOption::VALUE_NONE,
|
||||||
|
description: "Only removes the character softly (soft delete)."
|
||||||
|
),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
|
{
|
||||||
|
$em = $this->game->getEntityManager();
|
||||||
|
/** @var CharacterRepository $characterRepository */
|
||||||
|
$characterRepository = $em->getRepository(Character::class);
|
||||||
|
$logger = $this->getCliLogger();
|
||||||
|
|
||||||
|
$io = new SymfonyStyle($input, $output);
|
||||||
|
|
||||||
|
$id = $input->getArgument("id");
|
||||||
|
|
||||||
|
// Find character
|
||||||
|
/** @var Character $character */
|
||||||
|
$character = $characterRepository->findWithSoftDeleted($id);
|
||||||
|
|
||||||
|
if (!$character) {
|
||||||
|
$io->error("The character with the id {$id} was not found.");
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($character->isDeleted()) {
|
||||||
|
$io->info("Character was marked as soft-deleted.");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if ($input->getOption("soft")) {
|
||||||
|
// Only soft-delete if requested
|
||||||
|
$character->delete($em);
|
||||||
|
|
||||||
|
// Commit changes
|
||||||
|
$em->flush();
|
||||||
|
|
||||||
|
$io->success("{$character} was successfully soft-deleted.");
|
||||||
|
$logger->info("Character was soft-deleted.", ["character" => $character]);
|
||||||
|
} else {
|
||||||
|
$em->remove($character);
|
||||||
|
|
||||||
|
// Commit changes
|
||||||
|
$em->flush();
|
||||||
|
|
||||||
|
$io->success("{$character} was successfully removed.");
|
||||||
|
$logger->info("Character was removed.", ["character" => $character]);
|
||||||
|
}
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$io->error("Removing {$character} was not possible. Reason: {$e}.");
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Command::SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LotGD\Core\Console\Command\Character;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
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\Output\OutputInterface;
|
||||||
|
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the viewpoint of a given character.
|
||||||
|
*/
|
||||||
|
class CharacterResetViewpointCommand extends CharacterBaseCommand
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$this->setName($this->namespaced("resetViewpoint"))
|
||||||
|
->setDescription("Resets the viewpoint of a given character.")
|
||||||
|
->setDefinition(
|
||||||
|
new InputDefinition([
|
||||||
|
$this->getCharacterIdArgumentDefinition(),
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
|
{
|
||||||
|
$em = $this->game->getEntityManager();
|
||||||
|
$logger = $this->getCliLogger();
|
||||||
|
|
||||||
|
$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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($character->getViewpoint() === null) {
|
||||||
|
$io->info("Character does not have a viewpoint yet.");
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
$em->remove($character->getViewpoint());
|
||||||
|
$character->setViewpoint(null);
|
||||||
|
|
||||||
|
$io->success("Viewpoint was successfully reset.");
|
||||||
|
|
||||||
|
# Save
|
||||||
|
$em->flush();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$io->error("Resetting the viewpoint was not possible. Reason: {$e}");
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Command::SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LotGD\Core\Console\Command\Character;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use LotGD\Core\Console\Command\BaseCommand;
|
||||||
|
use LotGD\Core\Models\Character;
|
||||||
|
use Symfony\Component\Console\Command\Command;
|
||||||
|
use Symfony\Component\Console\Helper\TableSeparator;
|
||||||
|
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 CharacterShowCommand extends CharacterBaseCommand
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$this->setName($this->namespaced("show"))
|
||||||
|
->setDescription("Shows details about character.")
|
||||||
|
->setDefinition(
|
||||||
|
new InputDefinition([
|
||||||
|
$this->getCharacterIdArgumentDefinition(),
|
||||||
|
new InputOption(
|
||||||
|
"onlyViewpoint",
|
||||||
|
mode: InputOption::VALUE_NONE,
|
||||||
|
description: "Set to only display viewpoint",
|
||||||
|
)
|
||||||
|
])
|
||||||
|
)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
|
{
|
||||||
|
$em = $this->game->getEntityManager();
|
||||||
|
$logger = $this->game->getLogger();
|
||||||
|
|
||||||
|
$io = new SymfonyStyle($input, $output);
|
||||||
|
|
||||||
|
$id = $input->getArgument("id");
|
||||||
|
$onlyViewpoint = $input->getOption("onlyViewpoint");
|
||||||
|
|
||||||
|
// Find character
|
||||||
|
/** @var Character $character */
|
||||||
|
$character = $em->getRepository(Character::class)->find($id);
|
||||||
|
|
||||||
|
if (!$character) {
|
||||||
|
$io->error("The character with the id {$id} was not found.");
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$onlyViewpoint) {
|
||||||
|
$io->title("About Character {$character->getName()}");
|
||||||
|
|
||||||
|
$io->listing([
|
||||||
|
"ID: {$character->getId()}",
|
||||||
|
"Display name: {$character->getDisplayName()}",
|
||||||
|
"Level: {$character->getLevel()}",
|
||||||
|
"Health: {$character->getHealth()}/{$character->getMaxHealth()}",
|
||||||
|
"Alive: ".($character->isAlive()?"yes":"no"),
|
||||||
|
"Attack: {$character->getAttack()}",
|
||||||
|
"Defense: {$character->getDefense()}",
|
||||||
|
]);
|
||||||
|
|
||||||
|
$io->section("Viewpoint");
|
||||||
|
} else {
|
||||||
|
$io->title("Viewpoint of {$character->getName()}");
|
||||||
|
}
|
||||||
|
|
||||||
|
$viewpoint = $character->getViewpoint();
|
||||||
|
|
||||||
|
if (!$viewpoint) {
|
||||||
|
$io->text("No viewpoint yet");
|
||||||
|
} else {
|
||||||
|
$io->text($viewpoint->getTitle() . "\n");
|
||||||
|
$io->text($viewpoint->getDescription());
|
||||||
|
|
||||||
|
$io->section("Viewpoint actions");
|
||||||
|
$actionGroups = $viewpoint->getActionGroups();
|
||||||
|
|
||||||
|
$rows = [];
|
||||||
|
|
||||||
|
foreach ($actionGroups as $actionGroup) {
|
||||||
|
$rows[] = [$actionGroup->getId(), $actionGroup->getTitle(), "", "", ""];
|
||||||
|
|
||||||
|
foreach ($actionGroup->getActions() as $action) {
|
||||||
|
$rows[] = ["", "", $action->getId(), $action->getTitle(), $action->getDestinationSceneId()];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($actionGroup->getActions())) {
|
||||||
|
$rows[] = new TableSeparator();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$io->table(["Group id", "Group name", "Action id", "Action name", "Destination"], $rows);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Command::SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,8 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace LotGD\Core\Console\Command;
|
namespace LotGD\Core\Console\Command;
|
||||||
|
|
||||||
|
use LotGD\Core\Game;
|
||||||
|
use Symfony\Component\Console\Command\Command;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
|
||||||
@@ -17,26 +19,29 @@ class ConsoleCommand extends BaseCommand
|
|||||||
protected function configure()
|
protected function configure()
|
||||||
{
|
{
|
||||||
$this->setName('console')
|
$this->setName('console')
|
||||||
->setDescription('Start a shell to interact with the game');
|
->setDescription('Start a shell to interact with the game')
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
protected function execute(InputInterface $input, OutputInterface $output)
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
{
|
{
|
||||||
print("Daenerys console, the dragon prompt. lotgd/core " . \LotGD\Core\Game::getVersion() . ".\n");
|
print "Daenerys console, the dragon prompt. lotgd/core " . Game::getVersion() . ".\n";
|
||||||
print("Enter some PHP, but be careful, this is live and attached to your currently configured setup:\n\n");
|
print "Enter some PHP, but be careful, this is live and attached to your currently configured setup:\n\n";
|
||||||
print($this->game->getConfiguration());
|
print $this->game->getConfiguration();
|
||||||
|
|
||||||
print("\n");
|
print "\n";
|
||||||
print("Try things like `\$g::getVersion()`. To quit, ^D or `exit();`.\n");
|
print "Try things like `\$g::getVersion()`. To quit, ^D or `exit();`.\n";
|
||||||
print("\n");
|
print "\n";
|
||||||
|
|
||||||
$boris = new \Boris\Boris('🐲 > ');
|
$boris = new \Boris\Boris('🐲 > ');
|
||||||
$boris->setLocal(array(
|
$boris->setLocal([
|
||||||
'g' => $this->game
|
'g' => $this->game,
|
||||||
));
|
]);
|
||||||
$boris->start();
|
$boris->start();
|
||||||
|
|
||||||
|
return Command::SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-6
@@ -1,15 +1,13 @@
|
|||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace LotGD\Core\Console\Command;
|
namespace LotGD\Core\Console\Command\Database;
|
||||||
|
|
||||||
|
use LotGD\Core\Console\Command\BaseCommand;
|
||||||
use Symfony\Component\Console\Command\Command;
|
use Symfony\Component\Console\Command\Command;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
|
||||||
use LotGD\Core\Console\Main;
|
|
||||||
use LotGD\Core\Game;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Danerys command to initiate the database with default values.
|
* Danerys command to initiate the database with default values.
|
||||||
*/
|
*/
|
||||||
@@ -21,14 +19,17 @@ class DatabaseInitCommand extends BaseCommand
|
|||||||
protected function configure()
|
protected function configure()
|
||||||
{
|
{
|
||||||
$this->setName('database:init')
|
$this->setName('database:init')
|
||||||
->setDescription('Initiates database with default values.');
|
->setDescription('Initiates database with default values.')
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
protected function execute(InputInterface $input, OutputInterface $output)
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
{
|
{
|
||||||
$this->game->getEntityManager()->flush();
|
$this->game->getEntityManager()->flush();
|
||||||
|
|
||||||
|
return Command::SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LotGD\Core\Console\Command\Database;
|
||||||
|
|
||||||
|
use LotGD\Core\Console\Command\BaseCommand;
|
||||||
|
use Doctrine\ORM\Tools\SchemaTool;
|
||||||
|
use Symfony\Component\Console\Command\Command;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Danerys command to initiate the database with default values.
|
||||||
|
*/
|
||||||
|
class DatabaseSchemaUpdateCommand extends BaseCommand
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$this->setName('database:schemaUpdate')
|
||||||
|
->setDescription('Updates the database schema manually.')
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
|
{
|
||||||
|
$entityManager = $this->game->getEntityManager();
|
||||||
|
$metaData = $entityManager->getMetadataFactory()->getAllMetadata();
|
||||||
|
$schemaTool = new SchemaTool($entityManager);
|
||||||
|
$schemaTool->updateSchema($metaData);
|
||||||
|
|
||||||
|
$entityManager->flush();
|
||||||
|
|
||||||
|
return Command::SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LotGD\Core\Console\Command\Module;
|
||||||
|
|
||||||
|
use Doctrine\Persistence\ObjectRepository;
|
||||||
|
use LotGD\Core\Console\Command\BaseCommand;
|
||||||
|
use LotGD\Core\Models\Module;
|
||||||
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
|
||||||
|
class ModuleBaseCommand extends BaseCommand
|
||||||
|
{
|
||||||
|
protected ?string $namespace = "module";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return InputArgument
|
||||||
|
*/
|
||||||
|
protected function getModuleNameArgumentDefinition(): InputArgument
|
||||||
|
{
|
||||||
|
return new InputArgument(
|
||||||
|
name: "moduleName",
|
||||||
|
mode: InputArgument::REQUIRED,
|
||||||
|
description: "Name of the module, in vendor/package format",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getModuleRepository(): ObjectRepository
|
||||||
|
{
|
||||||
|
return $this->game->getEntityManager()->getRepository(Module::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getModuleModel(InputInterface $input): ?Module
|
||||||
|
{
|
||||||
|
return $this->game->getModuleManager()->getModule($input->getArgument("moduleName"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LotGD\Core\Console\Command\Module;
|
||||||
|
|
||||||
|
use LotGD\Core\Events\EventContextData;
|
||||||
|
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 ModuleConfigListCommand extends ModuleBaseCommand
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$this->setName($this->namespaced("config:list"))
|
||||||
|
->setDescription('List available configuration option for a module')
|
||||||
|
->setDefinition([
|
||||||
|
$this->getModuleNameArgumentDefinition(),
|
||||||
|
])
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output)
|
||||||
|
{
|
||||||
|
$io = new SymfonyStyle($input, $output);
|
||||||
|
$module = $this->getModuleModel($input);
|
||||||
|
|
||||||
|
if (!$module) {
|
||||||
|
$io->error("Module was not found.");
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create hook
|
||||||
|
$context = EventContextData::create([
|
||||||
|
"module" => $module,
|
||||||
|
"io" => $io,
|
||||||
|
"settings" => [],
|
||||||
|
]);
|
||||||
|
$newContext = $this->game->getEventManager()->publish(
|
||||||
|
event: "h/lotgd/core/cli/module-config-list/".$module->getLibrary(),
|
||||||
|
contextData: $context
|
||||||
|
);
|
||||||
|
$settings = $newContext->get("settings");
|
||||||
|
|
||||||
|
$io->title("Module ".$module->getLibrary());
|
||||||
|
|
||||||
|
if (count($settings) === 0) {
|
||||||
|
$io->note("This module does not provide any settings.");
|
||||||
|
} else {
|
||||||
|
$io->table(["setting", "value", "description"], $settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Command::SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LotGD\Core\Console\Command\Module;
|
||||||
|
|
||||||
|
use LotGD\Core\Events\EventContextData;
|
||||||
|
use Symfony\Component\Console\Command\Command;
|
||||||
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||||
|
|
||||||
|
class ModuleConfigResetCommand extends ModuleBaseCommand
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$this->setName($this->namespaced("config:reset"))
|
||||||
|
->setDescription('Reset a module setting')
|
||||||
|
->setDefinition([
|
||||||
|
$this->getModuleNameArgumentDefinition(),
|
||||||
|
new InputArgument(
|
||||||
|
"setting",
|
||||||
|
mode: InputArgument::REQUIRED,
|
||||||
|
description: "Name of setting, see {$this->namespaced('config:list')}.",
|
||||||
|
),
|
||||||
|
])
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output)
|
||||||
|
{
|
||||||
|
$logger = $this->getCliLogger();
|
||||||
|
$io = new SymfonyStyle($input, $output);
|
||||||
|
$module = $this->getModuleModel($input);
|
||||||
|
|
||||||
|
if (!$module) {
|
||||||
|
$io->error("Module was not found.");
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
$io->title("Module {$module->getLibrary()}");
|
||||||
|
|
||||||
|
// Create hook
|
||||||
|
$context = EventContextData::create([
|
||||||
|
"module" => $module,
|
||||||
|
"io" => $io,
|
||||||
|
"setting" => $input->getArgument("setting"),
|
||||||
|
"return" => Command::FAILURE,
|
||||||
|
"reason" => "Setting does not exist.",
|
||||||
|
]);
|
||||||
|
|
||||||
|
$newContext = $this->game->getEventManager()->publish(
|
||||||
|
event: "h/lotgd/core/cli/module-config-reset/{$module->getLibrary()}",
|
||||||
|
contextData: $context
|
||||||
|
);
|
||||||
|
if ($newContext->get("return") != Command::SUCCESS) {
|
||||||
|
$io->error($newContext->get("reason"));
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->game->getEntityManager()->flush();
|
||||||
|
|
||||||
|
return Command::SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LotGD\Core\Console\Command\Module;
|
||||||
|
|
||||||
|
use LotGD\Core\Events\EventContextData;
|
||||||
|
use Symfony\Component\Console\Command\Command;
|
||||||
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||||
|
|
||||||
|
class ModuleConfigSetCommand extends ModuleBaseCommand
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$this->setName($this->namespaced("config:set"))
|
||||||
|
->setDescription('Change a module setting')
|
||||||
|
->setDefinition([
|
||||||
|
$this->getModuleNameArgumentDefinition(),
|
||||||
|
new InputArgument(
|
||||||
|
"setting",
|
||||||
|
mode: InputArgument::REQUIRED,
|
||||||
|
description: "Name of setting, see {$this->namespaced('config:list')}.",
|
||||||
|
),
|
||||||
|
new InputArgument(
|
||||||
|
"value",
|
||||||
|
InputArgument::REQUIRED,
|
||||||
|
description: "New value for the given setting.",
|
||||||
|
),
|
||||||
|
])
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output)
|
||||||
|
{
|
||||||
|
$logger = $this->getCliLogger();
|
||||||
|
$io = new SymfonyStyle($input, $output);
|
||||||
|
$module = $this->getModuleModel($input);
|
||||||
|
|
||||||
|
if (!$module) {
|
||||||
|
$io->error("Module was not found.");
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
$io->title("Module {$module->getLibrary()}");
|
||||||
|
|
||||||
|
// Create hook
|
||||||
|
$context = EventContextData::create([
|
||||||
|
"module" => $module,
|
||||||
|
"io" => $io,
|
||||||
|
"setting" => $input->getArgument("setting"),
|
||||||
|
"value" => $input->getArgument("value"),
|
||||||
|
"return" => Command::FAILURE,
|
||||||
|
"reason" => "Setting does not exist.",
|
||||||
|
]);
|
||||||
|
$newContext = $this->game->getEventManager()->publish(
|
||||||
|
event: "h/lotgd/core/cli/module-config-set/{$module->getLibrary()}",
|
||||||
|
contextData: $context
|
||||||
|
);
|
||||||
|
if ($newContext->get("return") != Command::SUCCESS) {
|
||||||
|
$io->error($newContext->get("reason"));
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->game->getEntityManager()->flush();
|
||||||
|
|
||||||
|
return Command::SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LotGD\Core\Console\Command\Module;
|
||||||
|
|
||||||
|
use LotGD\Core\Models\Module;
|
||||||
|
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 ModuleListCommand extends ModuleBaseCommand
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$this->setName($this->namespaced("list"))
|
||||||
|
->setDescription('List all installed modules.')
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
|
{
|
||||||
|
$io = new SymfonyStyle($input, $output);
|
||||||
|
/** @var Module[] $modules */
|
||||||
|
$modules = $this->game->getModuleManager()->getModules();
|
||||||
|
|
||||||
|
$io->title("Installed modules");
|
||||||
|
|
||||||
|
if (count($modules) > 0) {
|
||||||
|
$listing = [];
|
||||||
|
foreach ($modules as $module) {
|
||||||
|
$listing[] = [$module->getLibrary() => $module->getCreatedAt()->format("d M Y, H:i")];
|
||||||
|
}
|
||||||
|
|
||||||
|
$io->definitionList(...$listing);
|
||||||
|
} else {
|
||||||
|
$io->note("No modules installed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Command::SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,125 @@
|
|||||||
|
<?php
|
||||||
|
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;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Danerys command to register and initiate any newly installed modules.
|
||||||
|
*/
|
||||||
|
class ModuleRegisterCommand extends ModuleBaseCommand
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$this->setName($this->namespaced("register"))
|
||||||
|
->setDescription('Register and initialize any newly installed modules')
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
|
{
|
||||||
|
$io = new SymfonyStyle($input, $output);
|
||||||
|
$modules = $this->game->getComposerManager()->getModulePackages();
|
||||||
|
|
||||||
|
$globalFlawless = true;
|
||||||
|
$registered = [];
|
||||||
|
foreach ($modules as $p) {
|
||||||
|
$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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 SymfonyStyle $io
|
||||||
|
* @param array $registered
|
||||||
|
* @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 true;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Skip if already registered
|
||||||
|
if (!empty($registered[$packageName])) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$io->text("Reading module {$packageName} {$package->getPrettyVersion()}");
|
||||||
|
|
||||||
|
# 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) {
|
||||||
|
$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 {
|
||||||
|
$this->game->getModuleManager()->register($library);
|
||||||
|
$io->success("\tRegistered new module {$packageName}");
|
||||||
|
} catch (ModuleAlreadyExistsException $e) {
|
||||||
|
$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;
|
||||||
|
}
|
||||||
|
}
|
||||||
+14
-10
@@ -1,40 +1,44 @@
|
|||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace LotGD\Core\Console\Command;
|
namespace LotGD\Core\Console\Command\Module;
|
||||||
|
|
||||||
|
use LotGD\Core\Console\Command\BaseCommand;
|
||||||
|
use Symfony\Component\Console\Command\Command;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Danerys command to validate installed modules.
|
* Danerys command to validate installed modules.
|
||||||
*/
|
*/
|
||||||
class ModuleValidateCommand extends BaseCommand
|
class ModuleValidateCommand extends ModuleBaseCommand
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
protected function configure()
|
protected function configure()
|
||||||
{
|
{
|
||||||
$this->setName('module:validate')
|
$this->setName($this->namespaced("validate"))
|
||||||
->setDescription('Validate installed modules');
|
->setDescription('Validate installed modules')
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
protected function execute(InputInterface $input, OutputInterface $output)
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
{
|
{
|
||||||
$results = $this->game->getModuleManager()->validate();
|
$results = $this->game->getModuleManager()->validate();
|
||||||
|
|
||||||
if (count($results) > 0) {
|
if (\count($results) > 0) {
|
||||||
foreach ($results as $r) {
|
foreach ($results as $r) {
|
||||||
$output->writeln($r);
|
$output->writeln($r);
|
||||||
}
|
}
|
||||||
return 1;
|
|
||||||
} else {
|
return Command::FAILURE;
|
||||||
$output->writeln("<info>LotGD modules validated</info>");
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
$output->writeln("<info>LotGD modules validated</info>");
|
||||||
|
|
||||||
|
return Command::SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
<?php
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace LotGD\Core\Console\Command;
|
|
||||||
|
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
|
||||||
|
|
||||||
use LotGD\Core\Exceptions\ClassNotFoundException;
|
|
||||||
use LotGD\Core\Exceptions\ModuleAlreadyExistsException;
|
|
||||||
use LotGD\Core\LibraryConfiguration;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Danerys command to register and initiate any newly installed modules.
|
|
||||||
*/
|
|
||||||
class ModuleRegisterCommand extends BaseCommand
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
protected function configure()
|
|
||||||
{
|
|
||||||
$this->setName('module:register')
|
|
||||||
->setDescription('Register and initialize any newly installed modules');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
protected function execute(InputInterface $input, OutputInterface $output)
|
|
||||||
{
|
|
||||||
$modules = $this->game->getComposerManager()->getModulePackages();
|
|
||||||
|
|
||||||
foreach ($modules as $p) {
|
|
||||||
$library = new LibraryConfiguration($this->game->getComposerManager(), $p, $this->game->getCWD());
|
|
||||||
$name = $library->getName();
|
|
||||||
|
|
||||||
try {
|
|
||||||
$this->game->getModuleManager()->register($library);
|
|
||||||
|
|
||||||
$output->writeln("<info>Registered new module {$name}</info>");
|
|
||||||
} catch (ModuleAlreadyExistsException $e) {
|
|
||||||
$output->writeln("Skipping already registered module {$name}");
|
|
||||||
} catch (ClassNotFoundException $e) {
|
|
||||||
$output->writeln("<error>Error installing module {$name}: " . $e->getMessage() . "</error>");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LotGD\Core\Console\Command\Scene;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use LotGD\Core\Models\Scene;
|
||||||
|
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 SceneBaseCommand
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$this->setName($this->namespaced("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();
|
||||||
|
$logger = $this->getCliLogger();
|
||||||
|
|
||||||
|
$io = new SymfonyStyle($input, $output);
|
||||||
|
|
||||||
|
$title = $input->getArgument("title");
|
||||||
|
$description = $input->getArgument("description");
|
||||||
|
$templateClass = $input->getOption("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 = new Scene(
|
||||||
|
title: $title,
|
||||||
|
description: $description,
|
||||||
|
template: $template
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$em->persist($scene);
|
||||||
|
|
||||||
|
// Commit changes
|
||||||
|
$em->flush();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$io->error("Persisting of the scene was not possible. Reason: {$e->getMessage()}.");
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
$io->success("Scene was successfully created. ID: {$scene->getId()}.");
|
||||||
|
$logger->info("{$scene} was created.");
|
||||||
|
|
||||||
|
return Command::SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LotGD\Core\Console\Command\Scene;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use LotGD\Core\Exceptions\ArgumentException;
|
||||||
|
use LotGD\Core\Models\Scene;
|
||||||
|
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\Output\OutputInterface;
|
||||||
|
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the viewpoint of a given character.
|
||||||
|
*/
|
||||||
|
class SceneAddConnectionGroupCommand extends SceneBaseCommand
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$this->setName($this->namespaced('addConnectionGroup'))
|
||||||
|
->setDescription("Add a connection group to an existing scene.")
|
||||||
|
->setDefinition(
|
||||||
|
new InputDefinition([
|
||||||
|
$this->getSceneIdArgumentDefinition(),
|
||||||
|
new InputArgument("groupName", InputArgument::REQUIRED, "Internal id of the group."),
|
||||||
|
new InputArgument("groupTitle", InputArgument::REQUIRED, "Title of the group (what the character can see"),
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
|
{
|
||||||
|
$em = $this->game->getEntityManager();
|
||||||
|
$logger = $this->getCliLogger();
|
||||||
|
|
||||||
|
$io = new SymfonyStyle($input, $output);
|
||||||
|
|
||||||
|
$sceneId = $input->getArgument("id");
|
||||||
|
$groupName = $input->getArgument("groupName");
|
||||||
|
$groupTitle = $input->getArgument("groupTitle");
|
||||||
|
|
||||||
|
// Search scene
|
||||||
|
/** @var ?Scene $scene */
|
||||||
|
$scene = $em->getRepository(Scene::class)->find($sceneId);
|
||||||
|
|
||||||
|
if (!$scene) {
|
||||||
|
$io->error("The requested scene with the ID {$sceneId} was not found.");
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make scene connection group
|
||||||
|
$connectionGroup = new SceneConnectionGroup($groupName, $groupTitle);
|
||||||
|
|
||||||
|
// Add
|
||||||
|
try {
|
||||||
|
$scene->addConnectionGroup($connectionGroup);
|
||||||
|
|
||||||
|
// Commit changes
|
||||||
|
$em->flush();
|
||||||
|
} catch(ArgumentException $e) {
|
||||||
|
// Catches the error if a group already exists.
|
||||||
|
$io->error($e->getMessage());
|
||||||
|
return Command::FAILURE;
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$io->error("An unknown error occurred: {$e->getMessage()}");
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
$io->success("{$connectionGroup} successfully added.");
|
||||||
|
$logger->info("{$connectionGroup} was added to {$scene}.");
|
||||||
|
|
||||||
|
return Command::SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LotGD\Core\Console\Command\Scene;
|
||||||
|
|
||||||
|
use LotGD\Core\Console\Command\BaseCommand;
|
||||||
|
use LotGD\Core\Models\Scene;
|
||||||
|
use LotGD\Core\SceneTemplates\SceneTemplateInterface;
|
||||||
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
|
|
||||||
|
class SceneBaseCommand extends BaseCommand
|
||||||
|
{
|
||||||
|
protected ?string $namespace = "scene";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return InputArgument
|
||||||
|
*/
|
||||||
|
protected function getSceneIdArgumentDefinition(): InputArgument
|
||||||
|
{
|
||||||
|
return new InputArgument(
|
||||||
|
name: "id",
|
||||||
|
mode: InputArgument::REQUIRED,
|
||||||
|
description: "Scene ID",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $id
|
||||||
|
* @return Scene|null
|
||||||
|
*/
|
||||||
|
protected function getScene(string $id): ?Scene
|
||||||
|
{
|
||||||
|
/** @var Scene|null $scene */
|
||||||
|
$scene = $this->game->getEntityManager()->getRepository(Scene::class)->find($id);
|
||||||
|
return $scene;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Scene $scene
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function getSceneTemplatePath(Scene $scene)
|
||||||
|
{
|
||||||
|
$sceneTemplate = "no-template";
|
||||||
|
if ($scene->getTemplate()) {
|
||||||
|
/** @var SceneTemplateInterface $templateClass */
|
||||||
|
$templateClass = $scene->getTemplate()->getClass();
|
||||||
|
$sceneTemplate = $templateClass::getNavigationEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $sceneTemplate;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LotGD\Core\Console\Command\Scene;
|
||||||
|
|
||||||
|
use LotGD\Core\Events\EventContextData;
|
||||||
|
use LotGD\Core\SceneTemplates\SceneTemplateInterface;
|
||||||
|
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 SceneConfigListCommand extends SceneBaseCommand
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$this->setName($this->namespaced("config:list"))
|
||||||
|
->setDescription('List available settings for a scene')
|
||||||
|
->setDefinition([
|
||||||
|
$this->getSceneIdArgumentDefinition(),
|
||||||
|
])
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output)
|
||||||
|
{
|
||||||
|
$io = new SymfonyStyle($input, $output);
|
||||||
|
$scene = $this->getScene($input->getArgument("id"));
|
||||||
|
|
||||||
|
if (!$scene) {
|
||||||
|
$io->error("Scene was not found.");
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
$sceneTemplate = $this->getSceneTemplatePath($scene);
|
||||||
|
|
||||||
|
// Create hook
|
||||||
|
$context = EventContextData::create([
|
||||||
|
"scene" => $scene,
|
||||||
|
"io" => $io,
|
||||||
|
"settings" => [],
|
||||||
|
]);
|
||||||
|
$newContext = $this->game->getEventManager()->publish(
|
||||||
|
event: "h/lotgd/core/cli/scene-config-list/$sceneTemplate",
|
||||||
|
contextData: $context
|
||||||
|
);
|
||||||
|
$settings = $newContext->get("settings");
|
||||||
|
|
||||||
|
$io->title("Scene ".$scene->getTitle());
|
||||||
|
|
||||||
|
if (count($settings) === 0) {
|
||||||
|
$io->note("There are no scene settings available.");
|
||||||
|
} else {
|
||||||
|
$io->table(["setting", "value", "description"], $settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Command::SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LotGD\Core\Console\Command\Scene;
|
||||||
|
|
||||||
|
use LotGD\Core\Events\EventContextData;
|
||||||
|
use LotGD\Core\SceneTemplates\SceneTemplateInterface;
|
||||||
|
use Symfony\Component\Console\Command\Command;
|
||||||
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||||
|
|
||||||
|
class SceneConfigResetCommand extends SceneBaseCommand
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$this->setName($this->namespaced("config:reset"))
|
||||||
|
->setDescription('Reset a scene setting')
|
||||||
|
->setDefinition([
|
||||||
|
$this->getSceneIdArgumentDefinition(),
|
||||||
|
new InputArgument(
|
||||||
|
"setting",
|
||||||
|
mode: InputArgument::REQUIRED,
|
||||||
|
description: "Name of setting, see {$this->namespaced('config:list')}.",
|
||||||
|
),
|
||||||
|
])
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output)
|
||||||
|
{
|
||||||
|
$logger = $this->getCliLogger();
|
||||||
|
$io = new SymfonyStyle($input, $output);
|
||||||
|
$scene = $this->getScene($input->getArgument("id"));
|
||||||
|
|
||||||
|
if (!$scene) {
|
||||||
|
$io->error("Scene was not found.");
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
$sceneTemplate = $this->getSceneTemplatePath($scene);
|
||||||
|
|
||||||
|
$io->title("Scene {$scene->getTitle()}");
|
||||||
|
|
||||||
|
// Create hook
|
||||||
|
$context = EventContextData::create([
|
||||||
|
"scene" => $scene,
|
||||||
|
"io" => $io,
|
||||||
|
"setting" => $input->getArgument("setting"),
|
||||||
|
"return" => Command::FAILURE,
|
||||||
|
"reason" => "Setting does not exist.",
|
||||||
|
]);
|
||||||
|
|
||||||
|
$newContext = $this->game->getEventManager()->publish(
|
||||||
|
event: "h/lotgd/core/cli/scene-config-reset/{$sceneTemplate}",
|
||||||
|
contextData: $context
|
||||||
|
);
|
||||||
|
if ($newContext->get("return") != Command::SUCCESS) {
|
||||||
|
$io->error($newContext->get("reason"));
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->game->getEntityManager()->flush();
|
||||||
|
|
||||||
|
return Command::SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LotGD\Core\Console\Command\Scene;
|
||||||
|
|
||||||
|
use LotGD\Core\Events\EventContextData;
|
||||||
|
use Symfony\Component\Console\Command\Command;
|
||||||
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||||
|
|
||||||
|
class SceneConfigSetCommand extends SceneBaseCommand
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$this->setName($this->namespaced("config:set"))
|
||||||
|
->setDescription('Change a scene setting')
|
||||||
|
->setDefinition([
|
||||||
|
$this->getSceneIdArgumentDefinition(),
|
||||||
|
new InputArgument(
|
||||||
|
"setting",
|
||||||
|
mode: InputArgument::REQUIRED,
|
||||||
|
description: "Name of setting, see {$this->namespaced('config:list')}.",
|
||||||
|
),
|
||||||
|
new InputArgument(
|
||||||
|
"value",
|
||||||
|
InputArgument::REQUIRED,
|
||||||
|
description: "New value for the given setting.",
|
||||||
|
),
|
||||||
|
])
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output)
|
||||||
|
{
|
||||||
|
$logger = $this->getCliLogger();
|
||||||
|
$io = new SymfonyStyle($input, $output);
|
||||||
|
$scene = $this->getScene($input->getArgument("id"));
|
||||||
|
|
||||||
|
if (!$scene) {
|
||||||
|
$io->error("Scene was not found.");
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
$sceneTemplate = $this->getSceneTemplatePath($scene);
|
||||||
|
|
||||||
|
$io->title("Scene {$scene->getTitle()}");
|
||||||
|
|
||||||
|
// Create hook
|
||||||
|
$context = EventContextData::create([
|
||||||
|
"scene" => $scene,
|
||||||
|
"io" => $io,
|
||||||
|
"setting" => $input->getArgument("setting"),
|
||||||
|
"value" => $input->getArgument("value"),
|
||||||
|
"return" => Command::FAILURE,
|
||||||
|
"reason" => "Setting does not exist.",
|
||||||
|
]);
|
||||||
|
$newContext = $this->game->getEventManager()->publish(
|
||||||
|
event: "h/lotgd/core/cli/scene-config-set/{$sceneTemplate}",
|
||||||
|
contextData: $context
|
||||||
|
);
|
||||||
|
if ($newContext->get("return") != Command::SUCCESS) {
|
||||||
|
$io->error($newContext->get("reason"));
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->game->getEntityManager()->flush();
|
||||||
|
|
||||||
|
return Command::SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,155 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LotGD\Core\Console\Command\Scene;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use LotGD\Core\Exceptions\ArgumentException;
|
||||||
|
use LotGD\Core\Models\Scene;
|
||||||
|
use LotGD\Core\Models\SceneConnectable;
|
||||||
|
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 SceneConnectCommand extends SceneBaseCommand
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$this->setName($this->namespaced("connect"))
|
||||||
|
->setDescription("Connects two scenes.")
|
||||||
|
->setDefinition(
|
||||||
|
new InputDefinition([
|
||||||
|
new InputArgument(
|
||||||
|
"outgoing",
|
||||||
|
mode: InputArgument::REQUIRED,
|
||||||
|
description: "Outgoing scene ID",
|
||||||
|
),
|
||||||
|
new InputArgument(
|
||||||
|
"incoming",
|
||||||
|
mode: InputArgument::REQUIRED,
|
||||||
|
description: "Incoming scene ID",
|
||||||
|
),
|
||||||
|
new InputOption(
|
||||||
|
"outgoingGroupName",
|
||||||
|
shortcut: "o",
|
||||||
|
mode: InputOption::VALUE_OPTIONAL,
|
||||||
|
description: "A valid, user-assignable scene template. Check sceneTemplate:list to get all available scenes.",
|
||||||
|
default: null,
|
||||||
|
),
|
||||||
|
new InputOption(
|
||||||
|
"incomingGroupName",
|
||||||
|
shortcut: "i",
|
||||||
|
mode: InputOption::VALUE_OPTIONAL,
|
||||||
|
description: "A valid, user-assignable scene template. Check sceneTemplate:list to get all available scenes.",
|
||||||
|
default: null,
|
||||||
|
),
|
||||||
|
new InputOption(
|
||||||
|
"directionality",
|
||||||
|
shortcut: "d",
|
||||||
|
mode: InputOption::VALUE_OPTIONAL,
|
||||||
|
description: "0 for bidirectional, 1 for unidirectional (outgoing->incoming)",
|
||||||
|
default: 0,
|
||||||
|
)
|
||||||
|
])
|
||||||
|
)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
|
{
|
||||||
|
$em = $this->game->getEntityManager();
|
||||||
|
$logger = $this->getCliLogger();
|
||||||
|
$sceneRepository = $em->getRepository(Scene::class);
|
||||||
|
|
||||||
|
$io = new SymfonyStyle($input, $output);
|
||||||
|
|
||||||
|
/** @var ?Scene $outgoingScene */
|
||||||
|
$outgoingScene = $sceneRepository->find($input->getArgument("outgoing"));
|
||||||
|
/** @var ?Scene $incomingScene */
|
||||||
|
$incomingScene = $sceneRepository->find($input->getArgument("incoming"));
|
||||||
|
|
||||||
|
// Check of scenes actually exist
|
||||||
|
if (!$outgoingScene) {
|
||||||
|
$io->error("The outgoing scene was not found.");
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$incomingScene) {
|
||||||
|
$io->error("The incoming scene was not found");
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get group names
|
||||||
|
$outgoingGroupName = $input->getOption("outgoingGroupName");
|
||||||
|
$incomingGroupName = $input->getOption("incomingGroupName");
|
||||||
|
|
||||||
|
/** @var SceneConnectable $outgoing */
|
||||||
|
$outgoing = null;
|
||||||
|
/** @var SceneConnectable $outgoing */
|
||||||
|
$incoming = null;
|
||||||
|
|
||||||
|
// Determine the outgoing Connectable
|
||||||
|
if ($outgoingGroupName) {
|
||||||
|
if (!$outgoingScene->hasConnectionGroup($outgoingGroupName)) {
|
||||||
|
$io->error("The outgoing scene does not have a connection group with the id {$outgoingGroupName}");
|
||||||
|
return Command::FAILURE;
|
||||||
|
} else {
|
||||||
|
$outgoing = $outgoingScene->getConnectionGroup($outgoingGroupName);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$outgoing = $outgoingScene;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine the incoming Connectable
|
||||||
|
if ($incomingGroupName) {
|
||||||
|
if (!$incomingScene->hasConnectionGroup($incomingGroupName)) {
|
||||||
|
$io->error("The incoming scene does not have a connection group with the id {$incomingGroupName}");
|
||||||
|
return Command::FAILURE;
|
||||||
|
} else {
|
||||||
|
$incoming = $incomingScene->getConnectionGroup($incomingGroupName);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$incoming = $incomingScene;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get directionality
|
||||||
|
$directionality = intval($input->getOption("directionality"));
|
||||||
|
|
||||||
|
if ($directionality < 0 or $directionality > 1) {
|
||||||
|
$io->warning("Directionality was not either 0 or 1. It was forced to 0.");
|
||||||
|
$directionality = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connect the connectables
|
||||||
|
try {
|
||||||
|
$outgoing->connect($incoming, $directionality);
|
||||||
|
|
||||||
|
// Commit changes
|
||||||
|
$em->flush();
|
||||||
|
} catch (ArgumentException $e) {
|
||||||
|
$io->error("Scenes were not connected. Reason: {$e->getMessage()}.");
|
||||||
|
return Command::FAILURE;
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$io->error("An unknown error occurred: {$e}");
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
$io->success("The two scenes were successfully connected.");
|
||||||
|
$logger->info("Connected {$outgoingScene} to {$incomingScene}.");
|
||||||
|
|
||||||
|
return Command::SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LotGD\Core\Console\Command\Scene;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use LotGD\Core\Models\Scene;
|
||||||
|
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\Output\OutputInterface;
|
||||||
|
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the viewpoint of a given character.
|
||||||
|
*/
|
||||||
|
class SceneDisconnectCommand extends SceneBaseCommand
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$this->setName($this->namespaced("disconnect"))
|
||||||
|
->setDescription("Disconnects two scenes.")
|
||||||
|
->setDefinition(
|
||||||
|
new InputDefinition([
|
||||||
|
new InputArgument(
|
||||||
|
"scene1",
|
||||||
|
mode: InputArgument::REQUIRED,
|
||||||
|
description: "One scene ID",
|
||||||
|
),
|
||||||
|
new InputArgument(
|
||||||
|
"scene2",
|
||||||
|
mode: InputArgument::REQUIRED,
|
||||||
|
description: "The other scene ID",
|
||||||
|
),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
|
{
|
||||||
|
$em = $this->game->getEntityManager();
|
||||||
|
$logger = $this->getCliLogger();
|
||||||
|
$sceneRepository = $em->getRepository(Scene::class);
|
||||||
|
|
||||||
|
$io = new SymfonyStyle($input, $output);
|
||||||
|
|
||||||
|
/** @var Scene $scene1 */
|
||||||
|
$scene1 = $sceneRepository->find($input->getArgument("scene1"));
|
||||||
|
/** @var Scene $scene2 */
|
||||||
|
$scene2 = $sceneRepository->find($input->getArgument("scene2"));
|
||||||
|
|
||||||
|
if (!$scene1) {
|
||||||
|
$io->error("Scene with id {$input->getArgument('scene1')} was not found.");
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$scene2) {
|
||||||
|
$io->error("Scene with id {$input->getArgument('scene2')} was not found.");
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
$connection = $scene1->getConnectionTo($scene2);
|
||||||
|
|
||||||
|
if (!$connection) {
|
||||||
|
$io->error("The given scenes do not share a connection.");
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Commit changes
|
||||||
|
$em->remove($connection);
|
||||||
|
$em->flush();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$io->error("An unknown error occurred: {$e->getMessage()}");
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
$io->success("The connections between the two given scenes was removed.");
|
||||||
|
$logger->info("Disconnected {$connection->getOutgoingScene()} and {$connection->getIncomingScene()}.");
|
||||||
|
|
||||||
|
return Command::SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
<?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 SceneBaseCommand
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$this->setName($this->namespaced("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", "template"], []];
|
||||||
|
foreach ($scenes as $scene) {
|
||||||
|
$table[1][] = [
|
||||||
|
$scene->getId(),
|
||||||
|
$scene->getTitle(),
|
||||||
|
count($scene->getConnectedScenes()),
|
||||||
|
$scene->getTemplate()?->getClass(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$io->table(...$table);
|
||||||
|
|
||||||
|
return Command::SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LotGD\Core\Console\Command\Scene;
|
||||||
|
|
||||||
|
use LotGD\Core\Models\Scene;
|
||||||
|
use Symfony\Component\Console\Command\Command;
|
||||||
|
use Symfony\Component\Console\Input\InputDefinition;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the viewpoint of a given character.
|
||||||
|
*/
|
||||||
|
class SceneRemoveCommand extends SceneBaseCommand
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$this->setName($this->namespaced("remove"))
|
||||||
|
->setDescription("Removes a scene.")
|
||||||
|
->setDefinition(
|
||||||
|
new InputDefinition([
|
||||||
|
$this->getSceneIdArgumentDefinition(),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
|
{
|
||||||
|
$em = $this->game->getEntityManager();
|
||||||
|
|
||||||
|
$io = new SymfonyStyle($input, $output);
|
||||||
|
|
||||||
|
$sceneId = $input->getArgument("id");
|
||||||
|
|
||||||
|
// Get scene
|
||||||
|
/** @var Scene $scene */
|
||||||
|
$scene = $em->getRepository(Scene::class)->find($sceneId);
|
||||||
|
|
||||||
|
if (!$scene) {
|
||||||
|
$io->error("The scene with the ID {$sceneId} was not found.");
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$scene->isRemovable()) {
|
||||||
|
$io->error("The scene with the ID {$sceneId} was marked as not removable. Please remove the responsible module instead.");
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark for removal and flush
|
||||||
|
try {
|
||||||
|
$em->remove($scene);
|
||||||
|
$em->flush();
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$io->error("Removal of {$sceneId} was not possible: {$e->getMessage()}");
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
$io->success("{$scene} was successfully removed.");
|
||||||
|
|
||||||
|
return Command::SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LotGD\Core\Console\Command\Scene;
|
||||||
|
|
||||||
|
use LotGD\Core\Models\Scene;
|
||||||
|
use LotGD\Core\Models\SceneConnection;
|
||||||
|
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\Output\OutputInterface;
|
||||||
|
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the viewpoint of a given character.
|
||||||
|
*/
|
||||||
|
class SceneRemoveConnectionGroupCommand extends SceneBaseCommand
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$this->setName($this->namespaced("removeConnectionGroup"))
|
||||||
|
->setDescription("Removes a connection group from an existing scene.")
|
||||||
|
->setDefinition(
|
||||||
|
new InputDefinition([
|
||||||
|
$this->getSceneIdArgumentDefinition(),
|
||||||
|
new InputArgument("groupName", InputArgument::REQUIRED, "Internal id of the group."),
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
|
{
|
||||||
|
$em = $this->game->getEntityManager();
|
||||||
|
$logger = $this->getCliLogger();
|
||||||
|
|
||||||
|
$io = new SymfonyStyle($input, $output);
|
||||||
|
|
||||||
|
$sceneId = $input->getArgument("id");
|
||||||
|
$groupName = $input->getArgument("groupName");
|
||||||
|
|
||||||
|
// Search scene
|
||||||
|
/** @var ?Scene $scene */
|
||||||
|
$scene = $em->getRepository(Scene::class)->find($sceneId);
|
||||||
|
|
||||||
|
if (!$scene) {
|
||||||
|
$io->error("The scene with the ID {$sceneId} was not found.");
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$scene->hasConnectionGroup($groupName)) {
|
||||||
|
$io->error("The scene {$sceneId} does not have a connection group with the name {$groupName}");
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
$connectionGroup = $scene->getConnectionGroup($groupName);
|
||||||
|
|
||||||
|
# Mark for removal
|
||||||
|
$em->remove($connectionGroup);
|
||||||
|
|
||||||
|
# Update outgoing connections if they refer to the deleted connectionGroup
|
||||||
|
$connections = $scene->getConnections();
|
||||||
|
/** @var SceneConnection $connection */
|
||||||
|
foreach ($connections as $connection) {
|
||||||
|
if ($connection->getIncomingScene() === $scene and $connection->getIncomingConnectionGroupName() === $groupName) {
|
||||||
|
$connection->setIncomingConnectionGroupName(null);
|
||||||
|
$io->comment("Updated connection to {$connection->getOutgoingScene()->getTitle()}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($connection->getOutgoingScene() === $scene and $connection->getOutgoingConnectionGroupName() === $groupName) {
|
||||||
|
$connection->setOutgoingConnectionGroupName(null);
|
||||||
|
$io->comment("Updated connection to {$connection->getIncomingScene()->getTitle()}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$em->flush();
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$io->error("An unknown error occurred: {$e->getMessage()}");
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
$io->success("{$connectionGroup} was successfully removed");
|
||||||
|
$logger->info("Removed {$connectionGroup} from {$scene}.");
|
||||||
|
|
||||||
|
return Command::SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LotGD\Core\Console\Command\Scene;
|
||||||
|
|
||||||
|
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\InputDefinition;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the viewpoint of a given character.
|
||||||
|
*/
|
||||||
|
class SceneShowCommand extends SceneBaseCommand
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$this->setName($this->namespaced("show"))
|
||||||
|
->setDescription("Show details about a specific scene.")
|
||||||
|
->setDefinition(
|
||||||
|
new InputDefinition([
|
||||||
|
$this->getSceneIdArgumentDefinition(),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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) {
|
||||||
|
# Get formatting for outgoing scene connection group name
|
||||||
|
$outgoingSceneConnectionGroup = $connection->getOutgoingConnectionGroupName();
|
||||||
|
if ($outgoingSceneConnectionGroup) {
|
||||||
|
$outgoingSceneConnectionGroup = " (on $outgoingSceneConnectionGroup)";
|
||||||
|
} else {
|
||||||
|
$outgoingSceneConnectionGroup = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get formatting for incoming scene connection group name
|
||||||
|
$incomingSceneConnectionGroup = $connection->getIncomingConnectionGroupName();
|
||||||
|
if ($incomingSceneConnectionGroup) {
|
||||||
|
$incomingSceneConnectionGroup = " (on $incomingSceneConnectionGroup)";
|
||||||
|
} else {
|
||||||
|
$incomingSceneConnectionGroup = " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
# Treat outgoing and incoming connections slightly differently
|
||||||
|
if ($connection->getOutgoingScene() === $scene) {
|
||||||
|
$other = $connection->getIncomingScene();
|
||||||
|
|
||||||
|
# Check if the connection is bidirectional (only out (this)->in)
|
||||||
|
if ($connection->isDirectionality(SceneConnectable::Bidirectional)) {
|
||||||
|
$list[] = "this$outgoingSceneConnectionGroup <=> {$other->getTitle()}$incomingSceneConnectionGroup(id={$other->getId()})";
|
||||||
|
} else {
|
||||||
|
$list[] = "this$outgoingSceneConnectionGroup => {$other->getTitle()}$incomingSceneConnectionGroup(id={$other->getId()})";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$other = $connection->getOutgoingScene();
|
||||||
|
|
||||||
|
# Check if the connection is bidirectional (only out->in (this))
|
||||||
|
if ($connection->isDirectionality(SceneConnectable::Bidirectional)) {
|
||||||
|
$list[] = "this$incomingSceneConnectionGroup <=> {$other->getTitle()}$outgoingSceneConnectionGroup (id={$other->getId()})";
|
||||||
|
} else {
|
||||||
|
$list[] = "this$incomingSceneConnectionGroup <= {$other->getTitle()}$outgoingSceneConnectionGroup (id={$other->getId()})";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$io->listing($list);
|
||||||
|
|
||||||
|
return Command::SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LotGD\Core\Console\Command\SceneTemplates;
|
||||||
|
|
||||||
|
use LotGD\Core\Console\Command\BaseCommand;
|
||||||
|
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", "module", "assignable", "# scenes", "# viewpoints"], []];
|
||||||
|
foreach ($templates as $template) {
|
||||||
|
$table[1][] = [
|
||||||
|
$template->getClass(),
|
||||||
|
$template->getModule(),
|
||||||
|
$template->isUserAssignable()?"X":"-",
|
||||||
|
count($template->getOwningScenes()),
|
||||||
|
count($template->getOwningViewpoints()),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$io->table(...$table);
|
||||||
|
|
||||||
|
return Command::SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
+79
-16
@@ -3,25 +3,49 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace LotGD\Core\Console;
|
namespace LotGD\Core\Console;
|
||||||
|
|
||||||
use Symfony\Component\Console\Application;
|
|
||||||
|
|
||||||
use LotGD\Core\Bootstrap;
|
use LotGD\Core\Bootstrap;
|
||||||
|
|
||||||
|
use LotGD\Core\Console\Command\Character\CharacterAddCommand;
|
||||||
|
use LotGD\Core\Console\Command\Character\CharacterConfigListCommand;
|
||||||
|
use LotGD\Core\Console\Command\Character\CharacterConfigResetCommand;
|
||||||
|
use LotGD\Core\Console\Command\Character\CharacterConfigSetCommand;
|
||||||
|
use LotGD\Core\Console\Command\Character\CharacterEditCommand;
|
||||||
|
use LotGD\Core\Console\Command\Character\CharacterListCommand;
|
||||||
|
use LotGD\Core\Console\Command\Character\CharacterRemoveCommand;
|
||||||
|
use LotGD\Core\Console\Command\Character\CharacterResetViewpointCommand;
|
||||||
|
use LotGD\Core\Console\Command\Character\CharacterShowCommand;
|
||||||
|
use LotGD\Core\Console\Command\ConsoleCommand;
|
||||||
|
use LotGD\Core\Console\Command\Database\DatabaseInitCommand;
|
||||||
|
use LotGD\Core\Console\Command\Database\DatabaseSchemaUpdateCommand;
|
||||||
|
use LotGD\Core\Console\Command\Module\ModuleConfigListCommand;
|
||||||
|
use LotGD\Core\Console\Command\Module\ModuleConfigResetCommand;
|
||||||
|
use LotGD\Core\Console\Command\Module\ModuleConfigSetCommand;
|
||||||
|
use LotGD\Core\Console\Command\Module\ModuleListCommand;
|
||||||
|
use LotGD\Core\Console\Command\Module\ModuleRegisterCommand;
|
||||||
|
use LotGD\Core\Console\Command\Module\ModuleValidateCommand;
|
||||||
|
use LotGD\Core\Console\Command\Scene\SceneConfigListCommand;
|
||||||
|
use LotGD\Core\Console\Command\Scene\SceneConfigResetCommand;
|
||||||
|
use LotGD\Core\Console\Command\Scene\SceneConfigSetCommand;
|
||||||
|
use LotGD\Core\Console\Command\SceneTemplates\SceneTemplateListCommand;
|
||||||
|
use LotGD\Core\Console\Command\Scene\SceneAddCommand;
|
||||||
|
use LotGD\Core\Console\Command\Scene\SceneAddConnectionGroupCommand;
|
||||||
|
use LotGD\Core\Console\Command\Scene\SceneConnectCommand;
|
||||||
|
use LotGD\Core\Console\Command\Scene\SceneDisconnectCommand;
|
||||||
|
use LotGD\Core\Console\Command\Scene\SceneListCommand;
|
||||||
|
use LotGD\Core\Console\Command\Scene\SceneRemoveCommand;
|
||||||
|
use LotGD\Core\Console\Command\Scene\SceneRemoveConnectionGroupCommand;
|
||||||
|
use LotGD\Core\Console\Command\Scene\SceneShowCommand;
|
||||||
use LotGD\Core\Game;
|
use LotGD\Core\Game;
|
||||||
use LotGD\Core\Console\Command\{
|
use Symfony\Component\Console\Application;
|
||||||
DatabaseInitCommand,
|
|
||||||
ModuleValidateCommand,
|
|
||||||
ModuleRegisterCommand,
|
|
||||||
ConsoleCommand
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main execution class for the daenerys tool.
|
* Main execution class for the daenerys tool.
|
||||||
*/
|
*/
|
||||||
class Main
|
class Main
|
||||||
{
|
{
|
||||||
private $application;
|
private Application $application;
|
||||||
private $bootstrap;
|
private Bootstrap $bootstrap;
|
||||||
private $game;
|
private Game $game;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new daenerys tool instance.
|
* Construct a new daenerys tool instance.
|
||||||
@@ -31,7 +55,7 @@ class Main
|
|||||||
$this->application = new Application();
|
$this->application = new Application();
|
||||||
|
|
||||||
$this->application->setName("daenerys 🐲 ");
|
$this->application->setName("daenerys 🐲 ");
|
||||||
$this->application->setVersion("0.0.1 (lotgd/core version " . \LotGD\Core\Game::getVersion() . ")");
|
$this->application->setVersion("lotgd/core version " . Game::getVersion() . "");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -39,23 +63,62 @@ class Main
|
|||||||
*/
|
*/
|
||||||
protected function addCommands()
|
protected function addCommands()
|
||||||
{
|
{
|
||||||
$this->application->add(new ModuleValidateCommand($this->game));
|
|
||||||
$this->application->add(new ModuleRegisterCommand($this->game));
|
|
||||||
$this->application->add(new DatabaseInitCommand($this->game));
|
$this->application->add(new DatabaseInitCommand($this->game));
|
||||||
|
$this->application->add(new DatabaseSchemaUpdateCommand($this->game));
|
||||||
|
|
||||||
$this->application->add(new ConsoleCommand($this->game));
|
$this->application->add(new ConsoleCommand($this->game));
|
||||||
|
|
||||||
|
// Module commands
|
||||||
|
$this->application->add(new ModuleConfigListCommand($this->game));
|
||||||
|
$this->application->add(new ModuleConfigResetCommand($this->game));
|
||||||
|
$this->application->add(new ModuleConfigSetCommand($this->game));
|
||||||
|
$this->application->add(new ModuleListCommand($this->game));
|
||||||
|
$this->application->add(new ModuleRegisterCommand($this->game));
|
||||||
|
$this->application->add(new ModuleValidateCommand($this->game));
|
||||||
|
|
||||||
|
// Character commands
|
||||||
|
$this->application->add(new CharacterAddCommand($this->game));
|
||||||
|
$this->application->add(new CharacterConfigListCommand($this->game));
|
||||||
|
$this->application->add(new CharacterConfigResetCommand($this->game));
|
||||||
|
$this->application->add(new CharacterConfigSetCommand($this->game));
|
||||||
|
$this->application->add(new CharacterEditCommand($this->game));
|
||||||
|
$this->application->add(new CharacterListCommand($this->game));
|
||||||
|
$this->application->add(new CharacterRemoveCommand($this->game));
|
||||||
|
$this->application->add(new CharacterResetViewpointCommand($this->game));
|
||||||
|
$this->application->add(new CharacterShowCommand($this->game));
|
||||||
|
|
||||||
|
// Scene commands
|
||||||
|
$this->application->add(new SceneAddCommand($this->game));
|
||||||
|
$this->application->add(new SceneConfigListCommand($this->game));
|
||||||
|
$this->application->add(new SceneConfigResetCommand($this->game));
|
||||||
|
$this->application->add(new SceneConfigSetCommand($this->game));
|
||||||
|
$this->application->add(new SceneListCommand($this->game));
|
||||||
|
$this->application->add(new SceneRemoveCommand($this->game));
|
||||||
|
$this->application->add(new SceneShowCommand($this->game));
|
||||||
|
|
||||||
|
// Scene connections
|
||||||
|
$this->application->add(new SceneConnectCommand($this->game));
|
||||||
|
$this->application->add(new SceneDisconnectCommand($this->game));
|
||||||
|
|
||||||
|
// Scene connection group
|
||||||
|
$this->application->add(new SceneAddConnectionGroupCommand($this->game));
|
||||||
|
$this->application->add(new SceneRemoveConnectionGroupCommand($this->game));
|
||||||
|
|
||||||
|
// Scene templates
|
||||||
|
$this->application->add(new SceneTemplateListCommand($this->game));
|
||||||
|
|
||||||
// Add additional ones
|
// Add additional ones
|
||||||
$this->bootstrap->addDaenerysCommands($this->application);
|
$this->bootstrap->addDaenerysCommands($this->application);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run the danerys tool.
|
* Run the Daenerys tool.
|
||||||
*/
|
*/
|
||||||
public function run()
|
public function run()
|
||||||
{
|
{
|
||||||
// Bootstrap application
|
// Bootstrap application
|
||||||
$this->bootstrap = new Bootstrap();
|
$this->bootstrap = new Bootstrap();
|
||||||
$this->game = $this->bootstrap->getGame(getcwd());
|
$this->game = $this->bootstrap->getGame(\getcwd());
|
||||||
|
|
||||||
// Add commands
|
// Add commands
|
||||||
$this->addCommands();
|
$this->addCommands();
|
||||||
|
|||||||
+39
-17
@@ -1,6 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
declare (strict_types = 1);
|
|
||||||
|
|
||||||
namespace LotGD\Core;
|
namespace LotGD\Core;
|
||||||
|
|
||||||
@@ -12,6 +11,7 @@ class DiceBag
|
|||||||
/**
|
/**
|
||||||
* Returns true $p percent of the time, where $p is between 0 and 1.
|
* Returns true $p percent of the time, where $p is between 0 and 1.
|
||||||
* @param float $p
|
* @param float $p
|
||||||
|
* @return bool True if you are lucky, False if not.
|
||||||
*/
|
*/
|
||||||
public function chance(float $p): bool
|
public function chance(float $p): bool
|
||||||
{
|
{
|
||||||
@@ -24,16 +24,39 @@ class DiceBag
|
|||||||
* Generates a uniformly randomly number between $min and $max.
|
* Generates a uniformly randomly number between $min and $max.
|
||||||
* @param float $min
|
* @param float $min
|
||||||
* @param float $max
|
* @param float $max
|
||||||
|
* @return float random number between $min and $max
|
||||||
*/
|
*/
|
||||||
public function uniform(float $min, float $max): float
|
public function uniform(float $min, float $max): float
|
||||||
{
|
{
|
||||||
return (mt_rand(0, 100) / 100.0) * ($max - $min) + $min;
|
return (\mt_rand(0, 100) / 100.0) * ($max - $min) + $min;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a uniformly randomly integer between $min and $max.
|
||||||
|
* @param int $min
|
||||||
|
* @param int $max
|
||||||
|
* @return int random number between $min and $max
|
||||||
|
*/
|
||||||
|
public function dice(int $min, int $max): int
|
||||||
|
{
|
||||||
|
if ($min == $max) {
|
||||||
|
return $min;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($min > $max) {
|
||||||
|
$a = $min;
|
||||||
|
$min = $max;
|
||||||
|
$max = $a;
|
||||||
|
}
|
||||||
|
|
||||||
|
return \mt_rand($min, $max);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a normally distributed random number between $min and $max.
|
* Generates a normally distributed random number between $min and $max.
|
||||||
* @param float $min
|
* @param float $min
|
||||||
* @param float $max
|
* @param float $max
|
||||||
|
* @return float normally distributed random number
|
||||||
*/
|
*/
|
||||||
public function normal(float $min, float $max): float
|
public function normal(float $min, float $max): float
|
||||||
{
|
{
|
||||||
@@ -48,9 +71,9 @@ class DiceBag
|
|||||||
$mean = ($max - $min) / 2;
|
$mean = ($max - $min) / 2;
|
||||||
$r = 0;
|
$r = 0;
|
||||||
do {
|
do {
|
||||||
$u1 = mt_rand() / mt_getrandmax();
|
$u1 = \mt_rand() / \mt_getrandmax();
|
||||||
$u2 = mt_rand() / mt_getrandmax();
|
$u2 = \mt_rand() / \mt_getrandmax();
|
||||||
$r = sqrt(-2 * log($u1)) * cos(2 * pi() * $u2) + $mean;
|
$r = \sqrt(-2 * \log($u1)) * \cos(2 * \pi() * $u2) + $mean;
|
||||||
} while ($r < $min || $r > $max);
|
} while ($r < $min || $r > $max);
|
||||||
|
|
||||||
return $r;
|
return $r;
|
||||||
@@ -59,31 +82,30 @@ class DiceBag
|
|||||||
/**
|
/**
|
||||||
* This function has uniform distribution except for the extreme values, which are
|
* This function has uniform distribution except for the extreme values, which are
|
||||||
* half as likely to happen.
|
* half as likely to happen.
|
||||||
* The code for this function was taken from LotGD in version 0.9.7
|
* The code for this function was taken from LotGD in version 0.9.7.
|
||||||
* @author MightyE, JT
|
* @author MightyE, JT
|
||||||
* @param int $min
|
* @param int|null $min
|
||||||
* @param int $max
|
* @param int|null $max
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function pseudoBell(int $min = null, int $max = null): int
|
public function pseudoBell(int $min = null, int $max = null): int
|
||||||
{
|
{
|
||||||
if (is_null($min)) {
|
if (\is_null($min)) {
|
||||||
return mt_rand();
|
return \mt_rand();
|
||||||
}
|
}
|
||||||
|
|
||||||
$min *= 1000;
|
$min *= 1000;
|
||||||
|
|
||||||
if (is_null($max)) {
|
if (\is_null($max)) {
|
||||||
return (int)round(mt_rand($min)/1000, 0);
|
return (int)\round(\mt_rand($min) / 1000, 0);
|
||||||
}
|
}
|
||||||
$max *= 1000;
|
$max *= 1000;
|
||||||
|
|
||||||
if ($min === $max) {
|
if ($min === $max) {
|
||||||
return (int)round($min/1000, 0);
|
return (int)\round($min / 1000, 0);
|
||||||
} elseif ($min < $max) {
|
} elseif ($min < $max) {
|
||||||
return (int)round(mt_rand($min, $max)/1000, 0);
|
return (int)\round(\mt_rand($min, $max) / 1000, 0);
|
||||||
} else {
|
|
||||||
return (int)round(mt_rand($max, $min)/1000, 0);
|
|
||||||
}
|
}
|
||||||
|
return (int)\round(\mt_rand($max, $min) / 1000, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LotGD\Core\Doctrine\Annotations;
|
||||||
|
|
||||||
|
use Doctrine\Common\Annotations\Annotation;
|
||||||
|
use Doctrine\Common\Annotations\Annotation\Attribute;
|
||||||
|
use Doctrine\Common\Annotations\Annotation\Attributes;
|
||||||
|
use LotGD\Core\Exceptions\ArgumentException;
|
||||||
|
use LotGD\Core\Models\ExtendableModelInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Annotation that is used to flag which entity a class extends.
|
||||||
|
* @Annotation
|
||||||
|
* @Target("CLASS")
|
||||||
|
* @Attributes({
|
||||||
|
* @Attribute("of", type="string")
|
||||||
|
* })
|
||||||
|
*/
|
||||||
|
class Extension
|
||||||
|
{
|
||||||
|
private string $modelClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extension constructor.
|
||||||
|
* @param array $attributes
|
||||||
|
* @throws ArgumentException
|
||||||
|
*/
|
||||||
|
public function __construct(array $attributes)
|
||||||
|
{
|
||||||
|
$this->modelClass = $attributes["of"];
|
||||||
|
|
||||||
|
if (!\class_exists($this->modelClass)) {
|
||||||
|
throw new ArgumentException("The class given in of must be a valid class.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!\in_array(ExtendableModelInterface::class, \class_implements($this->modelClass))) {
|
||||||
|
throw new ArgumentException("The class given in of must implement the ExtendableModelInterface.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the model class name.
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getModelClass(): string
|
||||||
|
{
|
||||||
|
return $this->modelClass;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LotGD\Core\Doctrine\Annotations;
|
||||||
|
|
||||||
|
use Doctrine\Common\Annotations\Annotation;
|
||||||
|
use Doctrine\Common\Annotations\Annotation\Attribute;
|
||||||
|
use Doctrine\Common\Annotations\Annotation\Attributes;
|
||||||
|
use LotGD\Core\Exceptions\ArgumentException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Annotation that is used to link a static method to a model entity.
|
||||||
|
* @Annotation
|
||||||
|
* @Target("METHOD")
|
||||||
|
* @Attributes({
|
||||||
|
* @Attribute("as", type="string")
|
||||||
|
* })
|
||||||
|
*/
|
||||||
|
class ExtensionMethod
|
||||||
|
{
|
||||||
|
private string $methodName = "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ExtensionMethod constructor.
|
||||||
|
* @param array $attributes
|
||||||
|
* @throws ArgumentException
|
||||||
|
*/
|
||||||
|
public function __construct(array $attributes)
|
||||||
|
{
|
||||||
|
$this->methodName = $attributes["as"];
|
||||||
|
|
||||||
|
if (!\is_string($this->methodName)) {
|
||||||
|
throw new ArgumentException("Property 'as' must be a string.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (\strlen($this->methodName) == 0) {
|
||||||
|
throw new ArgumentException("Property 'as' must not be an empty string.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the method name.
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getMethodName(): string
|
||||||
|
{
|
||||||
|
return $this->methodName;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LotGD\Core\Doctrine;
|
||||||
|
|
||||||
|
use Doctrine\ORM\Event\LifecycleEventArgs;
|
||||||
|
use LotGD\Core\Game;
|
||||||
|
use LotGD\Core\GameAwareInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class EntityPostLoadEventListener.
|
||||||
|
*/
|
||||||
|
class EntityPostLoadEventListener
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EntityPostLoadEventListener constructor.
|
||||||
|
* @param Game $game
|
||||||
|
*/
|
||||||
|
public function __construct(private Game $game) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called upon event postLoad.
|
||||||
|
* @param LifecycleEventArgs $args
|
||||||
|
*/
|
||||||
|
public function postLoad(LifecycleEventArgs $args)
|
||||||
|
{
|
||||||
|
$entity = $args->getEntity();
|
||||||
|
if ($entity instanceof GameAwareInterface) {
|
||||||
|
$entity->setGame($this->game);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace LotGD\Core;
|
namespace LotGD\Core;
|
||||||
|
|
||||||
use LotGD\Core\Events\EventContext;
|
use LotGD\Core\Events\EventContext;
|
||||||
|
|
||||||
interface EventHandler
|
interface EventHandler
|
||||||
@@ -10,9 +11,8 @@ interface EventHandler
|
|||||||
* Called when an event is published that is handled by this class.
|
* Called when an event is published that is handled by this class.
|
||||||
*
|
*
|
||||||
* @param Game $g The game.
|
* @param Game $g The game.
|
||||||
* @param string $event Name of this event.
|
* @param EventContext $context Arbitrary dictionary representing context around this event.
|
||||||
* @param array $context Arbitrary dictionary representing context around this event.
|
* @return EventContext Return an array if you want to make changes to the $context before
|
||||||
* @return array|null Return an array if you want to make changes to the $context before
|
|
||||||
* the next handler is called. Otherwise, return null. Any changes made will be propogated
|
* the next handler is called. Otherwise, return null. Any changes made will be propogated
|
||||||
* to the event publisher as well.
|
* to the event publisher as well.
|
||||||
*/
|
*/
|
||||||
|
|||||||
+16
-22
@@ -3,31 +3,23 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace LotGD\Core;
|
namespace LotGD\Core;
|
||||||
|
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
|
||||||
|
|
||||||
use LotGD\Core\Events\EventContext;
|
use LotGD\Core\Events\EventContext;
|
||||||
use LotGD\Core\Models\EventSubscription;
|
use LotGD\Core\Events\EventContextData;
|
||||||
use LotGD\Core\EventHandler;
|
|
||||||
use LotGD\Core\Exceptions\ClassNotFoundException;
|
use LotGD\Core\Exceptions\ClassNotFoundException;
|
||||||
use LotGD\Core\Exceptions\SubscriptionNotFoundException;
|
use LotGD\Core\Exceptions\SubscriptionNotFoundException;
|
||||||
use LotGD\Core\Exceptions\WrongTypeException;
|
use LotGD\Core\Exceptions\WrongTypeException;
|
||||||
use LotGD\Core\Events\EventContextData;
|
use LotGD\Core\Models\EventSubscription;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages a simple publish/subscribe system based on regular expressions
|
* Manages a simple publish/subscribe system based on regular expressions
|
||||||
* matching event names and running a fixed
|
* matching event names and running a fixed.
|
||||||
*/
|
*/
|
||||||
class EventManager
|
class EventManager
|
||||||
{
|
{
|
||||||
private $g;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Game $g The game.
|
* @param Game $g The game.
|
||||||
*/
|
*/
|
||||||
public function __construct(Game $g)
|
public function __construct(private Game $g) {}
|
||||||
{
|
|
||||||
$this->g = $g;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Publish an event. Will immediately cause handleEvent() to be called on all
|
* Publish an event. Will immediately cause handleEvent() to be called on all
|
||||||
@@ -46,13 +38,13 @@ class EventManager
|
|||||||
// TODO: Add an in-memory cache here. Will likely only be in the 1000s of
|
// TODO: Add an in-memory cache here. Will likely only be in the 1000s of
|
||||||
// patterns, so no need to go to the remote key-value store.
|
// patterns, so no need to go to the remote key-value store.
|
||||||
|
|
||||||
$this->g->getLogger()->addDebug("Publishing event {$event}.");
|
$this->g->getLogger()->debug("Publishing event {$event}.");
|
||||||
|
|
||||||
$subscriptions = $this->getSubscriptions();
|
$subscriptions = $this->getSubscriptions();
|
||||||
foreach ($subscriptions as $s) {
|
foreach ($subscriptions as $s) {
|
||||||
if (preg_match($s->getPattern(), $event)) {
|
if (\preg_match($s->getPattern(), $event)) {
|
||||||
$class = $s->getClass();
|
$class = $s->getClass();
|
||||||
$this->g->getLogger()->addDebug(" Handling with {$class}.");
|
$this->g->getLogger()->debug(" Handling with {$class}.");
|
||||||
|
|
||||||
$eventContext = new EventContext($event, $s->getPattern(), $contextData);
|
$eventContext = new EventContext($event, $s->getPattern(), $contextData);
|
||||||
|
|
||||||
@@ -82,7 +74,7 @@ class EventManager
|
|||||||
*/
|
*/
|
||||||
public function subscribe(string $pattern, string $class, string $library)
|
public function subscribe(string $pattern, string $class, string $library)
|
||||||
{
|
{
|
||||||
$this->g->getLogger()->addDebug("Subscribing event pattern={$pattern} class={$class} library={$library}");
|
$this->g->getLogger()->debug("Subscribing event pattern={$pattern} class={$class} library={$library}");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Can we resolve this class?
|
// Can we resolve this class?
|
||||||
@@ -102,16 +94,17 @@ class EventManager
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Validate the regular expression.
|
// Validate the regular expression.
|
||||||
if (@preg_match($pattern, '') === false) {
|
if (@\preg_match($pattern, '') === false) {
|
||||||
throw new WrongTypeException("Invalid regular expression: {$pattern}");
|
throw new WrongTypeException("Invalid regular expression: {$pattern}");
|
||||||
}
|
}
|
||||||
|
|
||||||
$e = EventSubscription::create([
|
$e = EventSubscription::create([
|
||||||
'pattern' => $pattern,
|
'pattern' => $pattern,
|
||||||
'class' => $class,
|
'class' => $class,
|
||||||
'library' => $library
|
'library' => $library,
|
||||||
]);
|
]);
|
||||||
$e->save($this->g->getEntityManager());
|
|
||||||
|
$this->g->getEntityManager()->persist($e);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -121,15 +114,16 @@ class EventManager
|
|||||||
* @param string $pattern Regular expression, in PHP format, to match against
|
* @param string $pattern Regular expression, in PHP format, to match against
|
||||||
* published event names.
|
* published event names.
|
||||||
* @param string $class Fully qualified class name.
|
* @param string $class Fully qualified class name.
|
||||||
|
* @param string $library
|
||||||
* @throws SubscriptionNotFoundException if the specified subscription does not exist.
|
* @throws SubscriptionNotFoundException if the specified subscription does not exist.
|
||||||
*/
|
*/
|
||||||
public function unsubscribe(string $pattern, string $class, string $library)
|
public function unsubscribe(string $pattern, string $class, string $library)
|
||||||
{
|
{
|
||||||
$e = $this->g->getEntityManager()->getRepository(EventSubscription::class)->find(array(
|
$e = $this->g->getEntityManager()->getRepository(EventSubscription::class)->find([
|
||||||
'pattern' => $pattern,
|
'pattern' => $pattern,
|
||||||
'class' => $class,
|
'class' => $class,
|
||||||
'library' => $library
|
'library' => $library,
|
||||||
));
|
]);
|
||||||
if (!$e) {
|
if (!$e) {
|
||||||
throw new SubscriptionNotFoundException("Subscription not found with pattern={$pattern} class={$class} library={$library}.");
|
throw new SubscriptionNotFoundException("Subscription not found with pattern={$pattern} class={$class} library={$library}.");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LotGD\Core\Events;
|
||||||
|
|
||||||
|
use JetBrains\PhpStorm\ArrayShape;
|
||||||
|
use LotGD\Core\Models\Character;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class CharacterEventData.
|
||||||
|
*/
|
||||||
|
class CharacterEventData extends EventContextData
|
||||||
|
{
|
||||||
|
#[ArrayShape([
|
||||||
|
"character" => [
|
||||||
|
"type" => Character::class,
|
||||||
|
"required" => "bool",
|
||||||
|
],
|
||||||
|
"value" => [
|
||||||
|
"type" => "mixed",
|
||||||
|
"required" => "bool",
|
||||||
|
],
|
||||||
|
])]
|
||||||
|
protected static ?array $argumentConfig = [
|
||||||
|
"character" => ["type" => Character::class, "required" => true],
|
||||||
|
"value" => ["type" => "mixed", "required" => false],
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -3,18 +3,12 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace LotGD\Core\Events;
|
namespace LotGD\Core\Events;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class EventContext
|
* Class EventContext.
|
||||||
* @package LotGD\Core
|
|
||||||
* @immutable
|
* @immutable
|
||||||
*/
|
*/
|
||||||
class EventContext
|
class EventContext
|
||||||
{
|
{
|
||||||
private $matchingPattern;
|
|
||||||
private $event;
|
|
||||||
private $data;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* EventContext constructor.
|
* EventContext constructor.
|
||||||
* @param string $event The published event
|
* @param string $event The published event
|
||||||
@@ -22,13 +16,10 @@ class EventContext
|
|||||||
* @param EventContextData $data
|
* @param EventContextData $data
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
string $event,
|
private string $event,
|
||||||
string $matchingPattern,
|
private string $matchingPattern,
|
||||||
EventContextData $data
|
private EventContextData $data
|
||||||
) {
|
) {
|
||||||
$this->event = $event;
|
|
||||||
$this->matchingPattern = $matchingPattern;
|
|
||||||
$this->data = $data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -69,7 +60,7 @@ class EventContext
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a data field
|
* Returns a data field.
|
||||||
* @param $field
|
* @param $field
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
@@ -79,7 +70,7 @@ class EventContext
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets a data field
|
* Sets a data field.
|
||||||
* @param $field
|
* @param $field
|
||||||
* @param $value
|
* @param $value
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -6,15 +6,21 @@ namespace LotGD\Core\Events;
|
|||||||
use LotGD\Core\Exceptions\ArgumentException;
|
use LotGD\Core\Exceptions\ArgumentException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* EventContextDataContainer to provide a basic structure for managing contextual data of an event.
|
* EventContextData to provide a basic structure for managing contextual data of an event.
|
||||||
*
|
*
|
||||||
* This class must be immutable and returns always a new instance of itself for any change.
|
* This class must be immutable and returns always a new instance of itself for any change.
|
||||||
* @package LotGD\Core\Events
|
|
||||||
* @immutable
|
* @immutable
|
||||||
*/
|
*/
|
||||||
class EventContextData
|
class EventContextData
|
||||||
{
|
{
|
||||||
private $data;
|
protected static ?array $argumentConfig = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* protected constructor..
|
||||||
|
* @see self::create
|
||||||
|
* @param array $data
|
||||||
|
*/
|
||||||
|
protected function __construct(private array $data) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance of a data container.
|
* Creates a new instance of a data container.
|
||||||
@@ -25,17 +31,60 @@ class EventContextData
|
|||||||
*/
|
*/
|
||||||
public static function create(array $data): self
|
public static function create(array $data): self
|
||||||
{
|
{
|
||||||
|
if (isset(static::$argumentConfig)) {
|
||||||
|
static::checkConfiguration($data);
|
||||||
|
}
|
||||||
|
|
||||||
return new static($data);
|
return new static($data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* protected constructor..
|
* Checks a field configuration given in self::$argumentConfig.
|
||||||
* @see self::create
|
|
||||||
* @param array $data
|
* @param array $data
|
||||||
|
* @throws ArgumentException
|
||||||
*/
|
*/
|
||||||
protected function __construct(array $data)
|
public static function checkConfiguration(array $data)
|
||||||
{
|
{
|
||||||
$this->data = $data;
|
$configuration = static::$argumentConfig;
|
||||||
|
$types = [
|
||||||
|
"mixed" => function ($x) {
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
"int" => function ($x) {
|
||||||
|
return \is_int($x);
|
||||||
|
},
|
||||||
|
"float" => function ($x) {
|
||||||
|
return \is_float($x);
|
||||||
|
},
|
||||||
|
"numeric" => function ($x) {
|
||||||
|
return \is_numeric($x);
|
||||||
|
},
|
||||||
|
"string" => function ($x) {
|
||||||
|
return \is_string($x);
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
$keys = \array_keys($data);
|
||||||
|
foreach ($keys as $key) {
|
||||||
|
if (!isset($configuration[$key])) {
|
||||||
|
throw new ArgumentException(\sprintf("%s does not accept a field called %s", static::class, $key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach ($configuration as $key => $config) {
|
||||||
|
if ($config["required"] === true and !isset($data[$key])) {
|
||||||
|
throw new ArgumentException(\sprintf("%s must have a field called %s.", static::class, $key));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($types[$config["type"]])) {
|
||||||
|
if ($types[$config["type"]]($data[$key]) === false) {
|
||||||
|
throw new ArgumentException(\sprintf("The field %s of %s must be of type %s.", $key, static::class, $config["type"]));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!$data[$key] instanceof $config["type"]) {
|
||||||
|
throw new ArgumentException(\sprintf("The field %s of %s must be of type %s", $key, static::class, $config["type"]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -45,7 +94,7 @@ class EventContextData
|
|||||||
*/
|
*/
|
||||||
public function has(string $field): bool
|
public function has(string $field): bool
|
||||||
{
|
{
|
||||||
return array_key_exists($field, $this->data);
|
return \array_key_exists($field, $this->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -57,31 +106,29 @@ class EventContextData
|
|||||||
{
|
{
|
||||||
if ($this->has($field)) {
|
if ($this->has($field)) {
|
||||||
return $this->data[$field];
|
return $this->data[$field];
|
||||||
} else {
|
|
||||||
$this->throwException($field);
|
|
||||||
}
|
}
|
||||||
|
$this->throwException($field);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets a field to a new value and returns a new data container
|
* Sets a field to a new value and returns a new data container.
|
||||||
* @param string $field
|
* @param string $field
|
||||||
* @param $value
|
* @param mixed $value
|
||||||
* @return EventContextData
|
* @return EventContextData
|
||||||
*/
|
*/
|
||||||
public function set(string $field, $value): self
|
public function set(string $field, mixed $value): self
|
||||||
{
|
{
|
||||||
if ($this->has($field)) {
|
if ($this->has($field)) {
|
||||||
$data = $this->data;
|
$data = $this->data;
|
||||||
$data[$field] = $value;
|
$data[$field] = $value;
|
||||||
|
|
||||||
return new static($data);
|
return new static($data);
|
||||||
} else {
|
|
||||||
$this->throwException($field);
|
|
||||||
}
|
}
|
||||||
|
$this->throwException($field);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets multiple fields at once
|
* Sets multiple fields at once.
|
||||||
* @param array $data array of $field=>$value pairs
|
* @param array $data array of $field=>$value pairs
|
||||||
* @return EventContextData
|
* @return EventContextData
|
||||||
*/
|
*/
|
||||||
@@ -101,12 +148,12 @@ class EventContextData
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list of fields in this context
|
* Returns a list of fields in this context.
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
private function getListOfFields(): array
|
private function getListOfFields(): array
|
||||||
{
|
{
|
||||||
return array_keys($this->data);
|
return \array_keys($this->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -115,8 +162,8 @@ class EventContextData
|
|||||||
*/
|
*/
|
||||||
private function getFormattedListOfFields(): string
|
private function getFormattedListOfFields(): string
|
||||||
{
|
{
|
||||||
return substr(
|
return \substr(
|
||||||
implode(", ", $this->getListOfFields()),
|
\implode(", ", $this->getListOfFields()),
|
||||||
0,
|
0,
|
||||||
-2
|
-2
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -3,15 +3,11 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace LotGD\Core\Events;
|
namespace LotGD\Core\Events;
|
||||||
|
|
||||||
|
use JetBrains\PhpStorm\ArrayShape;
|
||||||
use Doctrine\Common\Util\Debug;
|
|
||||||
use Doctrine\DBAL\Schema\View;
|
|
||||||
use LotGD\Core\Exceptions\ArgumentException;
|
use LotGD\Core\Exceptions\ArgumentException;
|
||||||
use LotGD\Core\Models\Character;
|
|
||||||
use LotGD\Core\Models\Scene;
|
use LotGD\Core\Models\Scene;
|
||||||
use LotGD\Core\Models\Viewpoint;
|
use LotGD\Core\Models\Viewpoint;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NavigateToScene data container which can be used for navigational events.
|
* NavigateToScene data container which can be used for navigational events.
|
||||||
*
|
*
|
||||||
@@ -21,7 +17,6 @@ use LotGD\Core\Models\Viewpoint;
|
|||||||
* scene Scene
|
* scene Scene
|
||||||
* parameters array
|
* parameters array
|
||||||
* redirect Scene|null
|
* redirect Scene|null
|
||||||
* @package LotGD\Core\Events
|
|
||||||
*/
|
*/
|
||||||
class NavigateToSceneData extends EventContextData
|
class NavigateToSceneData extends EventContextData
|
||||||
{
|
{
|
||||||
@@ -30,37 +25,46 @@ class NavigateToSceneData extends EventContextData
|
|||||||
* @param array $data Must contain fields referrer, viewpoint, scene, parameters and redirect; none more.
|
* @param array $data Must contain fields referrer, viewpoint, scene, parameters and redirect; none more.
|
||||||
* @throws ArgumentException
|
* @throws ArgumentException
|
||||||
*/
|
*/
|
||||||
protected function __construct(array $data)
|
protected function __construct(
|
||||||
{
|
#[ArrayShape([
|
||||||
|
"referrer" => Scene::class . "|null",
|
||||||
|
"viewpoint" => Viewpoint::class,
|
||||||
|
"scene" => Scene::class,
|
||||||
|
"parameters" => "array",
|
||||||
|
"reddirect" => Scene::class . "|null",
|
||||||
|
])]
|
||||||
|
array $data,
|
||||||
|
) {
|
||||||
$mustHaveForm = ["referrer", "viewpoint", "scene", "parameters", "redirect"];
|
$mustHaveForm = ["referrer", "viewpoint", "scene", "parameters", "redirect"];
|
||||||
$doesHaveForm = array_keys($data);
|
$doesHaveForm = \array_keys($data);
|
||||||
sort($mustHaveForm); sort($doesHaveForm);
|
\sort($mustHaveForm);
|
||||||
|
\sort($doesHaveForm);
|
||||||
|
|
||||||
if ($doesHaveForm !== $mustHaveForm) {
|
if ($doesHaveForm !== $mustHaveForm) {
|
||||||
throw new ArgumentException("A new NavigateToScene event must have referrer, viewpoint, scene, parameters and redirect.");
|
throw new ArgumentException("A new NavigateToScene event must have referrer, viewpoint, scene, parameters and redirect.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($data["referrer"] instanceof Scene === false and $data["referrer"] !== null) {
|
if ($data["referrer"] instanceof Scene === false and $data["referrer"] !== null) {
|
||||||
throw new ArgumentException(sprintf(
|
throw new ArgumentException(\sprintf(
|
||||||
"data[referrer] must be an instance of %s, %s given.",
|
"data[referrer] must be an instance of %s, %s given.",
|
||||||
Scene::class,
|
Scene::class,
|
||||||
get_class($data["referrer"])
|
\get_class($data["referrer"])
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($data["scene"] instanceof Scene === false) {
|
if ($data["scene"] instanceof Scene === false) {
|
||||||
throw new ArgumentException(sprintf(
|
throw new ArgumentException(\sprintf(
|
||||||
"data[scene] must be an instance of %s, %s given.",
|
"data[scene] must be an instance of %s, %s given.",
|
||||||
Scene::class,
|
Scene::class,
|
||||||
get_class($data["scene"])
|
\get_class($data["scene"])
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($data["viewpoint"] instanceof Viewpoint === false) {
|
if ($data["viewpoint"] instanceof Viewpoint === false) {
|
||||||
throw new ArgumentException(sprintf(
|
throw new ArgumentException(\sprintf(
|
||||||
"data[viewpoint] must be an instance of %s, %s given.",
|
"data[viewpoint] must be an instance of %s, %s given.",
|
||||||
Viewpoint::class,
|
Viewpoint::class,
|
||||||
get_class($data["viewpoint"])
|
\get_class($data["viewpoint"])
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace LotGD\Core\Events;
|
namespace LotGD\Core\Events;
|
||||||
|
|
||||||
|
use JetBrains\PhpStorm\ArrayShape;
|
||||||
use LotGD\Core\Exceptions\ArgumentException;
|
use LotGD\Core\Exceptions\ArgumentException;
|
||||||
use LotGD\Core\Models\Character;
|
use LotGD\Core\Models\Character;
|
||||||
use LotGD\Core\Models\Scene;
|
use LotGD\Core\Models\Scene;
|
||||||
@@ -14,7 +14,6 @@ use LotGD\Core\Models\Scene;
|
|||||||
* Fields are:
|
* Fields are:
|
||||||
* character Character
|
* character Character
|
||||||
* scene Scene|null
|
* scene Scene|null
|
||||||
* @package LotGD\Core\Events
|
|
||||||
*/
|
*/
|
||||||
class NewViewpointData extends EventContextData
|
class NewViewpointData extends EventContextData
|
||||||
{
|
{
|
||||||
@@ -23,25 +22,30 @@ class NewViewpointData extends EventContextData
|
|||||||
* @param array $data
|
* @param array $data
|
||||||
* @throws ArgumentException In case $data contains invalid data.
|
* @throws ArgumentException In case $data contains invalid data.
|
||||||
*/
|
*/
|
||||||
protected function __construct(array $data)
|
protected function __construct(
|
||||||
{
|
#[ArrayShape([
|
||||||
if (array_keys($data) !== ["character", "scene"]) {
|
"character" => Character::class,
|
||||||
|
"scene" => Scene::class . "|null",
|
||||||
|
])]
|
||||||
|
array $data,
|
||||||
|
) {
|
||||||
|
if (\array_keys($data) !== ["character", "scene"]) {
|
||||||
throw new ArgumentException("A NewViewpoint event must have only character and scene.");
|
throw new ArgumentException("A NewViewpoint event must have only character and scene.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$data["character"] instanceof Character) {
|
if (!$data["character"] instanceof Character) {
|
||||||
throw new ArgumentException(sprintf(
|
throw new ArgumentException(\sprintf(
|
||||||
"NewViewpoint data[character] must be an instance of %s, %s given.",
|
"NewViewpoint data[character] must be an instance of %s, %s given.",
|
||||||
Character::class,
|
Character::class,
|
||||||
get_class($data)
|
\get_class($data)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($data["scene"] !== null and !$data["scene"] instanceof Scene) {
|
if ($data["scene"] !== null and !$data["scene"] instanceof Scene) {
|
||||||
throw new ArgumentException(sprintf(
|
throw new ArgumentException(\sprintf(
|
||||||
"NewViewpoint data[scene] must be an instance of %s or null, %s given.",
|
"NewViewpoint data[scene] must be an instance of %s or null, %s given.",
|
||||||
Scene::class,
|
Scene::class,
|
||||||
get_class($data)
|
\get_class($data)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LotGD\Core\Events;
|
||||||
|
|
||||||
|
use JetBrains\PhpStorm\ArrayShape;
|
||||||
|
use LotGD\Core\Models\Viewpoint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class ViewpointDecorationEventData.
|
||||||
|
*/
|
||||||
|
class ViewpointDecorationEventData extends EventContextData
|
||||||
|
{
|
||||||
|
#[ArrayShape([
|
||||||
|
"viewpoint" => [
|
||||||
|
"type" => Viewpoint::class,
|
||||||
|
"required" => "bool",
|
||||||
|
],
|
||||||
|
])]
|
||||||
|
protected static ?array $argumentConfig = [
|
||||||
|
"viewpoint" => ["type" => Viewpoint::class, "required" => true],
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -8,5 +8,4 @@ namespace LotGD\Core\Exceptions;
|
|||||||
*/
|
*/
|
||||||
class ActionNotFoundException extends CoreException
|
class ActionNotFoundException extends CoreException
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,8 @@ declare(strict_types=1);
|
|||||||
namespace LotGD\Core\Exceptions;
|
namespace LotGD\Core\Exceptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exception if a specific, required argument is missing
|
* Exception if a specific, required argument is missing.
|
||||||
*/
|
*/
|
||||||
class ArgumentEmptyException extends ArgumentException
|
class ArgumentEmptyException extends ArgumentException
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,8 @@ declare(strict_types=1);
|
|||||||
namespace LotGD\Core\Exceptions;
|
namespace LotGD\Core\Exceptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exception if a specific, required argument is missing
|
* Exception if a specific, required argument is missing.
|
||||||
*/
|
*/
|
||||||
class ArgumentException extends CoreException
|
class ArgumentException extends CoreException
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,8 @@ declare(strict_types=1);
|
|||||||
namespace LotGD\Core\Exceptions;
|
namespace LotGD\Core\Exceptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exception if a specific, required argument is missing
|
* Exception if a specific, required argument is missing.
|
||||||
*/
|
*/
|
||||||
class AttributeMissingException extends CoreException
|
class AttributeMissingException extends CoreException
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,8 @@ declare(strict_types=1);
|
|||||||
namespace LotGD\Core\Exceptions;
|
namespace LotGD\Core\Exceptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exception if a specific, required argument is missing
|
* Exception if a specific, required argument is missing.
|
||||||
*/
|
*/
|
||||||
class BattleEventException extends BattleException
|
class BattleEventException extends BattleException
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,8 @@ declare(strict_types=1);
|
|||||||
namespace LotGD\Core\Exceptions;
|
namespace LotGD\Core\Exceptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exception if a specific, required argument is missing
|
* Exception if a specific, required argument is missing.
|
||||||
*/
|
*/
|
||||||
class BattleException extends CoreException
|
class BattleException extends CoreException
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,8 @@ declare(strict_types=1);
|
|||||||
namespace LotGD\Core\Exceptions;
|
namespace LotGD\Core\Exceptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exception if a specific, required argument is missing
|
* Exception if a specific, required argument is missing.
|
||||||
*/
|
*/
|
||||||
class BattleIsOverException extends BattleException
|
class BattleIsOverException extends BattleException
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,8 @@ declare(strict_types=1);
|
|||||||
namespace LotGD\Core\Exceptions;
|
namespace LotGD\Core\Exceptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exception if a specific, required argument is missing
|
* Exception if a specific, required argument is missing.
|
||||||
*/
|
*/
|
||||||
class BattleNotOverException extends BattleException
|
class BattleNotOverException extends BattleException
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,8 @@ declare(strict_types=1);
|
|||||||
namespace LotGD\Core\Exceptions;
|
namespace LotGD\Core\Exceptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exception if a specific, required argument is missing
|
* Exception if a specific, required argument is missing.
|
||||||
*/
|
*/
|
||||||
class BuffListAlreadyActivatedException extends CoreException
|
class BuffListAlreadyActivatedException extends CoreException
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,8 @@ declare(strict_types=1);
|
|||||||
namespace LotGD\Core\Exceptions;
|
namespace LotGD\Core\Exceptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exception if a specific, required argument is missing
|
* Exception if a specific, required argument is missing.
|
||||||
*/
|
*/
|
||||||
class BuffSlotOccupiedException extends CoreException
|
class BuffSlotOccupiedException extends CoreException
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,8 @@ declare(strict_types=1);
|
|||||||
namespace LotGD\Core\Exceptions;
|
namespace LotGD\Core\Exceptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exception if a builder is missing an argument
|
* Exception if a builder is missing an argument.
|
||||||
*/
|
*/
|
||||||
class BuilderException extends CoreException
|
class BuilderException extends CoreException
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,5 +8,4 @@ namespace LotGD\Core\Exceptions;
|
|||||||
*/
|
*/
|
||||||
class CharacterNotFoundException extends CoreException
|
class CharacterNotFoundException extends CoreException
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LotGD\Core\Exceptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class CharacterStatException.
|
||||||
|
*/
|
||||||
|
class CharacterStatException extends CoreException
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LotGD\Core\Exceptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class CharacterStatExistsException.
|
||||||
|
*/
|
||||||
|
class CharacterStatExistsException extends CharacterStatException
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LotGD\Core\Exceptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class CharacterStatGroupExistsException.
|
||||||
|
*/
|
||||||
|
class CharacterStatGroupExistsException extends CharacterStatException
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LotGD\Core\Exceptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class CharacterStatGroupNotFoundException.
|
||||||
|
*/
|
||||||
|
class CharacterStatGroupNotFoundException extends CharacterStatException
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LotGD\Core\Exceptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class CharacterStatNotFoundException.
|
||||||
|
*/
|
||||||
|
class CharacterStatNotFoundException extends CharacterStatException
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -4,9 +4,8 @@ declare(strict_types=1);
|
|||||||
namespace LotGD\Core\Exceptions;
|
namespace LotGD\Core\Exceptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exception if a specific, required argument is missing
|
* Exception if a specific, required argument is missing.
|
||||||
*/
|
*/
|
||||||
class ClassNotFoundException extends CoreException
|
class ClassNotFoundException extends CoreException
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,5 +8,4 @@ namespace LotGD\Core\Exceptions;
|
|||||||
*/
|
*/
|
||||||
class CoreException extends \Exception
|
class CoreException extends \Exception
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,5 +8,4 @@ namespace LotGD\Core\Exceptions;
|
|||||||
*/
|
*/
|
||||||
class EntityAlreadyExistsException extends EntityException
|
class EntityAlreadyExistsException extends EntityException
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,5 +8,4 @@ namespace LotGD\Core\Exceptions;
|
|||||||
*/
|
*/
|
||||||
class EntityDoesNotExistException extends EntityException
|
class EntityDoesNotExistException extends EntityException
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,8 @@ declare(strict_types=1);
|
|||||||
namespace LotGD\Core\Exceptions;
|
namespace LotGD\Core\Exceptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A basic entity exception
|
* A basic entity exception.
|
||||||
*/
|
*/
|
||||||
class EntityException extends CoreException
|
class EntityException extends CoreException
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LotGD\Core\Exceptions;
|
||||||
|
|
||||||
|
class InsecureTwigTemplateError extends CoreException
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -8,5 +8,4 @@ namespace LotGD\Core\Exceptions;
|
|||||||
*/
|
*/
|
||||||
class InvalidConfigurationException extends CoreException
|
class InvalidConfigurationException extends CoreException
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,5 +8,4 @@ namespace LotGD\Core\Exceptions;
|
|||||||
*/
|
*/
|
||||||
class InvalidModelException extends CoreException
|
class InvalidModelException extends CoreException
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,8 @@ declare(strict_types=1);
|
|||||||
namespace LotGD\Core\Exceptions;
|
namespace LotGD\Core\Exceptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exception if a specific, required argument is missing
|
* Exception if a specific, required argument is missing.
|
||||||
*/
|
*/
|
||||||
class IsNullException extends CoreException
|
class IsNullException extends CoreException
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,8 @@ declare(strict_types=1);
|
|||||||
namespace LotGD\Core\Exceptions;
|
namespace LotGD\Core\Exceptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exception if a specific, required argument is missing
|
* Exception if a specific, required argument is missing.
|
||||||
*/
|
*/
|
||||||
class KeyNotFoundException extends CoreException
|
class KeyNotFoundException extends CoreException
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,5 +8,4 @@ namespace LotGD\Core\Exceptions;
|
|||||||
*/
|
*/
|
||||||
class LibraryDoesNotExistException extends CoreException
|
class LibraryDoesNotExistException extends CoreException
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,5 +8,4 @@ namespace LotGD\Core\Exceptions;
|
|||||||
*/
|
*/
|
||||||
class ModuleAlreadyExistsException extends CoreException
|
class ModuleAlreadyExistsException extends CoreException
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,5 +8,4 @@ namespace LotGD\Core\Exceptions;
|
|||||||
*/
|
*/
|
||||||
class ModuleDoesNotExistException extends CoreException
|
class ModuleDoesNotExistException extends CoreException
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,8 @@ declare(strict_types=1);
|
|||||||
namespace LotGD\Core\Exceptions;
|
namespace LotGD\Core\Exceptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exception if a specific, required argument is missing
|
* Exception if a specific, required argument is missing.
|
||||||
*/
|
*/
|
||||||
class NotImplementedException extends CoreException
|
class NotImplementedException extends CoreException
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,8 @@ declare(strict_types=1);
|
|||||||
namespace LotGD\Core\Exceptions;
|
namespace LotGD\Core\Exceptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exception if a specific, required argument is missing
|
* Exception if a specific, required argument is missing.
|
||||||
*/
|
*/
|
||||||
class ParentAlreadySetException extends CoreException
|
class ParentAlreadySetException extends CoreException
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,5 +8,4 @@ namespace LotGD\Core\Exceptions;
|
|||||||
*/
|
*/
|
||||||
class PermissionAlreadyExistsException extends EntityAlreadyExistsException
|
class PermissionAlreadyExistsException extends EntityAlreadyExistsException
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user