Compare commits
5 Commits
feature/re
...
feature/me
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b1ee22ef60 | ||
|
|
f245e0bf23 | ||
|
|
6346a10ce6 | ||
|
|
d83e9f3613 | ||
|
|
4d7589a934 |
2
.github/workflows/cypress.yml
vendored
@@ -22,7 +22,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
php-versions: [ '8.1', '8.2', '8.3', '8.4', '8.5' ]
|
php-versions: [ '8.1', '8.2', '8.3', '8.4' ]
|
||||||
ots: ['tfs-1.4', 'canary-3.1.2'] # TODO: add 'tfs-master' (actually doesn't work cause AAC doesn't support reading .env configuration)
|
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 }})
|
name: Cypress (PHP ${{ matrix.php-versions }}, ${{ matrix.ots }})
|
||||||
steps:
|
steps:
|
||||||
|
|||||||
@@ -1,18 +1,5 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## [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]
|
## [1.8.5 - 21.11.2025]
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ if (!hasFlag(FLAG_CONTENT_MENUS) && !superAdmin()) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$pluginThemes = Plugins::getThemes();
|
$pluginThemes = Plugins::getThemes();
|
||||||
|
$groups = new OTS_Groups_List();
|
||||||
|
|
||||||
if (isset($_POST['template'])) {
|
if (isset($_POST['template'])) {
|
||||||
$template = $_POST['template'];
|
$template = $_POST['template'];
|
||||||
@@ -32,6 +33,8 @@ if (isset($_POST['template'])) {
|
|||||||
$post_menu_link = $_POST['menu_link'] ?? [];
|
$post_menu_link = $_POST['menu_link'] ?? [];
|
||||||
$post_menu_blank = $_POST['menu_blank'] ?? [];
|
$post_menu_blank = $_POST['menu_blank'] ?? [];
|
||||||
$post_menu_color = $_POST['menu_color'] ?? [];
|
$post_menu_color = $_POST['menu_color'] ?? [];
|
||||||
|
$post_menu_access = $_POST['menu_access'] ?? [];
|
||||||
|
|
||||||
if (count($post_menu) != count($post_menu_link)) {
|
if (count($post_menu) != count($post_menu_link)) {
|
||||||
echo 'Menu count is not equal menu links. Something went wrong when sending form.';
|
echo 'Menu count is not equal menu links. Something went wrong when sending form.';
|
||||||
return;
|
return;
|
||||||
@@ -50,6 +53,7 @@ if (isset($_POST['template'])) {
|
|||||||
'link' => $post_menu_link[$category][$i],
|
'link' => $post_menu_link[$category][$i],
|
||||||
'blank' => $post_menu_blank[$category][$i] == 'on' ? 1 : 0,
|
'blank' => $post_menu_blank[$category][$i] == 'on' ? 1 : 0,
|
||||||
'color' => str_replace('#', '', $post_menu_color[$category][$i]),
|
'color' => str_replace('#', '', $post_menu_color[$category][$i]),
|
||||||
|
'access' => $post_menu_access[$category][$i],
|
||||||
'category' => $category,
|
'category' => $category,
|
||||||
'ordering' => $i
|
'ordering' => $i
|
||||||
]);
|
]);
|
||||||
@@ -122,7 +126,7 @@ if (isset($_POST['template'])) {
|
|||||||
?>
|
?>
|
||||||
<?php
|
<?php
|
||||||
$menus = Menu::query()
|
$menus = Menu::query()
|
||||||
->select('name', 'link', 'blank', 'color', 'category', 'ordering')
|
->select('name', 'link', 'access', 'blank', 'color', 'category', 'ordering')
|
||||||
->where('enabled', 1)
|
->where('enabled', 1)
|
||||||
->where('template', $template)
|
->where('template', $template)
|
||||||
->orderBy('ordering')
|
->orderBy('ordering')
|
||||||
@@ -151,11 +155,34 @@ if (isset($_POST['template'])) {
|
|||||||
foreach ($menus[$id] as $menu):
|
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']);
|
$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']); ?>"/>
|
<li class="ui-state-default" id="list-<?php echo $id ?>-<?php echo $i ?>">
|
||||||
<label>Link:</label> <input type="text" name="menu_link[<?php echo $id ?>][]" value="<?php echo $menu['link'] ?>"/>
|
<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']); ?>"/>
|
||||||
<input type="hidden" name="menu_blank[<?php echo $id ?>][]" value="0"/>
|
</label>
|
||||||
<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; ?>"/>
|
<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>
|
<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;
|
<?php $i++; $last_id[$id] = $i;
|
||||||
endforeach;
|
endforeach;
|
||||||
|
|||||||
15
common.php
@@ -27,7 +27,7 @@ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is
|
|||||||
|
|
||||||
const MYAAC = true;
|
const MYAAC = true;
|
||||||
const MYAAC_VERSION = '2.0-dev';
|
const MYAAC_VERSION = '2.0-dev';
|
||||||
const DATABASE_VERSION = 47;
|
const DATABASE_VERSION = 48;
|
||||||
const TABLE_PREFIX = 'myaac_';
|
const TABLE_PREFIX = 'myaac_';
|
||||||
define('START_TIME', microtime(true));
|
define('START_TIME', microtime(true));
|
||||||
define('MYAAC_OS', stripos(PHP_OS, 'WIN') === 0 ? 'WINDOWS' : (strtoupper(PHP_OS) === 'DARWIN' ? 'MAC' : 'LINUX'));
|
define('MYAAC_OS', stripos(PHP_OS, 'WIN') === 0 ? 'WINDOWS' : (strtoupper(PHP_OS) === 'DARWIN' ? 'MAC' : 'LINUX'));
|
||||||
@@ -148,17 +148,16 @@ if(!IS_CLI) {
|
|||||||
|
|
||||||
/** @var array $config */
|
/** @var array $config */
|
||||||
ini_set('log_errors', 1);
|
ini_set('log_errors', 1);
|
||||||
if(isset($config['env']) && $config['env'] !== 'dev' && !defined('MYAAC_INSTALL')) {
|
if(@$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_errors', 1);
|
||||||
ini_set('display_startup_errors', 1);
|
ini_set('display_startup_errors', 1);
|
||||||
error_reporting(E_ALL);
|
error_reporting(E_ALL);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
ini_set('display_errors', 0);
|
||||||
|
ini_set('display_startup_errors', 0);
|
||||||
|
error_reporting(E_ALL & ~E_DEPRECATED & ~E_STRICT);
|
||||||
|
}
|
||||||
|
|
||||||
$autoloadFile = VENDOR . 'autoload.php';
|
$autoloadFile = VENDOR . 'autoload.php';
|
||||||
if (!is_file($autoloadFile)) {
|
if (!is_file($autoloadFile)) {
|
||||||
|
|||||||
BIN
images/druid.png
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 12 KiB |
BIN
images/monk.png
|
Before Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 8.2 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 10 KiB |
@@ -102,6 +102,7 @@ CREATE TABLE IF NOT EXISTS `myaac_menu`
|
|||||||
`template` varchar(255) NOT NULL,
|
`template` varchar(255) NOT NULL,
|
||||||
`name` varchar(255) NOT NULL,
|
`name` varchar(255) NOT NULL,
|
||||||
`link` varchar(255) NOT NULL,
|
`link` varchar(255) NOT NULL,
|
||||||
|
`access` tinyint NOT NULL DEFAULT 0,
|
||||||
`blank` tinyint NOT NULL DEFAULT 0,
|
`blank` tinyint NOT NULL DEFAULT 0,
|
||||||
`color` varchar(6) NOT NULL DEFAULT '',
|
`color` varchar(6) NOT NULL DEFAULT '',
|
||||||
`category` int NOT NULL DEFAULT 1,
|
`category` int NOT NULL DEFAULT 1,
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ $deprecatedConfig = [
|
|||||||
'genders',
|
'genders',
|
||||||
'template',
|
'template',
|
||||||
'template_allow_change',
|
'template_allow_change',
|
||||||
|
'vocations_amount',
|
||||||
|
'vocations',
|
||||||
'client',
|
'client',
|
||||||
'session_prefix',
|
'session_prefix',
|
||||||
'friendly_urls',
|
'friendly_urls',
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ use MyAAC\CsrfToken;
|
|||||||
use MyAAC\Hooks;
|
use MyAAC\Hooks;
|
||||||
use MyAAC\Plugins;
|
use MyAAC\Plugins;
|
||||||
use MyAAC\Models\Town;
|
use MyAAC\Models\Town;
|
||||||
use MyAAC\Server\XML\Vocations;
|
|
||||||
use MyAAC\Settings;
|
use MyAAC\Settings;
|
||||||
|
|
||||||
defined('MYAAC') or die('Direct access not allowed!');
|
defined('MYAAC') or die('Direct access not allowed!');
|
||||||
@@ -215,5 +214,3 @@ if (count($towns) <= 0) {
|
|||||||
|
|
||||||
config(['towns', $towns]);
|
config(['towns', $towns]);
|
||||||
unset($towns);
|
unset($towns);
|
||||||
|
|
||||||
new Vocations();
|
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ use MyAAC\Cache\Cache;
|
|||||||
*/
|
*/
|
||||||
class OTS_DB_MySQL extends OTS_Base_DB
|
class OTS_DB_MySQL extends OTS_Base_DB
|
||||||
{
|
{
|
||||||
private bool $hasCacheChanged = false;
|
|
||||||
private array $has_table_cache = [];
|
private array $has_table_cache = [];
|
||||||
private array $has_column_cache = [];
|
private array $has_column_cache = [];
|
||||||
private array $get_column_info_cache = [];
|
private array $get_column_info_cache = [];
|
||||||
@@ -165,7 +164,7 @@ class OTS_DB_MySQL extends OTS_Base_DB
|
|||||||
$cache->delete('database_columns_info');
|
$cache->delete('database_columns_info');
|
||||||
$cache->delete('database_checksum');
|
$cache->delete('database_checksum');
|
||||||
}
|
}
|
||||||
else if ($this->hasCacheChanged) {
|
else {
|
||||||
$cache->set('database_tables', serialize($this->has_table_cache), 3600);
|
$cache->set('database_tables', serialize($this->has_table_cache), 3600);
|
||||||
$cache->set('database_columns', serialize($this->has_column_cache), 3600);
|
$cache->set('database_columns', serialize($this->has_column_cache), 3600);
|
||||||
$cache->set('database_columns_info', serialize($this->get_column_info_cache), 3600);
|
$cache->set('database_columns_info', serialize($this->get_column_info_cache), 3600);
|
||||||
@@ -229,8 +228,6 @@ class OTS_DB_MySQL extends OTS_Base_DB
|
|||||||
|
|
||||||
private function hasTableInternal($name): bool
|
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);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,8 +241,6 @@ class OTS_DB_MySQL extends OTS_Base_DB
|
|||||||
}
|
}
|
||||||
|
|
||||||
private function hasColumnInternal($table, $column): bool {
|
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);
|
return $this->hasTable($table) && ($this->has_column_cache[$table . '.' . $column] = count($this->query('SHOW COLUMNS FROM `' . $table . "` LIKE " . $this->quote($column))->fetchAll()) > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,8 +272,6 @@ class OTS_DB_MySQL extends OTS_Base_DB
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->hasCacheChanged = true;
|
|
||||||
|
|
||||||
$formatResult = function ($result) {
|
$formatResult = function ($result) {
|
||||||
return [
|
return [
|
||||||
'field' => $result['Field'],
|
'field' => $result['Field'],
|
||||||
|
|||||||
@@ -852,7 +852,13 @@ class OTS_Player extends OTS_Row_DAO
|
|||||||
throw new E_OTS_NotLoaded();
|
throw new E_OTS_NotLoaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
return \OTS_Toolbox::getVocationFromPromotion($this->data['vocation'], $this->data['promotion'] ?? 0);
|
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'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -13,8 +13,6 @@
|
|||||||
* @license http://www.gnu.org/licenses/lgpl-3.0.txt GNU Lesser General Public License, Version 3
|
* @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.
|
* Toolbox for common operations.
|
||||||
*
|
*
|
||||||
@@ -112,21 +110,14 @@ class OTS_Toolbox
|
|||||||
$list->setFilter($filter);
|
$list->setFilter($filter);
|
||||||
return $list;
|
return $list;
|
||||||
}
|
}
|
||||||
public static function getVocationFromPromotion($id, $promotion = 0): int
|
|
||||||
|
public static function getVocationName($id, $promotion = 0): string
|
||||||
{
|
{
|
||||||
if($promotion > 0) {
|
if($promotion > 0) {
|
||||||
for ($i = 0; $i < $promotion; $i++) {
|
$id = ($id + ($promotion * config('vocations_amount')));
|
||||||
if ($_id = Vocations::getPromoted($id)) {
|
|
||||||
$id = $_id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $id;
|
return config('vocations')[$id] ?? 'Unknown';
|
||||||
}
|
|
||||||
|
|
||||||
public static function getVocationName($id, $promotion = 0): string {
|
|
||||||
return config('vocations')[self::getVocationFromPromotion($id, $promotion)] ?? 'Unknown';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
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) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
$down = function () use ($db) {
|
$up = function () use ($db) {
|
||||||
if (!$db->hasColumn(TABLE_PREFIX . 'screenshots', 'name')) {
|
if (!$db->hasColumn(TABLE_PREFIX . 'screenshots', 'name')) {
|
||||||
$db->addColumn(TABLE_PREFIX . 'screenshots', 'name', 'VARCHAR(30) NOT NULL');
|
$db->addColumn(TABLE_PREFIX . 'screenshots', 'name', 'VARCHAR(30) NOT NULL');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -452,8 +452,10 @@ WHERE killers.death_id = '".$death['id']."' ORDER BY killers.final_hit DESC, kil
|
|||||||
if($query->rowCount() > 0) {
|
if($query->rowCount() > 0) {
|
||||||
echo 'Did you mean:<ul>';
|
echo 'Did you mean:<ul>';
|
||||||
foreach($query as $player) {
|
foreach($query as $player) {
|
||||||
$player['vocation'] = OTS_Toolbox::getVocationFromPromotion($player['vocation'], $player['promotion'] ?? 0);
|
if(isset($player['promotion'])) {
|
||||||
|
if((int)$player['promotion'] > 0)
|
||||||
|
$player['vocation'] += ($player['promotion'] * $config['vocations_amount']);
|
||||||
|
}
|
||||||
echo '<li>' . getPlayerLink($player['name']) . ' (<small><strong>level ' . $player['level'] . ', ' . $config['vocations'][$player['vocation']] . '</strong></small>)</li>';
|
echo '<li>' . getPlayerLink($player['name']) . ' (<small><strong>level ' . $player['level'] . ', ' . $config['vocations'][$player['vocation']] . '</strong></small>)</li>';
|
||||||
}
|
}
|
||||||
echo '</ul>';
|
echo '</ul>';
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ use MyAAC\Cache\Cache;
|
|||||||
use MyAAC\Models\Player;
|
use MyAAC\Models\Player;
|
||||||
use MyAAC\Models\PlayerDeath;
|
use MyAAC\Models\PlayerDeath;
|
||||||
use MyAAC\Models\PlayerKillers;
|
use MyAAC\Models\PlayerKillers;
|
||||||
use MyAAC\Server\XML\Vocations;
|
|
||||||
|
|
||||||
defined('MYAAC') or die('Direct access not allowed!');
|
defined('MYAAC') or die('Direct access not allowed!');
|
||||||
$title = 'Highscores';
|
$title = 'Highscores';
|
||||||
@@ -36,20 +35,24 @@ if(!is_numeric($page) || $page < 1 || $page > PHP_INT_MAX) {
|
|||||||
$query = Player::query();
|
$query = Player::query();
|
||||||
|
|
||||||
$configVocations = config('vocations');
|
$configVocations = config('vocations');
|
||||||
|
$configVocationsAmount = config('vocations_amount');
|
||||||
|
|
||||||
$vocationId = null;
|
$vocationId = null;
|
||||||
if($vocation !== 'all') {
|
if($vocation !== 'all') {
|
||||||
foreach($configVocations as $id => $name) {
|
foreach($configVocations as $id => $name) {
|
||||||
if(strtolower($name) == $vocation) {
|
if(strtolower($name) == $vocation) {
|
||||||
$vocationId = $id;
|
$vocationId = $id;
|
||||||
$filterVocations = [$id];
|
$add_vocs = [$id];
|
||||||
|
|
||||||
while($tmpVoc = Vocations::getPromoted($id)) {
|
if ($id !== 0) {
|
||||||
$id = $tmpVoc;
|
$i = $id + $configVocationsAmount;
|
||||||
$filterVocations[] = $tmpVoc;
|
while (isset($configVocations[$i])) {
|
||||||
|
$add_vocs[] = $i;
|
||||||
|
$i += $configVocationsAmount;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$query->whereIn('players.vocation', $filterVocations);
|
$query->whereIn('players.vocation', $add_vocs);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -173,9 +176,7 @@ if (empty($highscores)) {
|
|||||||
POT::SKILL_FISH => 'skill_fishing',
|
POT::SKILL_FISH => 'skill_fishing',
|
||||||
);
|
);
|
||||||
|
|
||||||
$query
|
$query->addSelect($skill_ids[$skill] . ' as value');
|
||||||
->addSelect($skill_ids[$skill] . ' as value')
|
|
||||||
->orderByDesc($skill_ids[$skill] . '_tries');
|
|
||||||
} else {
|
} else {
|
||||||
$query
|
$query
|
||||||
->join('player_skills', 'player_skills.player_id', '=', 'players.id')
|
->join('player_skills', 'player_skills.player_id', '=', 'players.id')
|
||||||
@@ -197,11 +198,11 @@ if (empty($highscores)) {
|
|||||||
if ($skill == POT::SKILL__MAGLEVEL) {
|
if ($skill == POT::SKILL__MAGLEVEL) {
|
||||||
$query
|
$query
|
||||||
->addSelect('players.maglevel as value', 'players.maglevel')
|
->addSelect('players.maglevel as value', 'players.maglevel')
|
||||||
->orderByDesc('manaspent');
|
->orderBy('manaspent');
|
||||||
} else { // level
|
} else { // level
|
||||||
$query
|
$query
|
||||||
->addSelect('players.level as value', 'players.experience')
|
->addSelect('players.level as value', 'players.experience')
|
||||||
->orderByDesc('experience');
|
->orderBy('experience');
|
||||||
$list = 'experience';
|
$list = 'experience';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -322,5 +323,4 @@ $twig->display('highscores.html.twig', [
|
|||||||
'page' => $page,
|
'page' => $page,
|
||||||
'baseLink' => $baseLink,
|
'baseLink' => $baseLink,
|
||||||
'updatedAt' => $updatedAt,
|
'updatedAt' => $updatedAt,
|
||||||
'baseVocations' => Vocations::getBase(true),
|
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
use MyAAC\Cache\Cache;
|
use MyAAC\Cache\Cache;
|
||||||
use MyAAC\Models\ServerConfig;
|
use MyAAC\Models\ServerConfig;
|
||||||
use MyAAC\Models\ServerRecord;
|
use MyAAC\Models\ServerRecord;
|
||||||
use MyAAC\Server\XML\Vocations;
|
|
||||||
|
|
||||||
defined('MYAAC') or die('Direct access not allowed!');
|
defined('MYAAC') or die('Direct access not allowed!');
|
||||||
$title = 'Who is online?';
|
$title = 'Who is online?';
|
||||||
@@ -57,14 +56,15 @@ $cached = Cache::remember("online_$order", setting('core.online_cache_ttl') * 60
|
|||||||
|
|
||||||
$vocations = array_map(function ($name) {
|
$vocations = array_map(function ($name) {
|
||||||
return 0;
|
return 0;
|
||||||
}, config('vocations'));
|
}, setting('core.vocations'));
|
||||||
|
|
||||||
if($db->hasTable('players_online')) // tfs 1.0
|
if($db->hasTable('players_online')) // tfs 1.0
|
||||||
$playersOnline = $db->query('SELECT `accounts`.`country`, `players`.`name`, `players`.`level`, `players`.`vocation`' . $outfit . ', `' . $skull_time . '` as `skulltime`, `' . $skull_type . '` as `skull` FROM `accounts`, `players`, `players_online` WHERE `players`.`id` = `players_online`.`player_id` AND `accounts`.`id` = `players`.`account_id` ORDER BY ' . $orderSql);
|
$playersOnline = $db->query('SELECT `accounts`.`country`, `players`.`name`, `players`.`level`, `players`.`vocation`' . $outfit . ', `' . $skull_time . '` as `skulltime`, `' . $skull_type . '` as `skull` FROM `accounts`, `players`, `players_online` WHERE `players`.`id` = `players_online`.`player_id` AND `accounts`.`id` = `players`.`account_id` ORDER BY ' . $orderSql);
|
||||||
else
|
else
|
||||||
$playersOnline = $db->query('SELECT `accounts`.`country`, `players`.`name`, `players`.`level`, `players`.`vocation`' . $outfit . ', ' . $promotion . ' `' . $skull_time . '` as `skulltime`, `' . $skull_type . '` as `skull` FROM `accounts`, `players` WHERE `players`.`online` > 0 AND `accounts`.`id` = `players`.`account_id` ORDER BY ' . $orderSql);
|
$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);
|
||||||
|
|
||||||
$configVocations = config('vocations');
|
$settingVocations = setting('core.vocations');
|
||||||
|
$settingVocationsAmount = setting('core.vocations_amount');
|
||||||
|
|
||||||
$players = [];
|
$players = [];
|
||||||
foreach($playersOnline as $player) {
|
foreach($playersOnline as $player) {
|
||||||
@@ -81,19 +81,22 @@ $cached = Cache::remember("online_$order", setting('core.online_cache_ttl') * 60
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$player['vocation'] = OTS_Toolbox::getVocationFromPromotion($player['vocation'], $player['promotion'] ?? 0);
|
if(isset($player['promotion'])) {
|
||||||
|
if((int)$player['promotion'] > 0)
|
||||||
|
$player['vocation'] += ($player['promotion'] * $settingVocationsAmount);
|
||||||
|
}
|
||||||
|
|
||||||
$players[] = array(
|
$players[] = array(
|
||||||
'name' => getPlayerLink($player['name']),
|
'name' => getPlayerLink($player['name']),
|
||||||
'player' => $player,
|
'player' => $player,
|
||||||
'level' => $player['level'],
|
'level' => $player['level'],
|
||||||
'vocation' => $configVocations[$player['vocation']],
|
'vocation' => $settingVocations[$player['vocation']],
|
||||||
'skull' => $skull,
|
'skull' => $skull,
|
||||||
'country_image' => getFlagImage($player['country']),
|
'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'],
|
'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[Vocations::getOriginal($player['vocation'])]++;
|
$vocations[($player['vocation'] > $settingVocationsAmount ? $player['vocation'] - $settingVocationsAmount : $player['vocation'])]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
$record = '';
|
$record = '';
|
||||||
@@ -139,7 +142,6 @@ $twig->display('online.html.twig', array(
|
|||||||
'vocations' => $cached['vocations'],
|
'vocations' => $cached['vocations'],
|
||||||
'vocs' => $cached['vocations'], // deprecated, to be removed
|
'vocs' => $cached['vocations'], // deprecated, to be removed
|
||||||
'order' => $order,
|
'order' => $order,
|
||||||
'baseVocations' => Vocations::getBase(false),
|
|
||||||
));
|
));
|
||||||
|
|
||||||
// search bar
|
// search bar
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
* @link https://my-aac.org
|
* @link https://my-aac.org
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use MyAAC\Models\Menu;
|
||||||
use MyAAC\Models\Pages;
|
use MyAAC\Models\Pages;
|
||||||
use MyAAC\Plugins;
|
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';
|
$page = '404';
|
||||||
$file = SYSTEM . 'pages/404.php';
|
$file = SYSTEM . 'pages/404.php';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -219,14 +219,7 @@ return [
|
|||||||
'cache_engine' => [
|
'cache_engine' => [
|
||||||
'name' => 'Cache Engine',
|
'name' => 'Cache Engine',
|
||||||
'type' => 'options',
|
'type' => 'options',
|
||||||
'options' => [
|
'options' => ['auto' => 'Auto', 'file' => 'Files', 'apc' => 'APC', 'apcu' => 'APCu', 'disable' => 'Disable'],
|
||||||
'auto' => 'Auto',
|
|
||||||
'file' => 'Files',
|
|
||||||
'apc' => 'APC',
|
|
||||||
'apcu' => 'APCu',
|
|
||||||
'php' => 'PHP',
|
|
||||||
'disable' => 'Disable',
|
|
||||||
],
|
|
||||||
'desc' => 'Auto is most reasonable. It will detect the best cache engine',
|
'desc' => 'Auto is most reasonable. It will detect the best cache engine',
|
||||||
'default' => 'auto',
|
'default' => 'auto',
|
||||||
'is_config' => true,
|
'is_config' => true,
|
||||||
@@ -319,6 +312,23 @@ 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',
|
'type' => 'category',
|
||||||
'title' => 'Database',
|
'title' => 'Database',
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ namespace MyAAC\Cache;
|
|||||||
|
|
||||||
class APC
|
class APC
|
||||||
{
|
{
|
||||||
private string $prefix;
|
private $prefix;
|
||||||
private bool $enabled;
|
private $enabled;
|
||||||
|
|
||||||
public function __construct($prefix = '')
|
public function __construct($prefix = '')
|
||||||
{
|
{
|
||||||
@@ -22,14 +22,14 @@ class APC
|
|||||||
$this->enabled = function_exists('apc_fetch');
|
$this->enabled = function_exists('apc_fetch');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function set($key, $var, $ttl = 0): void
|
public function set($key, $var, $ttl = 0)
|
||||||
{
|
{
|
||||||
$key = $this->prefix . $key;
|
$key = $this->prefix . $key;
|
||||||
apc_delete($key);
|
apc_delete($key);
|
||||||
apc_store($key, $var, $ttl);
|
apc_store($key, $var, $ttl);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get($key): string
|
public function get($key)
|
||||||
{
|
{
|
||||||
$tmp = '';
|
$tmp = '';
|
||||||
if ($this->fetch($this->prefix . $key, $tmp)) {
|
if ($this->fetch($this->prefix . $key, $tmp)) {
|
||||||
@@ -39,15 +39,18 @@ class APC
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function fetch($key, &$var): bool {
|
public function fetch($key, &$var)
|
||||||
|
{
|
||||||
return ($var = apc_fetch($this->prefix . $key)) !== false;
|
return ($var = apc_fetch($this->prefix . $key)) !== false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function delete($key): void {
|
public function delete($key)
|
||||||
|
{
|
||||||
apc_delete($this->prefix . $key);
|
apc_delete($this->prefix . $key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function enabled(): bool {
|
public function enabled()
|
||||||
|
{
|
||||||
return $this->enabled;
|
return $this->enabled;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ namespace MyAAC\Cache;
|
|||||||
|
|
||||||
class APCu
|
class APCu
|
||||||
{
|
{
|
||||||
private string $prefix;
|
private $prefix;
|
||||||
private bool $enabled;
|
private $enabled;
|
||||||
|
|
||||||
public function __construct($prefix = '')
|
public function __construct($prefix = '')
|
||||||
{
|
{
|
||||||
@@ -22,14 +22,14 @@ class APCu
|
|||||||
$this->enabled = function_exists('apcu_fetch');
|
$this->enabled = function_exists('apcu_fetch');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function set($key, $var, $ttl = 0): void
|
public function set($key, $var, $ttl = 0)
|
||||||
{
|
{
|
||||||
$key = $this->prefix . $key;
|
$key = $this->prefix . $key;
|
||||||
apcu_delete($key);
|
apcu_delete($key);
|
||||||
apcu_store($key, $var, $ttl);
|
apcu_store($key, $var, $ttl);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get($key): string
|
public function get($key)
|
||||||
{
|
{
|
||||||
$tmp = '';
|
$tmp = '';
|
||||||
if ($this->fetch($this->prefix . $key, $tmp)) {
|
if ($this->fetch($this->prefix . $key, $tmp)) {
|
||||||
@@ -39,15 +39,18 @@ class APCu
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function fetch($key, &$var): bool {
|
public function fetch($key, &$var)
|
||||||
|
{
|
||||||
return ($var = apcu_fetch($this->prefix . $key)) !== false;
|
return ($var = apcu_fetch($this->prefix . $key)) !== false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function delete($key): void {
|
public function delete($key)
|
||||||
|
{
|
||||||
apcu_delete($this->prefix . $key);
|
apcu_delete($this->prefix . $key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function enabled(): bool {
|
public function enabled()
|
||||||
|
{
|
||||||
return $this->enabled;
|
return $this->enabled;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ class Cache
|
|||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public static function detect(): string
|
public static function detect()
|
||||||
{
|
{
|
||||||
if (function_exists('apc_fetch'))
|
if (function_exists('apc_fetch'))
|
||||||
return 'apc';
|
return 'apc';
|
||||||
@@ -98,7 +98,8 @@ class Cache
|
|||||||
/**
|
/**
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function enabled(): bool {
|
public function enabled()
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,22 +12,18 @@ namespace MyAAC\Cache;
|
|||||||
|
|
||||||
class File
|
class File
|
||||||
{
|
{
|
||||||
private string $prefix;
|
private $prefix;
|
||||||
private string $dir;
|
private $dir;
|
||||||
private bool $enabled;
|
private $enabled;
|
||||||
|
|
||||||
public function __construct($prefix = '', $dir = '')
|
public function __construct($prefix = '', $dir = '')
|
||||||
{
|
{
|
||||||
$this->prefix = $prefix;
|
$this->prefix = $prefix;
|
||||||
$this->dir = $dir;
|
$this->dir = $dir;
|
||||||
|
|
||||||
ensureFolderExists($this->dir);
|
|
||||||
ensureIndexExists($this->dir);
|
|
||||||
|
|
||||||
$this->enabled = (file_exists($this->dir) && is_dir($this->dir) && is_writable($this->dir));
|
$this->enabled = (file_exists($this->dir) && is_dir($this->dir) && is_writable($this->dir));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function set($key, $var, $ttl = 0): void
|
public function set($key, $var, $ttl = 0)
|
||||||
{
|
{
|
||||||
$file = $this->_name($key);
|
$file = $this->_name($key);
|
||||||
file_put_contents($file, $var);
|
file_put_contents($file, $var);
|
||||||
@@ -39,7 +35,7 @@ class File
|
|||||||
touch($file, time() + $ttl);
|
touch($file, time() + $ttl);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get($key): string
|
public function get($key)
|
||||||
{
|
{
|
||||||
$tmp = '';
|
$tmp = '';
|
||||||
if ($this->fetch($key, $tmp)) {
|
if ($this->fetch($key, $tmp)) {
|
||||||
@@ -49,7 +45,7 @@ class File
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function fetch($key, &$var): bool
|
public function fetch($key, &$var)
|
||||||
{
|
{
|
||||||
$file = $this->_name($key);
|
$file = $this->_name($key);
|
||||||
if (!file_exists($file) || filemtime($file) < time()) {
|
if (!file_exists($file) || filemtime($file) < time()) {
|
||||||
@@ -60,7 +56,7 @@ class File
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function delete($key): void
|
public function delete($key)
|
||||||
{
|
{
|
||||||
$file = $this->_name($key);
|
$file = $this->_name($key);
|
||||||
if (file_exists($file)) {
|
if (file_exists($file)) {
|
||||||
@@ -68,11 +64,13 @@ class File
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function enabled(): bool {
|
public function enabled()
|
||||||
|
{
|
||||||
return $this->enabled;
|
return $this->enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function _name($key): string {
|
private function _name($key)
|
||||||
|
{
|
||||||
return sprintf('%s%s%s', $this->dir, $this->prefix, sha1($key));
|
return sprintf('%s%s%s', $this->dir, $this->prefix, sha1($key));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,40 +12,39 @@ namespace MyAAC\Cache;
|
|||||||
|
|
||||||
class PHP
|
class PHP
|
||||||
{
|
{
|
||||||
private string $prefix;
|
private $prefix;
|
||||||
private string $dir;
|
private $dir;
|
||||||
private bool $enabled;
|
private $enabled;
|
||||||
|
|
||||||
public function __construct($prefix = '', $dir = '')
|
public function __construct($prefix = '', $dir = '')
|
||||||
{
|
{
|
||||||
$this->prefix = $prefix;
|
$this->prefix = $prefix;
|
||||||
$this->dir = $dir;
|
$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);
|
ensureFolderExists($this->dir);
|
||||||
ensureIndexExists($this->dir);
|
ensureIndexExists($this->dir);
|
||||||
|
|
||||||
$this->enabled = (file_exists($this->dir) && is_dir($this->dir) && is_writable($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);
|
||||||
|
|
||||||
public function set($key, $var, $ttl = 0): void
|
$file = $this->_name($key);
|
||||||
{
|
rename($tmp, $file);
|
||||||
$var = var_export($var, true);
|
|
||||||
|
|
||||||
if ($ttl === 0) {
|
if ($ttl === 0) {
|
||||||
$ttl = 365 * 24 * 60 * 60; // 365 days
|
$ttl = 365 * 24 * 60 * 60; // 365 days
|
||||||
}
|
}
|
||||||
|
|
||||||
$expires = time() + $ttl;
|
touch($file, 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): string
|
public function get($key)
|
||||||
{
|
{
|
||||||
$tmp = '';
|
$tmp = '';
|
||||||
if ($this->fetch($key, $tmp)) {
|
if ($this->fetch($key, $tmp)) {
|
||||||
@@ -55,23 +54,19 @@ class PHP
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function fetch($key, &$var): bool
|
public function fetch($key, &$var)
|
||||||
{
|
{
|
||||||
$file = $this->_name($key);
|
$file = $this->_name($key);
|
||||||
if (!file_exists($file)) {
|
if (!file_exists($file) || filemtime($file) < time()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$content = include $file;
|
@include $file;
|
||||||
if (!isset($content) || $content['expires'] < time()) {
|
$var = isset($var) ? $var : null;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$var = $content['var'];
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function delete($key): void
|
public function delete($key)
|
||||||
{
|
{
|
||||||
$file = $this->_name($key);
|
$file = $this->_name($key);
|
||||||
if (file_exists($file)) {
|
if (file_exists($file)) {
|
||||||
@@ -79,11 +74,13 @@ class PHP
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function enabled(): bool {
|
public function enabled()
|
||||||
|
{
|
||||||
return $this->enabled;
|
return $this->enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function _name($key): string {
|
private function _name($key)
|
||||||
|
{
|
||||||
return sprintf('%s%s%s', $this->dir, $this->prefix, sha1($key) . '.php');
|
return sprintf('%s%s%s', $this->dir, $this->prefix, sha1($key) . '.php');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ namespace MyAAC\Cache;
|
|||||||
|
|
||||||
class XCache
|
class XCache
|
||||||
{
|
{
|
||||||
private string $prefix;
|
private $prefix;
|
||||||
private bool $enabled;
|
private $enabled;
|
||||||
|
|
||||||
public function __construct($prefix = '')
|
public function __construct($prefix = '')
|
||||||
{
|
{
|
||||||
@@ -22,14 +22,14 @@ class XCache
|
|||||||
$this->enabled = function_exists('xcache_get') && ini_get('xcache.var_size');
|
$this->enabled = function_exists('xcache_get') && ini_get('xcache.var_size');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function set($key, $var, $ttl = 0): void
|
public function set($key, $var, $ttl = 0)
|
||||||
{
|
{
|
||||||
$key = $this->prefix . $key;
|
$key = $this->prefix . $key;
|
||||||
xcache_unset($key);
|
xcache_unset($key);
|
||||||
xcache_set($key, $var, $ttl);
|
xcache_set($key, $var, $ttl);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get($key): string
|
public function get($key)
|
||||||
{
|
{
|
||||||
$tmp = '';
|
$tmp = '';
|
||||||
if ($this->fetch($this->prefix . $key, $tmp)) {
|
if ($this->fetch($this->prefix . $key, $tmp)) {
|
||||||
@@ -39,7 +39,7 @@ class XCache
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function fetch($key, &$var): bool
|
public function fetch($key, &$var)
|
||||||
{
|
{
|
||||||
$key = $this->prefix . $key;
|
$key = $this->prefix . $key;
|
||||||
if (!xcache_isset($key)) {
|
if (!xcache_isset($key)) {
|
||||||
@@ -50,11 +50,13 @@ class XCache
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function delete($key): void {
|
public function delete($key)
|
||||||
|
{
|
||||||
xcache_unset($this->prefix . $key);
|
xcache_unset($this->prefix . $key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function enabled(): bool {
|
public function enabled()
|
||||||
|
{
|
||||||
return $this->enabled;
|
return $this->enabled;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,6 @@ class Menu extends Model {
|
|||||||
|
|
||||||
public $timestamps = false;
|
public $timestamps = false;
|
||||||
|
|
||||||
protected $fillable = ['template', 'name', 'link', 'blank', 'color', 'category', 'ordering', 'enabled'];
|
protected $fillable = ['template', 'name', 'link', 'access', 'blank', 'color', 'category', 'ordering', 'enabled'];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,8 +46,14 @@ class Player extends Model {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getVocationNameAttribute() {
|
public function getVocationNameAttribute()
|
||||||
return \OTS_Toolbox::getVocationName($this->vocation, $this->promotion ?? 0);
|
{
|
||||||
|
$vocation = $this->vocation;
|
||||||
|
if (isset($this->promotion) && $this->promotion > 0) {
|
||||||
|
$vocation += ($this->promotion * setting('core.vocations_amount'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return config('vocations')[$vocation] ?? 'Unknown';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getIsDeletedAttribute()
|
public function getIsDeletedAttribute()
|
||||||
|
|||||||
@@ -1,93 +0,0 @@
|
|||||||
<?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 {
|
|
||||||
return self::$vocationsFrom[$id] ?? null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function getBase($includingRook = true): array {
|
|
||||||
$vocations = [];
|
|
||||||
foreach (self::$vocationsFrom as $vocId => $fromVoc) {
|
|
||||||
if ($vocId == $fromVoc && ($vocId != 0 || $includingRook)) {
|
|
||||||
$vocations[] = $vocId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $vocations;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -342,16 +342,6 @@ 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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -108,7 +108,6 @@ define('HOOK_FILTER_ROUTES', ++$i);
|
|||||||
define('HOOK_FILTER_TWIG_DISPLAY', ++$i);
|
define('HOOK_FILTER_TWIG_DISPLAY', ++$i);
|
||||||
define('HOOK_FILTER_TWIG_RENDER', ++$i);
|
define('HOOK_FILTER_TWIG_RENDER', ++$i);
|
||||||
define('HOOK_FILTER_THEME_FOOTER', ++$i);
|
define('HOOK_FILTER_THEME_FOOTER', ++$i);
|
||||||
define('HOOK_FILTER_VALIDATE_CHARACTER_NEW_NAME', ++$i);
|
|
||||||
|
|
||||||
const HOOK_FIRST = HOOK_INIT;
|
const HOOK_FIRST = HOOK_INIT;
|
||||||
define('HOOK_LAST', $i);
|
define('HOOK_LAST', $i);
|
||||||
|
|||||||
@@ -146,10 +146,10 @@ if($twig_loader) {
|
|||||||
|
|
||||||
function get_template_menus(): array
|
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 = 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)
|
->where('template', $template_name)
|
||||||
->orderBy('category')
|
->orderBy('category')
|
||||||
->orderBy('ordering')
|
->orderBy('ordering')
|
||||||
@@ -163,6 +163,10 @@ function get_template_menus(): array
|
|||||||
|
|
||||||
$menus = [];
|
$menus = [];
|
||||||
foreach($result as $menu) {
|
foreach($result as $menu) {
|
||||||
|
if ($menu['access'] > $logged_access) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (empty($menu['link'])) {
|
if (empty($menu['link'])) {
|
||||||
$menu['link'] = 'news';
|
$menu['link'] = 'news';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,8 @@
|
|||||||
<p class="note">You are editing: {{ template }}<br/><br/>
|
<p class="note">You are editing: {{ template }}<br/><br/>
|
||||||
Hint: You can drag menu items.<br/>
|
Hint: You can drag menu items.<br/>
|
||||||
Hint: Add links to external sites using: <b>http://</b> or <b>https://</b> prefix.<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>
|
</p>
|
||||||
<div class="row text-center">
|
<div class="row text-center">
|
||||||
<div class="col-md-2 col-sm-1"></div>
|
<div class="col-md-2 col-sm-1"></div>
|
||||||
|
|||||||
@@ -14,42 +14,62 @@
|
|||||||
colors[{{ cat }}] = '{{ options['default_links_color'] ?? (menuDefaultLinksColor ?? config('menu_default_color')) }}';
|
colors[{{ cat }}] = '{{ options['default_links_color'] ?? (menuDefaultLinksColor ?? config('menu_default_color')) }}';
|
||||||
{% endfor %}
|
{% 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 () {
|
$(function () {
|
||||||
const $sortable = $(".sortable");
|
const $sortable = $(".sortable");
|
||||||
$sortable.sortable();
|
$sortable.sortable();
|
||||||
$sortable.disableSelection();
|
$sortable.disableSelection();
|
||||||
|
|
||||||
$(".remove-button").on('click', function () {
|
$(".remove-button").on('click', function () {
|
||||||
var id = $(this).attr("id");
|
confirmRemoveMenuItem(this);
|
||||||
$('#list-' + id.replace('remove-button-', '')).remove();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
$(".add-button").on('click', function () {
|
$(".add-button").on('click', function () {
|
||||||
var cat = $(this).attr("id").replace('add-button-', '');
|
let cat = $(this).attr("id").replace('add-button-', '');
|
||||||
var id = last_id[cat];
|
let id = last_id[cat];
|
||||||
last_id[cat]++;
|
last_id[cat]++;
|
||||||
const color = colors[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) {
|
$("#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");
|
$(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");
|
$(obj).parent().prev().val("on");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<style type="text/css">
|
<style>
|
||||||
.sortable {
|
.sortable {
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@@ -60,24 +80,16 @@
|
|||||||
.remove-button, .add-button {
|
.remove-button, .add-button {
|
||||||
cursor: pointer;
|
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() {
|
.ui-sortable-handle {
|
||||||
$(".color-picker").spectrum({
|
padding: 10px;
|
||||||
preferredFormat: "hex",
|
|
||||||
showInput: true,
|
|
||||||
showPalette: true,
|
|
||||||
palette: [
|
|
||||||
['black', 'white', 'blanchedalmond',
|
|
||||||
'rgb(255, 128, 0);', 'hsv 100 70 50'],
|
|
||||||
['red', 'yellow', 'green', 'blue', 'violet']
|
|
||||||
]
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
</script>
|
|
||||||
|
.label_menu_name, .label_menu_link {
|
||||||
|
width: 45%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-name, .menu-link {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
<label for="vocationFilter">Choose a vocation</label>
|
<label for="vocationFilter">Choose a vocation</label>
|
||||||
<select onchange="location = this.value;" id="vocationFilter">
|
<select onchange="location = this.value;" id="vocationFilter">
|
||||||
<option value="{{ getLink('highscores') }}/{{ list|urlencode }}" class="size_xs">[ALL]</option>
|
<option value="{{ getLink('highscores') }}/{{ list|urlencode }}" class="size_xs">[ALL]</option>
|
||||||
{% for i in baseVocations %}
|
{% for i in 0..config.vocations_amount %}
|
||||||
<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>
|
<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 %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
@@ -120,7 +120,7 @@
|
|||||||
<tr bgcolor="{{ config.lightborder }}">
|
<tr bgcolor="{{ config.lightborder }}">
|
||||||
<td>
|
<td>
|
||||||
<a href="{{ getLink('highscores') }}/{{ list|urlencode }}" class="size_xs">[ALL]</a><br/>
|
<a href="{{ getLink('highscores') }}/{{ list|urlencode }}" class="size_xs">[ALL]</a><br/>
|
||||||
{% for i in baseVocations %}
|
{% for i in 0..config.vocations_amount %}
|
||||||
<a href="{{ getLink('highscores') }}/{{ list|urlencode }}/{{ config.vocations[i]|lower|urlencode }}" class="size_xs">{{ config.vocations[i]}}</a><br/>
|
<a href="{{ getLink('highscores') }}/{{ list|urlencode }}/{{ config.vocations[i]|lower|urlencode }}" class="size_xs">{{ config.vocations[i]}}</a><br/>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@@ -10,19 +10,22 @@
|
|||||||
{% if setting('core.online_vocations_images') %}
|
{% if setting('core.online_vocations_images') %}
|
||||||
<table width="200" cellspacing="1" cellpadding="0" border="0" align="center">
|
<table width="200" cellspacing="1" cellpadding="0" border="0" align="center">
|
||||||
<tr bgcolor="{{ config.darkborder }}">
|
<tr bgcolor="{{ config.darkborder }}">
|
||||||
{% for vocationId in baseVocations %}
|
<td><img src="images/sorcerer.png" /></td>
|
||||||
<td><img src="images/{{ config('vocations')[vocationId]|lower }}.png" width="150" height="200"/></td>
|
<td><img src="images/druid.png" /></td>
|
||||||
{% endfor %}
|
<td><img src="images/paladin.png" /></td>
|
||||||
|
<td><img src="images/knight.png" /></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr bgcolor="{{ config.vdarkborder }}">
|
<tr bgcolor="{{ config.vdarkborder }}">
|
||||||
{% for vocationId in baseVocations %}
|
<td class="white" style="text-align: center;"><strong>Sorcerers</strong></td>
|
||||||
<td class="white" style="text-align: center;"><strong>{{ config('vocations')[vocationId] }}s</strong></td>
|
<td class="white" style="text-align: center;"><strong>Druids</strong></td>
|
||||||
{% endfor %}
|
<td class="white" style="text-align: center;"><strong>Paladins</strong></td>
|
||||||
|
<td class="white" style="text-align: center;"><strong>Knights</strong></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr bgcolor="{{ config.lightborder }}">
|
<tr bgcolor="{{ config.lightborder }}">
|
||||||
{% for vocationId in baseVocations %}
|
<td style="text-align: center;">{{ vocs[1] }}</td>
|
||||||
<td style="text-align: center;">{{ vocs[vocationId] }}</td>
|
<td style="text-align: center;">{{ vocs[2] }}</td>
|
||||||
{% endfor %}
|
<td style="text-align: center;">{{ vocs[3] }}</td>
|
||||||
|
<td style="text-align: center;">{{ vocs[4] }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
<div style="text-align: center;"> </div>
|
<div style="text-align: center;"> </div>
|
||||||
@@ -32,14 +35,11 @@
|
|||||||
<td class="white" colspan="2"><b>Vocation statistics</b></td>
|
<td class="white" colspan="2"><b>Vocation statistics</b></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
{% set i = 0 %}
|
{% for i in 1..config.vocations_amount %}
|
||||||
{% for vocationId in baseVocations %}
|
|
||||||
<tr bgcolor="{{ getStyle(i) }}">
|
<tr bgcolor="{{ getStyle(i) }}">
|
||||||
<td width="25%">{{ config.vocations[vocationId] }}</td>
|
<td width="25%">{{ config.vocations[i] }}</td>
|
||||||
<td width="75%">{{ vocs[vocationId] }}</td>
|
<td width="75%">{{ vocs[i] }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
{% set i = i + 1 %}
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</table>
|
||||||
<br/>
|
<br/>
|
||||||
|
|||||||
@@ -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==);
|
|
||||||
}
|
|
||||||