Compare commits
86 Commits
v1.8.5
...
feature/ot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1c039c50b8 | ||
|
|
1faba9ed52 | ||
|
|
8b4d4fc627 | ||
|
|
0c4edf625c | ||
|
|
fcdd6debae | ||
|
|
57d4111ad8 | ||
|
|
c28dc29391 | ||
|
|
975accd794 | ||
|
|
2db4f6a57b | ||
|
|
9bfd0242af | ||
|
|
3ea2b68561 | ||
|
|
dcdaa5ef43 | ||
|
|
7289cce826 | ||
|
|
af9d4c2aeb | ||
|
|
a66edfad31 | ||
|
|
89a35b5335 | ||
|
|
3d6e4c074a | ||
|
|
55da00520d | ||
|
|
efef16ee86 | ||
|
|
2f0b67f840 | ||
|
|
c65d4e4b62 | ||
|
|
fec3f3d297 | ||
|
|
7e6480b380 | ||
|
|
7c9c8d2990 | ||
|
|
ca2e3bb576 | ||
|
|
2d8d35f5c8 | ||
|
|
aba50ca0f1 | ||
|
|
0110bf6ea2 | ||
|
|
ba1c63921d | ||
|
|
5c68fba82a | ||
|
|
18c0212f9a | ||
|
|
e0e0e46701 | ||
|
|
61bcdc0c37 | ||
|
|
6f87d8b322 | ||
|
|
cc220bedc1 | ||
|
|
f966dff5a8 | ||
|
|
402f3bb9b0 | ||
|
|
e98de451d8 | ||
|
|
8ec9bf1068 | ||
|
|
4fffaf6aff | ||
|
|
c44c9f9cf4 | ||
|
|
ccfd6f1a87 | ||
|
|
96b8e00f49 | ||
|
|
11cb1cf97e | ||
|
|
78a3535b6a | ||
|
|
497959fd30 | ||
|
|
6ba00eea96 | ||
|
|
c5d3d3a25f | ||
|
|
9ed06782e6 | ||
|
|
18a1178e4b | ||
|
|
c86257e6da | ||
|
|
fd74f01291 | ||
|
|
3011b969a4 | ||
|
|
8e6749c599 | ||
|
|
e1197515f3 | ||
|
|
ae5df2b704 | ||
|
|
eebfc600cb | ||
|
|
9aaa630976 | ||
|
|
9a99018dce | ||
|
|
6479546c22 | ||
|
|
effb23f367 | ||
|
|
08657c1599 | ||
|
|
1379c93439 | ||
|
|
19b1cfdd34 | ||
|
|
e719725841 | ||
|
|
bb3e90110d | ||
|
|
2f0758e351 | ||
|
|
6667c8c364 | ||
|
|
c13a540878 | ||
|
|
869ec035d9 | ||
|
|
9d696d31d8 | ||
|
|
8cc4caf587 | ||
|
|
e1d1c7d5db | ||
|
|
320733c2c1 | ||
|
|
c1809a98d1 | ||
|
|
46ed541015 | ||
|
|
29207361b7 | ||
|
|
25013ae91b | ||
|
|
5d630ba9dd | ||
|
|
feadf1314d | ||
|
|
08b8a716d4 | ||
|
|
cc26b5c744 | ||
|
|
cb6e9a6a88 | ||
|
|
4adb0758c5 | ||
|
|
7312383f73 | ||
|
|
3c1210fefa |
6
.github/workflows/cypress.yml
vendored
@@ -1,9 +1,9 @@
|
||||
name: Cypress
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
branches: [develop]
|
||||
push:
|
||||
branches: [main]
|
||||
branches: [develop]
|
||||
|
||||
jobs:
|
||||
cypress:
|
||||
@@ -22,7 +22,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
php-versions: [ '8.1', '8.2', '8.3', '8.4' ]
|
||||
php-versions: [ '8.1', '8.2', '8.3', '8.4', '8.5' ]
|
||||
ots: ['tfs-1.4', 'canary-3.1.2'] # TODO: add 'tfs-master' (actually doesn't work cause AAC doesn't support reading .env configuration)
|
||||
name: Cypress (PHP ${{ matrix.php-versions }}, ${{ matrix.ots }})
|
||||
steps:
|
||||
|
||||
4
.github/workflows/phplint.yml
vendored
@@ -1,9 +1,9 @@
|
||||
name: PHP Linting
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
branches: [develop]
|
||||
push:
|
||||
branches: [main]
|
||||
branches: [develop]
|
||||
|
||||
jobs:
|
||||
phplint:
|
||||
|
||||
4
.github/workflows/phpstan.yml
vendored
@@ -2,9 +2,9 @@ name: "PHPStan"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
branches: [develop]
|
||||
push:
|
||||
branches: [main]
|
||||
branches: [develop]
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
|
||||
@@ -1,5 +1,30 @@
|
||||
# Changelog
|
||||
|
||||
## [1.8.7 - 04.01.2026]
|
||||
|
||||
### Fixed
|
||||
* Fixed [player/guild/house] bb code in forum (https://github.com/slawkens/myaac/commit/8ec9bf10682c73f1fe40967a106ccda2a5073ed0)
|
||||
|
||||
### Changed
|
||||
* Settings: better responsiveness on mobile (https://github.com/slawkens/myaac/commit/c65d4e4b62ef26fb4e24ecb1d2bcc4556d746adf)
|
||||
* Signatures: Return 404 when the signature player is not found (https://github.com/slawkens/myaac/commit/7e6480b380799add7a2b1b7ce1d3c1f2b6819ff1)
|
||||
|
||||
### Removed
|
||||
* Remove setting: outfit_images_wrong_looktypes - is obsolete, the bug doesn't exist in the latest outfit images (https://github.com/slawkens/myaac/commit/cc220bedc1f01535eaac23f6961135e2e7a6e310)
|
||||
|
||||
## [1.8.6 - 14.12.2025]
|
||||
|
||||
### Added
|
||||
* Added hook for adding custom rules to validate new character name (https://github.com/slawkens/myaac/commit/8e6749c59984631288e8e9803819b2f0ff389761)
|
||||
|
||||
### Fixed
|
||||
* Highscores: Fix ordering by different skills (Adjust order by desc: skill_tries, manaspent, experience) - More exact results (https://github.com/slawkens/myaac/commit/c86257e6dacbad773aa09c0958eeaa106a967f2d)
|
||||
* Fix exception shown on first install, when there is no vendor - Before it displayed 500 white page, now it display the exception (https://github.com/slawkens/myaac/commit/18a1178e4b93607a350259679e0366cb83fb4126)
|
||||
* Fix typo $up -> $down, in migration nr 7, was failing due that (https://github.com/slawkens/myaac/commit/fd74f01291d0e9cdb92ee1b95021c9d7b591ad7c)
|
||||
|
||||
### Changed
|
||||
* Ini set html_errors = 0, to show html code in exceptions (https://github.com/slawkens/myaac/commit/9ed06782e67772826d927ad847a077b99df5060d)
|
||||
|
||||
## [1.8.5 - 21.11.2025]
|
||||
|
||||
### Added
|
||||
|
||||
12
CHANGELOG-2.x.md
Normal file
@@ -0,0 +1,12 @@
|
||||
## [2.0-dev - x.x.2025]
|
||||
|
||||
### Added
|
||||
* Add an "access" option to Menus (#340)
|
||||
* Possibility to hide menus for unauthorized users
|
||||
* Add the possibility to fetch skills in the getTopPlayers function
|
||||
|
||||
### Changed
|
||||
* Better handling of vocations: (#345)
|
||||
* Load from vocations.xml (No need to manually set)
|
||||
* Support for Monk vocation
|
||||
* Reworked account action logs to use a single IP column as varchar(45) for both ipv4 and ipv6 (#289)
|
||||
@@ -9,6 +9,7 @@
|
||||
*/
|
||||
|
||||
use MyAAC\Models\Account as AccountModel;
|
||||
use MyAAC\Models\AccountAction;
|
||||
use MyAAC\Models\Player;
|
||||
|
||||
defined('MYAAC') or die('Direct access not allowed!');
|
||||
@@ -481,9 +482,8 @@ else if (isset($_REQUEST['search'])) {
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
$accountActions = \MyAAC\Models\AccountAction::where('account_id', $account->getId())->orderByDesc('date')->get();
|
||||
$accountActions = AccountAction::where('account_id', $account->getId())->orderByDesc('date')->get();
|
||||
foreach ($accountActions as $i => $log):
|
||||
$log->ip = ($log->ip != 0 ? long2ip($log->ip) : inet_ntop($log->ipv6));
|
||||
?>
|
||||
<tr>
|
||||
<td><?php echo $i + 1; ?></td>
|
||||
|
||||
@@ -23,6 +23,7 @@ if (!hasFlag(FLAG_CONTENT_MENUS) && !superAdmin()) {
|
||||
}
|
||||
|
||||
$pluginThemes = Plugins::getThemes();
|
||||
$groups = new OTS_Groups_List();
|
||||
|
||||
if (isset($_POST['template'])) {
|
||||
$template = $_POST['template'];
|
||||
@@ -32,6 +33,8 @@ if (isset($_POST['template'])) {
|
||||
$post_menu_link = $_POST['menu_link'] ?? [];
|
||||
$post_menu_blank = $_POST['menu_blank'] ?? [];
|
||||
$post_menu_color = $_POST['menu_color'] ?? [];
|
||||
$post_menu_access = $_POST['menu_access'] ?? [];
|
||||
|
||||
if (count($post_menu) != count($post_menu_link)) {
|
||||
echo 'Menu count is not equal menu links. Something went wrong when sending form.';
|
||||
return;
|
||||
@@ -50,6 +53,7 @@ if (isset($_POST['template'])) {
|
||||
'link' => $post_menu_link[$category][$i],
|
||||
'blank' => $post_menu_blank[$category][$i] == 'on' ? 1 : 0,
|
||||
'color' => str_replace('#', '', $post_menu_color[$category][$i]),
|
||||
'access' => $post_menu_access[$category][$i],
|
||||
'category' => $category,
|
||||
'ordering' => $i
|
||||
]);
|
||||
@@ -122,7 +126,7 @@ if (isset($_POST['template'])) {
|
||||
?>
|
||||
<?php
|
||||
$menus = Menu::query()
|
||||
->select('name', 'link', 'blank', 'color', 'category', 'ordering')
|
||||
->select('name', 'link', 'access', 'blank', 'color', 'category', 'ordering')
|
||||
->where('enabled', 1)
|
||||
->where('template', $template)
|
||||
->orderBy('ordering')
|
||||
@@ -151,11 +155,34 @@ if (isset($_POST['template'])) {
|
||||
foreach ($menus[$id] as $menu):
|
||||
$color = (empty($menu['color']) ? ($cat['default_links_color'] ?? ($config['menu_default_links_color'] ?? ($config['menu_default_color'] ?? '#ffffff'))) : '#' . $menu['color']);
|
||||
?>
|
||||
<li class="ui-state-default" id="list-<?php echo $id ?>-<?php echo $i ?>"><label>Name:</label> <input type="text" name="menu[<?php echo $id ?>][]" value="<?php echo escapeHtml($menu['name']); ?>"/>
|
||||
<label>Link:</label> <input type="text" name="menu_link[<?php echo $id ?>][]" value="<?php echo $menu['link'] ?>"/>
|
||||
<input type="hidden" name="menu_blank[<?php echo $id ?>][]" value="0"/>
|
||||
<label><input class="blank-checkbox" type="checkbox" <?php echo($menu['blank'] == 1 ? 'checked' : '') ?>/><span title="Open in New Window">New Window</span></label>
|
||||
<input class="color-picker" type="text" name="menu_color[<?php echo $id ?>][]" value="<?php echo $color; ?>"/>
|
||||
<li class="ui-state-default" id="list-<?php echo $id ?>-<?php echo $i ?>">
|
||||
<label class="label_menu_name">Name: <input type="text" name="menu[<?php echo $id ?>][]" class="form-control menu-name" value="<?php echo escapeHtml($menu['name']); ?>"/>
|
||||
</label>
|
||||
|
||||
<label class="label_menu_link">Link: <input type="text" name="menu_link[<?= $id ?>][]" class="form-control menu-link" value="<?php echo $menu['link'] ?>"/>
|
||||
</label>
|
||||
|
||||
<br/>
|
||||
|
||||
<div class="menu-options-row">
|
||||
|
||||
<label>Access:
|
||||
<select name="menu_access[<?= $id ?>][]" class="form-control menu-access">
|
||||
<option value="0" <?= ($menu['access'] == 0 ? 'selected' : ''); ?>>Guest*</option>
|
||||
<?php foreach ($groups->getGroups() as $group): ?>
|
||||
<option value="<?= $group->getId(); ?>" <?= ($menu['access'] == $group->getId() ? 'selected' : ''); ?>><?= ucfirst($group->getName()); ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<label>Color: <input class="menu-color" type="color" name="menu_color[<?php echo $id ?>][]" value="<?php echo $color; ?>"/>
|
||||
</label>
|
||||
|
||||
<input type="hidden" name="menu_blank[<?php echo $id ?>][]" class="menu-blank" value="0"/>
|
||||
<label><input type="checkbox" class="menu-blank-checkbox" <?php echo($menu['blank'] == 1 ? 'checked' : '') ?>/><span title="Open in New Window">New Window</span></label>
|
||||
|
||||
</div>
|
||||
|
||||
<a class="remove-button" id="remove-button-<?php echo $id ?>-<?php echo $i ?>"><i class="fas fa-trash"></a></i></li>
|
||||
<?php $i++; $last_id[$id] = $i;
|
||||
endforeach;
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
use MyAAC\Forum;
|
||||
use MyAAC\Models\Player;
|
||||
use MyAAC\Server\XML\Vocations;
|
||||
|
||||
defined('MYAAC') or die('Direct access not allowed!');
|
||||
|
||||
@@ -34,6 +35,7 @@ $skills = array(
|
||||
$hasBlessingsColumn = $db->hasColumn('players', 'blessings');
|
||||
$hasBlessingColumn = $db->hasColumn('players', 'blessings1');
|
||||
$hasLookAddons = $db->hasColumn('players', 'lookaddons');
|
||||
$hasCapColumn = $db->hasColumn('players', 'cap');
|
||||
|
||||
$skull_type = array("None", "Yellow", "Green", "White", "Red", "Black", "Orange");
|
||||
?>
|
||||
@@ -166,8 +168,11 @@ else if (isset($_REQUEST['search'])) {
|
||||
$town = $_POST['town'];
|
||||
verify_number($town, 'Town', 11);
|
||||
|
||||
if ($hasCapColumn) {
|
||||
$capacity = $_POST['capacity'];
|
||||
verify_number($capacity, 'Capacity', 11);
|
||||
}
|
||||
|
||||
$sex = $_POST['sex'];
|
||||
verify_number($sex, 'Sex', 1);
|
||||
|
||||
@@ -237,7 +242,30 @@ else if (isset($_REQUEST['search'])) {
|
||||
$player->setGroup($groups->getGroup($group));
|
||||
$player->setLevel($level);
|
||||
$player->setExperience($experience);
|
||||
|
||||
if ($db->hasColumn('players', 'promotion')) {
|
||||
$promotion = 0;
|
||||
|
||||
$vocationOriginal = Vocations::getOriginal($vocation);
|
||||
if ($vocation != $vocationOriginal) {
|
||||
$tmpId = $vocationOriginal;
|
||||
while($promoted = Vocations::getPromoted($tmpId)) {
|
||||
$promotion++;
|
||||
|
||||
$tmpId = $promoted;
|
||||
if ($promoted == $vocation) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$vocation = $vocationOriginal;
|
||||
}
|
||||
|
||||
$player->setPromotion($promotion);
|
||||
}
|
||||
|
||||
$player->setVocation($vocation);
|
||||
|
||||
$player->setHealth($health);
|
||||
$player->setHealthMax($health_max);
|
||||
$player->setMagLevel($magic_level);
|
||||
@@ -249,16 +277,20 @@ else if (isset($_REQUEST['search'])) {
|
||||
$player->setLookHead($look_head);
|
||||
$player->setLookLegs($look_legs);
|
||||
$player->setLookType($look_type);
|
||||
if ($hasLookAddons)
|
||||
if ($hasLookAddons) {
|
||||
$player->setLookAddons($look_addons);
|
||||
if ($db->hasColumn('players', 'offlinetraining_time'))
|
||||
$player->setCustomField('offlinetraining_time', $offlinetraining);
|
||||
}
|
||||
|
||||
$player->setPosX($pos_x);
|
||||
$player->setPosY($pos_y);
|
||||
$player->setPosZ($pos_z);
|
||||
$player->setSoul($soul);
|
||||
$player->setTownId($town);
|
||||
|
||||
if ($hasCapColumn) {
|
||||
$player->setCap($capacity);
|
||||
}
|
||||
|
||||
$player->setSex($sex);
|
||||
$player->setLastLogin($lastlogin);
|
||||
$player->setLastLogout($lastlogout);
|
||||
@@ -275,23 +307,11 @@ else if (isset($_REQUEST['search'])) {
|
||||
if ($hasBlessingsColumn)
|
||||
$player->setBlessings($blessings);
|
||||
|
||||
if ($hasBlessingColumn) {
|
||||
for ($i = 1; $i <= $bless_count; $i++) {
|
||||
$a = 'blessing' . $i;
|
||||
$player->setCustomField('blessings' . $i, ${'blessing' . $i} ? '1' : '0');
|
||||
}
|
||||
}
|
||||
$player->setBalance($balance);
|
||||
if ($db->hasColumn('players', 'stamina'))
|
||||
$player->setStamina($stamina);
|
||||
if ($db->hasColumn('players', 'deletion'))
|
||||
$player->setCustomField('deletion', $deleted ? '1' : '0');
|
||||
else
|
||||
$player->setCustomField('deleted', $deleted ? '1' : '0');
|
||||
$player->setCustomField('hide', $hide ? '1' : '0');
|
||||
$player->setCustomField('created', $created);
|
||||
if (isset($comment))
|
||||
$player->setCustomField('comment', $comment);
|
||||
|
||||
$player->setDeleted($deleted ? '1' : '0');
|
||||
|
||||
foreach ($_POST['skills'] as $skill => $value) {
|
||||
$player->setSkill($skill, $value);
|
||||
@@ -300,6 +320,24 @@ else if (isset($_REQUEST['search'])) {
|
||||
$player->setSkillTries($skill, $value);
|
||||
}
|
||||
$player->save();
|
||||
|
||||
if ($db->hasColumn('players', 'offlinetraining_time')) {
|
||||
$player->setCustomField('offlinetraining_time', $offlinetraining);
|
||||
}
|
||||
|
||||
if ($hasBlessingColumn) {
|
||||
for ($i = 1; $i <= $bless_count; $i++) {
|
||||
$a = 'blessing' . $i;
|
||||
$player->setCustomField('blessings' . $i, ${'blessing' . $i} ? '1' : '0');
|
||||
}
|
||||
}
|
||||
|
||||
$player->setCustomField('hide', $hide ? '1' : '0');
|
||||
$player->setCustomField('created', $created);
|
||||
if (isset($comment)) {
|
||||
$player->setCustomField('comment', $comment);
|
||||
}
|
||||
|
||||
echo_success('Player saved at: ' . date('G:i'));
|
||||
$player->load($id);
|
||||
}
|
||||
@@ -531,10 +569,12 @@ else if (isset($_REQUEST['search'])) {
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<?php if($hasCapColumn): ?>
|
||||
<div class="col-12 col-sm-12 col-lg-6">
|
||||
<label for="capacity" class="control-label">Capacity:</label>
|
||||
<input type="text" class="form-control" id="capacity" name="capacity" autocomplete="off" size="3" maxlength="11" value="<?php echo $player->getCap(); ?>"/>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="col-12 col-sm-12 col-lg-6">
|
||||
<label for="soul" class="control-label">Soul:</label>
|
||||
<input type="text" class="form-control" id="soul" name="soul" autocomplete="off" size="3" maxlength="10" value="<?php echo $player->getSoul(); ?>"/>
|
||||
|
||||
@@ -19,14 +19,14 @@
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,300italic,400italic,600italic">
|
||||
<?php $hooks->trigger(HOOK_ADMIN_HEAD_END); ?>
|
||||
</head>
|
||||
<body class="sidebar-mini ">
|
||||
<body class="sidebar-mini <?= (session('admin.menu-collapse') ? 'sidebar-collapse' : ''); ?>">
|
||||
<?php $hooks->trigger(HOOK_ADMIN_BODY_START); ?>
|
||||
<?php if ($logged && admin()) { ?>
|
||||
<div class="wrapper">
|
||||
<nav class="main-header navbar navbar-expand navbar-white navbar-light">
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-widget="pushmenu" href="#"><i class="fas fa-bars"></i></a>
|
||||
<a class="nav-link sidebar-toggle" data-widget="pushmenu" href="#"><i class="fas fa-bars"></i></a>
|
||||
</li>
|
||||
<li class="nav-item d-none d-sm-inline-block">
|
||||
<a href="<?php echo ADMIN_URL; ?>" class="nav-link">Home</a>
|
||||
@@ -198,6 +198,7 @@ if ($logged && admin()) {
|
||||
<script src="<?php echo BASE_URL; ?>tools/js/datatables.bs.min.js"></script>
|
||||
<?php } ?>
|
||||
<script src="<?php echo BASE_URL; ?>tools/js/adminlte.min.js"></script>
|
||||
<?php $twig->display('admin.menu-collapse.html.twig'); ?>
|
||||
<?php $hooks->trigger(HOOK_ADMIN_BODY_END); ?>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
23
admin/tools/menu_collapse.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
const MYAAC_ADMIN = true;
|
||||
const IGNORE_SET_LAST_VISIT = true;
|
||||
|
||||
require '../../common.php';
|
||||
require SYSTEM . 'functions.php';
|
||||
require SYSTEM . 'init.php';
|
||||
require SYSTEM . 'login.php';
|
||||
|
||||
if(!admin()) {
|
||||
http_response_code(500);
|
||||
die('You are not logged in. Probably session expired. Please login again.');
|
||||
}
|
||||
|
||||
if (!isset($_POST['collapse'])) {
|
||||
http_response_code(500);
|
||||
die('Something went wrong.');
|
||||
}
|
||||
|
||||
csrfProtect();
|
||||
|
||||
setSession('admin.menu-collapse', $_POST['collapse'] == 'true');
|
||||
17
common.php
@@ -26,8 +26,8 @@
|
||||
if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.');
|
||||
|
||||
const MYAAC = true;
|
||||
const MYAAC_VERSION = '1.8.5';
|
||||
const DATABASE_VERSION = 46;
|
||||
const MYAAC_VERSION = '2.0-dev';
|
||||
const DATABASE_VERSION = 48;
|
||||
const TABLE_PREFIX = 'myaac_';
|
||||
define('START_TIME', microtime(true));
|
||||
define('MYAAC_OS', stripos(PHP_OS, 'WIN') === 0 ? 'WINDOWS' : (strtoupper(PHP_OS) === 'DARWIN' ? 'MAC' : 'LINUX'));
|
||||
@@ -148,16 +148,17 @@ if(!IS_CLI) {
|
||||
|
||||
/** @var array $config */
|
||||
ini_set('log_errors', 1);
|
||||
if(@$config['env'] === 'dev' || defined('MYAAC_INSTALL')) {
|
||||
ini_set('display_errors', 1);
|
||||
ini_set('display_startup_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
}
|
||||
else {
|
||||
if(isset($config['env']) && $config['env'] !== 'dev' && !defined('MYAAC_INSTALL')) {
|
||||
ini_set('display_errors', 0);
|
||||
ini_set('display_startup_errors', 0);
|
||||
error_reporting(E_ALL & ~E_DEPRECATED & ~E_STRICT);
|
||||
}
|
||||
else {
|
||||
ini_set('html_errors', 0);
|
||||
ini_set('display_errors', 1);
|
||||
ini_set('display_startup_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
}
|
||||
|
||||
$autoloadFile = VENDOR . 'autoload.php';
|
||||
if (!is_file($autoloadFile)) {
|
||||
|
||||
BIN
images/druid.png
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 33 KiB |
BIN
images/monk.png
Normal file
|
After Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 1005 B |
|
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 31 KiB |
@@ -1,11 +1,11 @@
|
||||
CREATE TABLE IF NOT EXISTS `myaac_account_actions`
|
||||
(
|
||||
`id` int NOT NULL AUTO_INCREMENT,
|
||||
`account_id` int NOT NULL,
|
||||
`ip` int unsigned NOT NULL DEFAULT 0,
|
||||
`ipv6` binary(16) NOT NULL DEFAULT 0,
|
||||
`ip` varchar(45) NOT NULL DEFAULT '',
|
||||
`date` int NOT NULL DEFAULT 0,
|
||||
`action` varchar(255) NOT NULL DEFAULT '',
|
||||
KEY (`account_id`)
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `myaac_account_emails_verify`
|
||||
@@ -102,6 +102,7 @@ CREATE TABLE IF NOT EXISTS `myaac_menu`
|
||||
`template` varchar(255) NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`link` varchar(255) NOT NULL,
|
||||
`access` tinyint NOT NULL DEFAULT 0,
|
||||
`blank` tinyint NOT NULL DEFAULT 0,
|
||||
`color` varchar(6) NOT NULL DEFAULT '',
|
||||
`category` int NOT NULL DEFAULT 1,
|
||||
|
||||
@@ -37,8 +37,46 @@ if ($db->hasTable('players')) {
|
||||
|
||||
$query = $db->query('SELECT `id` FROM `players` WHERE `name` = ' . $db->quote($p['name']));
|
||||
if ($query->rowCount() == 0) {
|
||||
if (!query("INSERT INTO `players` (`id`, `name`, `group_id`, `account_id`, `level`, `vocation`, `health`, `healthmax`, `experience`, `lookbody`, `lookfeet`, `lookhead`, `looklegs`, `looktype`, `maglevel`, `mana`, `manamax`, `manaspent`, `soul`, `town_id`, `posx`, `posy`, `posz`, `conditions`, `cap`, `sex`, `lastlogin`, `lastip`, `save`, `lastlogout`, `balance`, `$deleted`, `created`, `hide`, `comment`) VALUES (null, " . $db->quote($p['name']) . ", 1, " . getSession('account') . ", " . $p['level'] . ", " . $p['vocation_id'] . ", " . $p['health'] . ", " . $p['healthmax'] . ", " . $p['experience'] . ", 118, 114, 38, 57, " . $p['looktype'] . ", 0, " . $p['mana'] . ", " . $p['manamax'] . ", 0, " . $p['soul'] . ", 1, 1000, 1000, 7, '', " . $p['cap'] . ", 1, " . $time . ", 2130706433, 1, " . $time . ", 0, 0, " . $time . ", 1, '');"))
|
||||
$success = false;
|
||||
$player = new OTS_Player();
|
||||
|
||||
$player->setData([
|
||||
'name' => $p['name'],
|
||||
'group_id' => 1,
|
||||
'account_id' => getSession('account'),
|
||||
'level' => $p['level'],
|
||||
'vocation' => $p['vocation_id'],
|
||||
'health' => $p['health'],
|
||||
'healthmax' => $p['healthmax'],
|
||||
'experience' => $p['experience'],
|
||||
'lookbody' => 118,
|
||||
'lookfeet' => 114,
|
||||
'lookhead' => 38,
|
||||
'looklegs' => 57,
|
||||
'looktype' => $p['looktype'],
|
||||
'maglevel' => 0,
|
||||
'mana' => $p['mana'],
|
||||
'manamax' => $p['manamax'],
|
||||
'manaspent' => 0,
|
||||
'soul' => $p['soul'],
|
||||
'town_id' => 1,
|
||||
'posx' => 1000,
|
||||
'posy' => 1000,
|
||||
'posz' => 7,
|
||||
'conditions' => '',
|
||||
'cap' => $p['cap'],
|
||||
'sex' => 1,
|
||||
'lastlogin' => $time,
|
||||
'lastip' => 2130706433,
|
||||
'save' => 1,
|
||||
'lastlogout' => $time,
|
||||
'balance' => 0,
|
||||
$deleted => 0,
|
||||
'created' => $time,
|
||||
'hide' => 1,
|
||||
'comment' => '',
|
||||
]);
|
||||
|
||||
$player->save();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,8 +5,6 @@ $deprecatedConfig = [
|
||||
'genders',
|
||||
'template',
|
||||
'template_allow_change',
|
||||
'vocations_amount',
|
||||
'vocations',
|
||||
'client',
|
||||
'session_prefix',
|
||||
'friendly_urls',
|
||||
@@ -21,7 +19,6 @@ $deprecatedConfig = [
|
||||
'visitors_counter_ttl',
|
||||
'views_counter',
|
||||
'outfit_images_url',
|
||||
'outfit_images_wrong_looktypes',
|
||||
'item_images_url',
|
||||
'account_country',
|
||||
'towns',
|
||||
@@ -52,6 +49,7 @@ $deprecatedConfig = [
|
||||
'online_skulls',
|
||||
'online_outfit',
|
||||
'online_afk',
|
||||
'team_style',
|
||||
'team_display_outfit' => 'team_outfit',
|
||||
'team_display_status' => 'team_status',
|
||||
'team_display_world' => 'team_world',
|
||||
|
||||
@@ -17,6 +17,8 @@ use MyAAC\Models\Guild;
|
||||
use MyAAC\Models\House;
|
||||
use MyAAC\Models\Pages;
|
||||
use MyAAC\Models\Player;
|
||||
use MyAAC\Models\PlayerDeath;
|
||||
use MyAAC\Models\PlayerKillers;
|
||||
use MyAAC\News;
|
||||
use MyAAC\Plugins;
|
||||
use MyAAC\Settings;
|
||||
@@ -1135,11 +1137,44 @@ function csrfProtect(): void
|
||||
}
|
||||
}
|
||||
|
||||
function getTopPlayers($limit = 5, $skill = 'level') {
|
||||
function getSkillIdByName(string $name): int|null
|
||||
{
|
||||
$skills = [
|
||||
'level' => POT::SKILL_LEVEL,
|
||||
'experience' => POT::SKILL_LEVEL,
|
||||
|
||||
'magic' => POT::SKILL_MAGIC,
|
||||
'maglevel' => POT::SKILL_MAGIC,
|
||||
|
||||
'balance' => SKILL_BALANCE,
|
||||
'frags' => SKILL_FRAGS,
|
||||
|
||||
'club' => POT::SKILL_CLUB,
|
||||
'sword' => POT::SKILL_SWORD,
|
||||
'axe' => POT::SKILL_AXE,
|
||||
'dist' => POT::SKILL_DIST,
|
||||
'distance' => POT::SKILL_DIST,
|
||||
'shield' => POT::SKILL_SHIELD,
|
||||
'shielding' => POT::SKILL_SHIELD,
|
||||
'fish' => POT::SKILL_FISH,
|
||||
'fishing' => POT::SKILL_FISH,
|
||||
];
|
||||
|
||||
return $skills[$name] ?? null;
|
||||
}
|
||||
|
||||
function getTopPlayers($limit = 5, $skill = POT::SKILL_LEVEL)
|
||||
{
|
||||
global $db;
|
||||
|
||||
if ($skill === 'level') {
|
||||
$skill = 'experience';
|
||||
$skillOriginal = $skill;
|
||||
|
||||
if (is_string($skill)) {
|
||||
$skill = getSkillIdByName($skill);
|
||||
}
|
||||
|
||||
if (!is_numeric($skill)) {
|
||||
throw new RuntimeException("getTopPlayers: Invalid skill: $skillOriginal");
|
||||
}
|
||||
|
||||
return Cache::remember("top_{$limit}_{$skill}", 2 * 60, function () use ($db, $limit, $skill) {
|
||||
@@ -1160,15 +1195,64 @@ function getTopPlayers($limit = 5, $skill = 'level') {
|
||||
$columns[] = 'lookmount';
|
||||
}
|
||||
|
||||
return Player::query()
|
||||
$query = Player::query()
|
||||
->select($columns)
|
||||
->withOnlineStatus()
|
||||
->notDeleted()
|
||||
->where('group_id', '<', setting('core.highscores_groups_hidden'))
|
||||
->whereNotIn('id', setting('core.highscores_ids_hidden'))
|
||||
->where('account_id', '!=', 1)
|
||||
->orderByDesc($skill)
|
||||
->limit($limit)
|
||||
->orderByDesc('value');
|
||||
|
||||
if ($limit > 0) {
|
||||
$query->limit($limit);
|
||||
}
|
||||
|
||||
if ($skill >= POT::SKILL_FIRST && $skill <= POT::SKILL_LAST) { // skills
|
||||
if ($db->hasColumn('players', 'skill_fist')) {// tfs 1.0
|
||||
$skill_ids = array(
|
||||
POT::SKILL_FIST => 'skill_fist',
|
||||
POT::SKILL_CLUB => 'skill_club',
|
||||
POT::SKILL_SWORD => 'skill_sword',
|
||||
POT::SKILL_AXE => 'skill_axe',
|
||||
POT::SKILL_DIST => 'skill_dist',
|
||||
POT::SKILL_SHIELD => 'skill_shielding',
|
||||
POT::SKILL_FISH => 'skill_fishing',
|
||||
);
|
||||
|
||||
$query
|
||||
->addSelect($skill_ids[$skill] . ' as value')
|
||||
->orderByDesc($skill_ids[$skill] . '_tries');
|
||||
} else {
|
||||
$query
|
||||
->join('player_skills', 'player_skills.player_id', '=', 'players.id')
|
||||
->where('skillid', $skill)
|
||||
->addSelect('player_skills.value as value');
|
||||
}
|
||||
} else if ($skill == SKILL_FRAGS) // frags
|
||||
{
|
||||
if ($db->hasTable('player_killers')) {
|
||||
$query->addSelect(['value' => PlayerKillers::whereColumn('player_killers.player_id', 'players.id')->selectRaw('COUNT(*)')]);
|
||||
} else {
|
||||
$query->addSelect(['value' => PlayerDeath::unjustified()->whereColumn('player_deaths.killed_by', 'players.name')->selectRaw('COUNT(*)')]);
|
||||
}
|
||||
} else if ($skill == SKILL_BALANCE) // balance
|
||||
{
|
||||
$query
|
||||
->addSelect('players.balance as value');
|
||||
} else {
|
||||
if ($skill == POT::SKILL_MAGIC) {
|
||||
$query
|
||||
->addSelect('players.maglevel as value', 'players.maglevel')
|
||||
->orderByDesc('manaspent');
|
||||
} else { // level
|
||||
$query
|
||||
->addSelect('players.level as value', 'players.experience')
|
||||
->orderByDesc('experience');
|
||||
}
|
||||
}
|
||||
|
||||
return $query
|
||||
->get()
|
||||
->map(function ($e, $i) {
|
||||
$row = $e->toArray();
|
||||
|
||||
@@ -14,6 +14,7 @@ use MyAAC\CsrfToken;
|
||||
use MyAAC\Hooks;
|
||||
use MyAAC\Plugins;
|
||||
use MyAAC\Models\Town;
|
||||
use MyAAC\Server\XML\Vocations;
|
||||
use MyAAC\Settings;
|
||||
|
||||
defined('MYAAC') or die('Direct access not allowed!');
|
||||
@@ -214,3 +215,5 @@ if (count($towns) <= 0) {
|
||||
|
||||
config(['towns', $towns]);
|
||||
unset($towns);
|
||||
|
||||
new Vocations();
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
* @license http://www.gnu.org/licenses/lgpl-3.0.txt GNU Lesser General Public License, Version 3
|
||||
*/
|
||||
|
||||
use MyAAC\Models\AccountAction;
|
||||
|
||||
/**
|
||||
* OTServ account abstraction.
|
||||
*
|
||||
@@ -1007,26 +1009,16 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
|
||||
|
||||
public function logAction($action)
|
||||
{
|
||||
$ip = get_browser_real_ip();
|
||||
if(!str_contains($ip, ":")) {
|
||||
$ipv6 = '0';
|
||||
}
|
||||
else {
|
||||
$ipv6 = $ip;
|
||||
$ip = '';
|
||||
AccountAction::create([
|
||||
'account_id' => $this->getId(),
|
||||
'ip' => get_browser_real_ip(),
|
||||
'date' => time(),
|
||||
'action' => $action,
|
||||
]);
|
||||
}
|
||||
|
||||
return $this->db->exec('INSERT INTO `' . TABLE_PREFIX . 'account_actions` (`account_id`, `ip`, `ipv6`, `date`, `action`) VALUES (' . $this->db->quote($this->getId()).', ' . ($ip == '' ? '0' : $this->db->quote(ip2long($ip))) . ', (' . ($ipv6 == '0' ? $this->db->quote('') : $this->db->quote(inet_pton($ipv6))) . '), UNIX_TIMESTAMP(NOW()), ' . $this->db->quote($action).')');
|
||||
}
|
||||
|
||||
public function getActionsLog($limit1, $limit2)
|
||||
{
|
||||
$actions = array();
|
||||
|
||||
foreach($this->db->query('SELECT `ip`, `ipv6`, `date`, `action` FROM `' . TABLE_PREFIX . 'account_actions` WHERE `account_id` = ' . $this->data['id'] . ' ORDER by `date` DESC LIMIT ' . $limit1 . ', ' . $limit2 . '')->fetchAll() as $a)
|
||||
$actions[] = array('ip' => $a['ip'], 'ipv6' => $a['ipv6'], 'date' => $a['date'], 'action' => $a['action']);
|
||||
|
||||
return $actions;
|
||||
public function getActionsLog($limit) {
|
||||
return AccountAction::where('account_id', $this->data['id'])->orderByDesc('date')->limit($limit)->get()->toArray();
|
||||
}
|
||||
/**
|
||||
* Returns players iterator.
|
||||
|
||||
@@ -26,6 +26,7 @@ use MyAAC\Cache\Cache;
|
||||
*/
|
||||
class OTS_DB_MySQL extends OTS_Base_DB
|
||||
{
|
||||
private bool $hasCacheChanged = false;
|
||||
private array $has_table_cache = [];
|
||||
private array $has_column_cache = [];
|
||||
private array $get_column_info_cache = [];
|
||||
@@ -164,7 +165,7 @@ class OTS_DB_MySQL extends OTS_Base_DB
|
||||
$cache->delete('database_columns_info');
|
||||
$cache->delete('database_checksum');
|
||||
}
|
||||
else {
|
||||
else if ($this->hasCacheChanged) {
|
||||
$cache->set('database_tables', serialize($this->has_table_cache), 3600);
|
||||
$cache->set('database_columns', serialize($this->has_column_cache), 3600);
|
||||
$cache->set('database_columns_info', serialize($this->get_column_info_cache), 3600);
|
||||
@@ -228,6 +229,8 @@ class OTS_DB_MySQL extends OTS_Base_DB
|
||||
|
||||
private function hasTableInternal($name): bool
|
||||
{
|
||||
$this->hasCacheChanged = true;
|
||||
|
||||
return ($this->has_table_cache[$name] = $this->query('SELECT `TABLE_NAME` FROM `information_schema`.`tables` WHERE `TABLE_SCHEMA` = ' . $this->quote(config('database_name')) . ' AND `TABLE_NAME` = ' . $this->quote($name) . ' LIMIT 1;')->rowCount() > 0);
|
||||
}
|
||||
|
||||
@@ -241,6 +244,8 @@ class OTS_DB_MySQL extends OTS_Base_DB
|
||||
}
|
||||
|
||||
private function hasColumnInternal($table, $column): bool {
|
||||
$this->hasCacheChanged = true;
|
||||
|
||||
return $this->hasTable($table) && ($this->has_column_cache[$table . '.' . $column] = count($this->query('SHOW COLUMNS FROM `' . $table . "` LIKE " . $this->quote($column))->fetchAll()) > 0);
|
||||
}
|
||||
|
||||
@@ -272,11 +277,14 @@ class OTS_DB_MySQL extends OTS_Base_DB
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->hasCacheChanged = true;
|
||||
|
||||
$formatResult = function ($result) {
|
||||
return [
|
||||
'field' => $result['Field'],
|
||||
'type' => $result['Type'],
|
||||
'null' => strtolower($result['Null']),
|
||||
'key' => strtolower($result['Key'] ?? ''),
|
||||
'default' => $result['Default'],
|
||||
'extra' => $result['Extra'],
|
||||
];
|
||||
|
||||
@@ -1,20 +1,6 @@
|
||||
<?php
|
||||
$__load = array();
|
||||
/*
|
||||
'loss_experience' => NULL,
|
||||
'loss_items' => NULL,
|
||||
'guild_info' => NULL,
|
||||
'skull_type' => NULL,
|
||||
'skull_time' => NULL,
|
||||
'blessings' => NULL,
|
||||
'direction' => NULL,
|
||||
'stamina' => NULL,
|
||||
'world_id' => NULL,
|
||||
'online' => NULL,
|
||||
'deletion' => NULL,
|
||||
'promotion' => NULL,
|
||||
'marriage' => NULL
|
||||
);*/
|
||||
|
||||
use MyAAC\Models\Player as PlayerModel;
|
||||
|
||||
/**#@+
|
||||
* @version 0.0.1
|
||||
@@ -109,6 +95,10 @@ class OTS_Player extends OTS_Row_DAO
|
||||
POT::SKILL_FISH => array('value' => 0, 'tries' => 0)
|
||||
);
|
||||
|
||||
private array $columns = ['name', 'account_id', 'group_id', 'sex', 'vocation', 'experience', 'level', 'maglevel', 'health', 'healthmax', 'mana', 'manamax', 'manaspent', 'soul', 'lookbody', 'lookfeet', 'lookhead', 'looklegs', 'looktype', 'posx', 'posy', 'posz', 'lastlogin', 'lastlogout', 'lastip', 'town_id', 'balance', 'created', 'comment', 'hide'];
|
||||
|
||||
private array $optionalColumns = ['cap', 'skull', 'skull_type', 'skull_time', 'loss_experience', 'loss_mana', 'loss_skills', 'loss_items', 'loss_containers', 'guildnick', 'rank_id', 'promotion', 'direction', 'blessings', 'stamina', 'lookaddons', 'save', 'conditions', 'world_id', 'online', 'deletion', 'deleted', 'marriage'];
|
||||
|
||||
private static array $playersOnline;
|
||||
/**
|
||||
* Magic PHP5 method.
|
||||
@@ -133,90 +123,14 @@ class OTS_Player extends OTS_Row_DAO
|
||||
*/
|
||||
public function load($id, $fields = null, $load_skills = true)
|
||||
{
|
||||
global $__load;
|
||||
|
||||
if(!isset($__load['loss_experience']))
|
||||
{
|
||||
$loss = '';
|
||||
if($this->db->hasColumn('players', 'loss_experience')) {
|
||||
$loss = ', `loss_experience`, `loss_mana`, `loss_skills`';
|
||||
$columns = $this->columns;
|
||||
foreach ($this->optionalColumns as $column) {
|
||||
if ($this->db->hasColumn('players', $column)) {
|
||||
$columns[] = $column;
|
||||
}
|
||||
|
||||
$__load['loss_experience'] = $loss;
|
||||
}
|
||||
|
||||
if(!isset($__load['loss_items']))
|
||||
{
|
||||
$loss_items = '';
|
||||
if($this->db->hasColumn('players', 'loss_items')) {
|
||||
$loss_items = ', `loss_items`, `loss_containers`';
|
||||
}
|
||||
|
||||
$__load['loss_items'] = $loss_items;
|
||||
}
|
||||
|
||||
if(!isset($__load['guild_info']))
|
||||
{
|
||||
$guild_info = '';
|
||||
if(!$this->db->hasTable('guild_members') && $this->db->hasColumn('players', 'guildnick')) {
|
||||
$guild_info = ', `guildnick`, `rank_id`';
|
||||
}
|
||||
|
||||
$__load['guild_info'] = $guild_info;
|
||||
}
|
||||
|
||||
if(!isset($__load['skull_type']))
|
||||
{
|
||||
$skull_type = 'skull';
|
||||
if($this->db->hasColumn('players', 'skull_type')) {
|
||||
$skull_type = 'skull_type';
|
||||
}
|
||||
|
||||
$__load['skull_type'] = $skull_type;
|
||||
}
|
||||
|
||||
if(!isset($__load['skull_time']))
|
||||
{
|
||||
$skull_time = 'skulltime';
|
||||
if($this->db->hasColumn('players', 'skull_time')) {
|
||||
$skull_time = 'skull_time';
|
||||
}
|
||||
|
||||
$__load['skull_time'] = $skull_time;
|
||||
}
|
||||
|
||||
if(!isset($__load['blessings'])) {
|
||||
$__load['blessings'] = $this->db->hasColumn('players', 'blessings');
|
||||
}
|
||||
if(!isset($__load['direction'])) {
|
||||
$__load['direction'] = $this->db->hasColumn('players', 'direction');
|
||||
}
|
||||
if(!isset($__load['stamina'])) {
|
||||
$__load['stamina'] = $this->db->hasColumn('players', 'stamina');
|
||||
}
|
||||
if(!isset($__load['world_id'])) {
|
||||
$__load['world_id'] = $this->db->hasColumn('players', 'world_id');
|
||||
}
|
||||
if(!isset($__load['online'])) {
|
||||
$__load['online'] = $this->db->hasColumn('players', 'online');
|
||||
}
|
||||
if(!isset($__load['deletion'])) {
|
||||
$__load['deletion'] = $this->db->hasColumn('players', 'deletion');
|
||||
}
|
||||
if(!isset($__load['promotion'])) {
|
||||
$__load['promotion'] = $this->db->hasColumn('players', 'promotion');
|
||||
}
|
||||
if(!isset($__load['marriage'])) {
|
||||
$__load['marriage'] = $this->db->hasColumn('players', 'marriage');
|
||||
}
|
||||
|
||||
if(isset($fields)) { // load only what we wish
|
||||
if(in_array('promotion', $fields)) {
|
||||
if(!$this->db->hasColumn('players', 'promotion')) {
|
||||
unset($fields[array_search('promotion', $fields)]);
|
||||
}
|
||||
}
|
||||
|
||||
if(in_array('deleted', $fields)) {
|
||||
if($this->db->hasColumn('players', 'deletion')) {
|
||||
unset($fields[array_search('deleted', $fields)]);
|
||||
@@ -224,21 +138,21 @@ class OTS_Player extends OTS_Row_DAO
|
||||
}
|
||||
}
|
||||
|
||||
if(in_array('online', $fields)) {
|
||||
if(!$this->db->hasColumn('players', 'online')) {
|
||||
unset($fields[array_search('online', $fields)]);
|
||||
$columns = [];
|
||||
foreach ($fields as $field) {
|
||||
if ($this->db->hasColumn('players', $field)) {
|
||||
$columns[] = $field;
|
||||
}
|
||||
}
|
||||
$this->data = $this->db->query('SELECT ' . implode(', ', $fields) . ' FROM `players` WHERE `id` = ' . (int)$id)->fetch();
|
||||
}
|
||||
else {
|
||||
// SELECT query on database
|
||||
$this->data = $this->db->query('SELECT `id`, `name`, `account_id`, `group_id`, `sex`, `vocation`, `experience`, `level`, `maglevel`, `health`, `healthmax`, `mana`, `manamax`, `manaspent`, `soul`, `lookbody`, `lookfeet`, `lookhead`, `looklegs`, `looktype`' . ($this->db->hasColumn('players', 'lookaddons') ? ', `lookaddons`' : '') . ', `posx`, `posy`, `posz`, `cap`, `lastlogin`, `lastlogout`, `lastip`, `save`, `conditions`, `' . $__load['skull_time'] . '` as `skulltime`, `' . $__load['skull_type'] . '` as `skull`' . $__load['guild_info'] . ', `town_id`' . $__load['loss_experience'] . $__load['loss_items'] . ', `balance`' . ($__load['blessings'] ? ', `blessings`' : '') . ($__load['direction'] ? ', `direction`' : '') . ($__load['stamina'] ? ', `stamina`' : '') . ($__load['world_id'] ? ', `world_id`' : '') . ($__load['online'] ? ', `online`' : '') . ', `' . ($__load['deletion'] ? 'deletion' : 'deleted') . '`' . ($__load['promotion'] ? ', `promotion`' : '') . ($__load['marriage'] ? ', `marriage`' : '') . ', `comment`, `created`, `hide` FROM `players` WHERE `id` = ' . (int)$id)->fetch();
|
||||
}
|
||||
|
||||
array_unshift($columns, 'id');
|
||||
|
||||
$query = PlayerModel::where('id', $id)->first($columns);
|
||||
$this->data = $query ? $query->toArray() : [];
|
||||
|
||||
// loads skills
|
||||
if( $this->isLoaded() && $load_skills)
|
||||
{
|
||||
if( $this->isLoaded() && $load_skills) {
|
||||
if($this->db->hasColumn('players', 'skill_fist')) {
|
||||
|
||||
$skill_ids = array(
|
||||
@@ -318,153 +232,57 @@ class OTS_Player extends OTS_Row_DAO
|
||||
*/
|
||||
public function save()
|
||||
{
|
||||
$skull_type = 'skull';
|
||||
if($this->db->hasColumn('players', 'skull_type')) {
|
||||
$skull_type = 'skull_type';
|
||||
$defaultValues = [
|
||||
'loss_experience' => 100,
|
||||
'loss_mana' => 100,
|
||||
'loss_skills' => 100,
|
||||
'loss_items' => 100,
|
||||
'loss_containers' => 100,
|
||||
'guildnick' => '',
|
||||
'rank_id' => 0,
|
||||
'promotion' => 0,
|
||||
'direction' => 0,
|
||||
'blessings' => 0,
|
||||
'conditions' => '',
|
||||
'town_id' => 1,
|
||||
'deletion' => 0,
|
||||
'deleted' => 0,
|
||||
'stamina' => 0,
|
||||
'marriage' => 0,
|
||||
];
|
||||
|
||||
foreach ($defaultValues as $key => $value) {
|
||||
if (!isset($this->data[$key])) {
|
||||
$this->data[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
$skull_time = 'skulltime';
|
||||
if($this->db->hasColumn('players', 'skull_time')) {
|
||||
$skull_time = 'skull_time';
|
||||
$columns = $this->columns;
|
||||
foreach ($this->optionalColumns as $column) {
|
||||
if ($this->db->hasColumn('players', $column)) {
|
||||
$columns[] = $column;
|
||||
}
|
||||
}
|
||||
|
||||
if(!isset($this->data['loss_experience']))
|
||||
$this->data['loss_experience'] = 100;
|
||||
$values = [];
|
||||
foreach ($columns as $column) {
|
||||
$value = $this->data[$column];
|
||||
|
||||
if(!isset($this->data['loss_mana']))
|
||||
$this->data['loss_mana'] = 100;
|
||||
|
||||
if(!isset($this->data['loss_skills']))
|
||||
$this->data['loss_skills'] = 100;
|
||||
|
||||
if(!isset($this->data['loss_items']))
|
||||
$this->data['loss_items'] = 10;
|
||||
|
||||
if(!isset($this->data['loss_containers']))
|
||||
$this->data['loss_containers'] = 100;
|
||||
|
||||
if(!isset($this->data['guildnick']))
|
||||
$this->data['guildnick'] = '';
|
||||
|
||||
if(!isset($this->data['rank_id']))
|
||||
$this->data['rank_id'] = 0;
|
||||
|
||||
if(!isset($this->data['promotion']))
|
||||
$this->data['promotion'] = 0;
|
||||
|
||||
if(!isset($this->data['direction']))
|
||||
$this->data['direction'] = 0;
|
||||
|
||||
if(!isset($this->data['conditions']))
|
||||
$this->data['conditions'] = '';
|
||||
|
||||
if(!isset($this->data['town_id']))
|
||||
$this->data['town_id'] = 1;
|
||||
$values[$column] = $value;
|
||||
}
|
||||
|
||||
// updates existing player
|
||||
if( isset($this->data['id']) )
|
||||
{
|
||||
$loss = '';
|
||||
if($this->db->hasColumn('players', 'loss_experience')) {
|
||||
$loss = ', `loss_experience` = ' . $this->data['loss_experience'] . ', `loss_mana` = ' . $this->data['loss_mana'] . ', `loss_skills` = ' . $this->data['loss_skills'];
|
||||
}
|
||||
|
||||
$loss_items = '';
|
||||
if($this->db->hasColumn('players', 'loss_items')) {
|
||||
$loss_items = ', `loss_items` = ' . $this->data['loss_items'] . ', `loss_containers` = ' . $this->data['loss_containers'];
|
||||
}
|
||||
|
||||
$guild_info = '';
|
||||
if(!$this->db->hasTable('guild_members') && $this->db->hasColumn('players', 'guildnick')) {
|
||||
$guild_info = ', `guildnick` = ' . $this->db->quote($this->data['guildnick']) . ', ' . $this->db->fieldName('rank_id') . ' = ' . $this->data['rank_id'];
|
||||
}
|
||||
|
||||
$direction = '';
|
||||
if($this->db->hasColumn('players', 'direction')) {
|
||||
$direction = ', `direction` = ' . $this->db->quote($this->data['direction']);
|
||||
}
|
||||
|
||||
$blessings = '';
|
||||
if($this->db->hasColumn('players', 'blessings')) {
|
||||
$blessings = ', `blessings` = ' . $this->db->quote($this->data['blessings']);
|
||||
}
|
||||
|
||||
$stamina = '';
|
||||
if($this->db->hasColumn('players', 'stamina')) {
|
||||
$stamina = ', `stamina` = ' . $this->db->quote($this->data['stamina']);
|
||||
}
|
||||
|
||||
$lookaddons = '';
|
||||
if($this->db->hasColumn('players', 'lookaddons')) {
|
||||
$lookaddons = ', `lookaddons` = ' . $this->db->quote($this->data['lookaddons']);
|
||||
}
|
||||
|
||||
// UPDATE query on database
|
||||
$this->db->query('UPDATE ' . $this->db->tableName('players') . ' SET ' . $this->db->fieldName('name') . ' = ' . $this->db->quote($this->data['name']) . ', ' . $this->db->fieldName('account_id') . ' = ' . $this->data['account_id'] . ', ' . $this->db->fieldName('group_id') . ' = ' . $this->data['group_id'] . ', ' . $this->db->fieldName('sex') . ' = ' . $this->data['sex'] . ', ' . $this->db->fieldName('vocation') . ' = ' . $this->data['vocation'] . ', ' . $this->db->fieldName('experience') . ' = ' . $this->data['experience'] . ', ' . $this->db->fieldName('level') . ' = ' . $this->data['level'] . ', ' . $this->db->fieldName('maglevel') . ' = ' . $this->data['maglevel'] . ', ' . $this->db->fieldName('health') . ' = ' . $this->data['health'] . ', ' . $this->db->fieldName('healthmax') . ' = ' . $this->data['healthmax'] . ', ' . $this->db->fieldName('mana') . ' = ' . $this->data['mana'] . ', ' . $this->db->fieldName('manamax') . ' = ' . $this->data['manamax'] . ', ' . $this->db->fieldName('manaspent') . ' = ' . $this->data['manaspent'] . ', ' . $this->db->fieldName('soul') . ' = ' . $this->data['soul'] . ', ' . $this->db->fieldName('lookbody') . ' = ' . $this->data['lookbody'] . ', ' . $this->db->fieldName('lookfeet') . ' = ' . $this->data['lookfeet'] . ', ' . $this->db->fieldName('lookhead') . ' = ' . $this->data['lookhead'] . ', ' . $this->db->fieldName('looklegs') . ' = ' . $this->data['looklegs'] . ', ' . $this->db->fieldName('looktype') . ' = ' . $this->data['looktype'] . $lookaddons . ', ' . $this->db->fieldName('posx') . ' = ' . $this->data['posx'] . ', ' . $this->db->fieldName('posy') . ' = ' . $this->data['posy'] . ', ' . $this->db->fieldName('posz') . ' = ' . $this->data['posz'] . ', ' . $this->db->fieldName('cap') . ' = ' . $this->data['cap'] . ', ' . $this->db->fieldName('lastlogin') . ' = ' . $this->data['lastlogin'] . ', ' . $this->db->fieldName('lastlogout') . ' = ' . $this->data['lastlogout'] . ', ' . $this->db->fieldName('lastip') . ' = ' . $this->db->quote($this->data['lastip']) . ', ' . $this->db->fieldName('save') . ' = ' . (int) $this->data['save'] . ', ' . $this->db->fieldName('conditions') . ' = ' . $this->db->quote($this->data['conditions']) . ', `' . $skull_time . '` = ' . $this->data['skulltime'] . ', `' . $skull_type . '` = ' . (int) $this->data['skull'] . $guild_info . ', ' . $this->db->fieldName('town_id') . ' = ' . $this->data['town_id'] . $loss . $loss_items . ', ' . $this->db->fieldName('balance') . ' = ' . $this->data['balance'] . $blessings . $stamina . $direction . ' WHERE ' . $this->db->fieldName('id') . ' = ' . $this->data['id']);
|
||||
if( isset($this->data['id']) ) {
|
||||
PlayerModel::where('id', $this->data['id'])->update($values);
|
||||
}
|
||||
// creates new player
|
||||
else
|
||||
{
|
||||
$loss = '';
|
||||
$loss_data = '';
|
||||
if($this->db->hasColumn('players', 'loss_experience')) {
|
||||
$loss = ', `loss_experience`, `loss_mana`, `loss_skills`';
|
||||
$loss_data = ', ' . $this->data['loss_experience'] . ', ' . $this->data['loss_mana'] . ', ' . $this->data['loss_skills'];
|
||||
}
|
||||
else {
|
||||
$values['created'] = time();
|
||||
|
||||
$loss_items = '';
|
||||
$loss_items_data = '';
|
||||
if($this->db->hasColumn('players', 'loss_items')) {
|
||||
$loss_items = ', `loss_items`, `loss_containers`';
|
||||
$loss_items_data = ', ' . $this->data['loss_items'] . ', ' . $this->data['loss_containers'];
|
||||
}
|
||||
$player = PlayerModel::create($values);
|
||||
|
||||
$guild_info = '';
|
||||
$guild_info_data = '';
|
||||
if(!$this->db->hasTable('guild_members') && $this->db->hasColumn('players', 'guildnick')) {
|
||||
$guild_info = ', `guildnick`, `rank_id`';
|
||||
$guild_info_data = ', ' . $this->db->quote($this->data['guildnick']) . ', ' . $this->data['rank_id'];
|
||||
}
|
||||
|
||||
$promotion = '';
|
||||
$promotion_data = '';
|
||||
if($this->db->hasColumn('players', 'promotion')) {
|
||||
$promotion = ', `promotion`';
|
||||
$promotion_data = ', ' . $this->data['promotion'];
|
||||
}
|
||||
|
||||
$direction = '';
|
||||
$direction_data = '';
|
||||
if($this->db->hasColumn('players', 'direction')) {
|
||||
$direction = ', `direction`';
|
||||
$direction_data = ', ' . $this->data['direction'];
|
||||
}
|
||||
|
||||
$blessings = '';
|
||||
$blessings_data = '';
|
||||
if($this->db->hasColumn('players', 'blessings')) {
|
||||
$blessings = ', `blessings`';
|
||||
$blessings_data = ', ' . $this->data['blessings'];
|
||||
}
|
||||
|
||||
$stamina = '';
|
||||
$stamina_data = '';
|
||||
if($this->db->hasColumn('players', 'stamina')) {
|
||||
$stamina = ', `stamina`';
|
||||
$stamina_data = ', ' . $this->data['stamina'];
|
||||
}
|
||||
|
||||
$lookaddons = '';
|
||||
$lookaddons_data = '';
|
||||
if($this->db->hasColumn('players', 'lookaddons')) {
|
||||
$lookaddons = ', `lookaddons`';
|
||||
$lookaddons_data = ', ' . $this->data['lookaddons'];
|
||||
}
|
||||
|
||||
// INSERT query on database
|
||||
$this->db->query('INSERT INTO `players` (`name`, `account_id`, `group_id`, `sex`, `vocation`, `experience`, `level`, `maglevel`, `health`, `healthmax`, `mana`, `manamax`, `manaspent`, `soul`, `lookbody`, `lookfeet`, `lookhead`, `looklegs`, `looktype`' . $lookaddons . ', `posx`, `posy`, `posz`, `cap`, `lastlogin`, `lastlogout`, `lastip`, `save`, `conditions`, `' . $skull_time . '`, `' . $skull_type . '`' . $guild_info . ', `town_id`' . $loss . $loss_items . ', `balance`' . $blessings . $stamina . $direction . ', `created`' . $promotion . ', `comment`) VALUES (' . $this->db->quote($this->data['name']) . ', ' . $this->data['account_id'] . ', ' . $this->data['group_id'] . ', ' . $this->data['sex'] . ', ' . $this->data['vocation'] . ', ' . $this->data['experience'] . ', ' . $this->data['level'] . ', ' . $this->data['maglevel'] . ', ' . $this->data['health'] . ', ' . $this->data['healthmax'] . ', ' . $this->data['mana'] . ', ' . $this->data['manamax'] . ', ' . $this->data['manaspent'] . ', ' . $this->data['soul'] . ', ' . $this->data['lookbody'] . ', ' . $this->data['lookfeet'] . ', ' . $this->data['lookhead'] . ', ' . $this->data['looklegs'] . ', ' . $this->data['looktype'] . $lookaddons_data . ', ' . $this->data['posx'] . ', ' . $this->data['posy'] . ', ' . $this->data['posz'] . ', ' . $this->data['cap'] . ', ' . $this->data['lastlogin'] . ', ' . $this->data['lastlogout'] . ', ' . $this->data['lastip'] . ', ' . (int) $this->data['save'] . ', ' . $this->db->quote($this->data['conditions']) . ', ' . $this->data['skulltime'] . ', ' . (int) $this->data['skull'] . $guild_info_data . ', ' . $this->data['town_id'] . $loss_data . $loss_items_data . ', ' . $this->data['balance'] . $blessings_data . $stamina_data . $direction_data . ', ' . time() . $promotion_data . ', "")');
|
||||
// ID of new group
|
||||
$this->data['id'] = $this->db->lastInsertId();
|
||||
$this->data['id'] = $player->id;
|
||||
}
|
||||
|
||||
// updates skills - doesn't matter if we have just created character - trigger inserts new skills
|
||||
@@ -490,7 +308,7 @@ class OTS_Player extends OTS_Row_DAO
|
||||
$set .= ',';
|
||||
}
|
||||
|
||||
$skills = $this->db->query('UPDATE `players` SET ' . $set . ' WHERE `id` = ' . $this->data['id']);
|
||||
$this->db->query('UPDATE `players` SET ' . $set . ' WHERE `id` = ' . $this->data['id']);
|
||||
}
|
||||
else if($this->db->hasTable('player_skills')) {
|
||||
foreach($this->skills as $id => $skill)
|
||||
@@ -748,21 +566,25 @@ class OTS_Player extends OTS_Row_DAO
|
||||
|
||||
public function isDeleted()
|
||||
{
|
||||
$field = 'deleted';
|
||||
$column = 'deleted';
|
||||
if($this->db->hasColumn('players', 'deletion'))
|
||||
$field = 'deletion';
|
||||
$column = 'deletion';
|
||||
|
||||
if( !isset($this->data[$field]) )
|
||||
if( !isset($this->data[$column]) )
|
||||
{
|
||||
throw new E_OTS_NotLoaded();
|
||||
}
|
||||
|
||||
return $this->data[$field] > 0;
|
||||
return $this->data[$column] > 0;
|
||||
}
|
||||
|
||||
public function setDeleted($deleted)
|
||||
{
|
||||
$this->data['deleted'] = (int) $deleted;
|
||||
$column = 'deleted';
|
||||
if($this->db->hasColumn('players', 'deletion'))
|
||||
$column = 'deletion';
|
||||
|
||||
$this->data[$column] = (int) $deleted;
|
||||
}
|
||||
|
||||
public function isOnline()
|
||||
@@ -852,13 +674,7 @@ class OTS_Player extends OTS_Row_DAO
|
||||
throw new E_OTS_NotLoaded();
|
||||
}
|
||||
|
||||
if(isset($this->data['promotion'])) {
|
||||
global $config;
|
||||
if((int)$this->data['promotion'] > 0)
|
||||
return ($this->data['vocation'] + ($this->data['promotion'] * $config['vocations_amount']));
|
||||
}
|
||||
|
||||
return $this->data['vocation'];
|
||||
return \OTS_Toolbox::getVocationFromPromotion($this->data['vocation'], $this->data['promotion'] ?? 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -1574,12 +1390,7 @@ class OTS_Player extends OTS_Row_DAO
|
||||
*/
|
||||
public function getCap()
|
||||
{
|
||||
if( !isset($this->data['cap']) )
|
||||
{
|
||||
throw new E_OTS_NotLoaded();
|
||||
}
|
||||
|
||||
return $this->data['cap'];
|
||||
return $this->data['cap'] ?? 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1792,12 +1603,12 @@ class OTS_Player extends OTS_Row_DAO
|
||||
*/
|
||||
public function getSkullTime()
|
||||
{
|
||||
if( !isset($this->data['skulltime']) )
|
||||
{
|
||||
throw new E_OTS_NotLoaded();
|
||||
$column = 'skulltime';
|
||||
if($this->db->hasColumn('players', 'skull_time')) {
|
||||
$column = 'skull_time';
|
||||
}
|
||||
|
||||
return $this->data['skulltime'];
|
||||
return $this->data[$column] ?? 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1811,7 +1622,12 @@ class OTS_Player extends OTS_Row_DAO
|
||||
*/
|
||||
public function setSkullTime($skulltime)
|
||||
{
|
||||
$this->data['skulltime'] = (int) $skulltime;
|
||||
$column = 'skulltime';
|
||||
if($this->db->hasColumn('players', 'skull_time')) {
|
||||
$column = 'skull_time';
|
||||
}
|
||||
|
||||
$this->data[$column] = (int) $skulltime;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3250,6 +3066,10 @@ class OTS_Player extends OTS_Row_DAO
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function setData(array $data): void{
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic PHP5 method.
|
||||
*
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
* @license http://www.gnu.org/licenses/lgpl-3.0.txt GNU Lesser General Public License, Version 3
|
||||
*/
|
||||
|
||||
use MyAAC\Server\XML\Vocations;
|
||||
|
||||
/**
|
||||
* Toolbox for common operations.
|
||||
*
|
||||
@@ -110,14 +112,21 @@ class OTS_Toolbox
|
||||
$list->setFilter($filter);
|
||||
return $list;
|
||||
}
|
||||
|
||||
public static function getVocationName($id, $promotion = 0): string
|
||||
public static function getVocationFromPromotion($id, $promotion = 0): int
|
||||
{
|
||||
if($promotion > 0) {
|
||||
$id = ($id + ($promotion * config('vocations_amount')));
|
||||
for ($i = 0; $i < $promotion; $i++) {
|
||||
if ($_id = Vocations::getPromoted($id)) {
|
||||
$id = $_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return config('vocations')[$id] ?? 'Unknown';
|
||||
return $id;
|
||||
}
|
||||
|
||||
public static function getVocationName($id, $promotion = 0): string {
|
||||
return config('vocations')[self::getVocationFromPromotion($id, $promotion)] ?? 'Unknown';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
42
system/migrations/47.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/**
|
||||
* @var OTS_DB_MySQL $db
|
||||
*/
|
||||
|
||||
// 2025-02-27
|
||||
// remove ipv6, change to ip (for both ipv4 + ipv6) as VARCHAR(45)
|
||||
$up = function () use ($db) {
|
||||
$accountActionsInfo = $db->getColumnInfo(TABLE_PREFIX . 'account_actions', 'account_id');
|
||||
if ($accountActionsInfo && is_array($accountActionsInfo) && $accountActionsInfo['key'] == 'pri') {
|
||||
$db->query("ALTER TABLE `myaac_account_actions` DROP KEY `account_id`;");
|
||||
}
|
||||
|
||||
if (!$db->hasColumn(TABLE_PREFIX . 'account_actions', 'id')) {
|
||||
$db->addColumn(TABLE_PREFIX . 'account_actions', 'id', 'INT NOT NULL AUTO_INCREMENT FIRST, ADD PRIMARY KEY (`id`)');
|
||||
}
|
||||
|
||||
$db->modifyColumn(TABLE_PREFIX . 'account_actions', 'ip', "VARCHAR(45) NOT NULL DEFAULT ''");
|
||||
$db->query("UPDATE `" . TABLE_PREFIX . "account_actions` SET `ip` = INET_NTOA(`ip`) WHERE `ip` != '0';");
|
||||
$db->query("UPDATE `" . TABLE_PREFIX . "account_actions` SET `ip` = INET6_NTOA(`ipv6`) WHERE `ip` = '0';");
|
||||
|
||||
if ($db->hasColumn(TABLE_PREFIX . 'account_actions', 'ipv6')) {
|
||||
$db->dropColumn(TABLE_PREFIX . 'account_actions', 'ipv6');
|
||||
}
|
||||
};
|
||||
|
||||
$down = function () use ($db) {
|
||||
if ($db->hasColumn(TABLE_PREFIX . 'account_actions', 'id')) {
|
||||
$db->query("ALTER TABLE `" . TABLE_PREFIX . "account_actions` DROP `id`;");
|
||||
}
|
||||
|
||||
$db->query("ALTER TABLE `" . TABLE_PREFIX . "account_actions` ADD KEY (`account_id`);");
|
||||
|
||||
if (!$db->hasColumn(TABLE_PREFIX . 'account_actions', 'ipv6')) {
|
||||
$db->addColumn(TABLE_PREFIX . 'account_actions', 'ipv6', "BINARY(16) NOT NULL DEFAULT 0x00000000000000000000000000000000 AFTER ip");
|
||||
}
|
||||
|
||||
$db->query("UPDATE `" . TABLE_PREFIX . "account_actions` SET `ipv6` = INET6_ATON(ip) WHERE NOT IS_IPV4(`ip`);");
|
||||
$db->query("UPDATE `" . TABLE_PREFIX . "account_actions` SET `ip` = INET_ATON(`ip`) WHERE IS_IPV4(`ip`);");
|
||||
$db->query("UPDATE `" . TABLE_PREFIX . "account_actions` SET `ip` = 0 WHERE `ipv6` != 0x00000000000000000000000000000000;");
|
||||
$db->modifyColumn(TABLE_PREFIX . 'account_actions', 'ip', "INT(11) UNSIGNED NOT NULL DEFAULT 0;");
|
||||
};
|
||||
16
system/migrations/48.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
/**
|
||||
* @var OTS_DB_MySQL $db
|
||||
*/
|
||||
|
||||
$up = function () use ($db) {
|
||||
if (!$db->hasColumn(TABLE_PREFIX . 'menu', 'access')) {
|
||||
$db->addColumn(TABLE_PREFIX . 'menu', 'access', 'TINYINT NOT NULL DEFAULT 0 AFTER `link`');
|
||||
}
|
||||
};
|
||||
|
||||
$down = function () use ($db) {
|
||||
if ($db->hasColumn(TABLE_PREFIX . 'menu', 'access')) {
|
||||
$db->dropColumn(TABLE_PREFIX . 'menu', 'access');
|
||||
}
|
||||
};
|
||||
@@ -9,7 +9,7 @@ $up = function () use ($db) {
|
||||
}
|
||||
};
|
||||
|
||||
$up = function () use ($db) {
|
||||
$down = function () use ($db) {
|
||||
if (!$db->hasColumn(TABLE_PREFIX . 'screenshots', 'name')) {
|
||||
$db->addColumn(TABLE_PREFIX . 'screenshots', 'name', 'VARCHAR(30) NOT NULL');
|
||||
}
|
||||
|
||||
29
system/pages/#examples/top-5.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
/**
|
||||
* Example of using getTopPlayers() function
|
||||
* to display the best players for each skill
|
||||
*/
|
||||
defined('MYAAC') or die('Direct access not allowed!');
|
||||
|
||||
$skills = [
|
||||
'magic', 'level',
|
||||
'balance', 'frags',
|
||||
POT::SKILL_FIST, POT::SKILL_CLUB,
|
||||
POT::SKILL_SWORD, POT::SKILL_AXE,
|
||||
POT::SKILL_DISTANCE, POT::SKILL_SHIELD,
|
||||
POT::SKILL_FISH
|
||||
];
|
||||
|
||||
foreach ($skills as $skill) {?>
|
||||
<ul>
|
||||
<?php
|
||||
echo '<strong>' . ucwords(is_string($skill) ? $skill : getSkillName($skill)) . '</strong>';
|
||||
foreach (getTopPlayers(5, $skill) as $player) {?>
|
||||
<li><?= $player['rank'] . '. ' . $player['name'] . ' - ' . $player['value']; ?></li>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</ul>
|
||||
<?php
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ csrfProtect();
|
||||
$new_password = $_POST['new_password'] ?? null;
|
||||
$new_password_confirm = $_POST['new_password_confirm'] ?? null;
|
||||
$old_password = $_POST['old_password'] ?? null;
|
||||
if(empty($new_password) && empty($new_password_confirm) && empty($old_password)) {
|
||||
if(is_null($new_password) && is_null($new_password_confirm) && is_null($old_password)) {
|
||||
$twig->display('account.change-password.html.twig');
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -96,12 +96,8 @@ if($email_new_time > 1)
|
||||
}
|
||||
}
|
||||
|
||||
$actions = array();
|
||||
foreach($account_logged->getActionsLog(0, 1000) as $action) {
|
||||
$actions[] = array('action' => $action['action'], 'date' => $action['date'], 'ip' => $action['ip'] != 0 ? long2ip($action['ip']) : inet_ntop($action['ipv6']));
|
||||
}
|
||||
$actions = $account_logged->getActionsLog(1000);
|
||||
|
||||
$players = array();
|
||||
/** @var OTS_Players_List $account_players */
|
||||
$account_players = $account_logged->getPlayersList();
|
||||
$account_players->orderBy('id');
|
||||
|
||||
@@ -48,7 +48,7 @@ else
|
||||
$account_logged->setCustomField('key', $new_rec_key);
|
||||
$account_logged->setCustomField(setting('core.donate_column'), $account_logged->getCustomField(setting('core.donate_column')) - setting('core.account_generate_new_reckey_price'));
|
||||
$account_logged->logAction('Generated new recovery key for ' . setting('core.account_generate_new_reckey_price') . ' premium points.');
|
||||
$message = '<br />Your recovery key were send on email address <b>'.$account_logged->getEMail().'</b> for '.setting('core.account_generate_new_reckey_price').' premium points.';
|
||||
$message = '<br />Your recovery key was sent on email address <b>'.$account_logged->getEMail().'</b> for '.setting('core.account_generate_new_reckey_price').' premium points.';
|
||||
}
|
||||
else
|
||||
$message = '<br /><p class="error">An error occurred while sending email ( <b>'.$account_logged->getEMail().'</b> ) with recovery key! Recovery key not changed. Try again later. For Admin: More info can be found in system/logs/mailer-error.log</p>';
|
||||
|
||||
@@ -452,10 +452,8 @@ WHERE killers.death_id = '".$death['id']."' ORDER BY killers.final_hit DESC, kil
|
||||
if($query->rowCount() > 0) {
|
||||
echo 'Did you mean:<ul>';
|
||||
foreach($query as $player) {
|
||||
if(isset($player['promotion'])) {
|
||||
if((int)$player['promotion'] > 0)
|
||||
$player['vocation'] += ($player['promotion'] * $config['vocations_amount']);
|
||||
}
|
||||
$player['vocation'] = OTS_Toolbox::getVocationFromPromotion($player['vocation'], $player['promotion'] ?? 0);
|
||||
|
||||
echo '<li>' . getPlayerLink($player['name']) . ' (<small><strong>level ' . $player['level'] . ', ' . $config['vocations'][$player['vocation']] . '</strong></small>)</li>';
|
||||
}
|
||||
echo '</ul>';
|
||||
|
||||
@@ -42,35 +42,12 @@ for($i = 0; $i < $threads_count['threads_count'] / setting('core.forum_threads_p
|
||||
$links_to_pages .= '<b>'.($i + 1).' </b>';
|
||||
}
|
||||
|
||||
echo '<a href="' . getLink('forum') . '">Boards</a> >> <b>'.$sections[$section_id]['name'].'</b>';
|
||||
|
||||
if($logged && (!$sections[$section_id]['closed'] || Forum::isModerator())) {
|
||||
echo '<br /><br />
|
||||
<a href="' . getLink('forum') . '?action=new_thread§ion_id='.$section_id.'"><img src="images/forum/topic.gif" border="0" /></a>';
|
||||
}
|
||||
|
||||
echo '<br /><br />Page: '.$links_to_pages.'<br />';
|
||||
$last_threads = $db->query("SELECT `players`.`id` as `player_id`, `players`.`name`, `" . FORUM_TABLE_PREFIX . "forum`.`first_post`, `" . FORUM_TABLE_PREFIX . "forum`.`post_text`, `" . FORUM_TABLE_PREFIX . "forum`.`post_topic`, `" . FORUM_TABLE_PREFIX . "forum`.`id`, `" . FORUM_TABLE_PREFIX . "forum`.`last_post`, `" . FORUM_TABLE_PREFIX . "forum`.`replies`, `" . FORUM_TABLE_PREFIX . "forum`.`views`, `" . FORUM_TABLE_PREFIX . "forum`.`post_date` FROM `players`, `" . FORUM_TABLE_PREFIX . "forum` WHERE `players`.`id` = `" . FORUM_TABLE_PREFIX . "forum`.`author_guid` AND `" . FORUM_TABLE_PREFIX . "forum`.`section` = ".$section_id." AND `" . FORUM_TABLE_PREFIX . "forum`.`first_post` = `" . FORUM_TABLE_PREFIX . "forum`.`id` ORDER BY `" . FORUM_TABLE_PREFIX . "forum`.`last_post` DESC LIMIT ".setting('core.forum_threads_per_page')." OFFSET ".($_page * setting('core.forum_threads_per_page')))->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
if(isset($last_threads[0])) {
|
||||
echo '<table width="100%">
|
||||
<tr bgcolor="'.$config['vdarkborder'].'" align="center">
|
||||
<td class="white">
|
||||
<span style="font-size: 10px"><b>Thread</b></span></td>
|
||||
<td><span style="font-size: 10px"><b>Thread Starter</b></span></td>
|
||||
<td><span style="font-size: 10px"><b>Replies</b></span></td>
|
||||
<td><span style="font-size: 10px"><b>Views</b></span></td>
|
||||
<td><span style="font-size: 10px"><b>Last Post</b></span></td>
|
||||
</tr>';
|
||||
|
||||
$threads = [];
|
||||
if(count($last_threads) > 0) {
|
||||
$player = new OTS_Player();
|
||||
foreach($last_threads as $thread) {
|
||||
echo '<tr bgcolor="' . getStyle($number_of_rows++) . '"><td>';
|
||||
if(Forum::isModerator()) {
|
||||
echo '<a href="' . getLink('forum') . '?action=move_thread&id=' . $thread['id'] . '" title="Move Thread"><img src="images/icons/arrow_right.gif"/></a>';
|
||||
$twig->display('forum.remove_post.html.twig', ['post' => $thread]);
|
||||
}
|
||||
|
||||
$player->load($thread['player_id']);
|
||||
if(!$player->isLoaded()) {
|
||||
throw new RuntimeException('Forum error: Player not loaded.');
|
||||
@@ -79,28 +56,29 @@ if(isset($last_threads[0])) {
|
||||
$player_account = $player->getAccount();
|
||||
$canEditForum = $player_account->hasFlag(FLAG_CONTENT_FORUM) || $player_account->isAdmin();
|
||||
|
||||
echo '<a href="' . getForumThreadLink($thread['id']) . '">'.htmlspecialchars($thread['post_topic']). '</a><br /><small>'.($canEditForum ? substr(strip_tags($thread['post_text']), 0, 50) : htmlspecialchars(substr($thread['post_text'], 0, 50))).'...</small></td><td>' . getPlayerLink($thread['name']) . '</td><td>'.(int) $thread['replies'].'</td><td>'.(int) $thread['views'].'</td><td>';
|
||||
$thread['link'] = getForumThreadLink($thread['id']);
|
||||
|
||||
$thread['post_shortened'] = ($canEditForum ? substr(strip_tags($thread['post_text']), 0, 50) : htmlspecialchars(substr($thread['post_text'], 0, 50)));
|
||||
|
||||
$thread['player'] = $player;
|
||||
$thread['player_link'] = getPlayerLink($thread['name']);
|
||||
|
||||
if($thread['last_post'] > 0) {
|
||||
$last_post = $db->query("SELECT `players`.`name`, `" . FORUM_TABLE_PREFIX . "forum`.`post_date` FROM `players`, `" . FORUM_TABLE_PREFIX . "forum` WHERE `" . FORUM_TABLE_PREFIX . "forum`.`first_post` = ".(int) $thread['id']." AND `players`.`id` = `" . FORUM_TABLE_PREFIX . "forum`.`author_guid` ORDER BY `post_date` DESC LIMIT 1")->fetch();
|
||||
|
||||
if(isset($last_post['name'])) {
|
||||
echo date('d.m.y H:i:s', $last_post['post_date']) . '<br />by ' . getPlayerLink($last_post['name']);
|
||||
}
|
||||
else {
|
||||
echo 'No posts.';
|
||||
}
|
||||
}
|
||||
else {
|
||||
echo date('d.m.y H:i:s', $thread['post_date']) . '<br />by ' . getPlayerLink($thread['name']);
|
||||
}
|
||||
echo '</td></tr>';
|
||||
$last_post['player_link'] = getPlayerLink($last_post['name']);
|
||||
$thread['latest_post'] = $last_post;
|
||||
}
|
||||
|
||||
echo '</table>';
|
||||
if($logged && (!$sections[$section_id]['closed'] || Forum::isModerator())) {
|
||||
echo '<br /><a href="' . getLink('forum') . '?action=new_thread§ion_id=' . $section_id . '"><img src="images/forum/topic.gif" border="0" /></a>';
|
||||
$threads[] = $thread;
|
||||
}
|
||||
}
|
||||
else {
|
||||
echo '<h3>No threads in this board.</h3>';
|
||||
}
|
||||
|
||||
$twig->display('forum.show_board.html.twig', [
|
||||
'threads' => $threads,
|
||||
'section_id' => $section_id,
|
||||
'section_name' => $sections[$section_id]['name'],
|
||||
'links_to_pages' => $links_to_pages,
|
||||
'is_moderator' => Forum::isModerator(),
|
||||
'closed' => $sections[$section_id]['closed'],
|
||||
]);
|
||||
|
||||
@@ -13,6 +13,7 @@ use MyAAC\Cache\Cache;
|
||||
use MyAAC\Models\Player;
|
||||
use MyAAC\Models\PlayerDeath;
|
||||
use MyAAC\Models\PlayerKillers;
|
||||
use MyAAC\Server\XML\Vocations;
|
||||
|
||||
defined('MYAAC') or die('Direct access not allowed!');
|
||||
$title = 'Highscores';
|
||||
@@ -35,24 +36,20 @@ if(!is_numeric($page) || $page < 1 || $page > PHP_INT_MAX) {
|
||||
$query = Player::query();
|
||||
|
||||
$configVocations = config('vocations');
|
||||
$configVocationsAmount = config('vocations_amount');
|
||||
|
||||
$vocationId = null;
|
||||
if($vocation !== 'all') {
|
||||
foreach($configVocations as $id => $name) {
|
||||
if(strtolower($name) == $vocation) {
|
||||
$vocationId = $id;
|
||||
$add_vocs = [$id];
|
||||
$filterVocations = [$id];
|
||||
|
||||
if ($id !== 0) {
|
||||
$i = $id + $configVocationsAmount;
|
||||
while (isset($configVocations[$i])) {
|
||||
$add_vocs[] = $i;
|
||||
$i += $configVocationsAmount;
|
||||
}
|
||||
while($tmpVoc = Vocations::getPromoted($id)) {
|
||||
$id = $tmpVoc;
|
||||
$filterVocations[] = $tmpVoc;
|
||||
}
|
||||
|
||||
$query->whereIn('players.vocation', $add_vocs);
|
||||
$query->whereIn('players.vocation', $filterVocations);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -176,7 +173,9 @@ if (empty($highscores)) {
|
||||
POT::SKILL_FISH => 'skill_fishing',
|
||||
);
|
||||
|
||||
$query->addSelect($skill_ids[$skill] . ' as value');
|
||||
$query
|
||||
->addSelect($skill_ids[$skill] . ' as value')
|
||||
->orderByDesc($skill_ids[$skill] . '_tries');
|
||||
} else {
|
||||
$query
|
||||
->join('player_skills', 'player_skills.player_id', '=', 'players.id')
|
||||
@@ -198,11 +197,11 @@ if (empty($highscores)) {
|
||||
if ($skill == POT::SKILL__MAGLEVEL) {
|
||||
$query
|
||||
->addSelect('players.maglevel as value', 'players.maglevel')
|
||||
->orderBy('manaspent');
|
||||
->orderByDesc('manaspent');
|
||||
} else { // level
|
||||
$query
|
||||
->addSelect('players.level as value', 'players.experience')
|
||||
->orderBy('experience');
|
||||
->orderByDesc('experience');
|
||||
$list = 'experience';
|
||||
}
|
||||
}
|
||||
@@ -247,7 +246,7 @@ foreach($highscores as $id => &$player)
|
||||
|
||||
$player['link'] = getPlayerLink($player['name'], false);
|
||||
$player['flag'] = getFlagImage($player['country']);
|
||||
$player['outfit'] = '<img style="position:absolute;margin-top:' . (in_array($player['looktype'], setting('core.outfit_images_wrong_looktypes')) ? '-15px;margin-left:5px' : '-45px;margin-left:-25px') . ';" src="' . $player['outfit_url'] . '" alt="" />';
|
||||
$player['outfit'] = '<img style="position:absolute;margin-top:-50px;margin-left:-30px" src="' . $player['outfit_url'] . '" alt="" />';
|
||||
|
||||
if ($skill != POT::SKILL__LEVEL) {
|
||||
if (isset($lastValue) && $lastValue == $player['value']) {
|
||||
@@ -323,4 +322,5 @@ $twig->display('highscores.html.twig', [
|
||||
'page' => $page,
|
||||
'baseLink' => $baseLink,
|
||||
'updatedAt' => $updatedAt,
|
||||
'baseVocations' => Vocations::getBase(true),
|
||||
]);
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
use MyAAC\Cache\Cache;
|
||||
use MyAAC\Models\ServerConfig;
|
||||
use MyAAC\Models\ServerRecord;
|
||||
use MyAAC\Server\XML\Vocations;
|
||||
|
||||
defined('MYAAC') or die('Direct access not allowed!');
|
||||
$title = 'Who is online?';
|
||||
@@ -56,15 +57,14 @@ $cached = Cache::remember("online_$order", setting('core.online_cache_ttl') * 60
|
||||
|
||||
$vocations = array_map(function ($name) {
|
||||
return 0;
|
||||
}, setting('core.vocations'));
|
||||
}, config('vocations'));
|
||||
|
||||
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 ' . $orderSql);
|
||||
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 ' . $orderSql);
|
||||
|
||||
$settingVocations = setting('core.vocations');
|
||||
$settingVocationsAmount = setting('core.vocations_amount');
|
||||
$configVocations = config('vocations');
|
||||
|
||||
$players = [];
|
||||
foreach($playersOnline as $player) {
|
||||
@@ -81,22 +81,19 @@ $cached = Cache::remember("online_$order", setting('core.online_cache_ttl') * 60
|
||||
}
|
||||
}
|
||||
|
||||
if(isset($player['promotion'])) {
|
||||
if((int)$player['promotion'] > 0)
|
||||
$player['vocation'] += ($player['promotion'] * $settingVocationsAmount);
|
||||
}
|
||||
$player['vocation'] = OTS_Toolbox::getVocationFromPromotion($player['vocation'], $player['promotion'] ?? 0);
|
||||
|
||||
$players[] = array(
|
||||
'name' => getPlayerLink($player['name']),
|
||||
'player' => $player,
|
||||
'level' => $player['level'],
|
||||
'vocation' => $settingVocations[$player['vocation']],
|
||||
'vocation' => $configVocations[$player['vocation']],
|
||||
'skull' => $skull,
|
||||
'country_image' => getFlagImage($player['country']),
|
||||
'outfit' => setting('core.outfit_images_url') . '?id=' . $player['looktype'] . ($outfit_addons ? '&addons=' . $player['lookaddons'] : '') . '&head=' . $player['lookhead'] . '&body=' . $player['lookbody'] . '&legs=' . $player['looklegs'] . '&feet=' . $player['lookfeet'],
|
||||
);
|
||||
|
||||
$vocations[($player['vocation'] > $settingVocationsAmount ? $player['vocation'] - $settingVocationsAmount : $player['vocation'])]++;
|
||||
$vocations[Vocations::getOriginal($player['vocation'])]++;
|
||||
}
|
||||
|
||||
$record = '';
|
||||
@@ -142,6 +139,7 @@ $twig->display('online.html.twig', array(
|
||||
'vocations' => $cached['vocations'],
|
||||
'vocs' => $cached['vocations'], // deprecated, to be removed
|
||||
'order' => $order,
|
||||
'baseVocations' => Vocations::getBase(false),
|
||||
));
|
||||
|
||||
// search bar
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* @link https://my-aac.org
|
||||
*/
|
||||
|
||||
use MyAAC\Models\Menu;
|
||||
use MyAAC\Models\Pages;
|
||||
use MyAAC\Plugins;
|
||||
|
||||
@@ -331,7 +332,20 @@ else {
|
||||
}
|
||||
}
|
||||
|
||||
if (!$found) {
|
||||
$tmpPageOriginal = $page;
|
||||
$pagesWithDynamicPart = ['characters', 'forum', 'highscores', 'monsters'];
|
||||
foreach ($pagesWithDynamicPart as $_page) {
|
||||
if (str_contains($page, $_page)) {
|
||||
$tmpPageOriginal = $_page;
|
||||
}
|
||||
}
|
||||
|
||||
$themeMenu = Menu::select(['name'])
|
||||
->where('template', $template_name)
|
||||
->where('link', $tmpPageOriginal)
|
||||
->where('access', '>', $logged_access);
|
||||
|
||||
if (!$found || $themeMenu->count() >= 1) {
|
||||
$page = '404';
|
||||
$file = SYSTEM . 'pages/404.php';
|
||||
}
|
||||
|
||||
@@ -219,7 +219,14 @@ return [
|
||||
'cache_engine' => [
|
||||
'name' => 'Cache Engine',
|
||||
'type' => 'options',
|
||||
'options' => ['auto' => 'Auto', 'file' => 'Files', 'apc' => 'APC', 'apcu' => 'APCu', 'disable' => 'Disable'],
|
||||
'options' => [
|
||||
'auto' => 'Auto',
|
||||
'file' => 'Files',
|
||||
'apc' => 'APC',
|
||||
'apcu' => 'APCu',
|
||||
'php' => 'PHP',
|
||||
'disable' => 'Disable',
|
||||
],
|
||||
'desc' => 'Auto is most reasonable. It will detect the best cache engine',
|
||||
'default' => 'auto',
|
||||
'is_config' => true,
|
||||
@@ -312,23 +319,6 @@ return [
|
||||
},
|
||||
],
|
||||
],
|
||||
'vocations_amount' => [
|
||||
'name' => 'Vocations Amount',
|
||||
'type' => 'number',
|
||||
'desc' => 'How much basic vocations your server got (without promotion)',
|
||||
'default' => 4,
|
||||
],
|
||||
'vocations' => [
|
||||
'name' => 'Vocation Names',
|
||||
'type' => 'textarea',
|
||||
'desc' => 'Separated by comma. Must be in the same order as in vocations.xml, starting with id: 0.',
|
||||
'default' => 'None, Sorcerer, Druid, Paladin, Knight, Master Sorcerer, Elder Druid,Royal Paladin, Elite Knight',
|
||||
'callbacks' => [
|
||||
'get' => function ($value) {
|
||||
return array_map('trim', explode(',', $value));
|
||||
},
|
||||
],
|
||||
],
|
||||
[
|
||||
'type' => 'category',
|
||||
'title' => 'Database',
|
||||
@@ -1482,17 +1472,6 @@ Sent by MyAAC,<br/>
|
||||
'desc' => 'Set to animoutfit.php for animated outfit',
|
||||
'default' => 'https://outfit-images.ots.me/latest/outfit.php',
|
||||
],
|
||||
'outfit_images_wrong_looktypes' => [
|
||||
'name' => 'Outfit Images Wrong Looktypes',
|
||||
'type' => 'text',
|
||||
'desc' => 'This looktypes needs to have different margin-top and margin-left because they are wrong positioned',
|
||||
'default' => '75, 126, 127, 266, 302',
|
||||
'callbacks' => [
|
||||
'get' => function ($value) {
|
||||
return array_map('trim', explode(',', $value));
|
||||
},
|
||||
],
|
||||
],
|
||||
[
|
||||
'type' => 'section',
|
||||
'title' => 'Monster Images'
|
||||
|
||||
@@ -13,8 +13,8 @@ namespace MyAAC\Cache;
|
||||
|
||||
class APC
|
||||
{
|
||||
private $prefix;
|
||||
private $enabled;
|
||||
private string $prefix;
|
||||
private bool $enabled;
|
||||
|
||||
public function __construct($prefix = '')
|
||||
{
|
||||
@@ -22,14 +22,14 @@ class APC
|
||||
$this->enabled = function_exists('apc_fetch');
|
||||
}
|
||||
|
||||
public function set($key, $var, $ttl = 0)
|
||||
public function set($key, $var, $ttl = 0): void
|
||||
{
|
||||
$key = $this->prefix . $key;
|
||||
apc_delete($key);
|
||||
apc_store($key, $var, $ttl);
|
||||
}
|
||||
|
||||
public function get($key)
|
||||
public function get($key): string
|
||||
{
|
||||
$tmp = '';
|
||||
if ($this->fetch($this->prefix . $key, $tmp)) {
|
||||
@@ -39,18 +39,15 @@ class APC
|
||||
return '';
|
||||
}
|
||||
|
||||
public function fetch($key, &$var)
|
||||
{
|
||||
public function fetch($key, &$var): bool {
|
||||
return ($var = apc_fetch($this->prefix . $key)) !== false;
|
||||
}
|
||||
|
||||
public function delete($key)
|
||||
{
|
||||
public function delete($key): void {
|
||||
apc_delete($this->prefix . $key);
|
||||
}
|
||||
|
||||
public function enabled()
|
||||
{
|
||||
public function enabled(): bool {
|
||||
return $this->enabled;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,8 +13,8 @@ namespace MyAAC\Cache;
|
||||
|
||||
class APCu
|
||||
{
|
||||
private $prefix;
|
||||
private $enabled;
|
||||
private string $prefix;
|
||||
private bool $enabled;
|
||||
|
||||
public function __construct($prefix = '')
|
||||
{
|
||||
@@ -22,14 +22,14 @@ class APCu
|
||||
$this->enabled = function_exists('apcu_fetch');
|
||||
}
|
||||
|
||||
public function set($key, $var, $ttl = 0)
|
||||
public function set($key, $var, $ttl = 0): void
|
||||
{
|
||||
$key = $this->prefix . $key;
|
||||
apcu_delete($key);
|
||||
apcu_store($key, $var, $ttl);
|
||||
}
|
||||
|
||||
public function get($key)
|
||||
public function get($key): string
|
||||
{
|
||||
$tmp = '';
|
||||
if ($this->fetch($this->prefix . $key, $tmp)) {
|
||||
@@ -39,18 +39,15 @@ class APCu
|
||||
return '';
|
||||
}
|
||||
|
||||
public function fetch($key, &$var)
|
||||
{
|
||||
public function fetch($key, &$var): bool {
|
||||
return ($var = apcu_fetch($this->prefix . $key)) !== false;
|
||||
}
|
||||
|
||||
public function delete($key)
|
||||
{
|
||||
public function delete($key): void {
|
||||
apcu_delete($this->prefix . $key);
|
||||
}
|
||||
|
||||
public function enabled()
|
||||
{
|
||||
public function enabled(): bool {
|
||||
return $this->enabled;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,35 +47,15 @@ class Cache
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
switch (strtolower($engine)) {
|
||||
case 'apc':
|
||||
self::$instance = new APC($prefix);
|
||||
break;
|
||||
|
||||
case 'apcu':
|
||||
self::$instance = new APCu($prefix);
|
||||
break;
|
||||
|
||||
case 'xcache':
|
||||
self::$instance = new XCache($prefix);
|
||||
break;
|
||||
|
||||
case 'file':
|
||||
self::$instance = new File($prefix, CACHE);
|
||||
break;
|
||||
|
||||
case 'php':
|
||||
self::$instance = new PHP($prefix, CACHE);
|
||||
break;
|
||||
|
||||
case 'auto':
|
||||
self::$instance = self::generateInstance(self::detect(), $prefix);
|
||||
break;
|
||||
|
||||
default:
|
||||
self::$instance = new self();
|
||||
break;
|
||||
}
|
||||
self::$instance = match (strtolower($engine)) {
|
||||
'apc' => new APC($prefix),
|
||||
'apcu' => new APCu($prefix),
|
||||
'xcache' => new XCache($prefix),
|
||||
'file' => new File($prefix, CACHE),
|
||||
'php' => new PHP($prefix, CACHE),
|
||||
'auto' => self::generateInstance(self::detect(), $prefix),
|
||||
default => new self(),
|
||||
};
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
@@ -83,7 +63,7 @@ class Cache
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public static function detect()
|
||||
public static function detect(): string
|
||||
{
|
||||
if (function_exists('apc_fetch'))
|
||||
return 'apc';
|
||||
@@ -98,8 +78,7 @@ class Cache
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function enabled()
|
||||
{
|
||||
public function enabled(): bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,18 +12,22 @@ namespace MyAAC\Cache;
|
||||
|
||||
class File
|
||||
{
|
||||
private $prefix;
|
||||
private $dir;
|
||||
private $enabled;
|
||||
private string $prefix;
|
||||
private string $dir;
|
||||
private bool $enabled;
|
||||
|
||||
public function __construct($prefix = '', $dir = '')
|
||||
{
|
||||
$this->prefix = $prefix;
|
||||
$this->dir = $dir;
|
||||
|
||||
ensureFolderExists($this->dir);
|
||||
ensureIndexExists($this->dir);
|
||||
|
||||
$this->enabled = (file_exists($this->dir) && is_dir($this->dir) && is_writable($this->dir));
|
||||
}
|
||||
|
||||
public function set($key, $var, $ttl = 0)
|
||||
public function set($key, $var, $ttl = 0): void
|
||||
{
|
||||
$file = $this->_name($key);
|
||||
file_put_contents($file, $var);
|
||||
@@ -35,7 +39,7 @@ class File
|
||||
touch($file, time() + $ttl);
|
||||
}
|
||||
|
||||
public function get($key)
|
||||
public function get($key): string
|
||||
{
|
||||
$tmp = '';
|
||||
if ($this->fetch($key, $tmp)) {
|
||||
@@ -45,7 +49,7 @@ class File
|
||||
return '';
|
||||
}
|
||||
|
||||
public function fetch($key, &$var)
|
||||
public function fetch($key, &$var): bool
|
||||
{
|
||||
$file = $this->_name($key);
|
||||
if (!file_exists($file) || filemtime($file) < time()) {
|
||||
@@ -56,7 +60,7 @@ class File
|
||||
return true;
|
||||
}
|
||||
|
||||
public function delete($key)
|
||||
public function delete($key): void
|
||||
{
|
||||
$file = $this->_name($key);
|
||||
if (file_exists($file)) {
|
||||
@@ -64,13 +68,11 @@ class File
|
||||
}
|
||||
}
|
||||
|
||||
public function enabled()
|
||||
{
|
||||
public function enabled(): bool {
|
||||
return $this->enabled;
|
||||
}
|
||||
|
||||
private function _name($key)
|
||||
{
|
||||
private function _name($key): string {
|
||||
return sprintf('%s%s%s', $this->dir, $this->prefix, sha1($key));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,39 +12,40 @@ namespace MyAAC\Cache;
|
||||
|
||||
class PHP
|
||||
{
|
||||
private $prefix;
|
||||
private $dir;
|
||||
private $enabled;
|
||||
private string $prefix;
|
||||
private string $dir;
|
||||
private bool $enabled;
|
||||
|
||||
public function __construct($prefix = '', $dir = '')
|
||||
{
|
||||
$this->prefix = $prefix;
|
||||
$this->dir = $dir;
|
||||
$this->enabled = (file_exists($this->dir) && is_dir($this->dir) && is_writable($this->dir));
|
||||
}
|
||||
|
||||
public function set($key, $var, $ttl = 0)
|
||||
{
|
||||
$var = var_export($var, true);
|
||||
|
||||
ensureFolderExists($this->dir);
|
||||
ensureIndexExists($this->dir);
|
||||
|
||||
// Write to temp file first to ensure atomicity
|
||||
$tmp = $this->dir . "tmp_$key." . uniqid('', true) . '.tmp';
|
||||
file_put_contents($tmp, '<?php $var = ' . $var . ';', LOCK_EX);
|
||||
$this->enabled = (file_exists($this->dir) && is_dir($this->dir) && is_writable($this->dir));
|
||||
}
|
||||
|
||||
$file = $this->_name($key);
|
||||
rename($tmp, $file);
|
||||
public function set($key, $var, $ttl = 0): void
|
||||
{
|
||||
$var = var_export($var, true);
|
||||
|
||||
if ($ttl === 0) {
|
||||
$ttl = 365 * 24 * 60 * 60; // 365 days
|
||||
}
|
||||
|
||||
touch($file, time() + $ttl);
|
||||
$expires = time() + $ttl;
|
||||
|
||||
// Write to temp file first to ensure atomicity
|
||||
$tmp = $this->dir . "tmp_$key." . uniqid('', true) . '.tmp';
|
||||
file_put_contents($tmp, "<?php return ['expires' => $expires, 'var' => $var];", LOCK_EX);
|
||||
|
||||
$file = $this->_name($key);
|
||||
rename($tmp, $file);
|
||||
}
|
||||
|
||||
public function get($key)
|
||||
public function get($key): string
|
||||
{
|
||||
$tmp = '';
|
||||
if ($this->fetch($key, $tmp)) {
|
||||
@@ -54,19 +55,23 @@ class PHP
|
||||
return '';
|
||||
}
|
||||
|
||||
public function fetch($key, &$var)
|
||||
public function fetch($key, &$var): bool
|
||||
{
|
||||
$file = $this->_name($key);
|
||||
if (!file_exists($file) || filemtime($file) < time()) {
|
||||
if (!file_exists($file)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@include $file;
|
||||
$var = isset($var) ? $var : null;
|
||||
$content = include $file;
|
||||
if (!isset($content) || $content['expires'] < time()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$var = $content['var'];
|
||||
return true;
|
||||
}
|
||||
|
||||
public function delete($key)
|
||||
public function delete($key): void
|
||||
{
|
||||
$file = $this->_name($key);
|
||||
if (file_exists($file)) {
|
||||
@@ -74,13 +79,11 @@ class PHP
|
||||
}
|
||||
}
|
||||
|
||||
public function enabled()
|
||||
{
|
||||
public function enabled(): bool {
|
||||
return $this->enabled;
|
||||
}
|
||||
|
||||
private function _name($key)
|
||||
{
|
||||
private function _name($key): string {
|
||||
return sprintf('%s%s%s', $this->dir, $this->prefix, sha1($key) . '.php');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,8 +13,8 @@ namespace MyAAC\Cache;
|
||||
|
||||
class XCache
|
||||
{
|
||||
private $prefix;
|
||||
private $enabled;
|
||||
private string $prefix;
|
||||
private bool $enabled;
|
||||
|
||||
public function __construct($prefix = '')
|
||||
{
|
||||
@@ -22,14 +22,14 @@ class XCache
|
||||
$this->enabled = function_exists('xcache_get') && ini_get('xcache.var_size');
|
||||
}
|
||||
|
||||
public function set($key, $var, $ttl = 0)
|
||||
public function set($key, $var, $ttl = 0): void
|
||||
{
|
||||
$key = $this->prefix . $key;
|
||||
xcache_unset($key);
|
||||
xcache_set($key, $var, $ttl);
|
||||
}
|
||||
|
||||
public function get($key)
|
||||
public function get($key): string
|
||||
{
|
||||
$tmp = '';
|
||||
if ($this->fetch($this->prefix . $key, $tmp)) {
|
||||
@@ -39,7 +39,7 @@ class XCache
|
||||
return '';
|
||||
}
|
||||
|
||||
public function fetch($key, &$var)
|
||||
public function fetch($key, &$var): bool
|
||||
{
|
||||
$key = $this->prefix . $key;
|
||||
if (!xcache_isset($key)) {
|
||||
@@ -50,13 +50,11 @@ class XCache
|
||||
return true;
|
||||
}
|
||||
|
||||
public function delete($key)
|
||||
{
|
||||
public function delete($key): void {
|
||||
xcache_unset($this->prefix . $key);
|
||||
}
|
||||
|
||||
public function enabled()
|
||||
{
|
||||
public function enabled(): bool {
|
||||
return $this->enabled;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,7 +149,10 @@ class CreateCharacter
|
||||
if($db->hasColumn('players', 'direction'))
|
||||
$player->setDirection($playerSample->getDirection());
|
||||
|
||||
if($db->hasColumn('players', 'conditions')) {
|
||||
$player->setConditions($playerSample->getConditions());
|
||||
}
|
||||
|
||||
$rank = $playerSample->getRank();
|
||||
if($rank->isLoaded()) {
|
||||
$player->setRank($playerSample->getRank());
|
||||
@@ -183,7 +186,11 @@ class CreateCharacter
|
||||
$player->setLookHead($playerSample->getLookHead());
|
||||
$player->setLookLegs($playerSample->getLookLegs());
|
||||
$player->setLookType($playerSample->getLookType());
|
||||
|
||||
if($db->hasColumn('players', 'cap')) {
|
||||
$player->setCap($playerSample->getCap());
|
||||
}
|
||||
|
||||
$player->setBalance(0);
|
||||
$player->setPosX(0);
|
||||
$player->setPosY(0);
|
||||
|
||||
@@ -231,6 +231,7 @@ class Forum
|
||||
if(!is_int($rows / 2)) { $bgcolor = 'ABED25'; } else { $bgcolor = '23ED25'; } $rows++;
|
||||
$text = str_ireplace('[code]'.$code.'[/code]', '<i>Code:</i><br /><table cellpadding="0" style="background-color: #'.$bgcolor.'; width: 480px; border-style: dotted; border-color: #CCCCCC; border-width: 2px"><tr><td>'.$code.'</td></tr></table>', $text);
|
||||
}
|
||||
|
||||
$rows = 0;
|
||||
while(stripos($text, '[quote]') !== false && stripos($text, '[/quote]') !== false )
|
||||
{
|
||||
@@ -238,11 +239,31 @@ class Forum
|
||||
if(!is_int($rows / 2)) { $bgcolor = 'AAAAAA'; } else { $bgcolor = 'CCCCCC'; } $rows++;
|
||||
$text = str_ireplace('[quote]'.$quote.'[/quote]', '<table cellpadding="0" style="background-color: #'.$bgcolor.'; width: 480px; border-style: dotted; border-color: #007900; border-width: 2px"><tr><td>'.$quote.'</td></tr></table>', $text);
|
||||
}
|
||||
$rows = 0;
|
||||
while(stripos($text, '[url]') !== false && stripos($text, '[/url]') !== false )
|
||||
|
||||
$tagsToParse = [
|
||||
'url' => function ($str) {
|
||||
return '<a href="'.$str.'" target="_blank">'.$str.'</a>';
|
||||
},
|
||||
'player' => function ($str) {
|
||||
return generateLink(getPlayerLink($str, false), $str, true);
|
||||
},
|
||||
'guild' => function ($str) {
|
||||
return generateLink(getGuildLink($str, false), $str, true);
|
||||
},
|
||||
'house' => function ($str) {
|
||||
return generateLink(getHouseLink($str, false), $str, true);
|
||||
}
|
||||
];
|
||||
|
||||
foreach ($tagsToParse as $tag => $callback) {
|
||||
while(stripos($text, "[$tag]") !== false && stripos($text, "[/$tag]") !== false
|
||||
&& stripos($text, "[$tag]") < stripos($text, "[/$tag]"))
|
||||
{
|
||||
$url = substr($text, stripos($text, '[url]')+5, stripos($text, '[/url]') - stripos($text, '[url]') - 5);
|
||||
$text = str_ireplace('[url]'.$url.'[/url]', '<a href="'.$url.'" target="_blank">'.$url.'</a>', $text);
|
||||
$length = strlen("[$tag]");
|
||||
$substr = substr($text, stripos($text, "[$tag]") + $length, stripos($text, "[/$tag]") - stripos($text, "[$tag]") - $length);
|
||||
|
||||
$text = str_ireplace('[' . $tag . ']' . $substr . '[/' . $tag . ']', $callback($substr), $text);
|
||||
}
|
||||
}
|
||||
|
||||
$xhtml = false;
|
||||
@@ -252,9 +273,6 @@ class Forum
|
||||
'#\[u\](.*?)\[/u\]#si' => ($xhtml ? '<span style="text-decoration: underline;">\\1</span>' : '<u>\\1</u>'),
|
||||
'#\[s\](.*?)\[/s\]#si' => ($xhtml ? '<strike>\\1</strike>' : '<s>\\1</s>'),
|
||||
|
||||
'#\[guild\](.*?)\[/guild\]#si' => urldecode(generateLink(getGuildLink('$1', false), '$1', true)),
|
||||
'#\[house\](.*?)\[/house\]#si' => urldecode(generateLink(getHouseLink('$1', false), '$1', true)),
|
||||
'#\[player\](.*?)\[/player\]#si' => urldecode(generateLink(getPlayerLink('$1', false), '$1', true)),
|
||||
// TODO: [poll] tag
|
||||
|
||||
'#\[color=(.*?)\](.*?)\[/color\]#si' => ($xhtml ? '<span style="color: \\1;">\\2</span>' : '<span style="color: \\1">\\2</span>'),
|
||||
|
||||
@@ -9,6 +9,6 @@ class AccountAction extends Model {
|
||||
|
||||
public $timestamps = false;
|
||||
|
||||
protected $fillable = ['account_id', 'ip', 'ipv6', 'date', 'action'];
|
||||
protected $fillable = ['account_id', 'ip', 'date', 'action'];
|
||||
|
||||
}
|
||||
|
||||
@@ -9,6 +9,6 @@ class Menu extends Model {
|
||||
|
||||
public $timestamps = false;
|
||||
|
||||
protected $fillable = ['template', 'name', 'link', 'blank', 'color', 'category', 'ordering', 'enabled'];
|
||||
protected $fillable = ['template', 'name', 'link', 'access', 'blank', 'color', 'category', 'ordering', 'enabled'];
|
||||
|
||||
}
|
||||
|
||||
@@ -23,6 +23,8 @@ class Player extends Model {
|
||||
|
||||
public $timestamps = false;
|
||||
|
||||
protected $guarded = [];
|
||||
|
||||
protected $casts = [
|
||||
'worldid' => 'integer',
|
||||
'sex' => 'integer',
|
||||
@@ -46,14 +48,8 @@ class Player extends Model {
|
||||
});
|
||||
}
|
||||
|
||||
public function getVocationNameAttribute()
|
||||
{
|
||||
$vocation = $this->vocation;
|
||||
if (isset($this->promotion) && $this->promotion > 0) {
|
||||
$vocation += ($this->promotion * setting('core.vocations_amount'));
|
||||
}
|
||||
|
||||
return config('vocations')[$vocation] ?? 'Unknown';
|
||||
public function getVocationNameAttribute() {
|
||||
return \OTS_Toolbox::getVocationName($this->vocation, $this->promotion ?? 0);
|
||||
}
|
||||
|
||||
public function getIsDeletedAttribute()
|
||||
|
||||
101
system/src/Server/XML/Vocations.php
Normal file
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
namespace MyAAC\Server\XML;
|
||||
|
||||
use MyAAC\Cache\Cache;
|
||||
|
||||
class Vocations
|
||||
{
|
||||
private static array $vocations;
|
||||
private static array $vocationsFrom;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$cached = Cache::remember('vocations', 10 * 60, function () {
|
||||
$this->load();
|
||||
$from = $this->getFrom();
|
||||
|
||||
$amount = 0;
|
||||
foreach ($from as $vocId => $fromVocation) {
|
||||
if ($vocId != 0 && $vocId == $fromVocation) {
|
||||
$amount++;
|
||||
}
|
||||
}
|
||||
|
||||
return ['vocations' => $this->get(), 'vocationsFrom' => $from, 'amount' => $amount];
|
||||
});
|
||||
|
||||
self::$vocations = $cached['vocations'];
|
||||
self::$vocationsFrom = $cached['vocationsFrom'];
|
||||
|
||||
config(['vocations', self::$vocations]);
|
||||
config(['vocations_amount', $cached['amount']]);
|
||||
}
|
||||
|
||||
public function load(): void
|
||||
{
|
||||
if(!class_exists('DOMDocument')) {
|
||||
throw new \RuntimeException('Please install PHP xml extension. MyAAC will not work without it.');
|
||||
}
|
||||
|
||||
$vocationsXML = new \DOMDocument();
|
||||
$file = config('data_path') . 'XML/vocations.xml';
|
||||
if(!@file_exists($file)) {
|
||||
$file = config('data_path') . 'vocations.xml';
|
||||
}
|
||||
|
||||
if(!$vocationsXML->load($file)) {
|
||||
throw new \RuntimeException('ERROR: Cannot load <i>vocations.xml</i> - the file is malformed. Check the file with xml syntax validator.');
|
||||
}
|
||||
|
||||
foreach($vocationsXML->getElementsByTagName('vocation') as $vocation) {
|
||||
$id = $vocation->getAttribute('id');
|
||||
|
||||
self::$vocations[$id] = $vocation->getAttribute('name');
|
||||
|
||||
$fromVocation = (int) $vocation->getAttribute('fromvoc');
|
||||
self::$vocationsFrom[$id] = $fromVocation;
|
||||
}
|
||||
}
|
||||
|
||||
public static function get(): array {
|
||||
return self::$vocations;
|
||||
}
|
||||
|
||||
public static function getFrom(): array {
|
||||
return self::$vocationsFrom;
|
||||
}
|
||||
|
||||
public static function getPromoted(int $id): ?int {
|
||||
foreach (self::$vocationsFrom as $vocId => $fromVocation) {
|
||||
if ($id == $fromVocation && $vocId != $id) {
|
||||
return $vocId;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function getOriginal(int $id): ?int {
|
||||
while ($tmpId = self::$vocationsFrom[$id]) {
|
||||
if ($tmpId == $id) {
|
||||
break;
|
||||
}
|
||||
|
||||
$id = $tmpId;
|
||||
}
|
||||
|
||||
return $id;
|
||||
}
|
||||
|
||||
public static function getBase($includingRook = true): array {
|
||||
$vocations = [];
|
||||
foreach (self::$vocationsFrom as $vocId => $fromVoc) {
|
||||
if ($vocId == $fromVoc && ($vocId != 0 || $includingRook)) {
|
||||
$vocations[] = $vocId;
|
||||
}
|
||||
}
|
||||
|
||||
return $vocations;
|
||||
}
|
||||
}
|
||||
@@ -184,11 +184,11 @@ class Settings implements \ArrayAccess
|
||||
}
|
||||
?>
|
||||
<h3 id="row_<?= $key ?>" style="text-align: center"><strong><?= $setting['title']; ?></strong></h3>
|
||||
<table class="table table-bordered table-striped">
|
||||
<table class="table table-bordered table-striped table-responsive d-md-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 13%">Name</th>
|
||||
<th style="width: 30%">Value</th>
|
||||
<th style="width: 30%; min-width: 200px">Value</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
@@ -342,6 +342,16 @@ class Validator
|
||||
}
|
||||
}
|
||||
|
||||
global $hooks;
|
||||
|
||||
$params = ['name' => $name, 'error' => ''];
|
||||
$hooks->triggerFilter(HOOK_FILTER_VALIDATE_CHARACTER_NEW_NAME, $params);
|
||||
|
||||
if (!empty($params['error'])) {
|
||||
self::$lastError = $params['error'];
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -108,6 +108,7 @@ define('HOOK_FILTER_ROUTES', ++$i);
|
||||
define('HOOK_FILTER_TWIG_DISPLAY', ++$i);
|
||||
define('HOOK_FILTER_TWIG_RENDER', ++$i);
|
||||
define('HOOK_FILTER_THEME_FOOTER', ++$i);
|
||||
define('HOOK_FILTER_VALIDATE_CHARACTER_NEW_NAME', ++$i);
|
||||
|
||||
const HOOK_FIRST = HOOK_INIT;
|
||||
define('HOOK_LAST', $i);
|
||||
|
||||
@@ -146,10 +146,10 @@ if($twig_loader) {
|
||||
|
||||
function get_template_menus(): array
|
||||
{
|
||||
global $template_name;
|
||||
global $template_name, $logged_access;
|
||||
|
||||
$result = Cache::remember('template_menus_' . $template_name, 10 * 60, function () use ($template_name) {
|
||||
$result = Menu::select(['name', 'link', 'blank', 'color', 'category'])
|
||||
$result = Menu::select(['name', 'link', 'access', 'blank', 'color', 'category'])
|
||||
->where('template', $template_name)
|
||||
->orderBy('category')
|
||||
->orderBy('ordering')
|
||||
@@ -163,6 +163,10 @@ function get_template_menus(): array
|
||||
|
||||
$menus = [];
|
||||
foreach($result as $menu) {
|
||||
if ($menu['access'] > $logged_access) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (empty($menu['link'])) {
|
||||
$menu['link'] = 'news';
|
||||
}
|
||||
|
||||
@@ -5,18 +5,18 @@ Please enter your password and the new email address. Make sure that you enter a
|
||||
<table style="width:100%;">
|
||||
<tr>
|
||||
<td class="LabelV" >
|
||||
<span>New Email Address:</span>
|
||||
<label for="new_email">New Email Address:</label>
|
||||
</td>
|
||||
<td style="width:90%;">
|
||||
<input form="form" name="new_email" value="{% if new_email is defined %}{{ new_email }}{% endif %}" size="30" maxlength="50" autofocus/>
|
||||
<input form="form" id="new_email" name="new_email" value="{% if new_email is defined %}{{ new_email }}{% endif %}" size="30" maxlength="50" autofocus/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="LabelV">
|
||||
<span >Password:</span>
|
||||
<label for="password">Password:</label>
|
||||
</td>
|
||||
<td>
|
||||
<input form="form" type="password" name="password" size="30" maxlength="29">
|
||||
<input form="form" type="password" id="password" name="password" size="30" maxlength="29">
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
@@ -4,20 +4,26 @@ Here you can tell other players about yourself. This information will be display
|
||||
{% set content %}
|
||||
<table style="width: 100%;" >
|
||||
<tr>
|
||||
<td class="LabelV">Real Name:</td>
|
||||
<td class="LabelV">
|
||||
<label for="info_rlname">Real Name:</label>
|
||||
</td>
|
||||
<td style="width:90%;" >
|
||||
<input form="form" name="info_rlname" value="{{ account_rlname }}" size="30" maxlength="50" >
|
||||
<input form="form" id="info_rlname" name="info_rlname" value="{{ account_rlname }}" size="30" maxlength="50" >
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="LabelV" >Location:</td>
|
||||
<td class="LabelV">
|
||||
<label for="info_location">Location:</label>
|
||||
</td>
|
||||
<td>
|
||||
<input form="form" name="info_location" value="{{ account_location }}" size="30" maxlength="50" >
|
||||
<input form="form" id="info_location" name="info_location" value="{{ account_location }}" size="30" maxlength="50" >
|
||||
</td>
|
||||
</tr>
|
||||
{% if setting('core.account_country') %}
|
||||
<tr>
|
||||
<td class="LabelV">Country:</td>
|
||||
<td class="LabelV">
|
||||
<label for="account_country">Country:</label>
|
||||
</td>
|
||||
<td>
|
||||
<select form="form" name="info_country" id="account_country">
|
||||
{% for code, country in countries %}
|
||||
|
||||
@@ -6,7 +6,7 @@ Please enter your current password and a new password. For your security, please
|
||||
<table style="width:100%;">
|
||||
<tr>
|
||||
<td class="LabelV">
|
||||
<span>Current Password:</span>
|
||||
<label for="old_password">Current Password:</label>
|
||||
</td>
|
||||
<td>
|
||||
<input form="form" type="password" id="old_password" name="old_password" size="30" maxlength="29">
|
||||
@@ -17,7 +17,7 @@ Please enter your current password and a new password. For your security, please
|
||||
|
||||
<tr>
|
||||
<td class="LabelV">
|
||||
<span>New Password:</span>
|
||||
<label for="new_password">New Password:</label>
|
||||
</td>
|
||||
<td style="width:90%;">
|
||||
<input form="form" type="password" id="new_password" name="new_password" size="30" maxlength="29">
|
||||
@@ -28,7 +28,7 @@ Please enter your current password and a new password. For your security, please
|
||||
|
||||
<tr>
|
||||
<td class="LabelV">
|
||||
<span>New Password Again:</span>
|
||||
<label for="new_password_confirm">New Password Again:</label>
|
||||
</td>
|
||||
<td>
|
||||
<input form="form" type="password" id="new_password_confirm" name="new_password_confirm" size="30" maxlength="29">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
To change a name of character select player and choose a new name.<br/>
|
||||
To change the name of a character, select a player and choose a new name.<br/>
|
||||
<span style="color: red">Change name cost {{ setting('core.account_change_character_name_price') }} {{ setting('core.donate_column') == 'coins' ? 'coins' : 'premium points' }}. You have {{ points }} {{ setting('core.donate_column') == 'coins' ? 'coins' : 'premium points' }}.</span><br/><br/>
|
||||
|
||||
{% set title = 'Change Name' %}
|
||||
@@ -6,9 +6,11 @@ To change a name of character select player and choose a new name.<br/>
|
||||
{% set content %}
|
||||
<table style="width:100%;" >
|
||||
<tr>
|
||||
<td class="LabelV" ><span>Character:</span></td>
|
||||
<td class="LabelV">
|
||||
<label for="player_id">Character:</label>
|
||||
</td>
|
||||
<td style="width:90%;" >
|
||||
<select form="form" name="player_id">
|
||||
<select form="form" id="player_id" name="player_id">
|
||||
{% for player in account_logged.getPlayersList(false) %}
|
||||
<option value="{{ player.getId() }}">{{ player.getName() }}</option>
|
||||
{% endfor %}
|
||||
@@ -16,7 +18,9 @@ To change a name of character select player and choose a new name.<br/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="LabelV" ><span>New Name:</span></td>
|
||||
<td class="LabelV">
|
||||
<label for="character_name">New Name:</label>
|
||||
</td>
|
||||
<td>
|
||||
<input form="form" type="text" name="name" id="character_name" size="25" maxlength="25" >
|
||||
<img id="character_indicator" src="images/global/general/{% if not save or errors|length > 0 %}n{% endif %}ok.gif" />
|
||||
|
||||
@@ -6,9 +6,11 @@ To change a sex of character select player and choose a new sex.<br/>
|
||||
{% set content %}
|
||||
<table style="width:100%;" >
|
||||
<tr>
|
||||
<td class="LabelV" ><span>Character:</span></td>
|
||||
<td class="LabelV">
|
||||
<label for="player_id">Character:</label>
|
||||
</td>
|
||||
<td style="width:90%;" >
|
||||
<select form="form" name="player_id">
|
||||
<select form="form" id="player_id" name="player_id">
|
||||
{% for player in players %}
|
||||
<option value="{{ player.getId() }}">{{ player.getName() }}</option>
|
||||
{% endfor %}
|
||||
@@ -16,9 +18,11 @@ To change a sex of character select player and choose a new sex.<br/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="LabelV" ><span>New Sex:</span></td>
|
||||
<td class="LabelV">
|
||||
<label for="new_sex">New Sex:</label>
|
||||
</td>
|
||||
<td>
|
||||
<select form="form" name="new_sex">
|
||||
<select form="form" id="new_sex" name="new_sex">
|
||||
{% for id, gender in config.genders %}
|
||||
<option value="{{ id }}"{% if player_sex == id %} selected{% endif %}>{{ gender }}</option>
|
||||
{% endfor %}
|
||||
|
||||
@@ -4,15 +4,19 @@ To delete a character enter the name of the character and your password.<br/><br
|
||||
{% set content %}
|
||||
<table style="width:100%;">
|
||||
<tr>
|
||||
<td class="LabelV" ><span>Character Name:</span></td>
|
||||
<td class="LabelV">
|
||||
<label for="delete_name">Character Name:</label>
|
||||
</td>
|
||||
<td style="width:90%;">
|
||||
<input form="form" name="delete_name" value="" size="30" maxlength="29"/>
|
||||
<input form="form" id="delete_name" name="delete_name" value="" size="30" maxlength="29"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="LabelV" ><span>Password:</span></td>
|
||||
<td class="LabelV">
|
||||
<label for="delete_password">Password:</label>
|
||||
</td>
|
||||
<td>
|
||||
<input form="form" type="password" name="delete_password" size="30" maxlength="29"/>
|
||||
<input form="form" type="password" id="delete_password" name="delete_password" size="30" maxlength="29"/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
</tr>
|
||||
|
||||
{% if setting('core.mail_enabled') and setting('core.account_mail_verify') %}
|
||||
<tr><td></td><td><span><strong>Please use real address!<br/>We will send a link to validate your Email.</strong></span></td></tr>
|
||||
<tr><td></td><td><span><strong>Please use a real address!<br/>We will send a link to validate your Email.</strong></span></td></tr>
|
||||
{% endif %}
|
||||
|
||||
{{ hook('HOOK_ACCOUNT_CREATE_AFTER_EMAIL') }}
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
To generate new recovery key for your account please enter your password.<br/>
|
||||
<span style="color: red"><b>New recovery key cost {{ setting('core.account_generate_new_reckey_price') }} Premium Points</b>.</span> You have {{ points }} premium points. You will receive e-mail with this recovery key.
|
||||
To generate a new recovery key for your account, please enter your password.<br/>
|
||||
<span style="color: red"><b>New recovery key cost {{ setting('core.account_change_character_name_price') }} {{ setting('core.donate_column') == 'coins' ? 'coins' : 'premium points' }}. You have {{ points }} {{ setting('core.donate_column') == 'coins' ? 'coins' : 'premium points' }}. You will receive an e-mail with this recovery key.
|
||||
<br/>
|
||||
{% set title = 'Generate recovery key' %}
|
||||
{% set background = config('darkborder') %}
|
||||
{% set content %}
|
||||
<table style="width:100%;">
|
||||
<tr>
|
||||
<td class="LabelV"><span>Password:</span></td>
|
||||
<td><input form="form" type="password" name="reg_password" size="30" maxlength="29" ></td>
|
||||
<td class="LabelV">
|
||||
<label for="reg_password">Password:</label>
|
||||
</td>
|
||||
<td><input form="form" type="password" id="reg_password" name="reg_password" size="30" maxlength="29" ></td>
|
||||
</tr>
|
||||
</table>
|
||||
{% endset %}
|
||||
@@ -18,7 +20,7 @@ To generate new recovery key for your account please enter your password.<br/>
|
||||
<td>
|
||||
<table border="0" cellspacing="0" cellpadding="0">
|
||||
<tr>
|
||||
<td style="border:0px;">
|
||||
<td style="border:0;">
|
||||
<form id="form" action="{{ getLink('account/register-new') }}" method="post">
|
||||
{{ csrf() }}
|
||||
<input type="hidden" name="registeraccountsave" value="1">
|
||||
@@ -31,7 +33,7 @@ To generate new recovery key for your account please enter your password.<br/>
|
||||
<td>
|
||||
<table border="0" cellspacing="0" cellpadding="0">
|
||||
<tr>
|
||||
<td style="border:0px;">
|
||||
<td style="border:0;">
|
||||
<form action="{{ getLink('account/manage') }}" method="post">
|
||||
{{ csrf() }}
|
||||
{{ include('buttons.back.html.twig') }}
|
||||
|
||||
@@ -5,10 +5,10 @@ To generate recovery key for your account please enter your password.<br/><br/>
|
||||
<table style="width:100%;" >
|
||||
<tr>
|
||||
<td class="LabelV">
|
||||
<span>Password:</span>
|
||||
<label for="reg_password">Password:</label>
|
||||
</td>
|
||||
<td>
|
||||
<input form="form" type="password" name="reg_password" size="30" maxlength="29" autofocus/>
|
||||
<input form="form" type="password" id="reg_password" name="reg_password" size="30" maxlength="29" autofocus/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
@@ -20,7 +20,7 @@ To generate recovery key for your account please enter your password.<br/><br/>
|
||||
<td>
|
||||
<table border="0" cellspacing="0" cellpadding="0" >
|
||||
<tr>
|
||||
<td style="border:0px;">
|
||||
<td style="border:0;">
|
||||
<form id="form" action="{{ getLink('account/register') }}" method="post">
|
||||
{{ csrf() }}
|
||||
<input type="hidden" name="registeraccountsave" value="1"/>
|
||||
|
||||
@@ -179,7 +179,7 @@
|
||||
{% set i = i + 1 %}
|
||||
<tr bgcolor="{{ getStyle(i) }}">
|
||||
<td>
|
||||
<a href="{{ getLink('characters/' ~ player.getName()|urlencode) }}">{{ player.getName() }}</a>
|
||||
<a href="{{ getLink('characters/' ~ player.getName()|urlencode) }}">{{ player.getName() }}</a>{% if player.isDeleted() %}<span style="color: red"><b> [ DELETED ] </b></span>{% endif %}
|
||||
</td>
|
||||
<td>{{ player.getLevel() }}</td>
|
||||
<td>{{ player.getVocationName() }}</td>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<div class="card card-info card-outline">
|
||||
<div class="card-header">
|
||||
<h5 class="m-0">News:
|
||||
<h5 class="m-0">Changelogs:
|
||||
<form method="post" class="float-right">
|
||||
{{ csrf() }}
|
||||
<input type="hidden" name="action" value="new" />
|
||||
|
||||
33
system/templates/admin.menu-collapse.html.twig
Normal file
@@ -0,0 +1,33 @@
|
||||
<link rel="stylesheet" type="text/css" href="{{ constant('BASE_URL') }}tools/css/toastify.min.css">
|
||||
<script type="text/javascript" src="{{ constant('BASE_URL') }}tools/js/toastify.min.js"></script>
|
||||
{{ include('script.ajax-setup.html.twig') }}
|
||||
|
||||
<script>
|
||||
$(function () {
|
||||
/* Store sidebar state */
|
||||
$('.sidebar-toggle').on('click',function(event) {
|
||||
event.preventDefault();
|
||||
|
||||
const isCollapsed = $('body').hasClass('sidebar-collapse');
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '{{ constant('ADMIN_URL') }}tools/menu_collapse.php',
|
||||
data : { collapse: !isCollapsed},
|
||||
success : function(response) {
|
||||
},
|
||||
error : function(response) {
|
||||
Toastify({
|
||||
position: 'center',
|
||||
text: response.responseText,
|
||||
duration: 3000,
|
||||
style: {
|
||||
background: 'red',
|
||||
},
|
||||
escapeMarkup: false,
|
||||
}).showToast();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@@ -2,7 +2,8 @@
|
||||
<p class="note">You are editing: {{ template }}<br/><br/>
|
||||
Hint: You can drag menu items.<br/>
|
||||
Hint: Add links to external sites using: <b>http://</b> or <b>https://</b> prefix.<br/>
|
||||
Not all templates support blank and colorful links.
|
||||
Not all templates support blank and colorful links.<br/>
|
||||
* Guest means everyone will see the link. Player means registered and logged-in user.
|
||||
</p>
|
||||
<div class="row text-center">
|
||||
<div class="col-md-2 col-sm-1"></div>
|
||||
|
||||
@@ -14,42 +14,62 @@
|
||||
colors[{{ cat }}] = '{{ options['default_links_color'] ?? (menuDefaultLinksColor ?? config('menu_default_color')) }}';
|
||||
{% endfor %}
|
||||
|
||||
function confirmRemoveMenuItem(that)
|
||||
{
|
||||
let id = $(that).attr("id");
|
||||
if (confirm('Are you sure, that you want to remove this element?')) {
|
||||
$('#list-' + id.replace('remove-button-', '')).remove();
|
||||
}
|
||||
}
|
||||
|
||||
$(function () {
|
||||
const $sortable = $(".sortable");
|
||||
$sortable.sortable();
|
||||
$sortable.disableSelection();
|
||||
|
||||
$(".remove-button").on('click', function () {
|
||||
var id = $(this).attr("id");
|
||||
$('#list-' + id.replace('remove-button-', '')).remove();
|
||||
confirmRemoveMenuItem(this);
|
||||
});
|
||||
|
||||
$(".add-button").on('click', function () {
|
||||
var cat = $(this).attr("id").replace('add-button-', '');
|
||||
var id = last_id[cat];
|
||||
let cat = $(this).attr("id").replace('add-button-', '');
|
||||
let id = last_id[cat];
|
||||
last_id[cat]++;
|
||||
const color = colors[cat];
|
||||
$('#sortable-' + cat).append('<li class="ui-state-default" id="list-' + cat + '-' + id + '"><label>Name:</label> <input type="text" name="menu[' + cat + '][]" value=""/> <label>Link:</label> <input type="text" name="menu_link[' + cat + '][]" value=""/><input type="hidden" name="menu_blank[' + cat + '][]" value="0" /> <label><input class="blank-checkbox" type="checkbox"/><span title="Open in New Window">New Window</span></label> <input class="color-picker" type="text" name="menu_color[' + cat + '][]" value="#' + color + '" /> <a class="remove-button" id="remove-button-' + cat + '-' + id + '"><i class="fas fa-trash"></i></a></li>'); //add input bo
|
||||
$('#remove-button-' + cat + '-' + id).on('click', function () {
|
||||
$('#list-' + $(this).attr("id").replace('remove-button-', '')).remove();
|
||||
});
|
||||
|
||||
initializeSpectrum();
|
||||
let copy = $('.ui-state-default:first').clone();
|
||||
|
||||
copy.attr('id', 'list-' + cat + '-' + id);
|
||||
|
||||
copy.find('.menu-name').val('').attr('name', 'menu[' + cat + '][]');
|
||||
copy.find('.menu-link').val('').attr('name', 'menu_link[' + cat + '][]');
|
||||
copy.find('.menu-access').val('0').attr('name', 'menu_access[' + cat + '][]');
|
||||
copy.find('.menu-color').val(color).attr('name', 'menu_color[' + cat + '][]');
|
||||
copy.find('.menu-blank').attr('name', 'menu_blank[' + cat + '][]');
|
||||
copy.find('.menu-blank-checkbox').prop('checked', false);
|
||||
|
||||
copy.find('.remove-button').attr('id', 'remove-button-' + cat + '-' + id);
|
||||
|
||||
$('#sortable-' + cat).append(copy);
|
||||
|
||||
$('#remove-button-' + cat + '-' + id).on('click', function () {
|
||||
confirmRemoveMenuItem(this);
|
||||
});
|
||||
});
|
||||
|
||||
$("#menus-form").on('submit', function (e) {
|
||||
$('.blank-checkbox:not(:checked)').each(function (i, obj) {
|
||||
$('.menu-blank-checkbox:not(:checked)').each(function (i, obj) {
|
||||
$(obj).parent().prev().val("off");
|
||||
});
|
||||
|
||||
$('.blank-checkbox:checked').each(function (i, obj) {
|
||||
$('.menu-blank-checkbox:checked').each(function (i, obj) {
|
||||
$(obj).parent().prev().val("on");
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
<style type="text/css">
|
||||
<style>
|
||||
.sortable {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
@@ -60,24 +80,16 @@
|
||||
.remove-button, .add-button {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript" src="{{ constant('BASE_URL') }}tools/js/spectrum.js"></script>
|
||||
<link type="text/css" rel="stylesheet" href="{{ constant('BASE_URL') }}tools/css/spectrum.css"/>
|
||||
<script type="text/javascript">
|
||||
$(function () {
|
||||
initializeSpectrum();
|
||||
});
|
||||
|
||||
function initializeSpectrum() {
|
||||
$(".color-picker").spectrum({
|
||||
preferredFormat: "hex",
|
||||
showInput: true,
|
||||
showPalette: true,
|
||||
palette: [
|
||||
['black', 'white', 'blanchedalmond',
|
||||
'rgb(255, 128, 0);', 'hsv 100 70 50'],
|
||||
['red', 'yellow', 'green', 'blue', 'violet']
|
||||
]
|
||||
});
|
||||
.ui-sortable-handle {
|
||||
padding: 10px;
|
||||
}
|
||||
</script>
|
||||
|
||||
.label_menu_name, .label_menu_link {
|
||||
width: 45%;
|
||||
}
|
||||
|
||||
.menu-name, .menu-link {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -73,13 +73,9 @@
|
||||
<!-- jQuery Form Submit No Refresh + Toastify -->
|
||||
<link rel="stylesheet" type="text/css" href="{{ constant('BASE_URL') }}tools/css/toastify.min.css">
|
||||
<script type="text/javascript" src="{{ constant('BASE_URL') }}tools/js/toastify.min.js"></script>
|
||||
<script>
|
||||
$.ajaxSetup({
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
|
||||
}
|
||||
});
|
||||
{{ include('script.ajax-setup.html.twig') }}
|
||||
|
||||
<script>
|
||||
const noChangesText = "No changes has been made";
|
||||
|
||||
$('form')
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
{% endif %}
|
||||
<table border="0" cellspacing="1" cellpadding="4" width="100%">
|
||||
{% if config.characters.outfit %}
|
||||
<div style="width:64px;height:64px;border:2px solid #F1E0C6; border-radius:50px; padding:13px; margin-top:38px;margin-left:376px;position:absolute;"><img style="margin-left:{% if player.getLookType() in setting('core.outfit_images_wrong_looktypes') %}-0px;margin-top:-0px;width:64px;height:64px;{% else %}-60px;margin-top:-60px;width:128px;height:128px;{% endif %}" src="{{ outfit }}" alt="player outfit"/></div>
|
||||
<div style="width:64px;height:64px;border:2px solid #F1E0C6; border-radius:50px; padding:13px; margin-top:38px;margin-left:376px;position:absolute;"><img style="margin-left:-60px;margin-top:-60px;width:128px;height:128px;" src="{{ outfit }}" alt="player outfit"/></div>
|
||||
{% endif %}
|
||||
|
||||
<tr bgcolor="{{ config.vdarkborder }}">
|
||||
|
||||
@@ -43,7 +43,8 @@
|
||||
</tr>
|
||||
</table>
|
||||
<div style="text-align:center">
|
||||
<input type="submit" value="Post Reply" />
|
||||
{% set button_name = 'Post Reply' %}
|
||||
{{ include('buttons.base.html.twig') }}
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
</tr>
|
||||
</table>
|
||||
<div style="text-align:center">
|
||||
<input type="submit" value="Post Thread" />
|
||||
{% set button_name = 'Post Thread' %}
|
||||
{{ include('buttons.base.html.twig') }}
|
||||
</div>
|
||||
</form>
|
||||
|
||||
57
system/templates/forum.show_board.html.twig
Normal file
@@ -0,0 +1,57 @@
|
||||
<a href="{{ getLink('forum') }}">Boards</a> >> <b>{{ section_name }}</b>
|
||||
|
||||
{% if (logged and (not closed or is_moderator)) %}
|
||||
<br/><br/>
|
||||
<a href="{{ getLink('forum') }}?action=new_thread§ion_id={{ section_id }}"><img src="images/forum/topic.gif" border="0" /></a>
|
||||
{% endif %}
|
||||
|
||||
{% if threads|length > 0 %}
|
||||
<br/><br/>Page: {{ links_to_pages|raw }}<br/>
|
||||
|
||||
<table width="100%">
|
||||
<tr bgcolor=" {{ config.vdarkborder }}" align="center">
|
||||
<td class="white"><span style="font-size: 10px"><b>Thread</b></span></td>
|
||||
<td class="white"><span style="font-size: 10px"><b>Thread Starter</b></span></td>
|
||||
<td class="white"><span style="font-size: 10px"><b>Replies</b></span></td>
|
||||
<td class="white"><span style="font-size: 10px"><b>Views</b></span></td>
|
||||
<td class="white"><span style="font-size: 10px"><b>Last Post</b></span></td>
|
||||
</tr>
|
||||
|
||||
{% set i = 0 %}
|
||||
{% for thread in threads %}
|
||||
<tr bgcolor="{{ getStyle(i) }}">
|
||||
<td>
|
||||
{% if is_moderator %}
|
||||
<a href="{{ getLink('forum') }}?action=move_thread&id={{ thread.id }}" title="Move Thread"><img src="images/icons/arrow_right.gif"/></a>
|
||||
{{ include('forum.remove_post.html.twig', {post: thread}) }}
|
||||
{% endif %}
|
||||
<a href="{{ thread.link }}">{{ thread.post_topic }}</a><br />
|
||||
<small>{{ thread.post_shortened|raw }}...</small>
|
||||
</td>
|
||||
<td>{{ thread.player_link|raw }}</td>
|
||||
<td>{{ thread.replies }}</td>
|
||||
<td>{{ thread.views }}</td>
|
||||
<td>
|
||||
{% if thread.last_post > 0 %}
|
||||
{% if thread.latest_post.name is defined %}
|
||||
{{ thread.latest_post.post_date|date('d.m.y H:i:s') }}<br />by {{ thread.latest_post.player_link|raw }}
|
||||
{% else %}
|
||||
No posts.
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{{ thread.post_date|date('d.m.y H:i:s') }}<br />by {{ thread.player_link|raw }}
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
{% set i = i + 1 %}
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
||||
{% else %}
|
||||
<h3>No threads in this board.</h3>
|
||||
{% endif %}
|
||||
|
||||
{% if(logged and (not closed or is_moderator)) %}
|
||||
<br /><a href="{{ getLink('forum') }}?action=new_thread§ion_id={{ section_id }}"><img src="images/forum/topic.gif" border="0" /></a>
|
||||
{% endif %}
|
||||
@@ -24,7 +24,7 @@ Page: {{ links_to_pages|raw }}<br/>
|
||||
{% set i = i + 1 %}
|
||||
<td valign="top">{{ post.player_link|raw }}<br/>
|
||||
{% if post.outfit is defined %}
|
||||
<img style="margin-left:{% if post.player.getLookType() in setting('core.outfit_images_wrong_looktypes') %}-0px;margin-top:-0px;width:64px;height:64px;{% else %}-60px;margin-top:-60px;width:128px;height:128px;{% endif %}" src="{{ post.outfit }}" alt="player outfit"/>
|
||||
<img style="margin-left:-60px;margin-top:-60px;width:128px;height:128px;" src="{{ post.outfit }}" alt="player outfit"/>
|
||||
<br />
|
||||
{% endif %}
|
||||
<span style="font-size: 10px">
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<td class="white"><b>Leave guild</b></td></tr>
|
||||
{% if players|length > 0 %}
|
||||
<tr bgcolor="{{ config.lightborder }}">
|
||||
<td width="100%">Select character to leave guild:</td>
|
||||
<td width="100%">Select a character to leave the guild:</td>
|
||||
</tr>
|
||||
<tr bgcolor="{{ config.darkborder }}">
|
||||
<td>
|
||||
|
||||
@@ -105,7 +105,8 @@ Here you can change names of ranks, delete and add ranks, pass leadership to oth
|
||||
<form action="{{ getLink('guilds') }}?guild={{ guild.getName() }}&action=delete_rank" method="post" style="display: inline;">
|
||||
{{ csrf() }}
|
||||
<input type="hidden" name="rankid" value="{{ rank.getId() }}" />
|
||||
<input type="image" src="/images/news/delete.png" border="0" alt="Delete" />
|
||||
|
||||
<input type="submit" value="Delete" />
|
||||
</form>
|
||||
</td>
|
||||
<td>
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<label for="vocationFilter">Choose a vocation</label>
|
||||
<select onchange="location = this.value;" id="vocationFilter">
|
||||
<option value="{{ getLink('highscores') }}/{{ list|urlencode }}" class="size_xs">[ALL]</option>
|
||||
{% for i in 0..config.vocations_amount %}
|
||||
{% for i in baseVocations %}
|
||||
<option value="{{ getLink('highscores') }}/{{ list|urlencode }}/{{ config.vocations[i]|lower|urlencode }}" class="size_xs" {% if vocationId is not null and vocationId == i %}selected{% endif %}>{{ config.vocations[i]}}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
@@ -120,7 +120,7 @@
|
||||
<tr bgcolor="{{ config.lightborder }}">
|
||||
<td>
|
||||
<a href="{{ getLink('highscores') }}/{{ list|urlencode }}" class="size_xs">[ALL]</a><br/>
|
||||
{% for i in 0..config.vocations_amount %}
|
||||
{% for i in baseVocations %}
|
||||
<a href="{{ getLink('highscores') }}/{{ list|urlencode }}/{{ config.vocations[i]|lower|urlencode }}" class="size_xs">{{ config.vocations[i]}}</a><br/>
|
||||
{% endfor %}
|
||||
</td>
|
||||
|
||||
@@ -4,55 +4,66 @@
|
||||
<br/>
|
||||
{% endif %}
|
||||
|
||||
<br/>
|
||||
|
||||
{# vocation statistics #}
|
||||
{% if setting('core.online_vocations') %}
|
||||
<br/>
|
||||
|
||||
{% set title = 'Vocation statistics' %}
|
||||
{% set tableClass = 'Table3' %}
|
||||
{% set background = config('darkborder') %}
|
||||
{% set content %}
|
||||
|
||||
{% if setting('core.online_vocations_images') %}
|
||||
<table width="200" cellspacing="1" cellpadding="0" border="0" align="center">
|
||||
<tr bgcolor="{{ config.darkborder }}">
|
||||
<td><img src="images/sorcerer.png" /></td>
|
||||
<td><img src="images/druid.png" /></td>
|
||||
<td><img src="images/paladin.png" /></td>
|
||||
<td><img src="images/knight.png" /></td>
|
||||
<table width="200" cellspacing="1" cellpadding="0" border="0" align="center" class="myaac-table">
|
||||
<thead>
|
||||
<tr>
|
||||
{% for vocationId in baseVocations %}
|
||||
<td style="text-align: center;"><strong>{{ config('vocations')[vocationId] }}s</strong></td>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
<tr bgcolor="{{ config.vdarkborder }}">
|
||||
<td class="white" style="text-align: center;"><strong>Sorcerers</strong></td>
|
||||
<td class="white" style="text-align: center;"><strong>Druids</strong></td>
|
||||
<td class="white" style="text-align: center;"><strong>Paladins</strong></td>
|
||||
<td class="white" style="text-align: center;"><strong>Knights</strong></td>
|
||||
</thead>
|
||||
|
||||
<tr>
|
||||
{% for vocationId in baseVocations %}
|
||||
<td><img src="images/{{ config('vocations')[vocationId]|lower }}.png" width="130" height="190"/></td>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
<tr bgcolor="{{ config.lightborder }}">
|
||||
<td style="text-align: center;">{{ vocs[1] }}</td>
|
||||
<td style="text-align: center;">{{ vocs[2] }}</td>
|
||||
<td style="text-align: center;">{{ vocs[3] }}</td>
|
||||
<td style="text-align: center;">{{ vocs[4] }}</td>
|
||||
|
||||
<tr>
|
||||
{% for vocationId in baseVocations %}
|
||||
<td style="text-align: center;">{{ vocs[vocationId] }}</td>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
</table>
|
||||
<div style="text-align: center;"> </div>
|
||||
{% else %}
|
||||
<table border="0" cellspacing="1" cellpadding="4" width="100%">
|
||||
<tr bgcolor="{{ config.vdarkborder }}">
|
||||
<td class="white" colspan="2"><b>Vocation statistics</b></td>
|
||||
<table border="0" cellspacing="1" cellpadding="4" width="100%" class="myaac-table">
|
||||
{% set i = 0 %}
|
||||
{% for vocationId in baseVocations %}
|
||||
<tr>
|
||||
<td width="25%">{{ config.vocations[vocationId] }}</td>
|
||||
<td width="75%">{{ vocs[vocationId] }}</td>
|
||||
</tr>
|
||||
|
||||
{% for i in 1..config.vocations_amount %}
|
||||
<tr bgcolor="{{ getStyle(i) }}">
|
||||
<td width="25%">{{ config.vocations[i] }}</td>
|
||||
<td width="75%">{{ vocs[i] }}</td>
|
||||
</tr>
|
||||
{% set i = i + 1 %}
|
||||
{% endfor %}
|
||||
</table>
|
||||
<br/>
|
||||
{% endif %}
|
||||
|
||||
{% endset %}
|
||||
{% include 'tables.headline.html.twig' %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
<br/>
|
||||
|
||||
{# show skulls #}
|
||||
{% if setting('core.online_skulls') %}
|
||||
<table width="100%" cellspacing="1">
|
||||
<table width="100%" cellspacing="1" class="myaac-table">
|
||||
<tr>
|
||||
<td style="background: {{ config.darkborder }};" align="center">
|
||||
<td align="center">
|
||||
<img src="images/white_skull.gif"/> - 1 - 6 Frags<br/>
|
||||
<img src="images/red_skull.gif"/> - 6+ Frags or Red Skull<br/>
|
||||
<img src="images/black_skull.gif"/> - 10+ Frags or Black Skull
|
||||
@@ -125,23 +136,24 @@
|
||||
{% set title = 'Players Online' %}
|
||||
{% set tableClass = 'Table2' %}
|
||||
{% set content %}
|
||||
<table width="100%">
|
||||
<tr class="LabelH" style="position: relative; z-index: 20;">
|
||||
<table width="100%" class="myaac-table">
|
||||
|
||||
<tr class="LabelH" style="z-index: 20;">
|
||||
{% if setting('core.account_country') %}
|
||||
<td width="11px"><a href="{{ getLink('online')}}?order=country_{{ order == 'country_asc' ? 'desc' : 'asc' }}">#  </a>
|
||||
<td style="width: 6px;"><a href="{{ getLink('online')}}?order=country_{{ order == 'country_asc' ? 'desc' : 'asc' }}">#  </a>
|
||||
</td>
|
||||
{% endif %}
|
||||
{% if setting('core.online_outfit') %}
|
||||
<td><b>Outfit</b></td>
|
||||
<td style="width: 32px;"><b>Outfit</b></td>
|
||||
{% endif %}
|
||||
<td style="text-align:left; width:50%">Name  
|
||||
<td style="text-align:left;">Name  
|
||||
<small style="font-weight:normal">[<a href="{{ getLink('online')}}?order=name_{{ order == 'name_asc' ? 'desc' : 'asc' }}">sort</a>]</small>
|
||||
<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  
|
||||
<td style="text-align:left;width:10%">Level  
|
||||
<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  
|
||||
<td style="text-align:left;width:20%">Vocation  
|
||||
<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>
|
||||
@@ -151,20 +163,20 @@
|
||||
{% for player in players %}
|
||||
{% set i = i + 1 %}
|
||||
|
||||
<tr style="background: {{ getStyle(i) }}; text-align: right; height: 40px;">
|
||||
<tr style="text-align: right; height: 40px;">
|
||||
{% if setting('core.account_country') %}
|
||||
<td>{{ player.country_image|raw }}</td>
|
||||
{% endif %}
|
||||
|
||||
{% if setting('core.online_outfit') %}
|
||||
<td width="5%"><img style="position:absolute;margin-top:-48px;margin-left:-70px;" src="{{ player.outfit }}" alt="player outfit"/></td>
|
||||
<td><img style="position:absolute;margin-top:-48px;margin-left:-70px;" src="{{ player.outfit }}" alt="player outfit"/></td>
|
||||
{% endif %}
|
||||
|
||||
<td style="width:70%; text-align:left">
|
||||
<td style="text-align:left">
|
||||
{{ player.name|raw }}{{ player.skull|raw }}
|
||||
</td>
|
||||
<td style="width:10%">{{ player.level }}</td>
|
||||
<td style="width:20%">{{ player.vocation }}</td>
|
||||
<td>{{ player.level }}</td>
|
||||
<td>{{ player.vocation }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
||||
7
system/templates/script.ajax-setup.html.twig
Normal file
@@ -0,0 +1,7 @@
|
||||
<script>
|
||||
$.ajaxSetup({
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -47,7 +47,7 @@
|
||||
|
||||
{% if setting('core.team_outfit') %}
|
||||
<td>
|
||||
<img style="position: absolute; margin-top: {% if member.player.looktype in setting('core.outfit_images_wrong_looktypes') %}-16px;margin-left:-0px;{% else %} -45px; margin-left: -30px;{% endif %}" src="{{ member.outfit }}" alt="player outfit"/>
|
||||
<img style="position: absolute; margin-top: -50px; margin-left: -30px;" src="{{ member.outfit }}" alt="player outfit"/>
|
||||
</td>
|
||||
{% endif %}
|
||||
|
||||
@@ -127,7 +127,7 @@
|
||||
<tr bgcolor="{{ getStyle(i) }}" style="height: 32px;">
|
||||
{% if setting('core.team_outfit') %}
|
||||
<td>
|
||||
<img style="position: absolute; margin-top: {% if member.player.looktype in setting('core.outfit_images_wrong_looktypes') %}-16px;margin-left:-0px;{% else %} -45px; margin-left: -30px;{% endif %}" src="{{ member.outfit }}" alt="player outfit"/>
|
||||
<img style="position: absolute; margin-top: -50px; margin-left: -30px;" src="{{ member.outfit }}" alt="player outfit"/>
|
||||
</td>
|
||||
{% endif %}
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
{% for player in topPlayers %}
|
||||
<div style="text-align:left"><a href="{{ getPlayerLink(player['name'], false) }} " class="topfont {% if player['online'] %}online{% else %}offline{% endif %}">
|
||||
{% if setting('core.online_outfit') %}
|
||||
<img style="position:absolute;margin-top:{% if 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"/>
|
||||
<img style="position:absolute;margin-top:-45px;margin-left:-25px;" src="{{ player.outfit }}" alt="player outfit"/>
|
||||
{% endif %}
|
||||
<span style="color: #CCC; margin-left: 40px">{{ player['rank'] }} - </span>
|
||||
{{ player['name'] }}
|
||||
|
||||
@@ -1,507 +0,0 @@
|
||||
/***
|
||||
Spectrum Colorpicker v1.8.0
|
||||
https://github.com/bgrins/spectrum
|
||||
Author: Brian Grinstead
|
||||
License: MIT
|
||||
***/
|
||||
|
||||
.sp-container {
|
||||
position:absolute;
|
||||
top:0;
|
||||
left:0;
|
||||
display:inline-block;
|
||||
*display: inline;
|
||||
*zoom: 1;
|
||||
/* https://github.com/bgrins/spectrum/issues/40 */
|
||||
z-index: 9999994;
|
||||
overflow: hidden;
|
||||
}
|
||||
.sp-container.sp-flat {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Fix for * { box-sizing: border-box; } */
|
||||
.sp-container,
|
||||
.sp-container * {
|
||||
-webkit-box-sizing: content-box;
|
||||
-moz-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
/* http://ansciath.tumblr.com/post/7347495869/css-aspect-ratio */
|
||||
.sp-top {
|
||||
position:relative;
|
||||
width: 100%;
|
||||
display:inline-block;
|
||||
}
|
||||
.sp-top-inner {
|
||||
position:absolute;
|
||||
top:0;
|
||||
left:0;
|
||||
bottom:0;
|
||||
right:0;
|
||||
}
|
||||
.sp-color {
|
||||
position: absolute;
|
||||
top:0;
|
||||
left:0;
|
||||
bottom:0;
|
||||
right:20%;
|
||||
}
|
||||
.sp-hue {
|
||||
position: absolute;
|
||||
top:0;
|
||||
right:0;
|
||||
bottom:0;
|
||||
left:84%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.sp-clear-enabled .sp-hue {
|
||||
top:33px;
|
||||
height: 77.5%;
|
||||
}
|
||||
|
||||
.sp-fill {
|
||||
padding-top: 80%;
|
||||
}
|
||||
.sp-sat, .sp-val {
|
||||
position: absolute;
|
||||
top:0;
|
||||
left:0;
|
||||
right:0;
|
||||
bottom:0;
|
||||
}
|
||||
|
||||
.sp-alpha-enabled .sp-top {
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
.sp-alpha-enabled .sp-alpha {
|
||||
display: block;
|
||||
}
|
||||
.sp-alpha-handle {
|
||||
position:absolute;
|
||||
top:-4px;
|
||||
bottom: -4px;
|
||||
width: 6px;
|
||||
left: 50%;
|
||||
cursor: pointer;
|
||||
border: 1px solid black;
|
||||
background: white;
|
||||
opacity: .8;
|
||||
}
|
||||
.sp-alpha {
|
||||
display: none;
|
||||
position: absolute;
|
||||
bottom: -14px;
|
||||
right: 0;
|
||||
left: 0;
|
||||
height: 8px;
|
||||
}
|
||||
.sp-alpha-inner {
|
||||
border: solid 1px #333;
|
||||
}
|
||||
|
||||
.sp-clear {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sp-clear.sp-clear-display {
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.sp-clear-enabled .sp-clear {
|
||||
display: block;
|
||||
position:absolute;
|
||||
top:0px;
|
||||
right:0;
|
||||
bottom:0;
|
||||
left:84%;
|
||||
height: 28px;
|
||||
}
|
||||
|
||||
/* Don't allow text selection */
|
||||
.sp-container, .sp-replacer, .sp-preview, .sp-dragger, .sp-slider, .sp-alpha, .sp-clear, .sp-alpha-handle, .sp-container.sp-dragging .sp-input, .sp-container button {
|
||||
-webkit-user-select:none;
|
||||
-moz-user-select: -moz-none;
|
||||
-o-user-select:none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.sp-container.sp-input-disabled .sp-input-container {
|
||||
display: none;
|
||||
}
|
||||
.sp-container.sp-buttons-disabled .sp-button-container {
|
||||
display: none;
|
||||
}
|
||||
.sp-container.sp-palette-buttons-disabled .sp-palette-button-container {
|
||||
display: none;
|
||||
}
|
||||
.sp-palette-only .sp-picker-container {
|
||||
display: none;
|
||||
}
|
||||
.sp-palette-disabled .sp-palette-container {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sp-initial-disabled .sp-initial {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
/* Gradients for hue, saturation and value instead of images. Not pretty... but it works */
|
||||
.sp-sat {
|
||||
background-image: -webkit-gradient(linear, 0 0, 100% 0, from(#FFF), to(rgba(204, 154, 129, 0)));
|
||||
background-image: -webkit-linear-gradient(left, #FFF, rgba(204, 154, 129, 0));
|
||||
background-image: -moz-linear-gradient(left, #fff, rgba(204, 154, 129, 0));
|
||||
background-image: -o-linear-gradient(left, #fff, rgba(204, 154, 129, 0));
|
||||
background-image: -ms-linear-gradient(left, #fff, rgba(204, 154, 129, 0));
|
||||
background-image: linear-gradient(to right, #fff, rgba(204, 154, 129, 0));
|
||||
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(GradientType = 1, startColorstr=#FFFFFFFF, endColorstr=#00CC9A81)";
|
||||
filter : progid:DXImageTransform.Microsoft.gradient(GradientType = 1, startColorstr='#FFFFFFFF', endColorstr='#00CC9A81');
|
||||
}
|
||||
.sp-val {
|
||||
background-image: -webkit-gradient(linear, 0 100%, 0 0, from(#000000), to(rgba(204, 154, 129, 0)));
|
||||
background-image: -webkit-linear-gradient(bottom, #000000, rgba(204, 154, 129, 0));
|
||||
background-image: -moz-linear-gradient(bottom, #000, rgba(204, 154, 129, 0));
|
||||
background-image: -o-linear-gradient(bottom, #000, rgba(204, 154, 129, 0));
|
||||
background-image: -ms-linear-gradient(bottom, #000, rgba(204, 154, 129, 0));
|
||||
background-image: linear-gradient(to top, #000, rgba(204, 154, 129, 0));
|
||||
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#00CC9A81, endColorstr=#FF000000)";
|
||||
filter : progid:DXImageTransform.Microsoft.gradient(startColorstr='#00CC9A81', endColorstr='#FF000000');
|
||||
}
|
||||
|
||||
.sp-hue {
|
||||
background: -moz-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
|
||||
background: -ms-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
|
||||
background: -o-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
|
||||
background: -webkit-gradient(linear, left top, left bottom, from(#ff0000), color-stop(0.17, #ffff00), color-stop(0.33, #00ff00), color-stop(0.5, #00ffff), color-stop(0.67, #0000ff), color-stop(0.83, #ff00ff), to(#ff0000));
|
||||
background: -webkit-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
|
||||
background: linear-gradient(to bottom, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
|
||||
}
|
||||
|
||||
/* IE filters do not support multiple color stops.
|
||||
Generate 6 divs, line them up, and do two color gradients for each.
|
||||
Yes, really.
|
||||
*/
|
||||
.sp-1 {
|
||||
height:17%;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0000', endColorstr='#ffff00');
|
||||
}
|
||||
.sp-2 {
|
||||
height:16%;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffff00', endColorstr='#00ff00');
|
||||
}
|
||||
.sp-3 {
|
||||
height:17%;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ff00', endColorstr='#00ffff');
|
||||
}
|
||||
.sp-4 {
|
||||
height:17%;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ffff', endColorstr='#0000ff');
|
||||
}
|
||||
.sp-5 {
|
||||
height:16%;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0000ff', endColorstr='#ff00ff');
|
||||
}
|
||||
.sp-6 {
|
||||
height:17%;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff00ff', endColorstr='#ff0000');
|
||||
}
|
||||
|
||||
.sp-hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Clearfix hack */
|
||||
.sp-cf:before, .sp-cf:after { content: ""; display: table; }
|
||||
.sp-cf:after { clear: both; }
|
||||
.sp-cf { *zoom: 1; }
|
||||
|
||||
/* Mobile devices, make hue slider bigger so it is easier to slide */
|
||||
@media (max-device-width: 480px) {
|
||||
.sp-color { right: 40%; }
|
||||
.sp-hue { left: 63%; }
|
||||
.sp-fill { padding-top: 60%; }
|
||||
}
|
||||
.sp-dragger {
|
||||
border-radius: 5px;
|
||||
height: 5px;
|
||||
width: 5px;
|
||||
border: 1px solid #fff;
|
||||
background: #000;
|
||||
cursor: pointer;
|
||||
position:absolute;
|
||||
top:0;
|
||||
left: 0;
|
||||
}
|
||||
.sp-slider {
|
||||
position: absolute;
|
||||
top:0;
|
||||
cursor:pointer;
|
||||
height: 3px;
|
||||
left: -1px;
|
||||
right: -1px;
|
||||
border: 1px solid #000;
|
||||
background: white;
|
||||
opacity: .8;
|
||||
}
|
||||
|
||||
/*
|
||||
Theme authors:
|
||||
Here are the basic themeable display options (colors, fonts, global widths).
|
||||
See http://bgrins.github.io/spectrum/themes/ for instructions.
|
||||
*/
|
||||
|
||||
.sp-container {
|
||||
border-radius: 0;
|
||||
background-color: #ECECEC;
|
||||
border: solid 1px #f0c49B;
|
||||
padding: 0;
|
||||
}
|
||||
.sp-container, .sp-container button, .sp-container input, .sp-color, .sp-hue, .sp-clear {
|
||||
font: normal 12px "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Geneva, Verdana, sans-serif;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
-ms-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.sp-top {
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
.sp-color, .sp-hue, .sp-clear {
|
||||
border: solid 1px #666;
|
||||
}
|
||||
|
||||
/* Input */
|
||||
.sp-input-container {
|
||||
float:right;
|
||||
width: 100px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.sp-initial-disabled .sp-input-container {
|
||||
width: 100%;
|
||||
}
|
||||
.sp-input {
|
||||
font-size: 12px !important;
|
||||
border: 1px inset;
|
||||
padding: 4px 5px;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
background:transparent;
|
||||
border-radius: 3px;
|
||||
color: #222;
|
||||
}
|
||||
.sp-input:focus {
|
||||
border: 1px solid orange;
|
||||
}
|
||||
.sp-input.sp-validation-error {
|
||||
border: 1px solid red;
|
||||
background: #fdd;
|
||||
}
|
||||
.sp-picker-container , .sp-palette-container {
|
||||
float:left;
|
||||
position: relative;
|
||||
padding: 10px;
|
||||
padding-bottom: 300px;
|
||||
margin-bottom: -290px;
|
||||
}
|
||||
.sp-picker-container {
|
||||
width: 172px;
|
||||
border-left: solid 1px #fff;
|
||||
}
|
||||
|
||||
/* Palettes */
|
||||
.sp-palette-container {
|
||||
border-right: solid 1px #ccc;
|
||||
}
|
||||
|
||||
.sp-palette-only .sp-palette-container {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.sp-palette .sp-thumb-el {
|
||||
display: block;
|
||||
position:relative;
|
||||
float:left;
|
||||
width: 24px;
|
||||
height: 15px;
|
||||
margin: 3px;
|
||||
cursor: pointer;
|
||||
border:solid 2px transparent;
|
||||
}
|
||||
.sp-palette .sp-thumb-el:hover, .sp-palette .sp-thumb-el.sp-thumb-active {
|
||||
border-color: orange;
|
||||
}
|
||||
.sp-thumb-el {
|
||||
position:relative;
|
||||
}
|
||||
|
||||
/* Initial */
|
||||
.sp-initial {
|
||||
float: left;
|
||||
border: solid 1px #333;
|
||||
}
|
||||
.sp-initial span {
|
||||
width: 30px;
|
||||
height: 25px;
|
||||
border:none;
|
||||
display:block;
|
||||
float:left;
|
||||
margin:0;
|
||||
}
|
||||
|
||||
.sp-initial .sp-clear-display {
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
/* Buttons */
|
||||
.sp-palette-button-container,
|
||||
.sp-button-container {
|
||||
float: right;
|
||||
}
|
||||
|
||||
/* Replacer (the little preview div that shows up instead of the <input>) */
|
||||
.sp-replacer {
|
||||
margin:0;
|
||||
overflow:hidden;
|
||||
cursor:pointer;
|
||||
padding: 4px;
|
||||
display:inline-block;
|
||||
*zoom: 1;
|
||||
*display: inline;
|
||||
border: solid 1px #91765d;
|
||||
background: #eee;
|
||||
color: #333;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.sp-replacer:hover, .sp-replacer.sp-active {
|
||||
border-color: #F0C49B;
|
||||
color: #111;
|
||||
}
|
||||
.sp-replacer.sp-disabled {
|
||||
cursor:default;
|
||||
border-color: silver;
|
||||
color: silver;
|
||||
}
|
||||
.sp-dd {
|
||||
padding: 2px 0;
|
||||
height: 16px;
|
||||
line-height: 16px;
|
||||
float:left;
|
||||
font-size:10px;
|
||||
}
|
||||
.sp-preview {
|
||||
position:relative;
|
||||
width:25px;
|
||||
height: 20px;
|
||||
border: solid 1px #222;
|
||||
margin-right: 5px;
|
||||
float:left;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.sp-palette {
|
||||
*width: 220px;
|
||||
max-width: 220px;
|
||||
}
|
||||
.sp-palette .sp-thumb-el {
|
||||
width:16px;
|
||||
height: 16px;
|
||||
margin:2px 1px;
|
||||
border: solid 1px #d0d0d0;
|
||||
}
|
||||
|
||||
.sp-container {
|
||||
padding-bottom:0;
|
||||
}
|
||||
|
||||
|
||||
/* Buttons: http://hellohappy.org/css3-buttons/ */
|
||||
.sp-container button {
|
||||
background-color: #eeeeee;
|
||||
background-image: -webkit-linear-gradient(top, #eeeeee, #cccccc);
|
||||
background-image: -moz-linear-gradient(top, #eeeeee, #cccccc);
|
||||
background-image: -ms-linear-gradient(top, #eeeeee, #cccccc);
|
||||
background-image: -o-linear-gradient(top, #eeeeee, #cccccc);
|
||||
background-image: linear-gradient(to bottom, #eeeeee, #cccccc);
|
||||
border: 1px solid #ccc;
|
||||
border-bottom: 1px solid #bbb;
|
||||
border-radius: 3px;
|
||||
color: #333;
|
||||
font-size: 14px;
|
||||
line-height: 1;
|
||||
padding: 5px 4px;
|
||||
text-align: center;
|
||||
text-shadow: 0 1px 0 #eee;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.sp-container button:hover {
|
||||
background-color: #dddddd;
|
||||
background-image: -webkit-linear-gradient(top, #dddddd, #bbbbbb);
|
||||
background-image: -moz-linear-gradient(top, #dddddd, #bbbbbb);
|
||||
background-image: -ms-linear-gradient(top, #dddddd, #bbbbbb);
|
||||
background-image: -o-linear-gradient(top, #dddddd, #bbbbbb);
|
||||
background-image: linear-gradient(to bottom, #dddddd, #bbbbbb);
|
||||
border: 1px solid #bbb;
|
||||
border-bottom: 1px solid #999;
|
||||
cursor: pointer;
|
||||
text-shadow: 0 1px 0 #ddd;
|
||||
}
|
||||
.sp-container button:active {
|
||||
border: 1px solid #aaa;
|
||||
border-bottom: 1px solid #888;
|
||||
-webkit-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;
|
||||
-moz-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;
|
||||
-ms-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;
|
||||
-o-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;
|
||||
box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;
|
||||
}
|
||||
.sp-cancel {
|
||||
font-size: 11px;
|
||||
color: #d93f3f !important;
|
||||
margin:0;
|
||||
padding:2px;
|
||||
margin-right: 5px;
|
||||
vertical-align: middle;
|
||||
text-decoration:none;
|
||||
|
||||
}
|
||||
.sp-cancel:hover {
|
||||
color: #d93f3f !important;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
|
||||
.sp-palette span:hover, .sp-palette span.sp-thumb-active {
|
||||
border-color: #000;
|
||||
}
|
||||
|
||||
.sp-preview, .sp-alpha, .sp-thumb-el {
|
||||
position:relative;
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==);
|
||||
}
|
||||
.sp-preview-inner, .sp-alpha-inner, .sp-thumb-inner {
|
||||
display:block;
|
||||
position:absolute;
|
||||
top:0;left:0;bottom:0;right:0;
|
||||
}
|
||||
|
||||
.sp-palette .sp-thumb-inner {
|
||||
background-position: 50% 50%;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.sp-palette .sp-thumb-light.sp-thumb-active .sp-thumb-inner {
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAIVJREFUeNpiYBhsgJFMffxAXABlN5JruT4Q3wfi/0DsT64h8UD8HmpIPCWG/KemIfOJCUB+Aoacx6EGBZyHBqI+WsDCwuQ9mhxeg2A210Ntfo8klk9sOMijaURm7yc1UP2RNCMbKE9ODK1HM6iegYLkfx8pligC9lCD7KmRof0ZhjQACDAAceovrtpVBRkAAAAASUVORK5CYII=);
|
||||
}
|
||||
|
||||
.sp-palette .sp-thumb-dark.sp-thumb-active .sp-thumb-inner {
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAMdJREFUOE+tkgsNwzAMRMugEAahEAahEAZhEAqlEAZhEAohEAYh81X2dIm8fKpEspLGvudPOsUYpxE2BIJCroJmEW9qJ+MKaBFhEMNabSy9oIcIPwrB+afvAUFoK4H0tMaQ3XtlrggDhOVVMuT4E5MMG0FBbCEYzjYT7OxLEvIHQLY2zWwQ3D+9luyOQTfKDiFD3iUIfPk8VqrKjgAiSfGFPecrg6HN6m/iBcwiDAo7WiBeawa+Kwh7tZoSCGLMqwlSAzVDhoK+6vH4G0P5wdkAAAAASUVORK5CYII=);
|
||||
}
|
||||
|
||||
.sp-clear-display {
|
||||
background-repeat:no-repeat;
|
||||
background-position: center;
|
||||
background-image: url(data:image/gif;base64,R0lGODlhFAAUAPcAAAAAAJmZmZ2dnZ6enqKioqOjo6SkpKWlpaampqenp6ioqKmpqaqqqqurq/Hx8fLy8vT09PX19ff39/j4+Pn5+fr6+vv7+wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAP8ALAAAAAAUABQAAAihAP9FoPCvoMGDBy08+EdhQAIJCCMybCDAAYUEARBAlFiQQoMABQhKUJBxY0SPICEYHBnggEmDKAuoPMjS5cGYMxHW3IiT478JJA8M/CjTZ0GgLRekNGpwAsYABHIypcAgQMsITDtWJYBR6NSqMico9cqR6tKfY7GeBCuVwlipDNmefAtTrkSzB1RaIAoXodsABiZAEFB06gIBWC1mLVgBa0AAOw==);
|
||||
}
|
||||
2323
tools/js/spectrum.js
@@ -35,14 +35,14 @@
|
||||
if(!isset($_REQUEST['name']))
|
||||
die('Please enter name as get or post parameter.');
|
||||
|
||||
$name = stripslashes(ucwords(strtolower(trim($_REQUEST['name']))));
|
||||
$player = new OTS_Player();
|
||||
$player->find($name);
|
||||
$player->find($_REQUEST['name']);
|
||||
|
||||
if(!$player->isLoaded())
|
||||
{
|
||||
header('Content-type: image/png');
|
||||
readfile(SIGNATURES_IMAGES.'nocharacter.png');
|
||||
//header('Content-type: image/png');
|
||||
//readfile(SIGNATURES_IMAGES.'nocharacter.png');
|
||||
http_response_code(404);
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||