mirror of
https://github.com/slawkens/myaac.git
synced 2026-01-23 14:36:22 +01:00
Merge branch 'develop' into feature/2fa
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -115,6 +94,11 @@ class Cache
|
||||
return unserialize($value);
|
||||
}
|
||||
|
||||
// -1 for infinite cache
|
||||
if ($ttl == -1) {
|
||||
$ttl = 10 * 365 * 24 * 60 * 60; // 10 years should be enough
|
||||
}
|
||||
|
||||
$value = $callback();
|
||||
$cache->set($key, serialize($value), $ttl);
|
||||
return $value;
|
||||
|
||||
@@ -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,33 +12,37 @@ 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;
|
||||
|
||||
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
|
||||
{
|
||||
$var = var_export($var, true);
|
||||
|
||||
// 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);
|
||||
|
||||
$file = $this->_name($key);
|
||||
rename($tmp, $file);
|
||||
|
||||
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)
|
||||
@@ -51,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)) {
|
||||
@@ -71,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;
|
||||
}
|
||||
}
|
||||
|
||||
33
system/src/Commands/Env.php
Normal file
33
system/src/Commands/Env.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace MyAAC\Commands;
|
||||
|
||||
use POT;
|
||||
|
||||
trait Env
|
||||
{
|
||||
protected function init(): void
|
||||
{
|
||||
global $config;
|
||||
if (!isset($config['installed']) || !$config['installed']) {
|
||||
throw new \RuntimeException('MyAAC has not been installed yet or there was error during installation. Please install again.');
|
||||
}
|
||||
|
||||
if(empty($config['server_path'])) {
|
||||
throw new \RuntimeException('Server Path has been not set. Go to config.php and set it.');
|
||||
}
|
||||
|
||||
// take care of trailing slash at the end
|
||||
if($config['server_path'][strlen($config['server_path']) - 1] !== '/')
|
||||
$config['server_path'] .= '/';
|
||||
|
||||
$config['lua'] = load_config_lua($config['server_path'] . 'config.lua');
|
||||
|
||||
// POT
|
||||
require_once SYSTEM . 'libs/pot/OTS.php';
|
||||
$ots = POT::getInstance();
|
||||
$eloquentConnection = null;
|
||||
|
||||
require_once SYSTEM . 'database.php';
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,8 @@ use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
class MigrateCommand extends Command
|
||||
{
|
||||
use Env;
|
||||
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->setName('migrate')
|
||||
@@ -17,9 +19,19 @@ class MigrateCommand extends Command
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
require SYSTEM . 'init.php';
|
||||
$this->init();
|
||||
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
|
||||
$tmp = '';
|
||||
if(fetchDatabaseConfig('database_version', $tmp)) { // we got version
|
||||
$tmp = (int)$tmp;
|
||||
if ($tmp >= DATABASE_VERSION) {
|
||||
$io->success('Already on latest version.');
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
require SYSTEM . 'migrate.php';
|
||||
|
||||
$io->success('Migrated to latest version (' . DATABASE_VERSION . ')');
|
||||
|
||||
@@ -10,6 +10,8 @@ use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
class MigrateRunCommand extends Command
|
||||
{
|
||||
use Env;
|
||||
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->setName('migrate:run')
|
||||
@@ -23,12 +25,12 @@ class MigrateRunCommand extends Command
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
require SYSTEM . 'init.php';
|
||||
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
|
||||
$ids = $input->getArgument('id');
|
||||
|
||||
$this->init();
|
||||
|
||||
// pre-check
|
||||
// in case one of the migrations doesn't exist - we won't execute any of them
|
||||
foreach ($ids as $id) {
|
||||
|
||||
@@ -11,6 +11,8 @@ use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
class MigrateToCommand extends Command
|
||||
{
|
||||
use Env;
|
||||
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->setName('migrate:to')
|
||||
@@ -32,7 +34,7 @@ class MigrateToCommand extends Command
|
||||
return Command::FAILURE;
|
||||
}
|
||||
|
||||
$this->initEnv();
|
||||
$this->init();
|
||||
|
||||
$currentVersion = Config::where('name', 'database_version')->first()->value;
|
||||
if ($currentVersion > $versionDest) {
|
||||
@@ -80,29 +82,4 @@ class MigrateToCommand extends Command
|
||||
|
||||
updateDatabaseConfig('database_version', ($_up ? $id : $id - 1));
|
||||
}
|
||||
|
||||
private function initEnv()
|
||||
{
|
||||
global $config;
|
||||
if (!isset($config['installed']) || !$config['installed']) {
|
||||
throw new \RuntimeException('MyAAC has not been installed yet or there was error during installation. Please install again.');
|
||||
}
|
||||
|
||||
if(empty($config['server_path'])) {
|
||||
throw new \RuntimeException('Server Path has been not set. Go to config.php and set it.');
|
||||
}
|
||||
|
||||
// take care of trailing slash at the end
|
||||
if($config['server_path'][strlen($config['server_path']) - 1] !== '/')
|
||||
$config['server_path'] .= '/';
|
||||
|
||||
$config['lua'] = load_config_lua($config['server_path'] . 'config.lua');
|
||||
|
||||
// POT
|
||||
require_once SYSTEM . 'libs/pot/OTS.php';
|
||||
$ots = POT::getInstance();
|
||||
$eloquentConnection = null;
|
||||
|
||||
require_once SYSTEM . 'database.php';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ class PluginDisableCommand extends Command
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->setName('plugin:disable')
|
||||
->setAliases(['plugin:deactivate'])
|
||||
->setDescription('This command disables plugin')
|
||||
->addArgument('plugin-name', InputArgument::REQUIRED, 'Plugin that you want to disable');
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ class PluginEnableCommand extends Command
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->setName('plugin:enable')
|
||||
->setAliases(['plugin:activate'])
|
||||
->setDescription('This command enables plugin')
|
||||
->addArgument('plugin-name', InputArgument::REQUIRED, 'Plugin that you want to enable');
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ class PluginUninstallCommand extends Command
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->setName('plugin:uninstall')
|
||||
->setAliases(['plugin:remove', 'plugin:delete'])
|
||||
->setDescription('This command uninstalls plugin')
|
||||
->addArgument('plugin-name', InputArgument::REQUIRED, 'Plugin that you want to uninstall');
|
||||
}
|
||||
|
||||
@@ -149,7 +149,10 @@ class CreateCharacter
|
||||
if($db->hasColumn('players', 'direction'))
|
||||
$player->setDirection($playerSample->getDirection());
|
||||
|
||||
$player->setConditions($playerSample->getConditions());
|
||||
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());
|
||||
$player->setCap($playerSample->getCap());
|
||||
|
||||
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 )
|
||||
{
|
||||
$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);
|
||||
|
||||
$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]"))
|
||||
{
|
||||
$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>'),
|
||||
|
||||
@@ -76,10 +76,11 @@ class Items
|
||||
|
||||
public static function get($id) {
|
||||
self::load();
|
||||
return isset(self::$items[$id]) ? self::$items[$id] : [];
|
||||
return self::$items[$id] ?? [];
|
||||
}
|
||||
|
||||
public static function getDescription($id, $count = 1) {
|
||||
public static function getDescription($id, $count = 1): string
|
||||
{
|
||||
$item = self::get($id);
|
||||
|
||||
$attr = $item['attributes'];
|
||||
@@ -112,15 +113,15 @@ class Items
|
||||
$s .= 'an item of type ' . $item['id'];
|
||||
|
||||
if(isset($attr['type']) && strtolower($attr['type']) == 'rune') {
|
||||
$item = Spell::where('item_id', $id)->first();
|
||||
if($item) {
|
||||
if($item->level > 0 && $item->maglevel > 0) {
|
||||
$s .= '. ' . ($count > 1 ? "They" : "It") . ' can only be used by ';
|
||||
$spell = Spell::where('item_id', $id)->first();
|
||||
if($spell) {
|
||||
if($spell->level > 0 && $spell->maglevel > 0) {
|
||||
$s .= '. ' . ($count > 1 ? 'They' : 'It') . ' can only be used by ';
|
||||
}
|
||||
|
||||
$configVocations = config('vocations');
|
||||
if(!empty(trim($item->vocations))) {
|
||||
$vocations = json_decode($item->vocations);
|
||||
if(!empty(trim($spell->vocations))) {
|
||||
$vocations = json_decode($spell->vocations);
|
||||
if(count($vocations) > 0) {
|
||||
foreach($vocations as $voc => $show) {
|
||||
$vocations[$configVocations[$voc]] = $show;
|
||||
@@ -133,8 +134,39 @@ class Items
|
||||
|
||||
$s .= ' with';
|
||||
|
||||
if ($spell->level > 0) {
|
||||
$s .= ' level ' . $spell->level;
|
||||
}
|
||||
|
||||
if ($spell->maglevel > 0) {
|
||||
if ($spell->level > 0) {
|
||||
$s .= ' and';
|
||||
}
|
||||
|
||||
$s .= ' magic level ' . $spell->maglevel;
|
||||
}
|
||||
|
||||
$s .= ' or higher';
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($item['weaponType'])) {
|
||||
if ($item['weaponType'] == 'distance' && isset($item['ammoType'])) {
|
||||
$s .= ' (Range:' . $item['range'];
|
||||
}
|
||||
|
||||
if (isset($item['attack']) && $item['attack'] != 0) {
|
||||
$s .= ', Atk ' . ($item['attack'] > 0 ? '+' . $item['attack'] : '-' . $item['attack']);
|
||||
}
|
||||
|
||||
if (isset($item['hitChance']) && $item['hitChance'] != -1) {
|
||||
$s .= ', Hit% ' . ($item['hitChance'] > 0 ? '+' . $item['hitChance'] : '-' . $item['hitChance']);
|
||||
}
|
||||
elseif ($item['weaponType'] != 'ammo') {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return $s;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,11 +5,15 @@ namespace MyAAC\Models;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* @property integer $premium_ends_at
|
||||
* @property integer $premend
|
||||
* @property integer $lastday
|
||||
* @property integer $premdays
|
||||
*/
|
||||
class Account extends Model {
|
||||
|
||||
const GRATIS_PREMIUM_DAYS = 65535;
|
||||
|
||||
protected $table = 'accounts';
|
||||
|
||||
public $timestamps = false;
|
||||
@@ -33,32 +37,35 @@ class Account extends Model {
|
||||
|
||||
public function getPremiumDaysAttribute()
|
||||
{
|
||||
if(isset($this->premium_ends_at) || isset($this->premend)) {
|
||||
$col = isset($this->premium_ends_at) ? 'premium_ends_at' : 'premend';
|
||||
$ret = ceil(($this->{$col}- time()) / (24 * 60 * 60));
|
||||
return $ret > 0 ? $ret : 0;
|
||||
if(isset($this->premium_ends_at) || isset($this->premend) ||
|
||||
(isCanary() && isset($this->lastday))) {
|
||||
$col = (isset($this->premium_ends_at) ? 'premium_ends_at' : (isset($this->lastday) ? 'lastday' : 'premend'));
|
||||
$ret = ceil(($this->{$col} - time()) / (24 * 60 * 60));
|
||||
return max($ret, 0);
|
||||
}
|
||||
|
||||
if($this->premdays == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if($this->premdays == 65535){
|
||||
return 65535;
|
||||
if($this->premdays == self::GRATIS_PREMIUM_DAYS){
|
||||
return self::GRATIS_PREMIUM_DAYS;
|
||||
}
|
||||
|
||||
$ret = ceil($this->premdays - ((int)date("z", time()) + (365 * (date("Y", time()) - date("Y", $this->lastday))) - date("z", $this->lastday)));
|
||||
return max($ret, 0);
|
||||
}
|
||||
|
||||
public function getIsPremiumAttribute()
|
||||
public function getIsPremiumAttribute(): bool
|
||||
{
|
||||
if(isset($this->premium_ends_at)) {
|
||||
return $this->premium_ends_at > time();
|
||||
if(isset($this->premium_ends_at) || isset($this->premend) ||
|
||||
(isCanary() && isset($this->lastday))) {
|
||||
$col = (isset($this->premium_ends_at) ? 'premium_ends_at' : (isset($this->lastday) ? 'lastday' : 'premend'));
|
||||
return $this->{$col} > time();
|
||||
}
|
||||
|
||||
if(isset($this->premend)) {
|
||||
return $this->premend > time();
|
||||
if($this->premdays == self::GRATIS_PREMIUM_DAYS){
|
||||
return true;
|
||||
}
|
||||
|
||||
return ($this->premdays - (date("z", time()) + (365 * (date("Y", time()) - date("Y", $this->lastday))) - date("z", $this->lastday)) > 0);
|
||||
|
||||
@@ -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'];
|
||||
|
||||
}
|
||||
|
||||
15
system/src/Models/AccountEmailVerify.php
Normal file
15
system/src/Models/AccountEmailVerify.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace MyAAC\Models;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class AccountEmailVerify extends Model
|
||||
{
|
||||
|
||||
protected $table = TABLE_PREFIX . 'account_emails_verify';
|
||||
|
||||
public $timestamps = false;
|
||||
|
||||
protected $fillable = ['account_id', 'hash', 'sent_at'];
|
||||
|
||||
}
|
||||
@@ -18,7 +18,16 @@ class Changelog extends Model {
|
||||
|
||||
public $timestamps = false;
|
||||
|
||||
protected $fillable = [
|
||||
'body', 'type', 'where',
|
||||
'date', 'player_id', 'hide',
|
||||
];
|
||||
|
||||
public function scopeIsPublic($query) {
|
||||
$query->where('hide', '!=', 1);
|
||||
}
|
||||
|
||||
public function player() {
|
||||
return $this->belongsTo(Player::class);
|
||||
}
|
||||
}
|
||||
|
||||
16
system/src/Models/ForumBoard.php
Normal file
16
system/src/Models/ForumBoard.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace MyAAC\Models;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class ForumBoard extends Model {
|
||||
|
||||
protected $table = TABLE_PREFIX . 'forum_boards';
|
||||
|
||||
public $timestamps = false;
|
||||
|
||||
protected $fillable = [
|
||||
'name', 'description', 'ordering',
|
||||
'guild', 'access', 'closed', 'hide',
|
||||
];
|
||||
}
|
||||
@@ -10,4 +10,9 @@ class Gallery extends Model {
|
||||
|
||||
public $timestamps = false;
|
||||
|
||||
protected $fillable = [
|
||||
'comment', 'image', 'thumb',
|
||||
'author', 'ordering', 'hide',
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
@@ -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'];
|
||||
|
||||
}
|
||||
|
||||
15
system/src/Models/NewsCategory.php
Normal file
15
system/src/Models/NewsCategory.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace MyAAC\Models;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class NewsCategory extends Model {
|
||||
|
||||
protected $table = TABLE_PREFIX . 'news_categories';
|
||||
|
||||
public $timestamps = false;
|
||||
|
||||
protected $fillable = [
|
||||
'name', 'description', 'icon_id', 'hide'
|
||||
];
|
||||
}
|
||||
@@ -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()
|
||||
|
||||
@@ -513,6 +513,9 @@ class Plugins {
|
||||
return false;
|
||||
}
|
||||
|
||||
ensureFolderExists($cachePlugins = CACHE . 'plugins');
|
||||
ensureIndexExists($cachePlugins);
|
||||
|
||||
self::$error = 'There was a problem with extracting zip archive.';
|
||||
$file_name = $plugin_temp_dir . $json_file;
|
||||
if(!file_exists($file_name)) {
|
||||
@@ -549,21 +552,21 @@ class Plugins {
|
||||
if(isset($plugin_json['require'])) {
|
||||
$require = $plugin_json['require'];
|
||||
|
||||
$myaac_satified = true;
|
||||
$myaac_satisfied = true;
|
||||
if(isset($require['myaac_'])) {
|
||||
$require_myaac = $require['myaac_'];
|
||||
if(!Semver::satisfies(MYAAC_VERSION, $require_myaac)) {
|
||||
$myaac_satified = false;
|
||||
$myaac_satisfied = false;
|
||||
}
|
||||
}
|
||||
else if(isset($require['myaac'])) {
|
||||
$require_myaac = $require['myaac'];
|
||||
if(version_compare(MYAAC_VERSION, $require_myaac, '<')) {
|
||||
$myaac_satified = false;
|
||||
$myaac_satisfied = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(!$myaac_satified) {
|
||||
if(!$myaac_satisfied) {
|
||||
self::$error = "Your AAC version doesn't meet the requirement of this plugin. Required version is: " . $require_myaac . ", and you're using version " . MYAAC_VERSION . ".";
|
||||
return false;
|
||||
}
|
||||
|
||||
101
system/src/Server/XML/Vocations.php
Normal file
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>
|
||||
@@ -248,7 +248,7 @@ class Settings implements \ArrayAccess
|
||||
echo '<div class="input-group" id="show-hide-' . $key . '">';
|
||||
}
|
||||
|
||||
echo '<input class="form-control" type="' . $setting['type'] . '" name="settings[' . $key . ']" value="' . ($settingsDb[$key] ?? ($setting['default'] ?? '')) . '" id="' . $key . '"' . $min . $max . $step . '/>';
|
||||
echo '<input class="form-control" type="' . $setting['type'] . '" name="settings[' . $key . ']" value="' . escapeHtml($settingsDb[$key] ?? ($setting['default'] ?? '')) . '" id="' . $key . '"' . $min . $max . $step . '/>';
|
||||
|
||||
if ($setting['type'] === 'password') {
|
||||
echo '<div class="input-group-append input-group-text"><a href=""><i class="fas fa-eye-slash" ></i></a></div></div>';
|
||||
@@ -266,7 +266,7 @@ class Settings implements \ArrayAccess
|
||||
if ($rows < 2) {
|
||||
$rows = 2; // always min 2 rows for textarea
|
||||
}
|
||||
echo '<textarea class="form-control" rows="' . $rows . '" name="settings[' . $key . ']" id="' . $key . '">' . $value . '</textarea>';
|
||||
echo '<textarea class="form-control" rows="' . $rows . '" name="settings[' . $key . ']" id="' . $key . '">' . escapeHtml($value) . '</textarea>';
|
||||
}
|
||||
|
||||
else if ($setting['type'] === 'options') {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,12 @@ define('HOOK_CHARACTERS_AFTER_CHARACTERS', ++$i);
|
||||
define('HOOK_LOGIN', ++$i);
|
||||
define('HOOK_LOGIN_ATTEMPT', ++$i);
|
||||
define('HOOK_LOGOUT', ++$i);
|
||||
define('HOOK_ACCOUNT_CHARACTERS_CHANGE_COMMENT_AFTER_SUCCESS', ++$i);
|
||||
define('HOOK_ACCOUNT_CHARACTERS_CHANGE_COMMENT_AFTER_NAME', ++$i);
|
||||
define('HOOK_ACCOUNT_CHARACTERS_CHANGE_COMMENT_AFTER_HIDE_ACCOUNT', ++$i);
|
||||
define('HOOK_ACCOUNT_CHARACTERS_CHANGE_COMMENT_AFTER_COMMENT', ++$i);
|
||||
define('HOOK_ACCOUNT_CHANGE_PASSWORD_AFTER_OLD_PASSWORD', ++$i);
|
||||
define('HOOK_ACCOUNT_CHANGE_PASSWORD_AFTER_NEW_PASSWORD', ++$i);
|
||||
define('HOOK_ACCOUNT_CHANGE_PASSWORD_POST', ++$i);
|
||||
define('HOOK_ACCOUNT_CREATE_BEFORE_FORM', ++$i);
|
||||
define('HOOK_ACCOUNT_CREATE_BEFORE_BOXES', ++$i);
|
||||
@@ -63,6 +69,14 @@ define('HOOK_ACCOUNT_LOGIN_AFTER_PASSWORD', ++$i);
|
||||
define('HOOK_ACCOUNT_LOGIN_AFTER_REMEMBER_ME', ++$i);
|
||||
define('HOOK_ACCOUNT_LOGIN_AFTER_PAGE', ++$i);
|
||||
define('HOOK_ACCOUNT_LOGIN_POST', ++$i);
|
||||
define('HOOK_ACCOUNT_LOST_CHECK_CODE_FINISH_AFTER_PASSWORD', ++$i);
|
||||
define('HOOK_ACCOUNT_LOST_CHECK_CODE_FINISH_AFTER_PASSWORD_REPEAT', ++$i);
|
||||
define('HOOK_ACCOUNT_LOST_EMAIL_SET_NEW_PASSWORD_POST', ++$i);
|
||||
define('HOOK_ACCOUNT_LOST_RECOVERY_KEY_STEP_2_AFTER_CHARACTER', ++$i);
|
||||
define('HOOK_ACCOUNT_LOST_RECOVERY_KEY_STEP_2_AFTER_EMAIL', ++$i);
|
||||
define('HOOK_ACCOUNT_LOST_RECOVERY_KEY_STEP_2_AFTER_PASSWORD', ++$i);
|
||||
define('HOOK_ACCOUNT_LOST_RECOVERY_KEY_STEP_2_AFTER_PASSWORD_REPEAT', ++$i);
|
||||
define('HOOK_ACCOUNT_LOST_RECOVERY_KEY_STEP_3_POST', ++$i);
|
||||
define('HOOK_ACCOUNT_CREATE_CHARACTER_AFTER', ++$i);
|
||||
define('HOOK_ACCOUNT_CREATE_CHARACTER_BEFORE_FIRST_TABLE', ++$i);
|
||||
define('HOOK_ACCOUNT_CREATE_CHARACTER_BEFORE_VOCATIONS', ++$i);
|
||||
@@ -106,6 +120,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);
|
||||
|
||||
Reference in New Issue
Block a user