Compare commits

...

46 Commits
v1.6.1 ... main

Author SHA1 Message Date
slawkens
2fe9924437 Start 1.7.2-dev 2025-07-08 19:20:45 +02:00
slawkens
f0f2e3785f Fix phpstan 2025-07-08 15:44:45 +02:00
slawkens
36ca755243 New setting: Display Skills Box on highscores
Better space management
2025-07-08 14:28:48 +02:00
slawkens
f17269e44c Move admin bar code into body_start place_holder 2025-07-08 14:22:51 +02:00
slawkens
dcb96f4ce1 Refactor code - early exit 2025-07-08 13:48:33 +02:00
slawkens
a89f9a8484 Set $process_sections to true 2025-07-08 09:22:12 +02:00
slawkens
45d6047031 Add Coins Transferable to accounts editor 2025-07-05 14:22:58 +02:00
slawkens
c92148d467 Revert delete clearRouteCache, is used somewhere else 2025-06-27 07:23:22 +02:00
slawkens
b4b62442fe Release v1.7.1 2025-06-27 07:21:19 +02:00
slawkens
047742848b Delete clearRouteCache, was useless
Directory is cleaned already
2025-06-27 07:15:13 +02:00
slawkens
fe8281594e Fix cache:clear command (missing init) 2025-06-27 07:13:33 +02:00
slawkens
0bff910a05 adjust command email:send + mail:send (alias) 2025-06-25 19:43:40 +02:00
slawkens
6d43fc181f In case the script don't have install option, inform the user 2025-06-25 17:36:43 +02:00
slawkens
13d33822b5 Rename to plugin:setup, also add alias to previous command 2025-06-25 17:36:02 +02:00
slawkens
f78ebad136 Remove error number from 404 & 405 pages 2025-06-24 14:57:01 +02:00
slawkens
d90fa323d7 Fix polls link 2025-06-24 12:44:43 +02:00
slawkens
181131f7f3 Use __DIR__ instead of template path 2025-06-24 12:44:34 +02:00
slawkens
0da524fefe Fix plugin install:install command 2025-06-23 00:21:41 +02:00
slawkens
6cf4b9dac5 Fix xdebug warnings in load_config_lua 2025-06-22 18:51:20 +02:00
slawkens
5cfa3a697f Start v1.7.1-dev 2025-06-22 11:25:45 +02:00
slawkens
bb830bce44 Release v1.7 2025-06-22 08:55:29 +02:00
slawkens
566c2a9151 Move out of $cache->enabled 2025-06-22 08:48:24 +02:00
slawkens
0f48f12e2e Update admin.plugins.outdated.html.twig 2025-06-19 18:53:11 +02:00
Slawomir Boczek
0ea247ce7e
Feature/plugins versions check (#310)
* Check plugins versions from plugins.my-aac.org/api

* Improve plugin update check messaging

Updated the success message when checking for plugin updates to clarify the source. Added an informational message when outdated plugins are found to improve user feedback.

* Use configurable API URI for plugin updates

Replaces hardcoded plugin API URI with a configurable value from config, defaulting to the official API. Also fixes a typo in the success message.
2025-06-19 16:46:22 +02:00
slawkens
b329da52aa Use apcu_clear_cache 2025-06-17 17:52:23 +02:00
slawkens
c720ccc451 Add missing csrf() 2025-06-15 19:35:12 +02:00
slawkens
8dc42b6544 Nothing important: just formatting 2025-06-15 19:05:47 +02:00
slawkens
dca904e61d Add missing csrf() 2025-06-15 19:05:19 +02:00
slawkens
29faa4f695 Add missing csrf() in success.html.twig 2025-06-15 19:03:03 +02:00
slawkens
4767120043 Update online.html.twig 2025-06-14 21:19:52 +02:00
slawkens
9a90e4aae2 Revamped online page 2025-06-14 21:12:47 +02:00
slawkens
ba4ed6a04b Add LabelV120, LabelV150, LabelV200 2025-06-14 20:52:38 +02:00
slawkens
a7efacdbac Delete online.form, use revamped characters.form 2025-06-14 20:50:54 +02:00
Goosey
577037becc
fix: boostedcreatures for 13.40 (#307)
* boostedcreatures fix for 13.40

Fixes the boosted boss/creature display on the login page for 13.40 running the default cipsoft client.

* Adjust version

---------

Co-authored-by: slawkens <slawkens@gmail.com>
2025-06-14 15:58:08 +02:00
slawkens
b8abc11b96 Update list.php 2025-06-14 11:33:47 +02:00
slawkens
4def6a6cae Style 2025-06-14 10:39:45 +02:00
slawkens
e6100a1b72 New hook: HOOK_GUILDS_AFTER_MANAGE_BUTTON 2025-06-14 10:36:38 +02:00
slawkens
522f6c11d8 Add OTS_Player->isNameLocked() 2025-06-14 08:26:43 +02:00
slawkens
00c3635c5f Add $config['site']['serverPath'] for better compatibility with Gesior 2025-06-14 00:59:10 +02:00
slawkens
c074a48f24 New hook: HOOK_ACCOUNT_MANAGE_AFTER_CHARACTERS 2025-06-14 00:44:00 +02:00
slawkens
e222957893 OTS_Toolbox::getVocationName($id, $promotion); 2025-06-13 22:25:36 +02:00
slawkens
d423ddd07a Nothing important: convert to tabs 2025-06-13 22:14:20 +02:00
slawkens
4d4f7759d3 Update visitors.php 2025-06-13 21:31:04 +02:00
slawkens
9510640ba9 Ignore empty values 2025-06-13 21:25:13 +02:00
slawkens
98b13c91a4 Update notice about how to enable Visitors Counter 2025-06-13 21:24:52 +02:00
slawkens
0c95bcfd06 Better $title inventing 2025-06-13 21:03:09 +02:00
46 changed files with 1250 additions and 413 deletions

View File

@ -1,5 +1,30 @@
# Changelog # Changelog
## [1.7.1 - 27.06.2025]
### Changed
* Rename plugin:install:install to plugin:setup, also add alias to previous command (https://github.com/slawkens/myaac/commit/13d33822b59df349199e885a78a3d6beb0863d0b)
### Fixed
* Fix commands: setup + cache:clear (https://github.com/slawkens/myaac/commit/0da524fefe93b3028392e9014550eea3324d3a22, https://github.com/slawkens/myaac/commit/fe8281594e989f00280ba1adc734a9198c6b5cc1)
* Fix polls link in tibiacom template (https://github.com/slawkens/myaac/commit/d90fa323d7c77d81768df60feeb1c374b1650a0c)
## [1.7 - 22.06.2025]
### Added
* Feature: plugins versions check (#310)
* New hooks: HOOK_ACCOUNT_MANAGE_AFTER_CHARACTERS, HOOK_GUILDS_AFTER_MANAGE_BUTTON (https://github.com/slawkens/myaac/commit/c074a48f245df55646b6705737f667b6a84149b2, https://github.com/slawkens/myaac/commit/e6100a1b72de8695bba1dae9ba4e28bfdce47b10)
* Add OTS_Toolbox::getVocationName(id, promotion) + OTS_Player->isNameLocked() (https://github.com/slawkens/myaac/commit/e222957893c4a1de0dc8dbba55bce1a43418d275, https://github.com/slawkens/myaac/commit/522f6c11d835afd36fd07a07074d96d7e219b488)
* Add missing csrf in more places, causing white page with error about Request (https://github.com/slawkens/myaac/commit/dca904e61d21d856bf809070e7652803a2df0f58, https://github.com/slawkens/myaac/commit/c720ccc451ff90ef40b2a1595468d061ffd7e1e4)
### Changed
* Revamped online page (https://github.com/slawkens/myaac/commit/9a90e4aae280e607430511c6727d9a714b11f4c5, https://github.com/slawkens/myaac/commit/4767120043b09141870383e249f3729638d53dc2)
* Better $title inventing (https://github.com/slawkens/myaac/commit/0c95bcfd06b68b21512e477646ef7bd3a0d4912b)
### Fixed
* Use apcu cache clear (https://github.com/slawkens/myaac/commit/b329da52aae9d0e21120a6444d3caf442420ce50, https://github.com/slawkens/myaac/commit/566c2a9151ab6392286f74e26853faa19a1b4f24)
* fix: boostedcreatures for 13.40 (by @GooseWithAKnife) (#307)
## [1.6.1 - 11.06.2025] ## [1.6.1 - 11.06.2025]
### Fixed ### Fixed

View File

@ -27,6 +27,13 @@ $nameOrNumberColumn = getAccountIdentityColumn();
$hasSecretColumn = $db->hasColumn('accounts', 'secret'); $hasSecretColumn = $db->hasColumn('accounts', 'secret');
$hasCoinsColumn = $db->hasColumn('accounts', 'coins'); $hasCoinsColumn = $db->hasColumn('accounts', 'coins');
$hasCoinsTransferableColumn = $db->hasColumn('accounts', 'coins_transferable');
$hasTransferableCoinsColumn = $db->hasColumn('accounts', 'transferable_coins');
$coinsTransferableColumn =
$hasTransferableCoinsColumn ?
'transferable_coins' : 'coins_transferable';
$hasPointsColumn = $db->hasColumn('accounts', 'premium_points'); $hasPointsColumn = $db->hasColumn('accounts', 'premium_points');
$hasTypeColumn = $db->hasColumn('accounts', 'type'); $hasTypeColumn = $db->hasColumn('accounts', 'type');
$hasGroupColumn = $db->hasColumn('accounts', 'group_id'); $hasGroupColumn = $db->hasColumn('accounts', 'group_id');
@ -136,11 +143,18 @@ else if (isset($_REQUEST['search'])) {
if (!Validator::email($email)) if (!Validator::email($email))
$errors['email'] = Validator::getLastError(); $errors['email'] = Validator::getLastError();
//tibia coins // tibia coins
if ($hasCoinsColumn) { if ($hasCoinsColumn) {
$t_coins = $_POST['t_coins']; $t_coins = $_POST['t_coins'];
verify_number($t_coins, 'Tibia coins', 12); verify_number($t_coins, 'Tibia coins', 12);
} }
// transferable tibia coins
if ($hasCoinsTransferableColumn || $hasTransferableCoinsColumn) {
$t_coins_transferable = $_POST['t_coins_transferable'];
verify_number($t_coins_transferable, 'Transferable Tibia coins', 12);
}
// prem days // prem days
$p_days = (int)$_POST['p_days']; $p_days = (int)$_POST['p_days'];
verify_number($p_days, 'Prem days', 11); verify_number($p_days, 'Prem days', 11);
@ -185,12 +199,18 @@ else if (isset($_REQUEST['search'])) {
if ($hasSecretColumn) { if ($hasSecretColumn) {
$account->setCustomField('secret', $secret); $account->setCustomField('secret', $secret);
} }
$account->setCustomField('key', $key); $account->setCustomField('key', $key);
$account->setEMail($email); $account->setEMail($email);
if ($hasCoinsColumn) { if ($hasCoinsColumn) {
$account->setCustomField('coins', $t_coins); $account->setCustomField('coins', $t_coins);
} }
if ($hasCoinsTransferableColumn || $hasTransferableCoinsColumn) {
$account->setCustomField($coinsTransferableColumn, $t_coins_transferable);
}
$lastDay = 0; $lastDay = 0;
if($p_days != 0 && $p_days != OTS_Account::GRATIS_PREMIUM_DAYS) { if($p_days != 0 && $p_days != OTS_Account::GRATIS_PREMIUM_DAYS) {
$lastDay = time(); $lastDay = time();
@ -401,6 +421,12 @@ else if (isset($_REQUEST['search'])) {
<input type="text" class="form-control" id="t_coins" name="t_coins" autocomplete="off" maxlength="11" value="<?php echo $account->getCustomField('coins') ?>"/> <input type="text" class="form-control" id="t_coins" name="t_coins" autocomplete="off" maxlength="11" value="<?php echo $account->getCustomField('coins') ?>"/>
</div> </div>
<?php endif; ?> <?php endif; ?>
<?php if ($hasCoinsTransferableColumn || $hasTransferableCoinsColumn): ?>
<div class="col-12 col-sm-12 col-lg-6">
<label for="t_coins_transferable">Transferable Tibia Coins:</label>
<input type="text" class="form-control" id="t_coins_transferable" name="t_coins_transferable" autocomplete="off" maxlength="11" value="<?php echo $account->getCustomField($coinsTransferableColumn) ?>"/>
</div>
<?php endif; ?>
<div class="col-12 col-sm-12 col-lg-6"> <div class="col-12 col-sm-12 col-lg-6">
<label for="p_days">Premium Days:</label> <label for="p_days">Premium Days:</label>
<input type="text" class="form-control" id="p_days" name="p_days" autocomplete="off" maxlength="11" value="<?php echo $account->getPremDays(); ?>"/> <input type="text" class="form-control" id="p_days" name="p_days" autocomplete="off" maxlength="11" value="<?php echo $account->getPremDays(); ?>"/>

View File

@ -51,6 +51,56 @@ else {
} else { } else {
error('Error while disabling plugin ' . $disable . ': ' . Plugins::getError()); error('Error while disabling plugin ' . $disable . ': ' . Plugins::getError());
} }
}
else if (isset($_GET['check-updates'])) {
$repoUri = $config['admin_plugins_api_uri'] ?? 'https://plugins.my-aac.org/api/';
success("Fetching latest info from $repoUri..");
$adminPlugins = new \MyAAC\Admin\Plugins();
$adminPlugins->setApiBaseUri($repoUri);
try {
$plugins = $adminPlugins->getLatestVersions();
}
catch (Exception $e) {
error($e->getMessage());
}
if (isset($plugins) && count($plugins) > 0) {
$outdated = [];
foreach (get_plugins(true) as $plugin) {
$string = file_get_contents(BASE . 'plugins/' . $plugin . '.json');
$plugin_info = json_decode($string, true);
if (!$plugin_info) {
continue;
}
$disabled = (str_contains($plugin, 'disabled.'));
$pluginOriginal = ($disabled ? str_replace('disabled.', '', $plugin) : $plugin);
$info = $plugins[$pluginOriginal] ?? false;
if ($info && version_compare($info['version'], $plugin_info['version'], '>')) {
$outdated[] = [
'name' => $pluginOriginal,
'yourVersion' => $plugin_info['version'],
'latestVersion' => $info['version'],
'link' => $info['link'] ?? 'Unknown',
'download_link' => $info['download_link'] ?? 'Unknown',
];
}
}
if (count($outdated) > 0) {
info('Following updates have been found for your plugins:');
$twig->display('admin.plugins.outdated.html.twig', ['plugins' => $outdated]);
}
else {
success('All plugins up to date!');
}
}
} else if (isset($_FILES['plugin']['name'])) { } else if (isset($_FILES['plugin']['name'])) {
$file = $_FILES['plugin']; $file = $_FILES['plugin'];
$filename = $file['name']; $filename = $file['name'];

View File

@ -19,8 +19,7 @@ $use_datatable = true;
if (!setting('core.visitors_counter')): ?> if (!setting('core.visitors_counter')): ?>
Visitors counter is disabled.<br/> Visitors counter is disabled.<br/>
You can enable it by editing this configurable in <b>config.local.php</b> file:<br/> You can enable it in Settings -> General -> Visitors Counter.<br/>
<p style="margin-left: 3em;"><b>$config['visitors_counter'] = true;</b></p>
<?php <?php
return; return;
endif; endif;
@ -46,7 +45,7 @@ foreach ($tmp as &$visitor) {
if ($dd->isBot()) { if ($dd->isBot()) {
$bot = $dd->getBot(); $bot = $dd->getBot();
$message = '(Bot) %s, <a href="%s" target="_blank">%s</a>'; $message = '(Bot) %s, <a href="%s" target="_blank">%s</a>';
$browser = sprintf($message, $bot['category'], $bot['url'], $bot['name']); $browser = sprintf($message, $bot['category'] ?? 'Unknown', $bot['url'] ?? '', $bot['name'] ?? 'Unknown name');
} }
else { else {
$osFamily = OperatingSystem::getOsFamily($dd->getOs('name')); $osFamily = OperatingSystem::getOsFamily($dd->getOs('name'));

View File

@ -26,7 +26,7 @@
if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.');
const MYAAC = true; const MYAAC = true;
const MYAAC_VERSION = '1.6.1'; const MYAAC_VERSION = '1.7.2-dev';
const DATABASE_VERSION = 45; const DATABASE_VERSION = 45;
const TABLE_PREFIX = 'myaac_'; const TABLE_PREFIX = 'myaac_';
define('START_TIME', microtime(true)); define('START_TIME', microtime(true));

View File

@ -18,7 +18,8 @@
"symfony/string": "^6.4", "symfony/string": "^6.4",
"symfony/var-dumper": "^6.4", "symfony/var-dumper": "^6.4",
"filp/whoops": "^2.15", "filp/whoops": "^2.15",
"maximebf/debugbar": "1.*" "maximebf/debugbar": "1.*",
"guzzlehttp/guzzle": "7.9.3"
}, },
"require-dev": { "require-dev": {
"phpstan/phpstan": "^1.10" "phpstan/phpstan": "^1.10"

537
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "be4d1489a53a9cd8eec6bcaa7a096f30", "content-hash": "5317e97a5025ebc2a977214bd3fa964c",
"packages": [ "packages": [
{ {
"name": "brick/math", "name": "brick/math",
@ -493,6 +493,331 @@
], ],
"time": "2024-09-25T12:00:00+00:00" "time": "2024-09-25T12:00:00+00:00"
}, },
{
"name": "guzzlehttp/guzzle",
"version": "7.9.3",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle.git",
"reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/7b2f29fe81dc4da0ca0ea7d42107a0845946ea77",
"reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77",
"shasum": ""
},
"require": {
"ext-json": "*",
"guzzlehttp/promises": "^1.5.3 || ^2.0.3",
"guzzlehttp/psr7": "^2.7.0",
"php": "^7.2.5 || ^8.0",
"psr/http-client": "^1.0",
"symfony/deprecation-contracts": "^2.2 || ^3.0"
},
"provide": {
"psr/http-client-implementation": "1.0"
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.8.2",
"ext-curl": "*",
"guzzle/client-integration-tests": "3.0.2",
"php-http/message-factory": "^1.1",
"phpunit/phpunit": "^8.5.39 || ^9.6.20",
"psr/log": "^1.1 || ^2.0 || ^3.0"
},
"suggest": {
"ext-curl": "Required for CURL handler support",
"ext-intl": "Required for Internationalized Domain Name (IDN) support",
"psr/log": "Required for using the Log middleware"
},
"type": "library",
"extra": {
"bamarni-bin": {
"bin-links": true,
"forward-command": false
}
},
"autoload": {
"files": [
"src/functions_include.php"
],
"psr-4": {
"GuzzleHttp\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Graham Campbell",
"email": "hello@gjcampbell.co.uk",
"homepage": "https://github.com/GrahamCampbell"
},
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
},
{
"name": "Jeremy Lindblom",
"email": "jeremeamia@gmail.com",
"homepage": "https://github.com/jeremeamia"
},
{
"name": "George Mponos",
"email": "gmponos@gmail.com",
"homepage": "https://github.com/gmponos"
},
{
"name": "Tobias Nyholm",
"email": "tobias.nyholm@gmail.com",
"homepage": "https://github.com/Nyholm"
},
{
"name": "Márk Sági-Kazár",
"email": "mark.sagikazar@gmail.com",
"homepage": "https://github.com/sagikazarmark"
},
{
"name": "Tobias Schultze",
"email": "webmaster@tubo-world.de",
"homepage": "https://github.com/Tobion"
}
],
"description": "Guzzle is a PHP HTTP client library",
"keywords": [
"client",
"curl",
"framework",
"http",
"http client",
"psr-18",
"psr-7",
"rest",
"web service"
],
"support": {
"issues": "https://github.com/guzzle/guzzle/issues",
"source": "https://github.com/guzzle/guzzle/tree/7.9.3"
},
"funding": [
{
"url": "https://github.com/GrahamCampbell",
"type": "github"
},
{
"url": "https://github.com/Nyholm",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle",
"type": "tidelift"
}
],
"time": "2025-03-27T13:37:11+00:00"
},
{
"name": "guzzlehttp/promises",
"version": "2.2.0",
"source": {
"type": "git",
"url": "https://github.com/guzzle/promises.git",
"reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/promises/zipball/7c69f28996b0a6920945dd20b3857e499d9ca96c",
"reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c",
"shasum": ""
},
"require": {
"php": "^7.2.5 || ^8.0"
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.8.2",
"phpunit/phpunit": "^8.5.39 || ^9.6.20"
},
"type": "library",
"extra": {
"bamarni-bin": {
"bin-links": true,
"forward-command": false
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\Promise\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Graham Campbell",
"email": "hello@gjcampbell.co.uk",
"homepage": "https://github.com/GrahamCampbell"
},
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
},
{
"name": "Tobias Nyholm",
"email": "tobias.nyholm@gmail.com",
"homepage": "https://github.com/Nyholm"
},
{
"name": "Tobias Schultze",
"email": "webmaster@tubo-world.de",
"homepage": "https://github.com/Tobion"
}
],
"description": "Guzzle promises library",
"keywords": [
"promise"
],
"support": {
"issues": "https://github.com/guzzle/promises/issues",
"source": "https://github.com/guzzle/promises/tree/2.2.0"
},
"funding": [
{
"url": "https://github.com/GrahamCampbell",
"type": "github"
},
{
"url": "https://github.com/Nyholm",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises",
"type": "tidelift"
}
],
"time": "2025-03-27T13:27:01+00:00"
},
{
"name": "guzzlehttp/psr7",
"version": "2.7.1",
"source": {
"type": "git",
"url": "https://github.com/guzzle/psr7.git",
"reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/c2270caaabe631b3b44c85f99e5a04bbb8060d16",
"reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16",
"shasum": ""
},
"require": {
"php": "^7.2.5 || ^8.0",
"psr/http-factory": "^1.0",
"psr/http-message": "^1.1 || ^2.0",
"ralouphie/getallheaders": "^3.0"
},
"provide": {
"psr/http-factory-implementation": "1.0",
"psr/http-message-implementation": "1.0"
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.8.2",
"http-interop/http-factory-tests": "0.9.0",
"phpunit/phpunit": "^8.5.39 || ^9.6.20"
},
"suggest": {
"laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
},
"type": "library",
"extra": {
"bamarni-bin": {
"bin-links": true,
"forward-command": false
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\Psr7\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Graham Campbell",
"email": "hello@gjcampbell.co.uk",
"homepage": "https://github.com/GrahamCampbell"
},
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
},
{
"name": "George Mponos",
"email": "gmponos@gmail.com",
"homepage": "https://github.com/gmponos"
},
{
"name": "Tobias Nyholm",
"email": "tobias.nyholm@gmail.com",
"homepage": "https://github.com/Nyholm"
},
{
"name": "Márk Sági-Kazár",
"email": "mark.sagikazar@gmail.com",
"homepage": "https://github.com/sagikazarmark"
},
{
"name": "Tobias Schultze",
"email": "webmaster@tubo-world.de",
"homepage": "https://github.com/Tobion"
},
{
"name": "Márk Sági-Kazár",
"email": "mark.sagikazar@gmail.com",
"homepage": "https://sagikazarmark.hu"
}
],
"description": "PSR-7 message implementation that also provides common utility methods",
"keywords": [
"http",
"message",
"psr-7",
"request",
"response",
"stream",
"uri",
"url"
],
"support": {
"issues": "https://github.com/guzzle/psr7/issues",
"source": "https://github.com/guzzle/psr7/tree/2.7.1"
},
"funding": [
{
"url": "https://github.com/GrahamCampbell",
"type": "github"
},
{
"url": "https://github.com/Nyholm",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7",
"type": "tidelift"
}
],
"time": "2025-03-27T12:30:47+00:00"
},
{ {
"name": "illuminate/collections", "name": "illuminate/collections",
"version": "v10.48.25", "version": "v10.48.25",
@ -1472,6 +1797,166 @@
}, },
"time": "2021-11-05T16:47:00+00:00" "time": "2021-11-05T16:47:00+00:00"
}, },
{
"name": "psr/http-client",
"version": "1.0.3",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-client.git",
"reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90",
"reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90",
"shasum": ""
},
"require": {
"php": "^7.0 || ^8.0",
"psr/http-message": "^1.0 || ^2.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Client\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common interface for HTTP clients",
"homepage": "https://github.com/php-fig/http-client",
"keywords": [
"http",
"http-client",
"psr",
"psr-18"
],
"support": {
"source": "https://github.com/php-fig/http-client"
},
"time": "2023-09-23T14:17:50+00:00"
},
{
"name": "psr/http-factory",
"version": "1.1.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-factory.git",
"reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a",
"reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a",
"shasum": ""
},
"require": {
"php": ">=7.1",
"psr/http-message": "^1.0 || ^2.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Message\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "PSR-17: Common interfaces for PSR-7 HTTP message factories",
"keywords": [
"factory",
"http",
"message",
"psr",
"psr-17",
"psr-7",
"request",
"response"
],
"support": {
"source": "https://github.com/php-fig/http-factory"
},
"time": "2024-04-15T12:06:14+00:00"
},
{
"name": "psr/http-message",
"version": "2.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-message.git",
"reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71",
"reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Message\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common interface for HTTP messages",
"homepage": "https://github.com/php-fig/http-message",
"keywords": [
"http",
"http-message",
"psr",
"psr-7",
"request",
"response"
],
"support": {
"source": "https://github.com/php-fig/http-message/tree/2.0"
},
"time": "2023-04-04T09:54:51+00:00"
},
{ {
"name": "psr/log", "name": "psr/log",
"version": "3.0.2", "version": "3.0.2",
@ -1573,6 +2058,50 @@
}, },
"time": "2021-10-29T13:26:27+00:00" "time": "2021-10-29T13:26:27+00:00"
}, },
{
"name": "ralouphie/getallheaders",
"version": "3.0.3",
"source": {
"type": "git",
"url": "https://github.com/ralouphie/getallheaders.git",
"reference": "120b605dfeb996808c31b6477290a714d356e822"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822",
"reference": "120b605dfeb996808c31b6477290a714d356e822",
"shasum": ""
},
"require": {
"php": ">=5.6"
},
"require-dev": {
"php-coveralls/php-coveralls": "^2.1",
"phpunit/phpunit": "^5 || ^6.5"
},
"type": "library",
"autoload": {
"files": [
"src/getallheaders.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Ralph Khattar",
"email": "ralph.khattar@gmail.com"
}
],
"description": "A polyfill for getallheaders.",
"support": {
"issues": "https://github.com/ralouphie/getallheaders/issues",
"source": "https://github.com/ralouphie/getallheaders/tree/develop"
},
"time": "2019-03-08T08:55:37+00:00"
},
{ {
"name": "symfony/console", "name": "symfony/console",
"version": "v6.4.17", "version": "v6.4.17",
@ -2910,7 +3439,7 @@
], ],
"aliases": [], "aliases": [],
"minimum-stability": "stable", "minimum-stability": "stable",
"stability-flags": [], "stability-flags": {},
"prefer-stable": false, "prefer-stable": false,
"prefer-lowest": false, "prefer-lowest": false,
"platform": { "platform": {
@ -2921,6 +3450,6 @@
"ext-xml": "*", "ext-xml": "*",
"ext-dom": "*" "ext-dom": "*"
}, },
"platform-dev": [], "platform-dev": {},
"plugin-api-version": "2.3.0" "plugin-api-version": "2.6.0"
} }

BIN
images/order_asc.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 B

BIN
images/order_desc.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 B

View File

@ -93,6 +93,7 @@ if(setting('core.backward_support')) {
if($logged && $account_logged) if($logged && $account_logged)
$group_id_of_acc_logged = $account_logged->getGroupId(); $group_id_of_acc_logged = $account_logged->getGroupId();
$config['serverPath'] = $config['server_path'];
$config['site'] = &$config; $config['site'] = &$config;
$config['server'] = &$config['lua']; $config['server'] = &$config['lua'];
$config['site']['shop_system'] = setting('core.gifts_system'); $config['site']['shop_system'] = setting('core.gifts_system');
@ -161,15 +162,6 @@ if(setting('core.anonymous_usage_statistics')) {
} }
} }
/**
* @var OTS_Account $account_logged
*/
if ($logged && admin()) {
$content .= $twig->render('admin-bar.html.twig', [
'username' => USE_ACCOUNT_NAME ? $account_logged->getName() : $account_logged->getId()
]);
}
$title_full = (isset($title) ? $title . ' - ' : '') . $config['lua']['serverName']; $title_full = (isset($title) ? $title . ' - ' : '') . $config['lua']['serverName'];
require $template_path . '/' . $template_index; require $template_path . '/' . $template_index;

View File

@ -88,8 +88,8 @@ switch ($action) {
case 'boostedcreature': case 'boostedcreature':
$clientVersion = (int)setting('core.client'); $clientVersion = (int)setting('core.client');
// 14.00 and up // 13.40 and up
if ($clientVersion >= 1400) { if ($clientVersion >= 1340) {
$creatureBoost = $db->query("SELECT * FROM " . $db->tableName('boosted_creature'))->fetchAll(); $creatureBoost = $db->query("SELECT * FROM " . $db->tableName('boosted_creature'))->fetchAll();
$bossBoost = $db->query("SELECT * FROM " . $db->tableName('boosted_boss'))->fetchAll(); $bossBoost = $db->query("SELECT * FROM " . $db->tableName('boosted_boss'))->fetchAll();
die(json_encode([ die(json_encode([

View File

@ -512,6 +512,13 @@ function template_place_holder($type): string
} }
elseif ($type === 'body_start') { elseif ($type === 'body_start') {
$ret .= $twig->render('browsehappy.html.twig'); $ret .= $twig->render('browsehappy.html.twig');
if (admin()) {
global $account_logged;
$ret .= $twig->render('admin-bar.html.twig', [
'username' => USE_ACCOUNT_NAME ? $account_logged->getName() : $account_logged->getId()
]);
}
} }
elseif($type === 'body_end') { elseif($type === 'body_end') {
$ret .= template_ga_code(); $ret .= template_ga_code();
@ -982,11 +989,12 @@ function load_config_lua($filename)
foreach($lines as $ln => $line) foreach($lines as $ln => $line)
{ {
$line = trim($line); $line = trim($line);
if(@$line[0] === '{' || @$line[0] === '}') { if(isset($line[0]) && ($line[0] === '{' || $line[0] === '}')) {
// arrays are not supported yet // arrays are not supported yet
// just ignore the error // just ignore the error
continue; continue;
} }
$tmp_exp = explode('=', $line, 2); $tmp_exp = explode('=', $line, 2);
if(str_contains($line, 'dofile')) { if(str_contains($line, 'dofile')) {
$delimiter = '"'; $delimiter = '"';
@ -1265,14 +1273,15 @@ function clearCache()
$db->setClearCacheAfter(true); $db->setClearCacheAfter(true);
} }
if (function_exists('apcu_clear_cache')) {
apcu_clear_cache();
}
deleteDirectory(CACHE . 'signatures', ['index.html'], true); deleteDirectory(CACHE . 'signatures', ['index.html'], true);
deleteDirectory(CACHE . 'twig', ['index.html'], true); deleteDirectory(CACHE . 'twig', ['index.html'], true);
deleteDirectory(CACHE . 'plugins', ['index.html'], true); deleteDirectory(CACHE . 'plugins', ['index.html'], true);
deleteDirectory(CACHE, ['signatures', 'twig', 'plugins', 'index.html', 'persistent'], true); deleteDirectory(CACHE, ['signatures', 'twig', 'plugins', 'index.html', 'persistent'], true);
// routes cache
clearRouteCache();
global $hooks; global $hooks;
$hooks->trigger(HOOK_CACHE_CLEAR, ['cache' => Cache::getInstance()]); $hooks->trigger(HOOK_CACHE_CLEAR, ['cache' => Cache::getInstance()]);

View File

@ -2919,6 +2919,32 @@ class OTS_Player extends OTS_Row_DAO
$this->data['banned'] = $ban['active']; $this->data['banned'] = $ban['active'];
$this->data['banned_time'] = $ban['expires']; $this->data['banned_time'] = $ban['expires'];
} }
public function isNameLocked(): bool
{
// nothing can't be banned
if( !$this->isLoaded() ) {
throw new E_OTS_NotLoaded();
}
if($this->db->hasTable('player_namelocks')) {
$ban = $this->db->query('SELECT 1 FROM `player_namelocks` WHERE `player_id` = ' . $this->data['id'])->fetch(PDO::FETCH_ASSOC);
return (isset($ban['1']));
}
else if($this->db->hasTable('bans')) {
if($this->db->hasColumn('bans', 'active')) {
$ban = $this->db->query('SELECT `active`, `expires` FROM `bans` WHERE `type` = 2 AND `active` = 1 AND `value` = ' . $this->data['id'] . ' AND (`expires` > ' . time() .' OR `expires` = -1) ORDER BY `expires` DESC')->fetch();
return isset($ban['active']);
}
else { // tfs 0.2
$ban = $this->db->query('SELECT `time` FROM `bans` WHERE `type` = 2 AND `account` = ' . $this->data['account_id'] . ' AND (`time` > ' . time() .' OR `time` = -1) ORDER BY `time` DESC')->fetch();
return isset($ban['time']) && ($ban['time'] == -1 || $ban['time'] > 0);
}
}
return false;
}
/** /**
* Deletes player. * Deletes player.
* *
@ -2953,21 +2979,14 @@ class OTS_Player extends OTS_Row_DAO
* @return string Player proffesion name. * @return string Player proffesion name.
* @throws E_OTS_NotLoaded If player is not loaded or global vocations list is not loaded. * @throws E_OTS_NotLoaded If player is not loaded or global vocations list is not loaded.
*/ */
public function getVocationName() public function getVocationName(): string
{ {
if( !isset($this->data['vocation']) ) if( !isset($this->data['vocation']) )
{ {
throw new E_OTS_NotLoaded(); throw new E_OTS_NotLoaded();
} }
global $config; return OTS_Toolbox::getVocationName($this->data['vocation'], $this->data['promotion'] ?? 0);
$voc = $this->getVocation();
if(!isset($config['vocations'][$voc])) {
return 'Unknown';
}
return $config['vocations'][$voc];
//return POT::getInstance()->getVocationsList()->getVocationName($this->data['vocation']);
} }
/** /**

View File

@ -15,7 +15,7 @@
/** /**
* Toolbox for common operations. * Toolbox for common operations.
* *
* @package POT * @package POT
* @version 0.1.5 * @version 0.1.5
*/ */
@ -23,41 +23,41 @@ class OTS_Toolbox
{ {
/** /**
* Calculates experience points needed for given level. * Calculates experience points needed for given level.
* *
* @param int $level Level for which experience should be calculated. * @param int $level Level for which experience should be calculated.
* @param int $experience Current experience points. * @param int $experience Current experience points.
* @return int Experience points for level. * @return int Experience points for level.
*/ */
public static function experienceForLevel($level, $experience = 0) public static function experienceForLevel($level, $experience = 0)
{ {
//return 50 * ($level - 1) * ($level * $level - 5 * $level + 12) / 3 - $experience; //return 50 * ($level - 1) * ($level * $level - 5 * $level + 12) / 3 - $experience;
$level = $level - 1; $level = $level - 1;
return ((50 * $level * $level * $level) - (150 * $level * $level) + (400 * $level)) / 3; return ((50 * $level * $level * $level) - (150 * $level * $level) + (400 * $level)) / 3;
} }
/** /**
* Finds out which level user have basing on his/her experience. * Finds out which level user have basing on his/her experience.
* *
* <p> * <p>
* PHP doesn't support complex numbers natively so solving third-level polynomials would be quite hard. Rather then doing this, this method iterates calculating experience for next levels until it finds one which requires enought experience we have. Because of that, for high experience values this function can take relatively long time to be executed. * PHP doesn't support complex numbers natively so solving third-level polynomials would be quite hard. Rather then doing this, this method iterates calculating experience for next levels until it finds one which requires enought experience we have. Because of that, for high experience values this function can take relatively long time to be executed.
* </p> * </p>
* *
* @param int $experience Current experience points. * @param int $experience Current experience points.
* @return int Experience level. * @return int Experience level.
*/ */
public static function levelForExperience($experience) public static function levelForExperience($experience)
{ {
// default level // default level
$level = 1; $level = 1;
// until we will find level which requires more experience then we have we will step to next // until we will find level which requires more experience then we have we will step to next
while( self::experienceForLevel($level + 1) <= $experience) while( self::experienceForLevel($level + 1) <= $experience)
{ {
$level++; $level++;
} }
return $level; return $level;
} }
/** /**
* @version 0.1.5 * @version 0.1.5
@ -65,25 +65,25 @@ class OTS_Toolbox
* @return OTS_Players_List Filtered list. * @return OTS_Players_List Filtered list.
* @deprecated 0.1.5 Use OTS_PlayerBans_List. * @deprecated 0.1.5 Use OTS_PlayerBans_List.
*/ */
public static function bannedPlayers() public static function bannedPlayers()
{ {
// creates filter // creates filter
$filter = new OTS_SQLFilter(); $filter = new OTS_SQLFilter();
$filter->addFilter( new OTS_SQLField('type', 'bans'), POT::BAN_PLAYER); $filter->addFilter( new OTS_SQLField('type', 'bans'), POT::BAN_PLAYER);
$filter->addFilter( new OTS_SQLField('active', 'bans'), 1); $filter->addFilter( new OTS_SQLField('active', 'bans'), 1);
$filter->addFilter( new OTS_SQLField('value', 'bans'), new OTS_SQLField('id', 'players') ); $filter->addFilter( new OTS_SQLField('value', 'bans'), new OTS_SQLField('id', 'players') );
// selects only active bans // selects only active bans
$actives = new OTS_SQLFilter(); $actives = new OTS_SQLFilter();
$actives->addFilter( new OTS_SQLField('expires', 'bans'), 0); $actives->addFilter( new OTS_SQLField('expires', 'bans'), 0);
$actives->addFilter( new OTS_SQLField('time', 'bans'), time(), OTS_SQLFilter::OPERATOR_GREATER, OTS_SQLFilter::CRITERIUM_OR); $actives->addFilter( new OTS_SQLField('time', 'bans'), time(), OTS_SQLFilter::OPERATOR_GREATER, OTS_SQLFilter::CRITERIUM_OR);
$filter->addFilter($actives); $filter->addFilter($actives);
// creates list and aplies filter // creates list and aplies filter
$list = new OTS_Players_List(); $list = new OTS_Players_List();
$list->setFilter($filter); $list->setFilter($filter);
return $list; return $list;
} }
/** /**
* @version 0.1.5 * @version 0.1.5
@ -91,25 +91,34 @@ class OTS_Toolbox
* @return OTS_Accounts_List Filtered list. * @return OTS_Accounts_List Filtered list.
* @deprecated 0.1.5 Use OTS_AccountBans_List. * @deprecated 0.1.5 Use OTS_AccountBans_List.
*/ */
public static function bannedAccounts() public static function bannedAccounts()
{ {
// creates filter // creates filter
$filter = new OTS_SQLFilter(); $filter = new OTS_SQLFilter();
$filter->addFilter( new OTS_SQLField('type', 'bans'), POT::BAN_ACCOUNT); $filter->addFilter( new OTS_SQLField('type', 'bans'), POT::BAN_ACCOUNT);
$filter->addFilter( new OTS_SQLField('active', 'bans'), 1); $filter->addFilter( new OTS_SQLField('active', 'bans'), 1);
$filter->addFilter( new OTS_SQLField('value', 'bans'), new OTS_SQLField('id', 'accounts') ); $filter->addFilter( new OTS_SQLField('value', 'bans'), new OTS_SQLField('id', 'accounts') );
// selects only active bans // selects only active bans
$actives = new OTS_SQLFilter(); $actives = new OTS_SQLFilter();
$actives->addFilter( new OTS_SQLField('expires', 'bans'), 0); $actives->addFilter( new OTS_SQLField('expires', 'bans'), 0);
$actives->addFilter( new OTS_SQLField('time', 'bans'), time(), OTS_SQLFilter::OPERATOR_GREATER, OTS_SQLFilter::CRITERIUM_OR); $actives->addFilter( new OTS_SQLField('time', 'bans'), time(), OTS_SQLFilter::OPERATOR_GREATER, OTS_SQLFilter::CRITERIUM_OR);
$filter->addFilter($actives); $filter->addFilter($actives);
// creates list and aplies filter // creates list and aplies filter
$list = new OTS_Accounts_List(); $list = new OTS_Accounts_List();
$list->setFilter($filter); $list->setFilter($filter);
return $list; return $list;
} }
public static function getVocationName($id, $promotion = 0): string
{
if($promotion > 0) {
$id = ($id + ($promotion * config('vocations_amount')));
}
return config('vocations')[$id] ?? 'Unknown';
}
} }
/**#@-*/ /**#@-*/

View File

@ -8,7 +8,7 @@
* @link https://my-aac.org * @link https://my-aac.org
*/ */
defined('MYAAC') or die('Direct access not allowed!'); defined('MYAAC') or die('Direct access not allowed!');
$title = '404 Not Found'; $title = 'Not Found';
header('HTTP/1.0 404 Not Found'); header('HTTP/1.0 404 Not Found');
?> ?>

View File

@ -8,7 +8,7 @@
* @link https://my-aac.org * @link https://my-aac.org
*/ */
defined('MYAAC') or die('Direct access not allowed!'); defined('MYAAC') or die('Direct access not allowed!');
$title = '405 Method Not Allowed'; $title = 'Method Not Allowed';
header('HTTP/1.0 405 Method Not Allowed'); header('HTTP/1.0 405 Method Not Allowed');
?> ?>

View File

@ -166,7 +166,7 @@ if(isset($_POST['emailchangecancel']) && $_POST['emailchangecancel'] == 1) {
$account_logged->setCustomField("email_new", ""); $account_logged->setCustomField("email_new", "");
$account_logged->setCustomField("email_new_time", 0); $account_logged->setCustomField("email_new_time", 0);
$custom_buttons = '<div style="text-align:center"><table border="0" cellspacing="0" cellpadding="0" ><form action="' . getLink('account/manage') . '" method="post" ><tr><td style="border:0px;" >' . $twig->render('buttons.back.html.twig') . '</td></tr></form></table></div>'; $custom_buttons = '<div style="text-align:center"><table border="0" cellspacing="0" cellpadding="0" ><form action="' . getLink('account/manage') . '" method="post" >' . csrf(true) . '<tr><td style="border:0px;" >' . $twig->render('buttons.back.html.twig') . '</td></tr></form></table></div>';
$twig->display('success.html.twig', array( $twig->display('success.html.twig', array(
'title' => 'Email Address Change Cancelled', 'title' => 'Email Address Change Cancelled',

View File

@ -36,10 +36,9 @@ if(count($guilds_list) > 0) {
$guildName = $guild->getName(); $guildName = $guild->getName();
$guilds[] = array('name' => $guildName, 'logo' => $guild_logo, 'link' => getGuildLink($guildName, false), 'description' => $description); $guilds[] = array('name' => $guildName, 'logo' => $guild_logo, 'link' => getGuildLink($guildName, false), 'description' => $description);
} }
}; }
$twig->display('guilds.list.html.twig', array( $twig->display('guilds.list.html.twig', array(
'guilds' => $guilds, 'guilds' => $guilds,
'logged' => $logged ?? false,
'isAdmin' => admin(), 'isAdmin' => admin(),
)); ));

View File

@ -22,13 +22,16 @@ $promotion = '';
if($db->hasColumn('players', 'promotion')) if($db->hasColumn('players', 'promotion'))
$promotion = '`promotion`,'; $promotion = '`promotion`,';
$order = $_GET['order'] ?? 'name'; $order = $_GET['order'] ?? 'name_asc';
if(!in_array($order, array('country', 'name', 'level', 'vocation'))) if(!in_array($order, ['country_asc', 'country_desc', 'name_asc', 'name_desc', 'level_asc', 'level_desc', 'vocation_asc', 'vocation_desc'])) {
$order = $db->fieldName('name'); $order = 'name_asc';
else if($order == 'country') }
$order = $db->tableName('accounts') . '.' . $db->fieldName('country'); else if($order == 'vocation_asc' || $order == 'vocation_desc') {
else if($order == 'vocation') $order = $promotion . 'vocation_' . (str_contains($order, 'asc') ? 'asc' : 'desc');
$order = $promotion . 'vocation ASC'; }
$orderExplode = explode('_', $order);
$orderSql = $orderExplode[0] . ' ' . $orderExplode[1];
$skull_type = 'skull'; $skull_type = 'skull';
if($db->hasColumn('players', 'skull_type')) { if($db->hasColumn('players', 'skull_type')) {
@ -58,11 +61,11 @@ if (setting('core.online_vocations')) {
} }
if($db->hasTable('players_online')) // tfs 1.0 if($db->hasTable('players_online')) // tfs 1.0
$playersOnline = $db->query('SELECT `accounts`.`country`, `players`.`name`, `players`.`level`, `players`.`vocation`' . $outfit . ', `' . $skull_time . '` as `skulltime`, `' . $skull_type . '` as `skull` FROM `accounts`, `players`, `players_online` WHERE `players`.`id` = `players_online`.`player_id` AND `accounts`.`id` = `players`.`account_id` ORDER BY ' . $order); $playersOnline = $db->query('SELECT `accounts`.`country`, `players`.`name`, `players`.`level`, `players`.`vocation`' . $outfit . ', `' . $skull_time . '` as `skulltime`, `' . $skull_type . '` as `skull` FROM `accounts`, `players`, `players_online` WHERE `players`.`id` = `players_online`.`player_id` AND `accounts`.`id` = `players`.`account_id` ORDER BY ' . $orderSql);
else else
$playersOnline = $db->query('SELECT `accounts`.`country`, `players`.`name`, `players`.`level`, `players`.`vocation`' . $outfit . ', ' . $promotion . ' `' . $skull_time . '` as `skulltime`, `' . $skull_type . '` as `skull` FROM `accounts`, `players` WHERE `players`.`online` > 0 AND `accounts`.`id` = `players`.`account_id` ORDER BY ' . $order); $playersOnline = $db->query('SELECT `accounts`.`country`, `players`.`name`, `players`.`level`, `players`.`vocation`' . $outfit . ', ' . $promotion . ' `' . $skull_time . '` as `skulltime`, `' . $skull_type . '` as `skull` FROM `accounts`, `players` WHERE `players`.`online` > 0 AND `accounts`.`id` = `players`.`account_id` ORDER BY ' . $orderSql);
$players_data = array(); $players_data = [];
$players = 0; $players = 0;
$data = ''; $data = '';
foreach($playersOnline as $player) { foreach($playersOnline as $player) {
@ -115,7 +118,7 @@ if(count($players_data) > 0) {
} }
if($result) { if($result) {
$record = 'The maximum on this game world was ' . $result['record'] . ' players' . ($timestamp ? ' on ' . date("M d Y, H:i:s", $result['timestamp']) . '.' : '.'); $record = $result['record'] . ' player' . ($result['record'] > 1 ? 's' : '') . ($timestamp ? ' (on ' . date("M d Y, H:i:s", $result['timestamp']) . ')' : '');
} }
} }
} }
@ -124,8 +127,9 @@ $twig->display('online.html.twig', array(
'players' => $players_data, 'players' => $players_data,
'record' => $record, 'record' => $record,
'vocs' => $vocs, 'vocs' => $vocs,
'order' => $order,
)); ));
//search bar //search bar
$twig->display('online.form.html.twig'); $twig->display('characters.form.html.twig');
?> ?>

View File

@ -326,7 +326,9 @@ if (isset($_REQUEST['_page_only'])) {
if(!isset($title)) { if(!isset($title)) {
$title = str_replace('index.php/', '', $page); $title = str_replace('index.php/', '', $page);
$title = ucfirst($title); $title = str_replace(['_', '-', '/'], ' ', $page);
$title = ucwords($title);
} }
if(setting('core.backward_support')) { if(setting('core.backward_support')) {

View File

@ -1062,6 +1062,12 @@ Sent by MyAAC,<br/>
'desc' => 'How often to update highscores from database in minutes. Too low may slow down your website.<br/>0 to disable.', 'desc' => 'How often to update highscores from database in minutes. Too low may slow down your website.<br/>0 to disable.',
'default' => 15, 'default' => 15,
], ],
'highscores_skills_box' => [
'name' => 'Display Skills Box',
'type' => 'boolean',
'desc' => 'show "Choose a skill" box on the highscores (allowing peoples to sort highscores by skill)?',
'default' => true,
],
'highscores_vocation_box' => [ 'highscores_vocation_box' => [
'name' => 'Display Vocation Box', 'name' => 'Display Vocation Box',
'type' => 'boolean', 'type' => 'boolean',
@ -1264,6 +1270,12 @@ Sent by MyAAC,<br/>
'desc' => '', 'desc' => '',
'default' => false, 'default' => false,
], ],
'online_datacenter' => [
'name' => 'Data Center',
'type' => 'text',
'desc' => 'Server Location, will be shown on online page',
'default' => 'Frankfurt - Germany',
],
[ [
'type' => 'section', 'type' => 'section',
'title' => 'Team Page' 'title' => 'Team Page'

View File

@ -0,0 +1,49 @@
<?php
namespace MyAAC\Admin;
use GuzzleHttp\Client;
class Plugins
{
private string $api_base_uri = 'https://plugins.my-aac.org/api/';
public function getLatestVersions(): array
{
$client = new Client([
// Base URI is used with relative requests
'base_uri' => $this->api_base_uri,
// You can set any number of default request options.
'timeout' => 3.0,
]);
$plugins = get_plugins(true);
foreach ($plugins as &$plugin) {
if (str_contains($plugin, 'disabled.')) {
$plugin = str_replace('disabled.', '', $plugin);
}
}
try {
$response = $client->get('get-latest-versions', [
'json' => ['plugins' => $plugins],
]);
}
catch (\Exception $e) {
error('API Error. Please try again later.');
return [];
}
$statusCode = $response->getStatusCode();
if ($statusCode != 200) {
throw new \Exception('Error getting info from plugins repository. Please try again later.');
}
$data = $response->getBody();
return json_decode($data, true);
}
public function setApiBaseUri(string $uri): void {
$this->api_base_uri = $uri;
}
}

View File

@ -17,10 +17,7 @@ class CacheClearCommand extends Command
protected function execute(InputInterface $input, OutputInterface $output): int protected function execute(InputInterface $input, OutputInterface $output): int
{ {
global $hooks; require SYSTEM . 'init.php';
$hooks = new Hooks();
$hooks->load();
$hooks->trigger(HOOK_INIT);
$io = new SymfonyStyle($input, $output); $io = new SymfonyStyle($input, $output);

View File

@ -12,9 +12,10 @@ class MailSendCommand extends Command
{ {
protected function configure(): void protected function configure(): void
{ {
$this->setName('mail:send') $this->setName('email:send')
->setAliases(['mail:send'])
->setDescription('This command sends E-Mail to single user. Message can be provided as follows: ' . PHP_EOL ->setDescription('This command sends E-Mail to single user. Message can be provided as follows: ' . PHP_EOL
. ' echo "Hello World" | php sa email:send --subject="This is the subject" test@test.com') . ' echo "Hello World" | php aac email:send --subject="This is the subject" test@test.com')
->addArgument('recipient', InputArgument::REQUIRED, 'Email, Account Name, Account id or Player Name') ->addArgument('recipient', InputArgument::REQUIRED, 'Email, Account Name, Account id or Player Name')
->addOption('subject', 's', InputOption::VALUE_REQUIRED, 'Subject'); ->addOption('subject', 's', InputOption::VALUE_REQUIRED, 'Subject');
} }

View File

@ -12,7 +12,8 @@ class PluginInstallInstallCommand extends Command
{ {
protected function configure(): void protected function configure(): void
{ {
$this->setName('plugin:install:install') $this->setName('plugin:setup')
->setAliases(['plugin:install:install'])
->setDescription('This command executes the "install" part of the plugin') ->setDescription('This command executes the "install" part of the plugin')
->addArgument('plugin', InputArgument::REQUIRED, 'Plugin name'); ->addArgument('plugin', InputArgument::REQUIRED, 'Plugin name');
} }

View File

@ -532,193 +532,192 @@ class Plugins {
self::$plugin_json = $plugin_json; self::$plugin_json = $plugin_json;
if ($plugin_json == null) { if ($plugin_json == null) {
self::$warnings[] = 'Cannot load ' . $file_name . '. File might be not a valid json code.'; self::$warnings[] = 'Cannot load ' . $file_name . '. File might be not a valid json code.';
return false;
} }
else {
$continue = true;
if(!isset($plugin_json['name']) || empty(trim($plugin_json['name']))) { $continue = true;
self::$error = 'Plugin "name" tag is not set.';
if(!isset($plugin_json['name']) || empty(trim($plugin_json['name']))) {
self::$error = 'Plugin "name" tag is not set.';
return false;
}
if(!isset($plugin_json['version']) || empty(trim($plugin_json['version']))) {
self::$warnings[] = 'Plugin "version" tag is not set.';
}
if(isset($plugin_json['require'])) {
$require = $plugin_json['require'];
$myaac_satified = true;
if(isset($require['myaac_'])) {
$require_myaac = $require['myaac_'];
if(!Semver::satisfies(MYAAC_VERSION, $require_myaac)) {
$myaac_satified = false;
}
}
else if(isset($require['myaac'])) {
$require_myaac = $require['myaac'];
if(version_compare(MYAAC_VERSION, $require_myaac, '<')) {
$myaac_satified = false;
}
}
if(!$myaac_satified) {
self::$error = "Your AAC version doesn't meet the requirement of this plugin. Required version is: " . $require_myaac . ", and you're using version " . MYAAC_VERSION . ".";
return false; return false;
} }
if(!isset($plugin_json['version']) || empty(trim($plugin_json['version']))) { $php_satisfied = true;
self::$warnings[] = 'Plugin "version" tag is not set.'; if(isset($require['php_'])) {
$require_php = $require['php_'];
if(!Semver::satisfies(phpversion(), $require_php)) {
$php_satisfied = false;
}
}
else if(isset($require['php'])) {
$require_php = $require['php'];
if(version_compare(phpversion(), $require_php, '<')) {
$php_satisfied = false;
}
} }
if(isset($plugin_json['require'])) { if(!$php_satisfied) {
$require = $plugin_json['require']; self::$error = "Your PHP version doesn't meet the requirement of this plugin. Required version is: " . $require_php . ", and you're using version " . phpversion() . ".";
$continue = false;
}
$myaac_satified = true; $database_satisfied = true;
if(isset($require['myaac_'])) { if(isset($require['database_'])) {
$require_myaac = $require['myaac_']; $require_database = $require['database_'];
if(!Semver::satisfies(MYAAC_VERSION, $require_myaac)) { if(!Semver::satisfies(DATABASE_VERSION, $require_database)) {
$myaac_satified = false; $database_satisfied = false;
}
}
else if(isset($require['database'])) {
$require_database = $require['database'];
if(version_compare(DATABASE_VERSION, $require_database, '<')) {
$database_satisfied = false;
}
}
if(!$database_satisfied) {
self::$error = "Your database version doesn't meet the requirement of this plugin. Required version is: " . $require_database . ", and you're using version " . DATABASE_VERSION . ".";
$continue = false;
}
if($continue) {
foreach($require as $req => $version) {
$req = strtolower(trim($req));
$version = trim($version);
if(in_array($req, array('myaac', 'myaac_', 'php', 'php_', 'database', 'database_'))) {
continue;
} }
}
else if(isset($require['myaac'])) {
$require_myaac = $require['myaac'];
if(version_compare(MYAAC_VERSION, $require_myaac, '<')) {
$myaac_satified = false;
}
}
if(!$myaac_satified) { if(in_array($req, array('php-ext', 'php-extension'))) { // require php extension
self::$error = "Your AAC version doesn't meet the requirement of this plugin. Required version is: " . $require_myaac . ", and you're using version " . MYAAC_VERSION . "."; $tmpDisplayError = false;
return false; $explode = explode(',', $version);
}
$php_satisfied = true; foreach ($explode as $item) {
if(isset($require['php_'])) { if(!extension_loaded($item)) {
$require_php = $require['php_']; $errors[] = "This plugin requires php extension: " . $item . " to be installed.";
if(!Semver::satisfies(phpversion(), $require_php)) { $tmpDisplayError = true;
$php_satisfied = false; }
}
}
else if(isset($require['php'])) {
$require_php = $require['php'];
if(version_compare(phpversion(), $require_php, '<')) {
$php_satisfied = false;
}
}
if(!$php_satisfied) {
self::$error = "Your PHP version doesn't meet the requirement of this plugin. Required version is: " . $require_php . ", and you're using version " . phpversion() . ".";
$continue = false;
}
$database_satisfied = true;
if(isset($require['database_'])) {
$require_database = $require['database_'];
if(!Semver::satisfies(DATABASE_VERSION, $require_database)) {
$database_satisfied = false;
}
}
else if(isset($require['database'])) {
$require_database = $require['database'];
if(version_compare(DATABASE_VERSION, $require_database, '<')) {
$database_satisfied = false;
}
}
if(!$database_satisfied) {
self::$error = "Your database version doesn't meet the requirement of this plugin. Required version is: " . $require_database . ", and you're using version " . DATABASE_VERSION . ".";
$continue = false;
}
if($continue) {
foreach($require as $req => $version) {
$req = strtolower(trim($req));
$version = trim($version);
if(in_array($req, array('myaac', 'myaac_', 'php', 'php_', 'database', 'database_'))) {
continue;
} }
if(in_array($req, array('php-ext', 'php-extension'))) { // require php extension if ($tmpDisplayError) {
$tmpDisplayError = false; self::$error = implode('<br/>', $errors);
$explode = explode(',', $version);
foreach ($explode as $item) {
if(!extension_loaded($item)) {
$errors[] = "This plugin requires php extension: " . $item . " to be installed.";
$tmpDisplayError = true;
}
}
if ($tmpDisplayError) {
self::$error = implode('<br/>', $errors);
$continue = false;
break;
}
}
else if($req == 'table') {
$tmpDisplayError = false;
$explode = explode(',', $version);
foreach ($explode as $item) {
if(!$db->hasTable($item)) {
$errors[] = "This plugin requires table: " . $item . " to exist in the database.";
$tmpDisplayError = true;
}
}
if ($tmpDisplayError) {
self::$error = implode('<br/>', $errors);
$continue = false;
break;
}
}
else if($req == 'column') {
$tmpDisplayError = false;
$explode = explode(',', $version);
foreach ($explode as $item) {
$tmp = explode('.', $item);
if(count($tmp) == 2) {
if(!$db->hasColumn($tmp[0], $tmp[1])) {
$errors[] = "This plugin requires database column: " . $tmp[0] . "." . $tmp[1] . " to exist in database.";
$tmpDisplayError = true;
}
}
else {
self::$warnings[] = "Invalid plugin require column: " . $item;
}
}
if ($tmpDisplayError) {
self::$error = implode('<br/>', $errors);
$continue = false;
break;
}
}
else if(strpos($req, 'ext-') !== false) {
$tmp = explode('-', $req);
if(count($tmp) == 2) {
if(!extension_loaded($tmp[1]) || !Semver::satisfies(phpversion($tmp[1]), $version)) {
self::$error = "This plugin requires php extension: " . $tmp[1] . ", version " . $version . " to be installed.";
$continue = false;
break;
}
}
}
else if(!self::is_installed($req, $version)) {
self::$error = "This plugin requires another plugin to run correctly. The another plugin is: " . $req . ", with version " . $version . ".";
$continue = false; $continue = false;
break; break;
} }
} }
} else if($req == 'table') {
} $tmpDisplayError = false;
$explode = explode(',', $version);
foreach ($explode as $item) {
if(!$db->hasTable($item)) {
$errors[] = "This plugin requires table: " . $item . " to exist in the database.";
$tmpDisplayError = true;
}
}
if($continue) { if ($tmpDisplayError) {
if(!$zip->extractTo(BASE)) { // "Real" Install self::$error = implode('<br/>', $errors);
self::$error = 'There was a problem with extracting zip archive to base directory.'; $continue = false;
$zip->close(); break;
return false; }
}
$install = $plugin_json['install'] ?? '';
if (self::getAutoLoadOption($plugin_json, 'install', true) && is_file(PLUGINS . $pluginFilename . '/install.php')) {
$install = 'plugins/' . $pluginFilename . '/install.php';
}
if (!empty($install)) {
if (file_exists(BASE . $install)) {
$db->revalidateCache();
require BASE . $install;
$db->revalidateCache();
} }
else { else if($req == 'column') {
self::$warnings[] = 'Cannot load install script. Your plugin might be not working correctly.'; $tmpDisplayError = false;
$explode = explode(',', $version);
foreach ($explode as $item) {
$tmp = explode('.', $item);
if(count($tmp) == 2) {
if(!$db->hasColumn($tmp[0], $tmp[1])) {
$errors[] = "This plugin requires database column: " . $tmp[0] . "." . $tmp[1] . " to exist in database.";
$tmpDisplayError = true;
}
}
else {
self::$warnings[] = "Invalid plugin require column: " . $item;
}
}
if ($tmpDisplayError) {
self::$error = implode('<br/>', $errors);
$continue = false;
break;
}
}
else if(strpos($req, 'ext-') !== false) {
$tmp = explode('-', $req);
if(count($tmp) == 2) {
if(!extension_loaded($tmp[1]) || !Semver::satisfies(phpversion($tmp[1]), $version)) {
self::$error = "This plugin requires php extension: " . $tmp[1] . ", version " . $version . " to be installed.";
$continue = false;
break;
}
}
}
else if(!self::is_installed($req, $version)) {
self::$error = "This plugin requires another plugin to run correctly. The another plugin is: " . $req . ", with version " . $version . ".";
$continue = false;
break;
} }
} }
clearCache();
return true;
} }
} }
return false; if(!$continue) {
return false;
}
if(!$zip->extractTo(BASE)) { // "Real" Install
self::$error = 'There was a problem with extracting zip archive to base directory.';
$zip->close();
return false;
}
$install = $plugin_json['install'] ?? '';
if (self::getAutoLoadOption($plugin_json, 'install', true) && is_file(PLUGINS . $pluginFilename . '/install.php')) {
$install = 'plugins/' . $pluginFilename . '/install.php';
}
if (!empty($install)) {
if (file_exists(BASE . $install)) {
$db->revalidateCache();
require BASE . $install;
$db->revalidateCache();
}
else {
self::$warnings[] = 'Cannot load install script. Your plugin might be not working correctly.';
}
}
clearCache();
return true;
} }
public static function isEnabled($pluginFileName): bool public static function isEnabled($pluginFileName): bool
@ -781,15 +780,20 @@ class Plugins {
return false; return false;
} }
if(!isset($plugin_json['install'])) { $install = $plugin_json['install'] ?? '';
self::$error = "Plugin doesn't have install options defined. Skipping..."; if (self::getAutoLoadOption($plugin_json, 'install', true) && is_file(PLUGINS . $plugin_name . '/install.php')) {
$install = 'plugins/' . $plugin_name . '/install.php';
}
if (empty($install)) {
self::$error = "This plugin doesn't seem to have install script defined.";
return false; return false;
} }
global $db; global $db;
if (file_exists(BASE . $plugin_json['install'])) { if (file_exists(BASE . $install)) {
$db->revalidateCache(); $db->revalidateCache();
require BASE . $plugin_json['install']; require BASE . $install;
$db->revalidateCache(); $db->revalidateCache();
} }
else { else {

View File

@ -54,6 +54,7 @@ define('HOOK_ACCOUNT_MANAGE_BEFORE_GENERAL_INFORMATION', ++$i);
define('HOOK_ACCOUNT_MANAGE_BEFORE_PUBLIC_INFORMATION', ++$i); define('HOOK_ACCOUNT_MANAGE_BEFORE_PUBLIC_INFORMATION', ++$i);
define('HOOK_ACCOUNT_MANAGE_BEFORE_ACCOUNT_LOGS', ++$i); define('HOOK_ACCOUNT_MANAGE_BEFORE_ACCOUNT_LOGS', ++$i);
define('HOOK_ACCOUNT_MANAGE_BEFORE_CHARACTERS', ++$i); define('HOOK_ACCOUNT_MANAGE_BEFORE_CHARACTERS', ++$i);
define('HOOK_ACCOUNT_MANAGE_AFTER_CHARACTERS', ++$i);
define('HOOK_ACCOUNT_LOGIN_BEFORE_PAGE', ++$i); define('HOOK_ACCOUNT_LOGIN_BEFORE_PAGE', ++$i);
define('HOOK_ACCOUNT_LOGIN_BEFORE_ACCOUNT', ++$i); define('HOOK_ACCOUNT_LOGIN_BEFORE_ACCOUNT', ++$i);
define('HOOK_ACCOUNT_LOGIN_AFTER_ACCOUNT', ++$i); define('HOOK_ACCOUNT_LOGIN_AFTER_ACCOUNT', ++$i);
@ -92,6 +93,7 @@ define('HOOK_EMAIL_CONFIRMED', ++$i);
define('HOOK_GUILDS_BEFORE_GUILD_HEADER', ++$i); define('HOOK_GUILDS_BEFORE_GUILD_HEADER', ++$i);
define('HOOK_GUILDS_AFTER_GUILD_HEADER', ++$i); define('HOOK_GUILDS_AFTER_GUILD_HEADER', ++$i);
define('HOOK_GUILDS_AFTER_GUILD_INFORMATION', ++$i); define('HOOK_GUILDS_AFTER_GUILD_INFORMATION', ++$i);
define('HOOK_GUILDS_AFTER_MANAGE_BUTTON', ++$i);
define('HOOK_GUILDS_AFTER_GUILD_MEMBERS', ++$i); define('HOOK_GUILDS_AFTER_GUILD_MEMBERS', ++$i);
define('HOOK_GUILDS_AFTER_INVITED_CHARACTERS', ++$i); define('HOOK_GUILDS_AFTER_INVITED_CHARACTERS', ++$i);
define('HOOK_TWIG', ++$i); define('HOOK_TWIG', ++$i);

View File

@ -91,7 +91,7 @@ else {
$file = BASE . $template_path . '/layout_config.ini'; $file = BASE . $template_path . '/layout_config.ini';
} }
$template_ini = parse_ini_file($file); $template_ini = parse_ini_file($file, true);
unset($file); unset($file);
if ($cache->enabled()) { if ($cache->enabled()) {

View File

@ -28,7 +28,7 @@ Please enter your password and the new email address. Make sure that you enter a
<td> <td>
<table border="0" cellspacing="0" cellpadding="0"> <table border="0" cellspacing="0" cellpadding="0">
<tr> <tr>
<td style="border:0px;"> <td style="border:0;">
<form id="form" action="{{ getLink('account/change-email') }}" method="post"> <form id="form" action="{{ getLink('account/change-email') }}" method="post">
{{ csrf() }} {{ csrf() }}
<input type="hidden" name="changeemailsave" value="1"/> <input type="hidden" name="changeemailsave" value="1"/>
@ -40,14 +40,14 @@ Please enter your password and the new email address. Make sure that you enter a
</td> </td>
<td> <td>
<table border="0" cellspacing="0" cellpadding="0"> <table border="0" cellspacing="0" cellpadding="0">
<form action="{{ getLink('account/manage') }}" method="post"> <tr>
{{ csrf() }} <td style="border:0;">
<tr> <form action="{{ getLink('account/manage') }}" method="post">
<td style="border:0px;"> {{ csrf() }}
{{ include('buttons.back.html.twig') }} {{ include('buttons.back.html.twig') }}
</td> </form>
</tr> </td>
</form> </tr>
</table> </table>
</td> </td>
</tr> </tr>

View File

@ -88,7 +88,7 @@ If you do not want to specify a certain field, just leave it blank.<br/><br/>
<td> <td>
<table border="0" cellspacing="0" cellpadding="0"> <table border="0" cellspacing="0" cellpadding="0">
<tr> <tr>
<td style="border:0px;"> <td style="border:0;">
<input type="hidden" name="name" value="{{ player.name }}"> <input type="hidden" name="name" value="{{ player.name }}">
<input type="hidden" name="changecommentsave" value="1"> <input type="hidden" name="changecommentsave" value="1">
{{ include('buttons.submit.html.twig') }} {{ include('buttons.submit.html.twig') }}
@ -99,15 +99,15 @@ If you do not want to specify a certain field, just leave it blank.<br/><br/>
</td> </td>
<td> <td>
<table border="0" cellspacing="0" cellpadding="0"> <table border="0" cellspacing="0" cellpadding="0">
<form action="{{ getLink('account/manage') }}" method="post"> <tr>
{{ csrf() }} <td style="border:0;">
<tr> <form action="{{ getLink('account/manage') }}" method="post">
<td style="border:0px;"> {{ csrf() }}
{{ include('buttons.back.html.twig') }} {{ include('buttons.back.html.twig') }}
</td> </form>
</tr> </td>
</form> </tr>
</table> </table>
</td> </td>
</tr> </tr>
</table> </table>

View File

@ -24,7 +24,7 @@ To delete a character enter the name of the character and your password.<br/><br
<td> <td>
<table border="0" cellspacing="0" cellpadding="0"> <table border="0" cellspacing="0" cellpadding="0">
<tr> <tr>
<td style="border:0px;"> <td style="border:0;">
<form id="form" action="{{ getLink('account/characters/delete') }}" method="post"> <form id="form" action="{{ getLink('account/characters/delete') }}" method="post">
{{ csrf() }} {{ csrf() }}
<input type="hidden" name="deletecharactersave" value="1"/> <input type="hidden" name="deletecharactersave" value="1"/>
@ -36,14 +36,14 @@ To delete a character enter the name of the character and your password.<br/><br
</td> </td>
<td> <td>
<table border="0" cellspacing="0" cellpadding="0"> <table border="0" cellspacing="0" cellpadding="0">
<form action="{{ getLink('account/manage') }}" method="post"> <tr>
{{ csrf() }} <td style="border:0;">
<tr> <form action="{{ getLink('account/manage') }}" method="post">
<td style="border:0px;"> {{ csrf() }}
{{ include('buttons.back.html.twig') }} {{ include('buttons.back.html.twig') }}
</td> </form>
</tr> </td>
</form> </tr>
</table> </table>
</td> </td>
</tr> </tr>

View File

@ -228,5 +228,7 @@
</td> </td>
</tr> </tr>
</table> </table>
<br/>
{{ hook('HOOK_ACCOUNT_MANAGE_AFTER_CHARACTERS') }}
</div> </div>
</div> </div>

View File

@ -1,7 +1,9 @@
<div id="install_plugin"> <div id="install_plugin">
<div class="card card-info card-outline"> <div class="card card-info card-outline">
<div class="card-header"> <div class="card-header">
<h5 class="m-0">Install plugin</h5> <h5 class="m-0">Install plugin
<a href="?p=plugins&check-updates" class="btn btn-primary float-right">Check for updates</a>
</h5>
</div> </div>
<form enctype="multipart/form-data" method="post" action="{{ constant('ADMIN_URL') }}?p=plugins"> <form enctype="multipart/form-data" method="post" action="{{ constant('ADMIN_URL') }}?p=plugins">
{{ csrf() }} {{ csrf() }}

View File

@ -0,0 +1,18 @@
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Plugin Name</th>
<th>Your Version</th>
<th>Latest Version</th>
<th>Download Link</th>
</tr>
</thead>
{% for plugin in plugins %}
<tr>
<td>{{ plugin.name }}</td>
<td>{{ plugin.yourVersion }}</td>
<td>{{ plugin.latestVersion }}</td>
<td><a href="{{ plugin.download_link }}" target="_blank">{{ plugin.download_link }}</a></td>
</tr>
{% endfor %}
</table>

View File

@ -1,17 +1,23 @@
<form action="{{ link }}" method="post"> <br/>
<table width="100%" border="0" cellspacing="1" cellpadding="4"> <form action="{{ getLink('characters') }}" method="post">
<tr><td bgcolor="{{ config.vdarkborder }}" class="white"><B>Search Character</B></TD></TR> {% set title = 'Search Character' %}
<tr> {% set tableClass = 'Table1' %}
<td bgcolor="{{ config.darkborder }}"> {% set background = config('darkborder') %}
<table border="0" cellpadding="1"> {% set content %}
<tr> <table width="100%">
<td>Name:</td><td><input name="name" value="" size="29" maxlength="29"{% if autofocus %} autofocus{% endif %}></TD> <tr>
<td> <td style="vertical-align:middle" class="LabelV150">
{{ include('buttons.submit.html.twig') }} Character Name:
</td> </td>
</tr> <td style="width:170px">
</table> <input style="width:165px" name="name" value="" size="29" maxlength="29"/>
</td> </td>
</tr> <td>
</table> {% set button_name = 'Submit' %}
</form> {{ include('buttons.base.html.twig') }}
</td>
</tr>
</table>
{% endset %}
{{ include('tables.headline.html.twig') }}
</form>

View File

@ -49,6 +49,7 @@
{% include('buttons.base.html.twig') %} {% include('buttons.base.html.twig') %}
</a> </a>
{% endif %} {% endif %}
{{ hook('HOOK_GUILDS_AFTER_MANAGE_BUTTON') }}
</div> </div>
</td> </td>
</tr> </tr>
@ -61,6 +62,7 @@
{{ hook('HOOK_GUILDS_AFTER_GUILD_INFORMATION') }} {{ hook('HOOK_GUILDS_AFTER_GUILD_INFORMATION') }}
{% set title = 'Guild Members' %} {% set title = 'Guild Members' %}
{% set background = config('lightborder') %}
{% set content %} {% set content %}
<table style="width:100%;"> <table style="width:100%;">
<tbody> <tbody>
@ -151,6 +153,7 @@
{{ hook('HOOK_GUILDS_AFTER_GUILD_MEMBERS') }} {{ hook('HOOK_GUILDS_AFTER_GUILD_MEMBERS') }}
{% set title = 'Invited Characters' %} {% set title = 'Invited Characters' %}
{% set background = config('lightborder') %}
{% set content %} {% set content %}
<table style="width:100%;"> <table style="width:100%;">
<tbody> <tbody>

View File

@ -94,8 +94,10 @@
{% endif %} {% endif %}
</table> </table>
</td> </td>
{% if setting('core.highscores_skills_box') or setting('core.highscores_vocation_box') %}
<td width="5%"></td> <td width="5%"></td>
<td width="15%" valign="top" align="right"> <td width="15%" valign="top" align="right">
{% if setting('core.highscores_skills_box') %}
<table style="border: 0; width: 100%" cellpadding="4" cellspacing="1"> <table style="border: 0; width: 100%" cellpadding="4" cellspacing="1">
<tr bgcolor="{{ config.vdarkborder }}"> <tr bgcolor="{{ config.vdarkborder }}">
<td class="white"><B>Choose a skill</B></TD> <td class="white"><B>Choose a skill</B></TD>
@ -109,7 +111,8 @@
</tr> </tr>
</table> </table>
<br/> <br/>
{% if config.highscores_vocation_box %} {% endif %}
{% if setting('core.highscores_vocation_box') %}
<table border="0" width="100%" cellpadding="4" cellspacing="1"> <table border="0" width="100%" cellpadding="4" cellspacing="1">
<tr bgcolor="{{ config.vdarkborder }}"> <tr bgcolor="{{ config.vdarkborder }}">
<td class="white"><b>Choose a vocation</b></td> <td class="white"><b>Choose a vocation</b></td>
@ -126,5 +129,6 @@
{% endif %} {% endif %}
</td> </td>
<td style="width: 18px"></td> <td style="width: 18px"></td>
{% endif %}
</tr> </tr>
</table> </table>

View File

@ -1,25 +0,0 @@
<br/>
<form action="{{ getLink('characters') }}" method=post>
<table width="100%" border="0" cellspacing="1" cellpadding="4">
<tr>
<td bgcolor="{{ config.vdarkborder }}" class="white">
<b>Search Character</b>
</td>
</tr>
<tr>
<td bgcolor="{{ config.darkborder }}">
<table border="0" cellpadding="1">
<tr>
<td>Name:</td>
<td>
<input name="name" value=""size=29 maxlength=29>
</td>
<td>
{{ include('buttons.submit.html.twig') }}
</td>
</tr>
</table>
</td>
</tr>
</table>
</form>

View File

@ -1,39 +1,7 @@
<table border="0" cellspacing="1" cellpadding="4" width="100%"> {# vocation statistics #}
<tr bgcolor="{{ config.vdarkborder }}"> {% if setting('core.online_vocations') %}
<td class="white"><b>Server Status</b></td>
</tr>
{% if players|length == 0 %}
<tr bgcolor="{{ config.darkborder }}"><td>Currently no one is playing on {{ config.lua.serverName }}.</td></tr></table>
{% else %}
<tr bgcolor="{{ config.darkborder }}">
<td>
{% if not status.online %}
Server is offline.<br/>
{% else %}
{% if setting('core.online_afk') %}
{% set players_count = players|length %}
{% set afk = players_count - status.players %}
{% if afk < 0 %}
{% set players_count = players_count + afk|abs %}
{% set afk = 0 %}
{% endif %}
Currently there are <b>{{ status.players }}</b> active and <b>{{ afk }}</b> AFK players.<br/>
Total number of players: <b>{{ players_count }}</b>.<br/>
{% else %}
Currently {{ players|length }} players are online.<br/>
{% endif %}
{% endif %}
{% if setting('core.online_record') %}
{{ record }}
{% endif %}
</td>
</tr>
</table>
<br/> <br/>
{# vocation statistics #} {% if setting('core.online_vocations_images') %}
{% if setting('core.online_vocations') %}
<br/>
{% if setting('core.online_vocations_images') %}
<table width="200" cellspacing="1" cellpadding="0" border="0" align="center"> <table width="200" cellspacing="1" cellpadding="0" border="0" align="center">
<tr bgcolor="{{ config.darkborder }}"> <tr bgcolor="{{ config.darkborder }}">
<td><img src="images/sorcerer.png" /></td> <td><img src="images/sorcerer.png" /></td>
@ -69,11 +37,13 @@
{% endfor %} {% endfor %}
</table> </table>
<br/> <br/>
{% endif %}
{% endif %} {% endif %}
{% endif %}
{# show skulls #} <br/>
{% if setting('core.online_skulls') %}
{# show skulls #}
{% if setting('core.online_skulls') %}
<table width="100%" cellspacing="1"> <table width="100%" cellspacing="1">
<tr> <tr>
<td style="background: {{ config.darkborder }};" align="center"> <td style="background: {{ config.darkborder }};" align="center">
@ -83,34 +53,114 @@
</td> </td>
</tr> </tr>
</table> </table>
{% endif %}
<br/>
{% set title = 'World Information' %}
{% set tableClass = 'Table3' %}
{% set background = config('darkborder') %}
{% set content %}
<table width="100%">
<tr>
<td class="LabelV150"><b>Status:</b></td>
<td>{% if not status.online %}Offline{% else %}Online{% endif %}</td>
</tr>
<tr>
<td class="LabelV150"><b>Players Online:</b></td>
<td>
{% if setting('core.online_afk') %}
{% set players_count = players|length %}
{% set afk = players_count - status.players %}
{% if afk < 0 %}
{% set players_count = players_count + afk|abs %}
{% set afk = 0 %}
{% endif %}
Currently there are <b>{{ status.players }}</b> active and <b>{{ afk }}</b> AFK players.<br/>
Total number of players: <b>{{ players_count }}</b>.<br/>
{% else %}
{{ players|length }}
{% endif %}
</td>
</tr>
{% if setting('core.online_record') %}
<tr>
<td class="LabelV150"><b>Online Record:</b></td>
<td>
{{ record }}
</td>
</tr>
{% endif %} {% endif %}
<table border="0" cellspacing="1" cellpadding="4" width="100%"> <tr>
<tr bgcolor="{{ config.vdarkborder }}"> <td class="LabelV150"><b>Location Datacenter:</b></td>
<td>{{ setting('core.online_datacenter') }} <small>(Server date & time: - {{ "now"|date("d/m/Y H:i:s") }})</small></td>
</tr>
<tr>
<td class="LabelV150"><b>PvP Type:</b></td>
<td>
{% set worldType = config('lua')['worldType']|lower %}
{% if worldType in ['pvp','2','normal','open','openpvp'] %}
Open PvP
{% elseif worldType in ['no-pvp','nopvp','non-pvp','nonpvp','1','safe','optional','optionalpvp'] %}
Optional PvP
{% elseif worldType in ['pvp-enforced','pvpenforced','pvp-enfo','pvpenfo','pvpe','enforced','enfo','3','war','hardcore','hardcorepvp'] %}
Hardcore PvP
{% endif %}
</td>
</tr>
</table>
{% endset %}
{% include 'tables.headline.html.twig' %}
<br/>
<br/>
{% set title = 'Players Online' %}
{% set tableClass = 'Table2' %}
{% set content %}
<table width="100%">
<tr class="LabelH" style="position: relative; z-index: 20;">
{% if setting('core.account_country') %} {% if setting('core.account_country') %}
<td width="11px"><a href="{{ getLink('online?order=country') }}" class="white">#</A></td> <td width="11px"><a href="{{ getLink('online')}}?order=country_{{ order == 'country_asc' ? 'desc' : 'asc' }}">#&#160;&#160;</a>
</td>
{% endif %} {% endif %}
{% if setting('core.online_outfit') %} {% if setting('core.online_outfit') %}
<td class="white"><b>Outfit</b></td> <td><b>Outfit</b></td>
{% endif %} {% endif %}
<td width="60%"><a href="{{ getLink('online?order=name') }}" class="white">Name</A></td> <td style="text-align:left; width:50%">Name&#160;&#160;
<td width="20%"><a href="{{ getLink('online?order=level') }}" class="white">Level</A></td> <small style="font-weight:normal">[<a href="{{ getLink('online')}}?order=name_{{ order == 'name_asc' ? 'desc' : 'asc' }}">sort</a>]</small>
<td width="20%"><a href="{{ getLink('online?order=vocation') }}" class="white">Vocation</td> <img class="sortarrow" src="images/{{ order == 'name_asc' ? 'order_desc' : (order == 'name_desc' ? 'order_asc' : 'news/blank') }}.gif"/></td>
<td style="text-align:left;width:30%">Level&#160;&#160;
<small style="font-weight:normal">[<a href="{{ getLink('online')}}?order=level_{{ order == 'level_asc' ? 'desc' : 'asc' }}">sort</a>]</small>
<img class="sortarrow" src="images/{{ order == 'level_asc' ? 'order_desc' : (order == 'level_desc' ? 'order_asc' : 'news/blank') }}.gif"/>
</td>
<td style="text-align:left;width:50%">Vocation&#160;&#160;
<small style="font-weight:normal">[<a href="{{ getLink('online')}}?order=vocation_{{ order == 'vocation_asc' ? 'desc' : 'asc' }}">sort</a>]</small>
<img class="sortarrow" src="images/{{ order == 'vocation_asc' ? 'order_desc' : (order == 'vocation_desc' ? 'order_asc' : 'news/blank') }}.gif"/>
</td>
</tr> </tr>
{% set i = 0 %} {% set i = 0 %}
{% for player in players %} {% for player in players %}
{% set i = i + 1 %} {% set i = i + 1 %}
<tr bgcolor="{{ getStyle(i) }}">
{% if setting('core.account_country') %} <tr style="background: {{ getStyle(i) }}; text-align: right; height: 40px;">
<td>{{ player.country_image|raw }}</td> {% if setting('core.account_country') %}
{% endif %} <td>{{ player.country_image|raw }}</td>
{% if setting('core.online_outfit') %} {% endif %}
<td width="5%"><img style="position:absolute;margin-top:{% if player.player.looktype in setting('core.outfit_images_wrong_looktypes') %}-20px;margin-left:-0px;{% else %}-45px;margin-left:-25px;{% endif %}" src="{{ player.outfit }}" alt="player outfit"/></td>
{% endif %} {% if setting('core.online_outfit') %}
<td>{{ player.name|raw }}{{ player.skull }}</td> <td width="5%"><img style="position:absolute;margin-top:-48px;margin-left:-70px;" src="{{ player.outfit }}" alt="player outfit"/></td>
<td>{{ player.level }}</td> {% endif %}
<td>{{ player.vocation }}</td>
<td style="width:70%; text-align:left">
{{ player.name|raw }}{{ player.skull }}
</td>
<td style="width:10%">{{ player.level }}</td>
<td style="width:20%">{{ player.vocation }}</td>
</tr> </tr>
{% endfor %} {% endfor %}
</table> </table>
{% endif %} {% endset %}
{{ include('tables.headline.html.twig') }}

View File

@ -18,13 +18,14 @@
{% else %} {% else %}
<div style="text-align:center"> <div style="text-align:center">
<table border="0" cellspacing="0" cellpadding="0"> <table border="0" cellspacing="0" cellpadding="0">
<form action="{{ getLink('account/manage') }}" method="post"> <tr>
<tr> <td style="border:0;">
<td style="border:0px;"> <form action="{{ getLink('account/manage') }}" method="post">
{{ csrf() }}
{{ include('buttons.back.html.twig') }} {{ include('buttons.back.html.twig') }}
</td> </form>
</tr> </td>
</form> </tr>
</table> </table>
</div> </div>
{% endif %} {% endif %}

View File

@ -453,6 +453,27 @@ a:hover
white-space: nowrap; white-space: nowrap;
vertical-align: top; vertical-align: top;
} }
.LabelV120 {
font-weight: bold;
padding-right: 10px;
white-space: nowrap;
vertical-align: top;
width: 120px;
}
.LabelV150 {
font-weight: bold;
padding-right: 10px;
white-space: nowrap;
vertical-align: top;
width: 150px;
}
.LabelV200 {
font-weight: bold;
padding-right: 10px;
white-space: nowrap;
vertical-align: top;
width: 200px;
}
.LabelH { .LabelH {
font-weight: bold; font-weight: bold;
padding-right: 10px; padding-right: 10px;

View File

@ -463,4 +463,7 @@
</table> </table>
{% endset %} {% endset %}
{% include 'tables.headline.html.twig' %} {% include 'tables.headline.html.twig' %}
<br/><br/> <br/>
{{ hook('HOOK_ACCOUNT_MANAGE_AFTER_CHARACTERS') }}
<br/>

View File

@ -1446,6 +1446,27 @@ img {
white-space: nowrap; white-space: nowrap;
vertical-align: top; vertical-align: top;
} }
.LabelV120 {
font-weight: bold;
padding-right: 10px;
white-space: nowrap;
vertical-align: top;
width: 120px;
}
.LabelV150 {
font-weight: bold;
padding-right: 10px;
white-space: nowrap;
vertical-align: top;
width: 150px;
}
.LabelV200 {
font-weight: bold;
padding-right: 10px;
white-space: nowrap;
vertical-align: top;
width: 200px;
}
.LabelH { .LabelH {
font-weight: bold; font-weight: bold;
padding-right: 10px; padding-right: 10px;

View File

@ -1,6 +1,6 @@
<div id="CurrentPollBox" class="Themebox" style="background-image:url({{ template_path }}/images/themeboxes/current-poll/currentpollbox.gif);"> <div id="CurrentPollBox" class="Themebox" style="background-image:url({{ template_path }}/images/themeboxes/current-poll/currentpollbox.gif);">
<div id="CurrentPollText">{{ poll.question }}</div> <div id="CurrentPollText">{{ poll.question }}</div>
<a class="ThemeboxButton" href="{{ getLink('polls') }}/{{ poll.id }}" onMouseOver="MouseOverBigButton(this);" onMouseOut="MouseOutBigButton(this);" style="background-image:url({{ template_path }}/images/global/buttons/sbutton.gif);"><div class="BigButtonOver" style="background-image:url({{ template_path }}/images/global/buttons/sbutton_over.gif);"></div><div class="ButtonText" style="background-image:url({{ template_path }}/images/global/buttons/_sbutton_votenow.gif);"></div> <a class="ThemeboxButton" href="{{ getLink('polls') }}?ìd={{ poll.id }}" onMouseOver="MouseOverBigButton(this);" onMouseOut="MouseOutBigButton(this);" style="background-image:url({{ template_path }}/images/global/buttons/sbutton.gif);"><div class="BigButtonOver" style="background-image:url({{ template_path }}/images/global/buttons/sbutton_over.gif);"></div><div class="ButtonText" style="background-image:url({{ template_path }}/images/global/buttons/_sbutton_votenow.gif);"></div>
</a> </a>
<div class="Bottom" style="background-image:url({{ template_path }}/images/general/box-bottom.gif);"></div> <div class="Bottom" style="background-image:url({{ template_path }}/images/general/box-bottom.gif);"></div>
</div> </div>

View File

@ -454,7 +454,7 @@ foreach($config['menu_categories'] as $id => $cat) {
foreach($config['boxes'] as $box) { foreach($config['boxes'] as $box) {
/** @var string $template_name */ /** @var string $template_name */
$file = TEMPLATES . $template_name . '/boxes/' . $box . '.php'; $file = __DIR__ . '/boxes/' . $box . '.php';
if(file_exists($file)) { if(file_exists($file)) {
include($file); ?> include($file); ?>
<?php <?php

View File

@ -35,6 +35,7 @@
<tr> <tr>
<td style="border:0;"> <td style="border:0;">
<form action="{{ getLink('account/manage') }}" method="post"> <form action="{{ getLink('account/manage') }}" method="post">
{{ csrf() }}
{{ include('buttons.back.html.twig') }} {{ include('buttons.back.html.twig') }}
</form> </form>
</td> </td>