Compare commits

..

95 Commits

Author SHA1 Message Date
slawkens
9aaa630976 [WIP] Rewrite OTS_Player class 2025-11-13 21:52:15 +01:00
slawkens
9a99018dce Merge branch 'main' into develop 2025-11-13 20:08:38 +01:00
slawkens
e440c0d6a6 Update .gitignore 2025-11-13 19:14:59 +01:00
slawkens
780d4ccef7 Server Status: Write to status-error.log if there is connection error 2025-11-06 22:06:05 +01:00
slawkens
0a6d44bf21 Fix $status['uptimeReadable'], was totally wrong 2025-11-06 13:47:09 +01:00
slawkens
4d17001a0b Add some popular network images (Facebook, Instagram, WhatsApp) 2025-11-06 12:48:33 +01:00
slawkens
946364f59d New Setting: Account Countries Most Popular 2025-11-06 12:01:33 +01:00
slawkens
5861efdbe9 Settings: escapeHtml in values (support for html code) 2025-11-06 11:48:42 +01:00
slawkens
175e97828b Don't display hidden news for admin - it's confusing 2025-11-05 22:21:42 +01:00
slawkens
9ce55db44c Display error message after failed settings save - just in case 2025-11-05 22:02:11 +01:00
slawkens
88532b0ebb Better message than "Access denied" 2025-11-05 19:32:31 +01:00
slawkens
1c7af30997 Revert "Just testing something, excuse me"
This reverts commit 7ca05e47ff.
2025-11-04 22:17:00 +01:00
slawkens
7ca05e47ff Just testing something, excuse me 2025-11-04 22:01:55 +01:00
slawkens
baec6c9ebf plugin:activate/deactivate alias 2025-11-04 08:17:41 +01:00
slawkens
6367054487 Add plugin:remove + plugin:delete as alias for plugin:uninstall 2025-11-03 21:06:27 +01:00
slawkens
ae7a47464f Update menus.php 2025-11-03 20:37:14 +01:00
slawkens
d201e75b11 Revert "Try to fix "VirtualProtect() failed [87] The parameter is incorrect" in php logs"
This reverts commit 4924696943.
2025-11-02 13:38:15 +01:00
slawkens
4924696943 Try to fix "VirtualProtect() failed [87] The parameter is incorrect" in php logs 2025-11-02 13:23:30 +01:00
slawkens
25a3db68e6 Use $db->hasTableAndColumns + move $skulls to correct place 2025-11-02 13:10:09 +01:00
slawkens
730a0f2912 Ensure some cache folders & index.html exists 2025-11-02 12:21:29 +01:00
slawkens
fd729242ff Fix typo -> satisfied 2025-11-02 12:05:47 +01:00
slawkens
6479546c22 Update CHANGELOG-2.x.md 2025-10-31 16:23:41 +01:00
slawkens
effb23f367 Create CHANGELOG-2.x.md 2025-10-31 15:32:49 +01:00
slawkens
08657c1599 Fix migration 47.php (convert IPs) 2025-10-31 15:25:55 +01:00
slawkens
1379c93439 Create 47.php 2025-10-31 07:00:11 +01:00
slawkens
19b1cfdd34 Merge branch 'main' into develop 2025-10-31 06:56:34 +01:00
slawkens
26c5aa2e51 Added more code into Items::getDescription
Is not ready yet
2025-10-31 06:52:56 +01:00
slawkens
bc4107bd16 Ignore only top-most Lua folder 2025-10-30 18:54:11 +01:00
slawkens
d24bde2c1d Start v1.8.5-dev 2025-10-27 21:45:34 +01:00
slawkens
a2f8759a52 Update CHANGELOG-1.x.md 2025-10-27 17:10:16 +01:00
slawkens
4b8c3ffae2 Code smell 2025-10-27 16:55:29 +01:00
slawkens
97321c9e80 Release v1.8.4 2025-10-27 16:43:34 +01:00
Slawomir Boczek
2580edadf8 Database import tables on every install with "IF NOT EXISTS" (#336)
* Database import tables on every install with "IF NOT EXISTS"

This fixed errors when one table is missing or is duplicated

* Add success message on import data

* Reorder
2025-10-27 16:27:22 +01:00
slawkens
8f47b36dc8 Add return type 2025-10-27 15:03:24 +01:00
slawkens
6cd38ee1ec Fix php stan 2025-10-27 14:38:52 +01:00
slawkens
9d92a11fb7 Fix the premium checks, introduced in v1.8.3 2025-10-27 14:34:53 +01:00
slawkens
44110a9496 Show if there is mysql error on import schema
Weird fix, don't know why it didn't worked with query()
2025-10-25 21:32:49 +02:00
slawkens
727f68a575 migrate command: show "Already on latest version" 2025-10-24 21:14:49 +02:00
slawkens
07fd034fe4 Use low level env init on migrate command 2025-10-24 21:12:40 +02:00
slawkens
13ea68cc0c Use low level env init on migrate:run + migrate:to 2025-10-24 21:10:55 +02:00
slawkens
598cec2fe4 Release v1.8.3 2025-10-21 17:18:07 +02:00
slawkens
89fae38caa Ignore set last visit for AJAX pages - Fixes template change redirect 2025-10-21 12:18:56 +02:00
slawkens
16849e7578 account/change-password refactor a bit
Add "The old password is same as the new password!"
Better post variables names
2025-10-16 21:36:14 +02:00
slawkens
470555f268 New hooks for account/change-password
HOOK_ACCOUNT_CHANGE_PASSWORD_AFTER_OLD_PASSWORD + HOOK_ACCOUNT_CHANGE_PASSWORD_AFTER_NEW_PASSWORD
2025-10-16 21:22:49 +02:00
slawkens
7f60b3d31d Add same code in Models\Account + Optimize code 2025-10-15 15:59:49 +02:00
slawkens
12e40b2592 Update functions.php 2025-10-15 15:50:25 +02:00
slawkens
38902c30d1 Comment code to update lastday 2025-10-15 15:50:22 +02:00
slawkens
3e61692780 Fix premDays count in canary 2025-10-15 15:49:58 +02:00
André Morais
c88b08eb1e feature: show vip days in account management (#334)
* feature: show vip days in account management

This feature causes VIP days to be shown in account management when vipSystemEnabled is true in the canary config.lua

* Some fixes & adjustments

* If freePremium = true and vipEnabled = show gratis VIP

* Revert to previous version

---------

Co-authored-by: slawkens <slawkens@gmail.com>
2025-10-15 11:46:52 +02:00
slawkens
82d417b590 Change spaces to tabs 2025-10-13 18:01:19 +02:00
slawkens
b797908e49 Update create.php 2025-10-13 17:53:26 +02:00
slawkens
90c8463797 Update create.php 2025-10-13 17:52:39 +02:00
slawkens
c91bb5d409 Fix guild create with freePremium 2025-10-12 21:53:01 +02:00
Slawomir Boczek
fe821c5808 Feature/resend email verify (#333)
* feat: Resend Email Verify

+ rework the whole concept, based on new table for email hashes
This make it possible that every email will work, not matter if first or last

* Nothing important: change variable name

* Change message
2025-10-12 11:19:30 +02:00
slawkens
9acad15451 Allow links in error_box 2025-10-12 00:15:04 +02:00
slawkens
8c3cb0e06f New configurable: hooks_debug
To view where hooks are located in .twig files
2025-10-11 18:34:15 +02:00
slawkens
2eae44e075 Add missing compat config: email_lai_sec_interval 2025-10-08 14:39:23 +02:00
slawkens
8272f1373c Fix database column info cache 2025-10-03 16:24:02 +02:00
slawkens
901df48d13 Add promotion into getTopPlayers 2025-10-03 00:31:03 +02:00
slawkens
2da0024c68 Add lookmount into getTopPlayers 2025-10-03 00:25:41 +02:00
slawkens
0d8f68a48e Fix menus for ?subtopic= 2025-10-02 22:31:16 +02:00
slawkens
0cb9d3a208 Fix routes_final cache 2025-10-02 22:31:02 +02:00
slawkens
d8b73f55a3 Fix routes_final for prod env 2025-10-02 22:16:29 +02:00
slawkens
3bb272ebbb Allow for img in online_datacenter 2025-10-02 22:13:33 +02:00
slawkens
64acf70d38 Cache::remember -1 = infinite 2025-10-02 22:13:15 +02:00
slawkens
97f9d3d6f6 Add option to use ?subtopic=x for plugins pages 2025-10-02 15:06:57 +02:00
Slawomir Boczek
f54b1bdd2a First attempt (#331) 2025-09-28 19:00:51 +02:00
slawkens
c898fe25ef New function: getColumnInfo($table, $column) 2025-09-28 16:21:31 +02:00
slawkens
73c07d470d Add variable types, don't use $config 2025-09-28 16:10:58 +02:00
slawkens
56bd7ec5ed Prevent injection in $db->hasColumn 2025-09-28 16:09:14 +02:00
slawkens
4c6277c124 Start v1.8.3-dev 2025-09-28 14:16:28 +02:00
slawkens
228780f0ad Just leaving it here, for future use (twig hook display)
Maybe configurable in the future
2025-09-28 14:14:26 +02:00
slawkens
4e9999cc0d Do not use constant on twig hooks
So it can be displayed which hook is used
2025-09-28 14:13:51 +02:00
slawkens
e719725841 Merge branch 'main' into develop 2025-05-09 13:45:54 +02:00
slawkens
bb3e90110d Merge branch 'main' into develop 2025-05-09 13:14:12 +02:00
slawkens
2f0758e351 Update schema.sql 2025-04-26 06:17:58 +02:00
slawkens
6667c8c364 Merge branch 'main' into develop 2025-04-26 06:17:38 +02:00
slawkens
c13a540878 Merge branch 'main' into develop 2025-04-18 13:58:42 +02:00
slawkens
869ec035d9 Merge branch 'main' into develop 2025-04-04 21:09:12 +02:00
slawkens
9d696d31d8 Merge branch 'main' into develop 2025-04-04 20:08:24 +02:00
slawkens
8cc4caf587 Merge branch 'main' into develop 2025-04-01 07:43:57 +02:00
slawkens
e1d1c7d5db Merge branch 'main' into develop 2025-03-31 22:21:16 +02:00
slawkens
320733c2c1 Merge branch 'main' into develop 2025-03-31 19:51:21 +02:00
slawkens
c1809a98d1 Merge branch 'main' into develop 2025-03-30 07:11:15 +02:00
slawkens
46ed541015 Merge branch 'main' into develop 2025-03-16 20:54:40 +01:00
slawkens
29207361b7 Merge branch 'main' into develop 2025-03-16 12:39:32 +01:00
slawkens
25013ae91b Merge branch 'main' into develop 2025-03-15 23:09:14 +01:00
slawkens
5d630ba9dd Fix the second "Save" button -> addition to previous commit 2025-03-15 22:49:43 +01:00
slawkens
feadf1314d Fix: add possibility to remove all menu items 2025-03-15 22:49:37 +01:00
slawkens
08b8a716d4 Fix the second "Save" button -> addition to previous commit 2025-03-10 13:04:57 +01:00
slawkens
cc26b5c744 Fix: add possibility to remove all menu items 2025-03-10 10:48:19 +01:00
Slawomir Boczek
cb6e9a6a88 Feature/twig hooks filters (#258)
* feat: Hooks filters

* Cleanup
2025-03-09 21:39:37 +01:00
slawkens
4adb0758c5 Set version to 2.0-dev 2025-03-09 21:26:24 +01:00
Slawomir Boczek
7312383f73 Account actions rework on ip (Use single column for IP - VARCHAR(45)) (#289)
* Account actions rework on ip (Use single column for IP - VARCHAR(45))

* No foreach needed here
2025-03-09 21:18:12 +01:00
slawkens
3c1210fefa Nothing important, just better code style 2025-03-03 20:07:54 +01:00
82 changed files with 1532 additions and 981 deletions

3
.gitignore vendored
View File

@@ -4,7 +4,7 @@ Thumbs.db
# #
/.htaccess /.htaccess
lua /lua
# composer # composer
composer.phar composer.phar
@@ -24,6 +24,7 @@ releases
tmp tmp
config.local.php config.local.php
config2.local.php
# all custom templates # all custom templates
templates/* templates/*

View File

@@ -1,5 +1,40 @@
# Changelog # Changelog
## [1.8.4 - 27.10.2025]
### Changed
* Reimport myaac_ tables on every install, this fixes errors when one table is missing or is duplicated (https://github.com/slawkens/myaac/commit/2580edadf84779f09fd395c21f92019b2c762f83)
* Use custom env init on migrate, migrate:run and migrate:to (https://github.com/slawkens/myaac/commit/13ea68cc0c9349380c8e4051d702a6c2c8256f44, https://github.com/slawkens/myaac/commit/07fd034fe4cb0ffdb88667b1e400f414d0c6d06f)
### Fixed
* Show if there is mysql error on import schema (https://github.com/slawkens/myaac/commit/44110a9496b4385e42c31b75de301037e711b6c3)
* Fix the premium checks, introduced in v1.8.3 (https://github.com/slawkens/myaac/commit/9d92a11fb7cb6d7a1619d79c12faaa0b1c01f980)
## [1.8.3 - 21.10.2025]
### Added
* Feature: resend email verify (https://github.com/slawkens/myaac/commit/fe821c58085483e70491dcf76376ad5b96de3fdd)
* New config: hooks_debug (To view where hooks are located in .twig files) (https://github.com/slawkens/myaac/commit/8c3cb0e06f9709c1de3398b48221241e7cbdd310)
* Functions: Add db->getColumnInfo(table, column) (https://github.com/slawkens/myaac/commit/c898fe25efff6793a01d11c26fc153cb23fcb858)
* Plugins: Add option to use ?subtopic=x for plugins pages (https://github.com/slawkens/myaac/commit/97f9d3d6f6c28aef6d824973058d7133f56e09c4)
* getTopPlayers() Function - Add lookmount & promotion (https://github.com/slawkens/myaac/commit/2da0024c68f1cedc38a16ebbc6f52ffa55e65f7a, https://github.com/slawkens/myaac/commit/901df48d134079d648a18f9d82b60182e818ac02)
* New hooks for account/change-password (https://github.com/slawkens/myaac/commit/470555f2687809a0c12491bbb27597e64b8929c1)
### Changed
* Feature: show vip days in account management (https://github.com/slawkens/myaac/commit/c88b08eb1ec1f560cbfdaaa16b24e3a0f26da7b3, by @andreoam)
* Allow links in error_box.html.twig (https://github.com/slawkens/myaac/commit/9acad15451071639acf7a7d4e81619b0a9742b12)
* Canary - Comment code to update lastday in login.php (https://github.com/slawkens/myaac/commit/38902c30d114fdbce259467f5820f97037b393e9)
* Cache::remember $ttl = -1 = infinite (https://github.com/slawkens/myaac/commit/64acf70d3854182d88aaf0b67f77cea2a254f179)
### Fixed
* Online - Allow for html code (example - img) in online_datacenter (https://github.com/slawkens/myaac/commit/3bb272ebbbd2eb7769d174b7082061d14a17bd44)
* Guilds - Fix guild create with freePremium enabled (https://github.com/slawkens/myaac/commit/c91bb5d4097647dca2196d3dea87bc90c89181d2)
* Canary - Fix premDays count (https://github.com/slawkens/myaac/commit/3e61692780d4add93b7b0e9f12f7a283bd8f4b7a)
* Template Change: Ignore set last visit for AJAX pages - Fixes template change redirect (https://github.com/slawkens/myaac/commit/89fae38caa7e4f645957fcf1a9330a36358ac04f)
* Admin Panel - Accounts: Fix lastip v6 (TFS master) (https://github.com/slawkens/myaac/commit/f54b1bdd2af4c16c64ddff0e87a6c96bc4cf9eeb)
* Functions - Prevent injection in $db->hasColumn (https://github.com/slawkens/myaac/commit/56bd7ec5ed904666074492f2e4f13e4fce226bee)
* Compat Config: Add missing config: email_lai_sec_interval (https://github.com/slawkens/myaac/commit/2eae44e0755e624a91be68b4d1ec26d01eb4d9a1)
## [1.8.2 - 26.09.2025] ## [1.8.2 - 26.09.2025]
### Added ### Added

4
CHANGELOG-2.x.md Normal file
View File

@@ -0,0 +1,4 @@
## [2.0-dev - x.x.2025]
### Changed
* Reworked account action logs to use single IP column as varchar(45) for both ipv4 and ipv6 (https://github.com/slawkens/myaac/pull/289)

4
aac
View File

@@ -25,7 +25,9 @@ foreach ($commandsGlob as $item) {
} }
$commandPre = '\\MyAAC\Commands\\'; $commandPre = '\\MyAAC\Commands\\';
$application->add(new ($commandPre . $name)); if (!trait_exists($class = $commandPre . $name)) {
$application->add(new $class);
}
} }
$pluginCommands = Plugins::getCommands(); $pluginCommands = Plugins::getCommands();

View File

@@ -9,6 +9,7 @@
*/ */
use MyAAC\Models\Account as AccountModel; use MyAAC\Models\Account as AccountModel;
use MyAAC\Models\AccountAction;
use MyAAC\Models\Player; use MyAAC\Models\Player;
defined('MYAAC') or die('Direct access not allowed!'); defined('MYAAC') or die('Direct access not allowed!');
@@ -481,9 +482,8 @@ else if (isset($_REQUEST['search'])) {
</thead> </thead>
<tbody> <tbody>
<?php <?php
$accountActions = \MyAAC\Models\AccountAction::where('account_id', $account->getId())->orderByDesc('date')->get(); $accountActions = AccountAction::where('account_id', $account->getId())->orderByDesc('date')->get();
foreach ($accountActions as $i => $log): foreach ($accountActions as $i => $log):
$log->ip = ($log->ip != 0 ? long2ip($log->ip) : inet_ntop($log->ipv6));
?> ?>
<tr> <tr>
<td><?php echo $i + 1; ?></td> <td><?php echo $i + 1; ?></td>

View File

@@ -6,6 +6,7 @@
* @package MyAAC * @package MyAAC
* @author Slawkens <slawkens@gmail.com> * @author Slawkens <slawkens@gmail.com>
* @author Lee * @author Lee
* @author gpedro
* @copyright 2020 MyAAC * @copyright 2020 MyAAC
* @link https://my-aac.org * @link https://my-aac.org
*/ */
@@ -19,9 +20,9 @@ $title = 'Mass Account Actions';
csrfProtect(); csrfProtect();
$hasPointsColumn = $db->hasColumn('accounts', 'premium_points'); $hasPointsColumn = $db->hasColumn('accounts', 'premium_points');
$freePremium = $config['lua']['freePremium']; $freePremium = getBoolean(configLua('freePremium'));
function admin_give_points($points) function admin_give_points($points): void
{ {
global $hasPointsColumn; global $hasPointsColumn;
@@ -37,7 +38,7 @@ function admin_give_points($points)
displayMessage($points . ' points added to all accounts.', true); displayMessage($points . ' points added to all accounts.', true);
} }
function admin_give_coins($coins) function admin_give_coins($coins): void
{ {
if (!HAS_ACCOUNT_COINS) { if (!HAS_ACCOUNT_COINS) {
displayMessage('Coins not supported.'); displayMessage('Coins not supported.');
@@ -52,7 +53,7 @@ function admin_give_coins($coins)
displayMessage($coins . ' coins added to all accounts.', true); displayMessage($coins . ' coins added to all accounts.', true);
} }
function admin_give_premdays($days) function admin_give_premdays($days): void
{ {
global $db, $freePremium; global $db, $freePremium;
@@ -63,6 +64,7 @@ function admin_give_premdays($days)
$value = $days * 86400; $value = $days * 86400;
$now = time(); $now = time();
// othire // othire
if ($db->hasColumn('accounts', 'premend')) { if ($db->hasColumn('accounts', 'premend')) {
// append premend // append premend
@@ -70,14 +72,11 @@ function admin_give_premdays($days)
// set premend // set premend
if (Account::where('premend', '<=', $now)->update(['premend' => $now + $value])) { if (Account::where('premend', '<=', $now)->update(['premend' => $now + $value])) {
displayMessage($days . ' premium days added to all accounts.', true); displayMessage($days . ' premium days added to all accounts.', true);
return;
} else { } else {
displayMessage('Failed to execute set query.'); displayMessage('Failed to execute set query.');
return;
} }
} else { } else {
displayMessage('Failed to execute append query.'); displayMessage('Failed to execute append query.');
return;
} }
return; return;
@@ -92,20 +91,14 @@ function admin_give_premdays($days)
// set lastday // set lastday
if (Account::where('lastday', '<=', $now)->update(['lastday' => $now + $value])) { if (Account::where('lastday', '<=', $now)->update(['lastday' => $now + $value])) {
displayMessage($days . ' premium days added to all accounts.', true); displayMessage($days . ' premium days added to all accounts.', true);
return;
} else { } else {
displayMessage('Failed to execute set query.'); displayMessage('Failed to execute set query.');
return;
} }
return;
} else { } else {
displayMessage('Failed to execute append query.'); displayMessage('Failed to execute append query.');
return;
} }
} else { } else {
displayMessage('Failed to execute set days query.'); displayMessage('Failed to execute set days query.');
return;
} }
return; return;
@@ -118,14 +111,11 @@ function admin_give_premdays($days)
// set premium_ends_at // set premium_ends_at
if (Account::where('premium_ends_at', '<=', $now)->update(['premium_ends_at' => $now + $value])) { if (Account::where('premium_ends_at', '<=', $now)->update(['premium_ends_at' => $now + $value])) {
displayMessage($days . ' premium days added to all accounts.', true); displayMessage($days . ' premium days added to all accounts.', true);
return;
} else { } else {
displayMessage('Failed to execute set query.'); displayMessage('Failed to execute set query.');
return;
} }
} else { } else {
displayMessage('Failed to execute append query.'); displayMessage('Failed to execute append query.');
return;
} }
return; return;
@@ -170,7 +160,8 @@ else {
)); ));
} }
function displayMessage($message, $success = false) { function displayMessage($message, $success = false): void
{
global $twig, $hasPointsColumn, $freePremium; global $twig, $hasPointsColumn, $freePremium;
$success ? success($message): error($message); $success ? success($message): error($message);

View File

@@ -249,10 +249,10 @@ else if (isset($_REQUEST['search'])) {
$player->setLookHead($look_head); $player->setLookHead($look_head);
$player->setLookLegs($look_legs); $player->setLookLegs($look_legs);
$player->setLookType($look_type); $player->setLookType($look_type);
if ($hasLookAddons) if ($hasLookAddons) {
$player->setLookAddons($look_addons); $player->setLookAddons($look_addons);
if ($db->hasColumn('players', 'offlinetraining_time')) }
$player->setCustomField('offlinetraining_time', $offlinetraining);
$player->setPosX($pos_x); $player->setPosX($pos_x);
$player->setPosY($pos_y); $player->setPosY($pos_y);
$player->setPosZ($pos_z); $player->setPosZ($pos_z);
@@ -275,23 +275,11 @@ else if (isset($_REQUEST['search'])) {
if ($hasBlessingsColumn) if ($hasBlessingsColumn)
$player->setBlessings($blessings); $player->setBlessings($blessings);
if ($hasBlessingColumn) {
for ($i = 1; $i <= $bless_count; $i++) {
$a = 'blessing' . $i;
$player->setCustomField('blessings' . $i, ${'blessing' . $i} ? '1' : '0');
}
}
$player->setBalance($balance); $player->setBalance($balance);
if ($db->hasColumn('players', 'stamina')) if ($db->hasColumn('players', 'stamina'))
$player->setStamina($stamina); $player->setStamina($stamina);
if ($db->hasColumn('players', 'deletion'))
$player->setCustomField('deletion', $deleted ? '1' : '0'); $player->setDeleted($deleted ? '1' : '0');
else
$player->setCustomField('deleted', $deleted ? '1' : '0');
$player->setCustomField('hide', $hide ? '1' : '0');
$player->setCustomField('created', $created);
if (isset($comment))
$player->setCustomField('comment', $comment);
foreach ($_POST['skills'] as $skill => $value) { foreach ($_POST['skills'] as $skill => $value) {
$player->setSkill($skill, $value); $player->setSkill($skill, $value);
@@ -300,6 +288,24 @@ else if (isset($_REQUEST['search'])) {
$player->setSkillTries($skill, $value); $player->setSkillTries($skill, $value);
} }
$player->save(); $player->save();
if ($db->hasColumn('players', 'offlinetraining_time')) {
$player->setCustomField('offlinetraining_time', $offlinetraining);
}
if ($hasBlessingColumn) {
for ($i = 1; $i <= $bless_count; $i++) {
$a = 'blessing' . $i;
$player->setCustomField('blessings' . $i, ${'blessing' . $i} ? '1' : '0');
}
}
$player->setCustomField('hide', $hide ? '1' : '0');
$player->setCustomField('created', $created);
if (isset($comment)) {
$player->setCustomField('comment', $comment);
}
echo_success('Player saved at: ' . date('G:i')); echo_success('Player saved at: ' . date('G:i'));
$player->load($id); $player->load($id);
} }
@@ -669,11 +675,17 @@ else if (isset($_REQUEST['search'])) {
<div class="col-12 col-sm-12 col-lg-6"> <div class="col-12 col-sm-12 col-lg-6">
<label for="lastip" class="control-label">Last IP:</label> <label for="lastip" class="control-label">Last IP:</label>
<input type="text" class="form-control" id="lastip" name="lastip" autocomplete="off" maxlength="10" value="<?php <input type="text" class="form-control" id="lastip" name="lastip" autocomplete="off" maxlength="10" value="<?php
if (strlen($player->getLastIP()) > 11) { $lastIPColumnInfo = $db->getColumnInfo('players', 'lastip');
echo inet_ntop($player->getLastIP()); if ($lastIPColumnInfo && is_array($lastIPColumnInfo)) {
if (str_contains($lastIPColumnInfo['type'], 'varbinary')) {
echo inet_ntop($player->getLastIP());
}
else {
echo longToIp($player->getLastIP());
}
} }
else { else {
echo longToIp($player->getLastIP()); echo 'Error';
} }
?>" readonly/> ?>" readonly/>
</div> </div>

View File

@@ -60,7 +60,7 @@ usort($menus, function ($a, $b) {
foreach ($menus as $i => $menu) { foreach ($menus as $i => $menu) {
if (isset($menu['link']) && is_array($menu['link'])) { if (isset($menu['link']) && is_array($menu['link'])) {
usort($menus[$i]['link'], function ($a, $b) { usort($menu['link'], function ($a, $b) {
return $a['order'] - $b['order']; return $a['order'] - $b['order'];
}); });
} }

View File

@@ -1,5 +1,6 @@
<?php <?php
define('MYAAC_ADMIN', true); const MYAAC_ADMIN = true;
const IGNORE_SET_LAST_VISIT = true;
require '../../common.php'; require '../../common.php';
require SYSTEM . 'functions.php'; require SYSTEM . 'functions.php';

View File

@@ -26,6 +26,7 @@
use MyAAC\DataLoader; use MyAAC\DataLoader;
const MYAAC_ADMIN = true; const MYAAC_ADMIN = true;
const IGNORE_SET_LAST_VISIT = true;
require '../../common.php'; require '../../common.php';
require SYSTEM . 'functions.php'; require SYSTEM . 'functions.php';

View File

@@ -3,6 +3,7 @@
use MyAAC\Settings; use MyAAC\Settings;
const MYAAC_ADMIN = true; const MYAAC_ADMIN = true;
const IGNORE_SET_LAST_VISIT = true;
require '../../common.php'; require '../../common.php';
require SYSTEM . 'functions.php'; require SYSTEM . 'functions.php';
@@ -11,7 +12,7 @@ require SYSTEM . 'login.php';
if(!admin()) { if(!admin()) {
http_response_code(500); http_response_code(500);
die('Access denied.'); die('You are not logged in. Probably session expired. Please login again.');
} }
csrfProtect(); csrfProtect();
@@ -39,3 +40,6 @@ if (count($errors) > 0) {
if ($success) { if ($success) {
echo 'Saved at ' . date('H:i'); echo 'Saved at ' . date('H:i');
} }
else {
echo 'Something unexpected happened - it was impossible to save the settings, please try again later. If problem persists - contact MyAAC developers.';
}

View File

@@ -1,5 +1,6 @@
<?php <?php
define('MYAAC_ADMIN', true); const MYAAC_ADMIN = true;
const IGNORE_SET_LAST_VISIT = true;
require '../../common.php'; require '../../common.php';
require SYSTEM . 'init.php'; require SYSTEM . 'init.php';

View File

@@ -1,5 +1,6 @@
<?php <?php
define('MYAAC_ADMIN', true); const MYAAC_ADMIN = true;
const IGNORE_SET_LAST_VISIT = true;
require '../../common.php'; require '../../common.php';
require SYSTEM . 'functions.php'; require SYSTEM . 'functions.php';

View File

@@ -26,8 +26,8 @@
if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.');
const MYAAC = true; const MYAAC = true;
const MYAAC_VERSION = '1.8.2'; const MYAAC_VERSION = '2.0-dev';
const DATABASE_VERSION = 45; const DATABASE_VERSION = 47;
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'));

BIN
images/facebook_16x16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 718 B

BIN
images/instagram_16x16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 721 B

BIN
images/whatsapp_16x16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 688 B

View File

@@ -0,0 +1,69 @@
<?php
defined('MYAAC') or die('Direct access not allowed!');
use MyAAC\Models\Changelog;
use MyAAC\Models\Config;
use MyAAC\Models\ForumBoard;
use MyAAC\Models\Gallery;
use MyAAC\Models\NewsCategory;
if (Changelog::count() === 0) {
Changelog::create([
'type' => 3,
'where' => 2,
'date' => time(),
'body' => 'MyAAC installed. (:',
'hide' => 0,
]);
}
if (Config::where('name', 'database_version')->count() === 0) {
Config::create([
'name' => 'database_version',
'value' => DATABASE_VERSION,
]);
}
if (ForumBoard::count() === 0) {
$forumBoards = [
['name' => 'News', 'description' => 'News commenting', 'closed' => 1],
['name' => 'Trade', 'description' => 'Trade offers.', 'closed' => 0],
['name' => 'Quests', 'description' => 'Quest making.', 'closed' => 0],
['name' => 'Pictures', 'description' => 'Your pictures.', 'closed' => 0],
['name' => 'Bug Report', 'description' => 'Report bugs there.', 'closed' => 0],
];
$i = 0;
foreach ($forumBoards as $forumBoard) {
ForumBoard::create([
'name' => $forumBoard['name'],
'description' => $forumBoard['description'],
'ordering' => $i++,
'closed' => $forumBoard['closed'],
]);
}
}
if (NewsCategory::count() === 0) {
$newsCategoriesIcons = [
0, 1, 2, 3, 4
];
foreach ($newsCategoriesIcons as $iconId) {
NewsCategory::create([
'icon_id' => $iconId,
]);
}
}
if (Gallery::count() === 0) {
Gallery::create([
'comment' => 'Demon',
'image' => 'images/gallery/demon.jpg',
'thumb' => 'images/gallery/demon_thumb.gif',
'author' => 'MyAAC',
'ordering' => 0,
]);
}
success($locale['step_database_success_import_data']);

View File

@@ -1,16 +1,23 @@
SET @myaac_database_version = 45; CREATE TABLE IF NOT EXISTS `myaac_account_actions`
CREATE TABLE `myaac_account_actions`
( (
`id` int NOT NULL AUTO_INCREMENT,
`account_id` int NOT NULL, `account_id` int NOT NULL,
`ip` int unsigned NOT NULL DEFAULT 0, `ip` varchar(45) NOT NULL DEFAULT '',
`ipv6` binary(16) NOT NULL DEFAULT 0,
`date` int NOT NULL DEFAULT 0, `date` int NOT NULL DEFAULT 0,
`action` varchar(255) NOT NULL DEFAULT '', `action` varchar(255) NOT NULL DEFAULT '',
KEY (`account_id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
CREATE TABLE `myaac_admin_menu` CREATE TABLE IF NOT EXISTS `myaac_account_emails_verify`
(
`id` int NOT NULL AUTO_INCREMENT,
`account_id` int NOT NULL,
`hash` varchar(32) NOT NULL,
`sent_at` int NOT NULL DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
CREATE TABLE IF NOT EXISTS `myaac_admin_menu`
( (
`id` int NOT NULL AUTO_INCREMENT, `id` int NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL DEFAULT '', `name` varchar(255) NOT NULL DEFAULT '',
@@ -21,7 +28,7 @@ CREATE TABLE `myaac_admin_menu`
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
CREATE TABLE `myaac_changelog` CREATE TABLE IF NOT EXISTS `myaac_changelog`
( (
`id` int NOT NULL AUTO_INCREMENT, `id` int NOT NULL AUTO_INCREMENT,
`body` varchar(500) NOT NULL DEFAULT '', `body` varchar(500) NOT NULL DEFAULT '',
@@ -33,9 +40,7 @@ CREATE TABLE `myaac_changelog`
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
INSERT INTO `myaac_changelog` (`id`, `type`, `where`, `date`, `body`, `hide`) VALUES (1, 3, 2, UNIX_TIMESTAMP(), 'MyAAC installed. (:', 0); CREATE TABLE IF NOT EXISTS `myaac_config`
CREATE TABLE `myaac_config`
( (
`id` int NOT NULL AUTO_INCREMENT, `id` int NOT NULL AUTO_INCREMENT,
`name` varchar(30) NOT NULL, `name` varchar(30) NOT NULL,
@@ -44,9 +49,7 @@ CREATE TABLE `myaac_config`
UNIQUE (`name`) UNIQUE (`name`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
INSERT INTO `myaac_config` (`name`, `value`) VALUES ('database_version', @myaac_database_version); CREATE TABLE IF NOT EXISTS `myaac_faq`
CREATE TABLE `myaac_faq`
( (
`id` int NOT NULL AUTO_INCREMENT, `id` int NOT NULL AUTO_INCREMENT,
`question` varchar(255) NOT NULL DEFAULT '', `question` varchar(255) NOT NULL DEFAULT '',
@@ -56,7 +59,7 @@ CREATE TABLE `myaac_faq`
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
CREATE TABLE `myaac_forum_boards` CREATE TABLE IF NOT EXISTS `myaac_forum_boards`
( (
`id` int NOT NULL AUTO_INCREMENT, `id` int NOT NULL AUTO_INCREMENT,
`name` varchar(32) NOT NULL, `name` varchar(32) NOT NULL,
@@ -68,13 +71,8 @@ CREATE TABLE `myaac_forum_boards`
`hide` tinyint NOT NULL DEFAULT 0, `hide` tinyint NOT NULL DEFAULT 0,
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
INSERT INTO `myaac_forum_boards` (`id`, `name`, `description`, `ordering`, `closed`) VALUES (NULL, 'News', 'News commenting', 0, 1);
INSERT INTO `myaac_forum_boards` (`id`, `name`, `description`, `ordering`) VALUES (NULL, 'Trade', 'Trade offers.', 1);
INSERT INTO `myaac_forum_boards` (`id`, `name`, `description`, `ordering`) VALUES (NULL, 'Quests', 'Quest making.', 2);
INSERT INTO `myaac_forum_boards` (`id`, `name`, `description`, `ordering`) VALUES (NULL, 'Pictures', 'Your pictures.', 3);
INSERT INTO `myaac_forum_boards` (`id`, `name`, `description`, `ordering`) VALUES (NULL, 'Bug Report', 'Report bugs there.', 4);
CREATE TABLE `myaac_forum` CREATE TABLE IF NOT EXISTS `myaac_forum`
( (
`id` int NOT NULL AUTO_INCREMENT, `id` int NOT NULL AUTO_INCREMENT,
`first_post` int NOT NULL DEFAULT 0, `first_post` int NOT NULL DEFAULT 0,
@@ -98,7 +96,7 @@ CREATE TABLE `myaac_forum`
KEY `section` (`section`) KEY `section` (`section`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
CREATE TABLE `myaac_menu` CREATE TABLE IF NOT EXISTS `myaac_menu`
( (
`id` int NOT NULL AUTO_INCREMENT, `id` int NOT NULL AUTO_INCREMENT,
`template` varchar(255) NOT NULL, `template` varchar(255) NOT NULL,
@@ -112,7 +110,7 @@ CREATE TABLE `myaac_menu`
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
CREATE TABLE `myaac_monsters` ( CREATE TABLE IF NOT EXISTS `myaac_monsters` (
`id` int NOT NULL AUTO_INCREMENT, `id` int NOT NULL AUTO_INCREMENT,
`hide` tinyint NOT NULL DEFAULT 0, `hide` tinyint NOT NULL DEFAULT 0,
`name` varchar(255) NOT NULL, `name` varchar(255) NOT NULL,
@@ -145,7 +143,7 @@ CREATE TABLE `myaac_monsters` (
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
CREATE TABLE `myaac_news` CREATE TABLE IF NOT EXISTS `myaac_news`
( (
`id` int NOT NULL AUTO_INCREMENT, `id` int NOT NULL AUTO_INCREMENT,
`title` varchar(100) NOT NULL, `title` varchar(100) NOT NULL,
@@ -163,7 +161,7 @@ CREATE TABLE `myaac_news`
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
CREATE TABLE `myaac_news_categories` CREATE TABLE IF NOT EXISTS `myaac_news_categories`
( (
`id` int NOT NULL AUTO_INCREMENT, `id` int NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL DEFAULT "", `name` varchar(50) NOT NULL DEFAULT "",
@@ -173,13 +171,7 @@ CREATE TABLE `myaac_news_categories`
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
INSERT INTO `myaac_news_categories` (`id`, `icon_id`) VALUES (NULL, 0); CREATE TABLE IF NOT EXISTS `myaac_notepad`
INSERT INTO `myaac_news_categories` (`id`, `icon_id`) VALUES (NULL, 1);
INSERT INTO `myaac_news_categories` (`id`, `icon_id`) VALUES (NULL, 2);
INSERT INTO `myaac_news_categories` (`id`, `icon_id`) VALUES (NULL, 3);
INSERT INTO `myaac_news_categories` (`id`, `icon_id`) VALUES (NULL, 4);
CREATE TABLE `myaac_notepad`
( (
`id` int NOT NULL AUTO_INCREMENT, `id` int NOT NULL AUTO_INCREMENT,
`account_id` int NOT NULL, `account_id` int NOT NULL,
@@ -189,7 +181,7 @@ CREATE TABLE `myaac_notepad`
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
CREATE TABLE `myaac_pages` CREATE TABLE IF NOT EXISTS `myaac_pages`
( (
`id` INT NOT NULL AUTO_INCREMENT, `id` INT NOT NULL AUTO_INCREMENT,
`name` varchar(30) NOT NULL, `name` varchar(30) NOT NULL,
@@ -205,7 +197,7 @@ CREATE TABLE `myaac_pages`
UNIQUE (`name`) UNIQUE (`name`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
CREATE TABLE `myaac_gallery` CREATE TABLE IF NOT EXISTS `myaac_gallery`
( (
`id` int NOT NULL AUTO_INCREMENT, `id` int NOT NULL AUTO_INCREMENT,
`comment` varchar(255) NOT NULL DEFAULT '', `comment` varchar(255) NOT NULL DEFAULT '',
@@ -217,9 +209,7 @@ CREATE TABLE `myaac_gallery`
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
INSERT INTO `myaac_gallery` (`id`, `ordering`, `comment`, `image`, `thumb`, `author`) VALUES (NULL, 1, 'Demon', 'images/gallery/demon.jpg', 'images/gallery/demon_thumb.gif', 'MyAAC'); CREATE TABLE IF NOT EXISTS `myaac_settings`
CREATE TABLE `myaac_settings`
( (
`id` int NOT NULL AUTO_INCREMENT, `id` int NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL DEFAULT '', `name` varchar(255) NOT NULL DEFAULT '',
@@ -229,7 +219,7 @@ CREATE TABLE `myaac_settings`
KEY `key` (`key`) KEY `key` (`key`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
CREATE TABLE `myaac_spells` CREATE TABLE IF NOT EXISTS `myaac_spells`
( (
`id` int NOT NULL AUTO_INCREMENT, `id` int NOT NULL AUTO_INCREMENT,
`spell` varchar(255) NOT NULL DEFAULT '', `spell` varchar(255) NOT NULL DEFAULT '',
@@ -252,7 +242,7 @@ CREATE TABLE `myaac_spells`
UNIQUE (`name`) UNIQUE (`name`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
CREATE TABLE `myaac_visitors` CREATE TABLE IF NOT EXISTS `myaac_visitors`
( (
`ip` varchar(45) NOT NULL, `ip` varchar(45) NOT NULL,
`lastvisit` int NOT NULL DEFAULT 0, `lastvisit` int NOT NULL DEFAULT 0,
@@ -261,7 +251,7 @@ CREATE TABLE `myaac_visitors`
UNIQUE (`ip`) UNIQUE (`ip`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
CREATE TABLE `myaac_weapons` CREATE TABLE IF NOT EXISTS `myaac_weapons`
( (
`id` int NOT NULL, `id` int NOT NULL,
`level` int NOT NULL DEFAULT 0, `level` int NOT NULL DEFAULT 0,

View File

@@ -30,26 +30,22 @@ if(!$error) {
} }
} }
if($db->hasTable(TABLE_PREFIX . 'account_actions')) { // import schema
$locale['step_database_error_table_exist'] = str_replace('$TABLE$', TABLE_PREFIX . 'account_actions', $locale['step_database_error_table_exist']); try {
warning($locale['step_database_error_table_exist']); $locale['step_database_importing'] = str_replace('$DATABASE_NAME$', config('database_name'), $locale['step_database_importing']);
} success($locale['step_database_importing']);
else {
// import schema
try {
$locale['step_database_importing'] = str_replace('$DATABASE_NAME$', config('database_name'), $locale['step_database_importing']);
success($locale['step_database_importing']);
$db->query(file_get_contents(BASE . 'install/includes/schema.sql')); $db->exec(file_get_contents(BASE . 'install/includes/schema.sql'));
$locale['step_database_success_schema'] = str_replace('$PREFIX$', TABLE_PREFIX, $locale['step_database_success_schema']); $locale['step_database_success_schema'] = str_replace('$PREFIX$', TABLE_PREFIX, $locale['step_database_success_schema']);
success($locale['step_database_success_schema']); success($locale['step_database_success_schema']);
}
catch(PDOException $error_) {
error($locale['step_database_error_schema'] . ' ' . $error_);
return;
}
} }
catch(PDOException $error_) {
error($locale['step_database_error_schema'] . ' ' . $error_);
return;
}
require BASE . 'install/includes/import_base_data.php';
if(!$db->hasColumn('accounts', 'email')) { if(!$db->hasColumn('accounts', 'email')) {
if(query("ALTER TABLE `accounts` ADD `email` varchar(255) NOT NULL DEFAULT '';")) if(query("ALTER TABLE `accounts` ADD `email` varchar(255) NOT NULL DEFAULT '';"))
@@ -102,18 +98,13 @@ if(!$db->hasColumn('accounts', 'web_flags')) {
success($locale['step_database_adding_field'] . ' accounts.web_flags...'); success($locale['step_database_adding_field'] . ' accounts.web_flags...');
} }
if(!$db->hasColumn('accounts', 'email_hash')) {
if(query("ALTER TABLE `accounts` ADD `email_hash` VARCHAR(32) NOT NULL DEFAULT '' AFTER `web_flags`;"))
success($locale['step_database_adding_field'] . ' accounts.email_hash...');
}
if(!$db->hasColumn('accounts', 'email_verified')) { if(!$db->hasColumn('accounts', 'email_verified')) {
if(query("ALTER TABLE `accounts` ADD `email_verified` TINYINT(1) NOT NULL DEFAULT 0 AFTER `email_hash`;")) if(query("ALTER TABLE `accounts` ADD `email_verified` TINYINT(1) NOT NULL DEFAULT 0 AFTER `web_flags`;"))
success($locale['step_database_adding_field'] . ' accounts.email_verified...'); success($locale['step_database_adding_field'] . ' accounts.email_verified...');
} }
if(!$db->hasColumn('accounts', 'email_new')) { if(!$db->hasColumn('accounts', 'email_new')) {
if(query("ALTER TABLE `accounts` ADD `email_new` VARCHAR(255) NOT NULL DEFAULT '' AFTER `email_hash`;")) if(query("ALTER TABLE `accounts` ADD `email_new` VARCHAR(255) NOT NULL DEFAULT '' AFTER `email_verified`;"))
success($locale['step_database_adding_field'] . ' accounts.email_new...'); success($locale['step_database_adding_field'] . ' accounts.email_new...');
} }

View File

@@ -37,8 +37,46 @@ if ($db->hasTable('players')) {
$query = $db->query('SELECT `id` FROM `players` WHERE `name` = ' . $db->quote($p['name'])); $query = $db->query('SELECT `id` FROM `players` WHERE `name` = ' . $db->quote($p['name']));
if ($query->rowCount() == 0) { if ($query->rowCount() == 0) {
if (!query("INSERT INTO `players` (`id`, `name`, `group_id`, `account_id`, `level`, `vocation`, `health`, `healthmax`, `experience`, `lookbody`, `lookfeet`, `lookhead`, `looklegs`, `looktype`, `maglevel`, `mana`, `manamax`, `manaspent`, `soul`, `town_id`, `posx`, `posy`, `posz`, `conditions`, `cap`, `sex`, `lastlogin`, `lastip`, `save`, `lastlogout`, `balance`, `$deleted`, `created`, `hide`, `comment`) VALUES (null, " . $db->quote($p['name']) . ", 1, " . getSession('account') . ", " . $p['level'] . ", " . $p['vocation_id'] . ", " . $p['health'] . ", " . $p['healthmax'] . ", " . $p['experience'] . ", 118, 114, 38, 57, " . $p['looktype'] . ", 0, " . $p['mana'] . ", " . $p['manamax'] . ", 0, " . $p['soul'] . ", 1, 1000, 1000, 7, '', " . $p['cap'] . ", 1, " . $time . ", 2130706433, 1, " . $time . ", 0, 0, " . $time . ", 1, '');")) $player = new OTS_Player();
$success = false;
$player->setData([
'name' => $p['name'],
'group_id' => 1,
'account_id' => getSession('account'),
'level' => $p['level'],
'vocation' => $p['vocation_id'],
'health' => $p['health'],
'healthmax' => $p['healthmax'],
'experience' => $p['experience'],
'lookbody' => 118,
'lookfeet' => 114,
'lookhead' => 38,
'looklegs' => 57,
'looktype' => $p['looktype'],
'maglevel' => 0,
'mana' => $p['mana'],
'manamax' => $p['manamax'],
'manaspent' => 0,
'soul' => $p['soul'],
'town_id' => 1,
'posx' => 1000,
'posy' => 1000,
'posz' => 7,
'conditions' => '',
'cap' => $p['cap'],
'sex' => 1,
'lastlogin' => $time,
'lastip' => 2130706433,
'save' => 1,
'lastlogout' => $time,
'balance' => 0,
$deleted => 0,
'created' => $time,
'hide' => 1,
'comment' => '',
]);
$player->save();
} }
} }

View File

@@ -220,6 +220,8 @@ switch ($action) {
} }
} }
/*
* not needed anymore?
if (fieldExist('premdays', 'accounts') && fieldExist('lastday', 'accounts')) { if (fieldExist('premdays', 'accounts') && fieldExist('lastday', 'accounts')) {
$save = false; $save = false;
$timeNow = time(); $timeNow = time();
@@ -256,6 +258,7 @@ switch ($action) {
$account->save(); $account->save();
} }
} }
*/
$worlds = [$world]; $worlds = [$world];
$playdata = compact('worlds', 'characters'); $playdata = compact('worlds', 'characters');

View File

@@ -81,6 +81,7 @@ $deprecatedConfig = [
'account_change_character_name_points' => 'account_change_character_name_price', 'account_change_character_name_points' => 'account_change_character_name_price',
'account_change_character_sex', 'account_change_character_sex',
'account_change_character_sex_points' => 'account_change_character_name_price', 'account_change_character_sex_points' => 'account_change_character_name_price',
'email_lai_sec_interval' => 'mail_lost_account_interval',
]; ];
foreach ($deprecatedConfig as $key => $value) { foreach ($deprecatedConfig as $key => $value) {

View File

@@ -1142,10 +1142,18 @@ function getTopPlayers($limit = 5, $skill = 'level') {
'looktype', 'lookhead', 'lookbody', 'looklegs', 'lookfeet' 'looktype', 'lookhead', 'lookbody', 'looklegs', 'lookfeet'
]; ];
if ($db->hasColumn('players', 'promotion')) {
$columns[] = 'promotion';
}
if ($db->hasColumn('players', 'lookaddons')) { if ($db->hasColumn('players', 'lookaddons')) {
$columns[] = 'lookaddons'; $columns[] = 'lookaddons';
} }
if ($db->hasColumn('players', 'lookmount')) {
$columns[] = 'lookmount';
}
return Player::query() return Player::query()
->select($columns) ->select($columns)
->withOnlineStatus() ->withOnlineStatus()
@@ -1169,7 +1177,8 @@ function getTopPlayers($limit = 5, $skill = 'level') {
}); });
} }
function deleteDirectory($dir, $ignore = array(), $contentOnly = false) { function deleteDirectory($dir, $ignore = array(), $contentOnly = false): bool
{
if(!file_exists($dir)) { if(!file_exists($dir)) {
return true; return true;
} }
@@ -1195,6 +1204,21 @@ function deleteDirectory($dir, $ignore = array(), $contentOnly = false) {
return rmdir($dir); return rmdir($dir);
} }
function ensureFolderExists($dir): void
{
if (!file_exists($dir)) {
mkdir($dir, 0777, true);
}
}
function ensureIndexExists($dir): void
{
$dir = rtrim($dir, '/');
if (!file_exists($file = $dir . '/index.html')) {
touch($file);
}
}
function config($key) { function config($key) {
global $config; global $config;
if (is_array($key)) { if (is_array($key)) {
@@ -1632,13 +1656,14 @@ function camelCaseToUnderscore($input)
return ltrim(strtolower(preg_replace('/[A-Z]([A-Z](?![a-z]))*/', '_$0', $input)), '_'); return ltrim(strtolower(preg_replace('/[A-Z]([A-Z](?![a-z]))*/', '_$0', $input)), '_');
} }
function removeIfFirstSlash(&$text) { function removeIfFirstSlash(&$text): void
{
if(strpos($text, '/') === 0) { if(strpos($text, '/') === 0) {
$text = str_replace_first('/', '', $text); $text = str_replace_first('/', '', $text);
} }
}; };
function escapeHtml($html) { function escapeHtml($html): string {
return htmlspecialchars($html); return htmlspecialchars($html);
} }
@@ -1652,7 +1677,7 @@ function getGuildNameById($id)
return false; return false;
} }
function getGuildLogoById($id) function getGuildLogoById($id): string
{ {
$logo = 'default.gif'; $logo = 'default.gif';
@@ -1668,7 +1693,8 @@ function getGuildLogoById($id)
return BASE_URL . GUILD_IMAGES_DIR . $logo; return BASE_URL . GUILD_IMAGES_DIR . $logo;
} }
function displayErrorBoxWithBackButton($errors, $action = null) { function displayErrorBoxWithBackButton($errors, $action = null): void
{
global $twig; global $twig;
$twig->display('error_box.html.twig', ['errors' => $errors]); $twig->display('error_box.html.twig', ['errors' => $errors]);
$twig->display('account.back_button.html.twig', [ $twig->display('account.back_button.html.twig', [
@@ -1696,6 +1722,49 @@ function getAccountIdentityColumn(): string
return 'id'; return 'id';
} }
function isCanary(): bool
{
$vipSystemEnabled = configLua('vipSystemEnabled');
return isset($vipSystemEnabled);
}
function getStatusUptimeReadable(int $uptime): string
{
$fullMinute = 60;
$fullHour = (60 * $fullMinute);
$fullDay = (24 * $fullHour);
$fullMonth = (30 * $fullDay);
$fullYear = (365 * $fullDay);
// years
$years = floor($uptime / $fullYear);
$y = ($years > 1 ? "$years years, " : ($years == 1 ? 'year, ' : ''));
$uptime -= $years * $fullYear;
// months
$months = floor($uptime / $fullMonth);
$m = ($months > 1 ? "$months months, " : ($months == 1 ? 'month, ' : ''));
$uptime -= $months * $fullMonth;
// days
$days = floor($uptime / $fullDay);
$d = ($days > 1 ? "$days days, " : ($days == 1 ? 'day, ' : ''));
$uptime -= $days * $fullDay;
// hours
$hours = floor($uptime / $fullHour);
$uptime -= $hours * $fullHour;
// minutes
$min = floor($uptime / $fullMinute);
return "{$y}{$m}{$d}{$hours}h {$min}m";
}
// validator functions // validator functions
require_once SYSTEM . 'compat/base.php'; require_once SYSTEM . 'compat/base.php';

View File

@@ -18,6 +18,9 @@ use MyAAC\Settings;
defined('MYAAC') or die('Direct access not allowed!'); defined('MYAAC') or die('Direct access not allowed!');
ensureIndexExists(CACHE);
ensureIndexExists(CACHE . 'twig/');
global $config; global $config;
if(!isset($config['installed']) || !$config['installed']) { if(!isset($config['installed']) || !$config['installed']) {
throw new RuntimeException('MyAAC has not been installed yet or there was error during installation. Please install again.'); throw new RuntimeException('MyAAC has not been installed yet or there was error during installation. Please install again.');

File diff suppressed because it is too large Load Diff

View File

@@ -26,10 +26,11 @@ use MyAAC\Cache\Cache;
*/ */
class OTS_DB_MySQL extends OTS_Base_DB class OTS_DB_MySQL extends OTS_Base_DB
{ {
private $has_table_cache = array(); private array $has_table_cache = [];
private $has_column_cache = array(); private array $has_column_cache = [];
private array $get_column_info_cache = [];
private $clearCacheAfter = false; private bool $clearCacheAfter = false;
/** /**
* Creates database connection. * Creates database connection.
* *
@@ -119,6 +120,11 @@ class OTS_DB_MySQL extends OTS_Base_DB
if($cache->fetch('database_columns', $tmp) && $tmp) { if($cache->fetch('database_columns', $tmp) && $tmp) {
$this->has_column_cache = unserialize($tmp); $this->has_column_cache = unserialize($tmp);
} }
$tmp = null;
if($cache->fetch('database_columns_info', $tmp) && $tmp) {
$this->get_column_info_cache = unserialize($tmp);
}
} }
} }
@@ -155,11 +161,13 @@ class OTS_DB_MySQL extends OTS_Base_DB
if ($this->clearCacheAfter) { if ($this->clearCacheAfter) {
$cache->delete('database_tables'); $cache->delete('database_tables');
$cache->delete('database_columns'); $cache->delete('database_columns');
$cache->delete('database_columns_info');
$cache->delete('database_checksum'); $cache->delete('database_checksum');
} }
else { 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_checksum', serialize(sha1($config['database_host'] . '.' . $config['database_name'])), 3600); $cache->set('database_checksum', serialize(sha1($config['database_host'] . '.' . $config['database_name'])), 3600);
} }
} }
@@ -209,7 +217,8 @@ class OTS_DB_MySQL extends OTS_Base_DB
return $sql; return $sql;
} }
public function hasTable($name) { public function hasTable($name): bool
{
if(isset($this->has_table_cache[$name])) { if(isset($this->has_table_cache[$name])) {
return $this->has_table_cache[$name]; return $this->has_table_cache[$name];
} }
@@ -217,12 +226,13 @@ class OTS_DB_MySQL extends OTS_Base_DB
return $this->hasTableInternal($name); return $this->hasTableInternal($name);
} }
private function hasTableInternal($name) { private function hasTableInternal($name): bool
global $config; {
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);
} }
public function hasColumn($table, $column) { public function hasColumn($table, $column): bool
{
if(isset($this->has_column_cache[$table . '.' . $column])) { if(isset($this->has_column_cache[$table . '.' . $column])) {
return $this->has_column_cache[$table . '.' . $column]; return $this->has_column_cache[$table . '.' . $column];
} }
@@ -230,8 +240,8 @@ class OTS_DB_MySQL extends OTS_Base_DB
return $this->hasColumnInternal($table, $column); return $this->hasColumnInternal($table, $column);
} }
private function hasColumnInternal($table, $column) { private function hasColumnInternal($table, $column): bool {
return $this->hasTable($table) && ($this->has_column_cache[$table . '.' . $column] = count($this->query('SHOW COLUMNS FROM `' . $table . "` LIKE '" . $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);
} }
public function hasTableAndColumns(string $table, array $columns = []): bool public function hasTableAndColumns(string $table, array $columns = []): bool
@@ -247,7 +257,54 @@ class OTS_DB_MySQL extends OTS_Base_DB
return true; return true;
} }
public function revalidateCache() { public function getColumnInfo(string $table, string $column): bool|array
{
if(isset($this->get_column_info_cache[$table . '.' . $column])) {
return $this->get_column_info_cache[$table . '.' . $column];
}
return $this->getColumnInfoInternal($table, $column);
}
private function getColumnInfoInternal(string $table, string $column): bool|array
{
if (!$this->hasTable($table) || !$this->hasColumn($table, $column)) {
return false;
}
$formatResult = function ($result) {
return [
'field' => $result['Field'],
'type' => $result['Type'],
'null' => strtolower($result['Null']),
'key' => strtolower($result['Key'] ?? ''),
'default' => $result['Default'],
'extra' => $result['Extra'],
];
};
$query = $this->query('SHOW COLUMNS FROM `' . $table . "` LIKE " . $this->quote($column));
$rowCount = $query->rowCount();
if ($rowCount > 1) {
$tmp = [];
$results = $query->fetchAll(PDO::FETCH_ASSOC);
foreach ($results as $result) {
$tmp[] = $formatResult($result);
}
return ($this->get_column_info_cache[$table . '.' . $column] = $tmp);
}
else if ($rowCount == 1) {
$result = $query->fetch(PDO::FETCH_ASSOC);
return ($this->get_column_info_cache[$table . '.' . $column] = $formatResult($result));
}
return [];
}
public function revalidateCache(): void
{
foreach($this->has_table_cache as $key => $value) { foreach($this->has_table_cache as $key => $value) {
$this->hasTableInternal($key); $this->hasTableInternal($key);
} }
@@ -262,6 +319,21 @@ class OTS_DB_MySQL extends OTS_Base_DB
$this->hasColumnInternal($explode[0], $explode[1]); $this->hasColumnInternal($explode[0], $explode[1]);
} }
} }
foreach($this->get_column_info_cache as $key => $value) {
$explode = explode('.', $key);
if(!isset($this->has_table_cache[$explode[0]])) { // first check if table exist
$this->hasTableInternal($explode[0]);
}
if($this->has_table_cache[$explode[0]]) {
$this->hasColumnInternal($explode[0], $explode[1]);
}
if($this->has_table_cache[$explode[0]]) {
$this->getColumnInfoInternal($explode[0], $explode[1]);
}
}
} }
public function setClearCacheAfter($clearCache) public function setClearCacheAfter($clearCache)

View File

@@ -1,20 +1,6 @@
<?php <?php
$__load = array();
/* use MyAAC\Models\Player as PlayerModel;
'loss_experience' => NULL,
'loss_items' => NULL,
'guild_info' => NULL,
'skull_type' => NULL,
'skull_time' => NULL,
'blessings' => NULL,
'direction' => NULL,
'stamina' => NULL,
'world_id' => NULL,
'online' => NULL,
'deletion' => NULL,
'promotion' => NULL,
'marriage' => NULL
);*/
/**#@+ /**#@+
* @version 0.0.1 * @version 0.0.1
@@ -109,6 +95,10 @@ class OTS_Player extends OTS_Row_DAO
POT::SKILL_FISH => array('value' => 0, 'tries' => 0) POT::SKILL_FISH => array('value' => 0, 'tries' => 0)
); );
private array $columns = ['name', 'account_id', 'group_id', 'sex', 'vocation', 'experience', 'level', 'maglevel', 'health', 'healthmax', 'mana', 'manamax', 'manaspent', 'soul', 'lookbody', 'lookfeet', 'lookhead', 'looklegs', 'looktype', 'posx', 'posy', 'posz', 'lastlogin', 'lastlogout', 'lastip', 'town_id', 'balance', 'created', 'comment', 'hide'];
private array $optionalColumns = ['cap', 'skull', 'skull_type', 'skull_time', 'loss_experience', 'loss_mana', 'loss_skills', 'loss_items', 'loss_containers', 'guildnick', 'rank_id', 'promotion', 'direction', 'blessings', 'stamina', 'lookaddons', 'save', 'conditions', 'world_id', 'online', 'deletion', 'deleted', 'marriage'];
private static array $playersOnline; private static array $playersOnline;
/** /**
* Magic PHP5 method. * Magic PHP5 method.
@@ -133,90 +123,14 @@ class OTS_Player extends OTS_Row_DAO
*/ */
public function load($id, $fields = null, $load_skills = true) public function load($id, $fields = null, $load_skills = true)
{ {
global $__load; $columns = $this->columns;
foreach ($this->optionalColumns as $column) {
if(!isset($__load['loss_experience'])) if ($this->db->hasColumn('players', $column)) {
{ $columns[] = $column;
$loss = '';
if($this->db->hasColumn('players', 'loss_experience')) {
$loss = ', `loss_experience`, `loss_mana`, `loss_skills`';
} }
$__load['loss_experience'] = $loss;
}
if(!isset($__load['loss_items']))
{
$loss_items = '';
if($this->db->hasColumn('players', 'loss_items')) {
$loss_items = ', `loss_items`, `loss_containers`';
}
$__load['loss_items'] = $loss_items;
}
if(!isset($__load['guild_info']))
{
$guild_info = '';
if(!$this->db->hasTable('guild_members') && $this->db->hasColumn('players', 'guildnick')) {
$guild_info = ', `guildnick`, `rank_id`';
}
$__load['guild_info'] = $guild_info;
}
if(!isset($__load['skull_type']))
{
$skull_type = 'skull';
if($this->db->hasColumn('players', 'skull_type')) {
$skull_type = 'skull_type';
}
$__load['skull_type'] = $skull_type;
}
if(!isset($__load['skull_time']))
{
$skull_time = 'skulltime';
if($this->db->hasColumn('players', 'skull_time')) {
$skull_time = 'skull_time';
}
$__load['skull_time'] = $skull_time;
}
if(!isset($__load['blessings'])) {
$__load['blessings'] = $this->db->hasColumn('players', 'blessings');
}
if(!isset($__load['direction'])) {
$__load['direction'] = $this->db->hasColumn('players', 'direction');
}
if(!isset($__load['stamina'])) {
$__load['stamina'] = $this->db->hasColumn('players', 'stamina');
}
if(!isset($__load['world_id'])) {
$__load['world_id'] = $this->db->hasColumn('players', 'world_id');
}
if(!isset($__load['online'])) {
$__load['online'] = $this->db->hasColumn('players', 'online');
}
if(!isset($__load['deletion'])) {
$__load['deletion'] = $this->db->hasColumn('players', 'deletion');
}
if(!isset($__load['promotion'])) {
$__load['promotion'] = $this->db->hasColumn('players', 'promotion');
}
if(!isset($__load['marriage'])) {
$__load['marriage'] = $this->db->hasColumn('players', 'marriage');
} }
if(isset($fields)) { // load only what we wish if(isset($fields)) { // load only what we wish
if(in_array('promotion', $fields)) {
if(!$this->db->hasColumn('players', 'promotion')) {
unset($fields[array_search('promotion', $fields)]);
}
}
if(in_array('deleted', $fields)) { if(in_array('deleted', $fields)) {
if($this->db->hasColumn('players', 'deletion')) { if($this->db->hasColumn('players', 'deletion')) {
unset($fields[array_search('deleted', $fields)]); unset($fields[array_search('deleted', $fields)]);
@@ -224,21 +138,20 @@ class OTS_Player extends OTS_Row_DAO
} }
} }
if(in_array('online', $fields)) { $columns = [];
if(!$this->db->hasColumn('players', 'online')) { foreach ($fields as $field) {
unset($fields[array_search('online', $fields)]); if ($this->db->hasColumn('players', $field)) {
$columns[] = $field;
} }
} }
$this->data = $this->db->query('SELECT ' . implode(', ', $fields) . ' FROM `players` WHERE `id` = ' . (int)$id)->fetch();
}
else {
// SELECT query on database
$this->data = $this->db->query('SELECT `id`, `name`, `account_id`, `group_id`, `sex`, `vocation`, `experience`, `level`, `maglevel`, `health`, `healthmax`, `mana`, `manamax`, `manaspent`, `soul`, `lookbody`, `lookfeet`, `lookhead`, `looklegs`, `looktype`' . ($this->db->hasColumn('players', 'lookaddons') ? ', `lookaddons`' : '') . ', `posx`, `posy`, `posz`, `cap`, `lastlogin`, `lastlogout`, `lastip`, `save`, `conditions`, `' . $__load['skull_time'] . '` as `skulltime`, `' . $__load['skull_type'] . '` as `skull`' . $__load['guild_info'] . ', `town_id`' . $__load['loss_experience'] . $__load['loss_items'] . ', `balance`' . ($__load['blessings'] ? ', `blessings`' : '') . ($__load['direction'] ? ', `direction`' : '') . ($__load['stamina'] ? ', `stamina`' : '') . ($__load['world_id'] ? ', `world_id`' : '') . ($__load['online'] ? ', `online`' : '') . ', `' . ($__load['deletion'] ? 'deletion' : 'deleted') . '`' . ($__load['promotion'] ? ', `promotion`' : '') . ($__load['marriage'] ? ', `marriage`' : '') . ', `comment`, `created`, `hide` FROM `players` WHERE `id` = ' . (int)$id)->fetch();
} }
array_unshift($columns, 'id');
$this->data = PlayerModel::where('id', $id)->first($columns)->toArray();
// loads skills // loads skills
if( $this->isLoaded() && $load_skills) if( $this->isLoaded() && $load_skills) {
{
if($this->db->hasColumn('players', 'skill_fist')) { if($this->db->hasColumn('players', 'skill_fist')) {
$skill_ids = array( $skill_ids = array(
@@ -318,153 +231,57 @@ class OTS_Player extends OTS_Row_DAO
*/ */
public function save() public function save()
{ {
$skull_type = 'skull'; $defaultValues = [
if($this->db->hasColumn('players', 'skull_type')) { 'loss_experience' => 100,
$skull_type = 'skull_type'; 'loss_mana' => 100,
'loss_skills' => 100,
'loss_items' => 100,
'loss_containers' => 100,
'guildnick' => '',
'rank_id' => 0,
'promotion' => 0,
'direction' => 0,
'blessings' => 0,
'conditions' => '',
'town_id' => 1,
'deletion' => 0,
'deleted' => 0,
'stamina' => 0,
'marriage' => 0,
];
foreach ($defaultValues as $key => $value) {
if (!isset($this->data[$key])) {
$this->data[$key] = $value;
}
} }
$skull_time = 'skulltime'; $columns = $this->columns;
if($this->db->hasColumn('players', 'skull_time')) { foreach ($this->optionalColumns as $column) {
$skull_time = 'skull_time'; if ($this->db->hasColumn('players', $column)) {
$columns[] = $column;
}
} }
if(!isset($this->data['loss_experience'])) $values = [];
$this->data['loss_experience'] = 100; foreach ($columns as $column) {
$value = $this->data[$column];
if ($column == 'created') {
$value = time();
}
if(!isset($this->data['loss_mana'])) $values[$column] = $value;
$this->data['loss_mana'] = 100; }
if(!isset($this->data['loss_skills']))
$this->data['loss_skills'] = 100;
if(!isset($this->data['loss_items']))
$this->data['loss_items'] = 10;
if(!isset($this->data['loss_containers']))
$this->data['loss_containers'] = 100;
if(!isset($this->data['guildnick']))
$this->data['guildnick'] = '';
if(!isset($this->data['rank_id']))
$this->data['rank_id'] = 0;
if(!isset($this->data['promotion']))
$this->data['promotion'] = 0;
if(!isset($this->data['direction']))
$this->data['direction'] = 0;
if(!isset($this->data['conditions']))
$this->data['conditions'] = '';
if(!isset($this->data['town_id']))
$this->data['town_id'] = 1;
// updates existing player // updates existing player
if( isset($this->data['id']) ) if( isset($this->data['id']) ) {
{ PlayerModel::where('id', $this->data['id'])->update($values);
$loss = '';
if($this->db->hasColumn('players', 'loss_experience')) {
$loss = ', `loss_experience` = ' . $this->data['loss_experience'] . ', `loss_mana` = ' . $this->data['loss_mana'] . ', `loss_skills` = ' . $this->data['loss_skills'];
}
$loss_items = '';
if($this->db->hasColumn('players', 'loss_items')) {
$loss_items = ', `loss_items` = ' . $this->data['loss_items'] . ', `loss_containers` = ' . $this->data['loss_containers'];
}
$guild_info = '';
if(!$this->db->hasTable('guild_members') && $this->db->hasColumn('players', 'guildnick')) {
$guild_info = ', `guildnick` = ' . $this->db->quote($this->data['guildnick']) . ', ' . $this->db->fieldName('rank_id') . ' = ' . $this->data['rank_id'];
}
$direction = '';
if($this->db->hasColumn('players', 'direction')) {
$direction = ', `direction` = ' . $this->db->quote($this->data['direction']);
}
$blessings = '';
if($this->db->hasColumn('players', 'blessings')) {
$blessings = ', `blessings` = ' . $this->db->quote($this->data['blessings']);
}
$stamina = '';
if($this->db->hasColumn('players', 'stamina')) {
$stamina = ', `stamina` = ' . $this->db->quote($this->data['stamina']);
}
$lookaddons = '';
if($this->db->hasColumn('players', 'lookaddons')) {
$lookaddons = ', `lookaddons` = ' . $this->db->quote($this->data['lookaddons']);
}
// UPDATE query on database
$this->db->query('UPDATE ' . $this->db->tableName('players') . ' SET ' . $this->db->fieldName('name') . ' = ' . $this->db->quote($this->data['name']) . ', ' . $this->db->fieldName('account_id') . ' = ' . $this->data['account_id'] . ', ' . $this->db->fieldName('group_id') . ' = ' . $this->data['group_id'] . ', ' . $this->db->fieldName('sex') . ' = ' . $this->data['sex'] . ', ' . $this->db->fieldName('vocation') . ' = ' . $this->data['vocation'] . ', ' . $this->db->fieldName('experience') . ' = ' . $this->data['experience'] . ', ' . $this->db->fieldName('level') . ' = ' . $this->data['level'] . ', ' . $this->db->fieldName('maglevel') . ' = ' . $this->data['maglevel'] . ', ' . $this->db->fieldName('health') . ' = ' . $this->data['health'] . ', ' . $this->db->fieldName('healthmax') . ' = ' . $this->data['healthmax'] . ', ' . $this->db->fieldName('mana') . ' = ' . $this->data['mana'] . ', ' . $this->db->fieldName('manamax') . ' = ' . $this->data['manamax'] . ', ' . $this->db->fieldName('manaspent') . ' = ' . $this->data['manaspent'] . ', ' . $this->db->fieldName('soul') . ' = ' . $this->data['soul'] . ', ' . $this->db->fieldName('lookbody') . ' = ' . $this->data['lookbody'] . ', ' . $this->db->fieldName('lookfeet') . ' = ' . $this->data['lookfeet'] . ', ' . $this->db->fieldName('lookhead') . ' = ' . $this->data['lookhead'] . ', ' . $this->db->fieldName('looklegs') . ' = ' . $this->data['looklegs'] . ', ' . $this->db->fieldName('looktype') . ' = ' . $this->data['looktype'] . $lookaddons . ', ' . $this->db->fieldName('posx') . ' = ' . $this->data['posx'] . ', ' . $this->db->fieldName('posy') . ' = ' . $this->data['posy'] . ', ' . $this->db->fieldName('posz') . ' = ' . $this->data['posz'] . ', ' . $this->db->fieldName('cap') . ' = ' . $this->data['cap'] . ', ' . $this->db->fieldName('lastlogin') . ' = ' . $this->data['lastlogin'] . ', ' . $this->db->fieldName('lastlogout') . ' = ' . $this->data['lastlogout'] . ', ' . $this->db->fieldName('lastip') . ' = ' . $this->db->quote($this->data['lastip']) . ', ' . $this->db->fieldName('save') . ' = ' . (int) $this->data['save'] . ', ' . $this->db->fieldName('conditions') . ' = ' . $this->db->quote($this->data['conditions']) . ', `' . $skull_time . '` = ' . $this->data['skulltime'] . ', `' . $skull_type . '` = ' . (int) $this->data['skull'] . $guild_info . ', ' . $this->db->fieldName('town_id') . ' = ' . $this->data['town_id'] . $loss . $loss_items . ', ' . $this->db->fieldName('balance') . ' = ' . $this->data['balance'] . $blessings . $stamina . $direction . ' WHERE ' . $this->db->fieldName('id') . ' = ' . $this->data['id']);
} }
// creates new player // creates new player
else else {
{ $player = PlayerModel::create($values);
$loss = '';
$loss_data = '';
if($this->db->hasColumn('players', 'loss_experience')) {
$loss = ', `loss_experience`, `loss_mana`, `loss_skills`';
$loss_data = ', ' . $this->data['loss_experience'] . ', ' . $this->data['loss_mana'] . ', ' . $this->data['loss_skills'];
}
$loss_items = '';
$loss_items_data = '';
if($this->db->hasColumn('players', 'loss_items')) {
$loss_items = ', `loss_items`, `loss_containers`';
$loss_items_data = ', ' . $this->data['loss_items'] . ', ' . $this->data['loss_containers'];
}
$guild_info = '';
$guild_info_data = '';
if(!$this->db->hasTable('guild_members') && $this->db->hasColumn('players', 'guildnick')) {
$guild_info = ', `guildnick`, `rank_id`';
$guild_info_data = ', ' . $this->db->quote($this->data['guildnick']) . ', ' . $this->data['rank_id'];
}
$promotion = '';
$promotion_data = '';
if($this->db->hasColumn('players', 'promotion')) {
$promotion = ', `promotion`';
$promotion_data = ', ' . $this->data['promotion'];
}
$direction = '';
$direction_data = '';
if($this->db->hasColumn('players', 'direction')) {
$direction = ', `direction`';
$direction_data = ', ' . $this->data['direction'];
}
$blessings = '';
$blessings_data = '';
if($this->db->hasColumn('players', 'blessings')) {
$blessings = ', `blessings`';
$blessings_data = ', ' . $this->data['blessings'];
}
$stamina = '';
$stamina_data = '';
if($this->db->hasColumn('players', 'stamina')) {
$stamina = ', `stamina`';
$stamina_data = ', ' . $this->data['stamina'];
}
$lookaddons = '';
$lookaddons_data = '';
if($this->db->hasColumn('players', 'lookaddons')) {
$lookaddons = ', `lookaddons`';
$lookaddons_data = ', ' . $this->data['lookaddons'];
}
// INSERT query on database
$this->db->query('INSERT INTO `players` (`name`, `account_id`, `group_id`, `sex`, `vocation`, `experience`, `level`, `maglevel`, `health`, `healthmax`, `mana`, `manamax`, `manaspent`, `soul`, `lookbody`, `lookfeet`, `lookhead`, `looklegs`, `looktype`' . $lookaddons . ', `posx`, `posy`, `posz`, `cap`, `lastlogin`, `lastlogout`, `lastip`, `save`, `conditions`, `' . $skull_time . '`, `' . $skull_type . '`' . $guild_info . ', `town_id`' . $loss . $loss_items . ', `balance`' . $blessings . $stamina . $direction . ', `created`' . $promotion . ', `comment`) VALUES (' . $this->db->quote($this->data['name']) . ', ' . $this->data['account_id'] . ', ' . $this->data['group_id'] . ', ' . $this->data['sex'] . ', ' . $this->data['vocation'] . ', ' . $this->data['experience'] . ', ' . $this->data['level'] . ', ' . $this->data['maglevel'] . ', ' . $this->data['health'] . ', ' . $this->data['healthmax'] . ', ' . $this->data['mana'] . ', ' . $this->data['manamax'] . ', ' . $this->data['manaspent'] . ', ' . $this->data['soul'] . ', ' . $this->data['lookbody'] . ', ' . $this->data['lookfeet'] . ', ' . $this->data['lookhead'] . ', ' . $this->data['looklegs'] . ', ' . $this->data['looktype'] . $lookaddons_data . ', ' . $this->data['posx'] . ', ' . $this->data['posy'] . ', ' . $this->data['posz'] . ', ' . $this->data['cap'] . ', ' . $this->data['lastlogin'] . ', ' . $this->data['lastlogout'] . ', ' . $this->data['lastip'] . ', ' . (int) $this->data['save'] . ', ' . $this->db->quote($this->data['conditions']) . ', ' . $this->data['skulltime'] . ', ' . (int) $this->data['skull'] . $guild_info_data . ', ' . $this->data['town_id'] . $loss_data . $loss_items_data . ', ' . $this->data['balance'] . $blessings_data . $stamina_data . $direction_data . ', ' . time() . $promotion_data . ', "")');
// ID of new group // ID of new group
$this->data['id'] = $this->db->lastInsertId(); $this->data['id'] = $player->id;
} }
// updates skills - doesn't matter if we have just created character - trigger inserts new skills // updates skills - doesn't matter if we have just created character - trigger inserts new skills
@@ -490,7 +307,7 @@ class OTS_Player extends OTS_Row_DAO
$set .= ','; $set .= ',';
} }
$skills = $this->db->query('UPDATE `players` SET ' . $set . ' WHERE `id` = ' . $this->data['id']); $this->db->query('UPDATE `players` SET ' . $set . ' WHERE `id` = ' . $this->data['id']);
} }
else if($this->db->hasTable('player_skills')) { else if($this->db->hasTable('player_skills')) {
foreach($this->skills as $id => $skill) foreach($this->skills as $id => $skill)
@@ -748,21 +565,25 @@ class OTS_Player extends OTS_Row_DAO
public function isDeleted() public function isDeleted()
{ {
$field = 'deleted'; $column = 'deleted';
if($this->db->hasColumn('players', 'deletion')) if($this->db->hasColumn('players', 'deletion'))
$field = 'deletion'; $column = 'deletion';
if( !isset($this->data[$field]) ) if( !isset($this->data[$column]) )
{ {
throw new E_OTS_NotLoaded(); throw new E_OTS_NotLoaded();
} }
return $this->data[$field] > 0; return $this->data[$column] > 0;
} }
public function setDeleted($deleted) public function setDeleted($deleted)
{ {
$this->data['deleted'] = (int) $deleted; $column = 'deleted';
if($this->db->hasColumn('players', 'deletion'))
$column = 'deletion';
$this->data[$column] = (int) $deleted;
} }
public function isOnline() public function isOnline()
@@ -1792,12 +1613,12 @@ class OTS_Player extends OTS_Row_DAO
*/ */
public function getSkullTime() public function getSkullTime()
{ {
if( !isset($this->data['skulltime']) ) $column = 'skulltime';
{ if($this->db->hasColumn('players', 'skull_time')) {
throw new E_OTS_NotLoaded(); $column = 'skull_time';
} }
return $this->data['skulltime']; return $this->data[$column] ?? 0;
} }
/** /**
@@ -1811,7 +1632,12 @@ class OTS_Player extends OTS_Row_DAO
*/ */
public function setSkullTime($skulltime) public function setSkullTime($skulltime)
{ {
$this->data['skulltime'] = (int) $skulltime; $column = 'skulltime';
if($this->db->hasColumn('players', 'skull_time')) {
$column = 'skull_time';
}
$this->data[$column] = (int) $skulltime;
} }
/** /**
@@ -3250,6 +3076,10 @@ class OTS_Player extends OTS_Row_DAO
return 0; return 0;
} }
public function setData(array $data): void{
$this->data = $data;
}
/** /**
* Magic PHP5 method. * Magic PHP5 method.
* *

View File

@@ -97,6 +97,8 @@ class OTS_ServerInfo
return new OTS_Buffer($data); return new OTS_Buffer($data);
} }
log_append('status-error.log', "Cannot connect to {$this->server}:{$this->port} - Error code: $error, message: $message");
return false; return false;
} }

View File

@@ -78,6 +78,7 @@ $locale['step_database_error_mysql_connect_3'] = 'MySQL ist nicht richtig konfig
$locale['step_database_error_mysql_connect_4'] = 'MySQL-Server läuft nicht.'; $locale['step_database_error_mysql_connect_4'] = 'MySQL-Server läuft nicht.';
$locale['step_database_error_schema'] = 'Fehler beim Importieren des Schemas:'; $locale['step_database_error_schema'] = 'Fehler beim Importieren des Schemas:';
$locale['step_database_success_schema'] = '$PREFIX$ Tabellen wurden erfolgreich installiert.'; $locale['step_database_success_schema'] = '$PREFIX$ Tabellen wurden erfolgreich installiert.';
$locale['step_database_success_import_data'] = 'Import von Daten für Tabellen was erfolgreich.';
$locale['step_database_error_file'] = '$FILE$ konnte nicht geöffnet werden. Bitte kopieren Sie diesen Inhalt und fügen Sie ihn dort ein:'; $locale['step_database_error_file'] = '$FILE$ konnte nicht geöffnet werden. Bitte kopieren Sie diesen Inhalt und fügen Sie ihn dort ein:';
$locale['step_database_adding_field'] = 'Folgendes Feld wurde hinzugefügt: '; $locale['step_database_adding_field'] = 'Folgendes Feld wurde hinzugefügt: ';
$locale['step_database_modifying_field'] = 'Folgendes Feld wurde geändert: '; $locale['step_database_modifying_field'] = 'Folgendes Feld wurde geändert: ';

View File

@@ -83,6 +83,7 @@ $locale['step_database_error_mysql_connect_3'] = 'MySQL is not configured proper
$locale['step_database_error_mysql_connect_4'] = 'MySQL server is not running.'; $locale['step_database_error_mysql_connect_4'] = 'MySQL server is not running.';
$locale['step_database_error_schema'] = 'Error while importing schema:'; $locale['step_database_error_schema'] = 'Error while importing schema:';
$locale['step_database_success_schema'] = 'Successfully installed $PREFIX$ tables.'; $locale['step_database_success_schema'] = 'Successfully installed $PREFIX$ tables.';
$locale['step_database_success_import_data'] = 'Successfully imported base data for tables.';
$locale['step_database_error_file'] = '$FILE$ couldn\'t be opened. Please copy this content and paste there:'; $locale['step_database_error_file'] = '$FILE$ couldn\'t be opened. Please copy this content and paste there:';
$locale['step_database_adding_field'] = 'Adding field'; $locale['step_database_adding_field'] = 'Adding field';
$locale['step_database_modifying_field'] = 'Modifying field'; $locale['step_database_modifying_field'] = 'Modifying field';

View File

@@ -81,7 +81,8 @@ $locale['step_database_error_mysql_connect_2'] = 'Możliwe przyczyny:';
$locale['step_database_error_mysql_connect_3'] = 'MySQL nie jest poprawnie skonfigurowane w <i>config.lua</i>.'; $locale['step_database_error_mysql_connect_3'] = 'MySQL nie jest poprawnie skonfigurowane w <i>config.lua</i>.';
$locale['step_database_error_mysql_connect_4'] = 'Serwer MySQL nie jest uruchomiony.'; $locale['step_database_error_mysql_connect_4'] = 'Serwer MySQL nie jest uruchomiony.';
$locale['step_database_error_schema'] = 'Błąd podczas importowania struktury bazy danych:'; $locale['step_database_error_schema'] = 'Błąd podczas importowania struktury bazy danych:';
$locale['step_database_success_schema'] = 'Pomyślnie zainstalowano tabele $PREFIX$.'; $locale['step_database_success_schema'] = 'Pomyślnie zaimportowano tabele $PREFIX$.';
$locale['step_database_success_import_data'] = 'Pomyślnie załadowano bazowe dane dla tabel.';
$locale['step_database_error_file'] = '$FILE$ nie mógł zostać otwarty. Proszę skopiować zawartość pola tekstowego i wkleić do tego pliku:'; $locale['step_database_error_file'] = '$FILE$ nie mógł zostać otwarty. Proszę skopiować zawartość pola tekstowego i wkleić do tego pliku:';
$locale['step_database_adding_field'] = 'Dodawanie pola'; $locale['step_database_adding_field'] = 'Dodawanie pola';
$locale['step_database_modifying_field'] = 'Modyfikacja pola'; $locale['step_database_modifying_field'] = 'Modyfikacja pola';

View File

@@ -34,8 +34,10 @@ if($logged) {
$twig->addGlobal('account_logged', $account_logged); $twig->addGlobal('account_logged', $account_logged);
} }
setSession('last_visit', time()); if (!defined('IGNORE_SET_LAST_VISIT') || !IGNORE_SET_LAST_VISIT) {
if(defined('PAGE')) { setSession('last_visit', time());
setSession('last_page', PAGE); if(defined('PAGE')) {
setSession('last_page', PAGE);
}
setSession('last_uri', $_SERVER['REQUEST_URI']);
} }
setSession('last_uri', $_SERVER['REQUEST_URI']);

View File

@@ -9,6 +9,8 @@
*/ */
defined('MYAAC') or die('Direct access not allowed!'); defined('MYAAC') or die('Direct access not allowed!');
global $db;
// database migrations // database migrations
$tmp = ''; $tmp = '';
if(fetchDatabaseConfig('database_version', $tmp)) { // we got version if(fetchDatabaseConfig('database_version', $tmp)) { // we got version

View File

@@ -0,0 +1,8 @@
CREATE TABLE `myaac_account_emails_verify`
(
`id` int NOT NULL AUTO_INCREMENT,
`account_id` int NOT NULL,
`hash` varchar(32) NOT NULL,
`sent_at` int NOT NULL DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;

24
system/migrations/46.php Normal file
View File

@@ -0,0 +1,24 @@
<?php
/**
* @var OTS_DB_MySQL $db
*/
$up = function () use ($db) {
if ($db->hasColumn('accounts', 'email_hash')) {
$db->dropColumn('accounts', 'email_hash');
}
if (!$db->hasTable(TABLE_PREFIX . 'account_emails_verify')) {
$db->query(file_get_contents(__DIR__ . '/46-account_emails_verify.sql'));
}
};
$down = function () use ($db) {
if (!$db->hasColumn('accounts', 'email_hash')) {
$db->addColumn('accounts', 'email_hash', "varchar(32) NOT NULL DEFAULT ''");
}
if ($db->hasTable(TABLE_PREFIX . 'account_emails_verify')) {
$db->dropTable(TABLE_PREFIX . 'account_emails_verify');
}
};

42
system/migrations/47.php Normal file
View File

@@ -0,0 +1,42 @@
<?php
/**
* @var OTS_DB_MySQL $db
*/
// 2025-02-27
// remove ipv6, change to ip (for both ipv4 + ipv6) as VARCHAR(45)
$up = function () use ($db) {
$accountActionsInfo = $db->getColumnInfo(TABLE_PREFIX . 'account_actions', 'account_id');
if ($accountActionsInfo && is_array($accountActionsInfo) && $accountActionsInfo['key'] == 'pri') {
$db->query("ALTER TABLE `myaac_account_actions` DROP KEY `account_id`;");
}
if (!$db->hasColumn(TABLE_PREFIX . 'account_actions', 'id')) {
$db->addColumn(TABLE_PREFIX . 'account_actions', 'id', 'INT NOT NULL AUTO_INCREMENT FIRST, ADD PRIMARY KEY (`id`)');
}
$db->modifyColumn(TABLE_PREFIX . 'account_actions', 'ip', "VARCHAR(45) NOT NULL DEFAULT ''");
$db->query("UPDATE `" . TABLE_PREFIX . "account_actions` SET `ip` = INET_NTOA(`ip`) WHERE `ip` != '0';");
$db->query("UPDATE `" . TABLE_PREFIX . "account_actions` SET `ip` = INET6_NTOA(`ipv6`) WHERE `ip` = '0';");
if ($db->hasColumn(TABLE_PREFIX . 'account_actions', 'ipv6')) {
$db->dropColumn(TABLE_PREFIX . 'account_actions', 'ipv6');
}
};
$down = function () use ($db) {
if ($db->hasColumn(TABLE_PREFIX . 'account_actions', 'id')) {
$db->query("ALTER TABLE `" . TABLE_PREFIX . "account_actions` DROP `id`;");
}
$db->query("ALTER TABLE `" . TABLE_PREFIX . "account_actions` ADD KEY (`account_id`);");
if (!$db->hasColumn(TABLE_PREFIX . 'account_actions', 'ipv6')) {
$db->addColumn(TABLE_PREFIX . 'account_actions', 'ipv6', "BINARY(16) NOT NULL DEFAULT 0x00000000000000000000000000000000 AFTER ip");
}
$db->query("UPDATE `" . TABLE_PREFIX . "account_actions` SET `ipv6` = INET6_ATON(ip) WHERE NOT IS_IPV4(`ip`);");
$db->query("UPDATE `" . TABLE_PREFIX . "account_actions` SET `ip` = INET_ATON(`ip`) WHERE IS_IPV4(`ip`);");
$db->query("UPDATE `" . TABLE_PREFIX . "account_actions` SET `ip` = 0 WHERE `ipv6` != 0x00000000000000000000000000000000;");
$db->modifyColumn(TABLE_PREFIX . 'account_actions', 'ip', "INT(11) UNSIGNED NOT NULL DEFAULT 0;");
};

View File

@@ -19,18 +19,17 @@ if(!$logged) {
csrfProtect(); csrfProtect();
$new_password = $_POST['newpassword'] ?? NULL; $new_password = $_POST['new_password'] ?? null;
$new_password_confirm = $_POST['newpassword_confirm'] ?? NULL; $new_password_confirm = $_POST['new_password_confirm'] ?? null;
$old_password = $_POST['oldpassword'] ?? NULL; $old_password = $_POST['old_password'] ?? null;
if(empty($new_password) && empty($new_password_confirm) && empty($old_password)) { if(empty($new_password) && empty($new_password_confirm) && empty($old_password)) {
$twig->display('account.change-password.html.twig'); $twig->display('account.change-password.html.twig');
} }
else else {
{
if(empty($new_password) || empty($new_password_confirm) || empty($old_password)){ if(empty($new_password) || empty($new_password_confirm) || empty($old_password)){
$errors[] = 'Please fill in form.'; $errors[] = 'Please fill in form.';
} }
$password_strlen = strlen($new_password);
if($new_password != $new_password_confirm) { if($new_password != $new_password_confirm) {
$errors[] = 'The new passwords do not match!'; $errors[] = 'The new passwords do not match!';
} }
@@ -41,10 +40,13 @@ else
} }
/** @var OTS_Account $account_logged */ /** @var OTS_Account $account_logged */
$old_password = encrypt((USE_ACCOUNT_SALT ? $account_logged->getCustomField('salt') : '') . $old_password); $old_password_hashed = encrypt((USE_ACCOUNT_SALT ? $account_logged->getCustomField('salt') : '') . $old_password);
if($old_password != $account_logged->getPassword()) { if($old_password_hashed != $account_logged->getPassword()) {
$errors[] = 'Current password is incorrect!'; $errors[] = 'Current password is incorrect!';
} }
else if ($old_password == $new_password) {
$errors[] = 'The old password is same as the new password!';
}
$hooks->trigger(HOOK_ACCOUNT_CHANGE_PASSWORD_POST); $hooks->trigger(HOOK_ACCOUNT_CHANGE_PASSWORD_POST);
} }

View File

@@ -9,6 +9,7 @@
*/ */
use MyAAC\Models\Account; use MyAAC\Models\Account;
use MyAAC\Models\AccountEmailVerify;
defined('MYAAC') or die('Direct access not allowed!'); defined('MYAAC') or die('Direct access not allowed!');
@@ -20,16 +21,20 @@ if(empty($hash)) {
return; return;
} }
if(!Account::where('email_hash', $hash)->exists()) { // by default link is valid for 30 days
note("Your email couldn't be verified. Please contact staff to do it manually."); $accountEmailVerify = AccountEmailVerify::where('hash', $hash)->where('sent_at', '>', time() - 30 * 24 * 60 * 60)->first();
if(!$accountEmailVerify) {
note("Wrong link or link has expired.");
} }
else else
{ {
$accountModel = Account::where('email_hash', $hash)->where('email_verified', 0)->first(); $accountModel = Account::where('id', $accountEmailVerify->account_id)->where('email_verified', 0)->first();
if ($accountModel) { if ($accountModel) {
$accountModel->email_verified = 1; $accountModel->email_verified = 1;
$accountModel->save(); $accountModel->save();
AccountEmailVerify::where('account_id', $accountModel->id)->delete();
success('You have now verified your e-mail, this will increase the security of your account. Thank you for doing this. You can now <a href=' . getLink('account/manage') . '>log in</a>.'); success('You have now verified your e-mail, this will increase the security of your account. Thank you for doing this. You can now <a href=' . getLink('account/manage') . '>log in</a>.');
$account = new OTS_Account(); $account = new OTS_Account();
@@ -39,6 +44,6 @@ else
} }
} }
else { else {
error('Link has expired.'); error('Your account is already verified.');
} }
} }

View File

@@ -10,6 +10,7 @@
*/ */
use MyAAC\CreateCharacter; use MyAAC\CreateCharacter;
use MyAAC\Models\AccountEmailVerify;
defined('MYAAC') or die('Direct access not allowed!'); defined('MYAAC') or die('Direct access not allowed!');
$title = 'Create Account'; $title = 'Create Account';
@@ -244,7 +245,12 @@ if($save)
if(setting('core.mail_enabled') && setting('core.account_mail_verify')) if(setting('core.mail_enabled') && setting('core.account_mail_verify'))
{ {
$hash = md5(generateRandomString(16, true, true) . $email); $hash = md5(generateRandomString(16, true, true) . $email);
$new_account->setCustomField('email_hash', $hash);
AccountEmailVerify::create([
'account_id' => $new_account->getId(),
'hash' => $hash,
'sent_at' => time(),
]);
$verify_url = getLink('account/confirm-email/' . $hash); $verify_url = getLink('account/confirm-email/' . $hash);
$body_html = $twig->render('mail.account.verify.html.twig', array( $body_html = $twig->render('mail.account.verify.html.twig', array(
@@ -361,7 +367,7 @@ if(!empty($errors))
if (setting('core.account_country')) { if (setting('core.account_country')) {
$countries = array(); $countries = array();
foreach (array('pl', 'se', 'br', 'us', 'gb') as $c) foreach (setting('core.account_countries_most_popular') ?? [] as $c)
$countries[$c] = $config['countries'][$c]; $countries[$c] = $config['countries'][$c];
$countries['--'] = '----------'; $countries['--'] = '----------';

View File

@@ -48,7 +48,9 @@ if(!empty($login_account) && !empty($login_password))
) )
{ {
if (setting('core.account_mail_verify') && (int)$account_logged->getCustomField('email_verified') !== 1) { if (setting('core.account_mail_verify') && (int)$account_logged->getCustomField('email_verified') !== 1) {
$errors[] = 'Your account is not verified. Please verify your email address. If the message is not coming check the SPAM folder in your E-Mail client.'; $link = getLink('account/resend-email-verify');
$errors[] = 'Your account is not verified. Please verify your email address. If the message is not coming check the SPAM folder in your E-Mail client.<br/>' .
'You can resend the Email here: <a href="' . $link . '">' . $link . '</a>';
} else { } else {
session_regenerate_id(); session_regenerate_id();
setSession('account', $account_logged->getId()); setSession('account', $account_logged->getId());

View File

@@ -38,15 +38,24 @@ csrfProtect();
$groups = new OTS_Groups_List(); $groups = new OTS_Groups_List();
$freePremium = isset($config['lua']['freePremium']) && getBoolean($config['lua']['freePremium']) || $account_logged->getPremDays() == OTS_Account::GRATIS_PREMIUM_DAYS;
$dayOrDays = $account_logged->getPremDays() == 1 ? 'day' : 'days';
/** /**
* @var OTS_Account $account_logged * @var OTS_Account $account_logged
*/ */
if(!$account_logged->isPremium()) $premDays = $account_logged->getPremDays();
$freePremium = isset($config['lua']['freePremium']) && getBoolean($config['lua']['freePremium']) || $premDays == OTS_Account::GRATIS_PREMIUM_DAYS;
$dayOrDays = ($premDays == 1 ? 'day' : 'days');
$vipSystemEnabled = isset($config['lua']['vipSystemEnabled']) && getBoolean($config['lua']['vipSystemEnabled']);
$premiumLabel = $vipSystemEnabled ? 'VIP' : 'Premium Account';
if ($freePremium && !$vipSystemEnabled) {
$account_status = '<b><span style="color: green">Gratis Premium Account</span></b>';
} else if(!$account_logged->isPremium()) {
$account_status = '<b><span style="color: red">Free Account</span></b>'; $account_status = '<b><span style="color: red">Free Account</span></b>';
else } else {
$account_status = '<b><span style="color: green">' . ($freePremium ? 'Gratis Premium Account' : 'Premium Account, ' . $account_logged->getPremDays() . ' '.$dayOrDays.' left') . '</span></b>'; $account_status = '<b><span style="color: green">' . $premiumLabel . ', ' . $premDays . ' '.$dayOrDays.' left</span></b>';
}
$recovery_key = $account_logged->getCustomField('key'); $recovery_key = $account_logged->getCustomField('key');
if(empty($recovery_key)) if(empty($recovery_key))
@@ -87,12 +96,8 @@ if($email_new_time > 1)
} }
} }
$actions = array(); $actions = $account_logged->getActionsLog(1000);
foreach($account_logged->getActionsLog(0, 1000) as $action) {
$actions[] = array('action' => $action['action'], 'date' => $action['date'], 'ip' => $action['ip'] != 0 ? long2ip($action['ip']) : inet_ntop($action['ipv6']));
}
$players = array();
/** @var OTS_Players_List $account_players */ /** @var OTS_Players_List $account_players */
$account_players = $account_logged->getPlayersList(); $account_players = $account_logged->getPlayersList();
$account_players->orderBy('id'); $account_players->orderBy('id');

View File

@@ -0,0 +1,94 @@
<?php
use MyAAC\Models\AccountEmailVerify;
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Resend Email';
$errorWithBackButton = function ($msg) use ($twig) {
$errors = [$msg];
$twig->display('error_box.html.twig', ['errors' => $errors]);
$twig->display('account.back_button.html.twig', [
'action' => getLink('account/resend-email-verify'),
]);
};
if (!setting('core.mail_enabled') || !setting('core.account_mail_verify')) {
$errorWithBackButton('Resending email is not possible on this server.');
return;
}
$showForm = true;
if (isset($_POST['submit']) && $_POST['submit'] == '1') {
$email = $_REQUEST['email'];
if (empty($email) || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errorWithBackButton('Please enter valid Email.');
return;
}
$account = new OTS_Account();
$account->findByEMail($email);
if ($account->isLoaded()) {
if ($account->getCustomField('email_verified') == '1') {
$errorWithBackButton('This account is already verified! You can <a href=' . getLink('account/manage') . '>log in</a> on the website.');
return;
}
$accountEmailVerify = AccountEmailVerify::where('account_id', $account->getId())->orderBy('sent_at', 'DESC')->first();
if ($accountEmailVerify && time() - $accountEmailVerify->sent_at < 60) {
$errorWithBackButton('Only one Email per minute is allowed. Please try again later.');
return;
}
$tmp_account = $email;
if (!config('account_login_by_email')) {
$tmp_account = (USE_ACCOUNT_NAME ? $account->getName() : $account->getId());
}
$hash = md5(generateRandomString(16, true, true) . $email);
AccountEmailVerify::create([
'account_id' => $account->getId(),
'hash' => $hash,
'sent_at' => time(),
]);
$verify_url = getLink('account/confirm-email/' . $hash);
$body_html = $twig->render('mail.account.resend-email-verify.html.twig', array(
'account' => $tmp_account,
'verify_url' => generateLink($verify_url, $verify_url, true)
));
if (_mail($account->getEMail(), configLua('serverName') . ' - Verify Account', $body_html)) {
$message = "If account with this email exists - you will become an email with verification link.";
$showForm = false;
} else {
$message = "<p class='error'>An error occurred while sending email (<b>{$email}</b> )! Try again later. For Admin: More info can be found in system/logs/mailer-error.log</p>";
}
}
else {
$message = "<br />If account with this email exists - you will become an email with verification link.";
$showForm = false;
}
$twig->display('success.html.twig', array(
'title' => 'Verify Email Sent',
'description' => $message,
));
}
//show errors if not empty
if (!empty($errors)) {
$twig->display('error_box.html.twig', ['errors' => $errors]);
$twig->display('account.back_button.html.twig', [
'action' => getLink('account/resend-email-verify'),
]);
}
if ($showForm) {
$twig->display('account.resend-email-verify.html.twig');
}

View File

@@ -202,36 +202,38 @@ if($player->isLoaded() && !$player->isDeleted())
unset($storage); unset($storage);
} }
if($db->hasTable('player_items') && $db->hasColumn('player_items', 'pid') && $db->hasColumn('player_items', 'sid') && $db->hasColumn('player_items', 'itemtype')) { if ($db->hasTableAndColumns('player_items', ['pid', 'sid', 'itemtype'])) {
$eq_sql = $db->query('SELECT `pid`, `itemtype` FROM player_items WHERE player_id = '.$player->getId().' AND (`pid` >= 1 and `pid` <= 10)'); $eq_sql = $db->query('SELECT `pid`, `itemtype` FROM player_items WHERE player_id = '.$player->getId().' AND (`pid` >= 1 and `pid` <= 10)');
$equipment = array(); $equipment = [];
foreach($eq_sql as $eq) foreach($eq_sql as $eq) {
$equipment[$eq['pid']] = $eq['itemtype']; $equipment[$eq['pid']] = $eq['itemtype'];
}
$empty_slots = array("", "no_helmet", "no_necklace", "no_backpack", "no_armor", "no_handleft", "no_handright", "no_legs", "no_boots", "no_ring", "no_ammo"); $empty_slots = ["", "no_helmet", "no_necklace", "no_backpack", "no_armor", "no_handleft", "no_handright", "no_legs", "no_boots", "no_ring", "no_ammo"];
for($i = 0; $i <= 10; $i++)
{ for($i = 0; $i <= 10; $i++) {
if(!isset($equipment[$i]) || $equipment[$i] == 0) if(!isset($equipment[$i]) || $equipment[$i] == 0)
$equipment[$i] = $empty_slots[$i]; $equipment[$i] = $empty_slots[$i];
} }
for($i = 1; $i < 11; $i++) for($i = 1; $i < 11; $i++) {
{ if(Validator::number($equipment[$i])) {
if(Validator::number($equipment[$i]))
$equipment[$i] = getItemImage($equipment[$i]); $equipment[$i] = getItemImage($equipment[$i]);
else }
else {
$equipment[$i] = '<img src="images/items/' . $equipment[$i] . '.gif" width="32" height="32" border="0" alt=" ' . $equipment[$i] . '" />'; $equipment[$i] = '<img src="images/items/' . $equipment[$i] . '.gif" width="32" height="32" border="0" alt=" ' . $equipment[$i] . '" />';
}
} }
$skulls = array(
1 => 'yellow_skull',
2 => 'green_skull',
3 => 'white_skull',
4 => 'red_skull',
5 => 'black_skull'
);
} }
$skulls = [
1 => 'yellow_skull',
2 => 'green_skull',
3 => 'white_skull',
4 => 'red_skull',
5 => 'black_skull',
];
$dead_add_content = ''; $dead_add_content = '';
$deaths = array(); $deaths = array();
if($db->hasTable('killers')) { if($db->hasTable('killers')) {

View File

@@ -21,6 +21,9 @@ if(!$logged) {
$errors[] = 'You are not logged in. You can\'t create guild.'; $errors[] = 'You are not logged in. You can\'t create guild.';
} }
$configLuaFreePremium = configLua('freePremium');
$freePremium = (isset($configLuaFreePremium) && getBoolean($configLuaFreePremium)) || ($logged && $account_logged->getPremDays() == OTS_Account::GRATIS_PREMIUM_DAYS);
$array_of_player_nig = array(); $array_of_player_nig = array();
if(empty($errors)) if(empty($errors))
{ {
@@ -31,7 +34,7 @@ if(empty($errors))
if(!$player_rank->isLoaded()) if(!$player_rank->isLoaded())
{ {
if($player->getLevel() >= setting('core.guild_need_level')) { if($player->getLevel() >= setting('core.guild_need_level')) {
if(!setting('core.guild_need_premium') || $account_logged->isPremium()) { if(!setting('core.guild_need_premium') || $account_logged->isPremium() || $freePremium) {
$array_of_player_nig[] = $player->getName(); $array_of_player_nig[] = $player->getName();
} }
} }
@@ -95,7 +98,7 @@ if($todo == 'save')
if($player->getLevel() < setting('core.guild_need_level')) { if($player->getLevel() < setting('core.guild_need_level')) {
$errors[] = 'Character <b>'.$name.'</b> has too low level. To create guild you need character with level <b>' . setting('core.guild_need_level') . '</b>.'; $errors[] = 'Character <b>'.$name.'</b> has too low level. To create guild you need character with level <b>' . setting('core.guild_need_level') . '</b>.';
} }
if(setting('core.guild_need_premium') && !$account_logged->isPremium()) { if(setting('core.guild_need_premium') && !$account_logged->isPremium() && !$freePremium) {
$errors[] = 'Character <b>'.$name.'</b> is on FREE account. To create guild you need PREMIUM account.'; $errors[] = 'Character <b>'.$name.'</b> is on FREE account. To create guild you need PREMIUM account.';
} }
} }

View File

@@ -122,7 +122,7 @@ if(!$news_cached)
); );
} }
$tickers_db = $db->query('SELECT * FROM `' . TABLE_PREFIX . 'news` WHERE `type` = ' . TICKER .($canEdit ? '' : ' AND `hide` != 1') .' ORDER BY `date` DESC LIMIT ' . setting('core.news_ticker_limit')); $tickers_db = $db->query('SELECT * FROM `' . TABLE_PREFIX . 'news` WHERE `type` = ' . TICKER . ' AND `hide` != 1 ORDER BY `date` DESC LIMIT ' . setting('core.news_ticker_limit'));
$tickers_content = ''; $tickers_content = '';
if($tickers_db->rowCount() > 0) if($tickers_db->rowCount() > 0)
{ {
@@ -142,7 +142,8 @@ if(!$news_cached)
if($cache->enabled() && !$canEdit) if($cache->enabled() && !$canEdit)
$cache->set('news_' . $template_name . '_' . TICKER, $tickers_content, 60 * 60); $cache->set('news_' . $template_name . '_' . TICKER, $tickers_content, 60 * 60);
$featured_article_db =$db->query('SELECT `id`, `title`, `article_text`, `article_image`, `hide` FROM `' . TABLE_PREFIX . 'news` WHERE `type` = ' . ARTICLE . ($canEdit ? '' : ' AND `hide` != 1') .' ORDER BY `date` DESC LIMIT 1'); $featured_article_db =$db->query('SELECT `id`, `title`, `article_text`, `article_image`, `hide` FROM `' . TABLE_PREFIX . 'news` WHERE `type` = ' . ARTICLE . ' AND `hide` != 1 ORDER BY `date` DESC LIMIT 1');
$article = ''; $article = '';
if($featured_article_db->rowCount() > 0) { if($featured_article_db->rowCount() > 0) {
$article = $featured_article_db->fetch(); $article = $featured_article_db->fetch();
@@ -175,7 +176,7 @@ else {
if(!$news_cached) if(!$news_cached)
{ {
ob_start(); ob_start();
$newses = $db->query('SELECT * FROM ' . $db->tableName(TABLE_PREFIX . 'news') . ' WHERE type = ' . NEWS . ($canEdit ? '' : ' AND hide != 1') . ' ORDER BY date' . ' DESC LIMIT ' . setting('core.news_limit')); $newses = $db->query('SELECT * FROM ' . $db->tableName(TABLE_PREFIX . 'news') . ' WHERE type = ' . NEWS . ' AND hide != 1 ORDER BY date' . ' DESC LIMIT ' . setting('core.news_limit'));
if($newses->rowCount() > 0) if($newses->rowCount() > 0)
{ {
foreach($newses as $news) foreach($newses as $news)

View File

@@ -88,8 +88,10 @@ if($logged && $account_logged && $account_logged->isLoaded()) {
/** /**
* Routes loading * Routes loading
*/ */
$routesFinal = [];
$dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r) { $dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r) {
$routesFinal = []; global $cache, $routesFinal;
foreach(getDatabasePages() as $page) { foreach(getDatabasePages() as $page) {
$routesFinal[] = ['*', $page, '__database__/' . $page, 100]; $routesFinal[] = ['*', $page, '__database__/' . $page, 100];
} }
@@ -165,7 +167,7 @@ $dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r)
echo '</pre>'; echo '</pre>';
die; die;
*/ */
foreach ($routesFinal as $route) { foreach ($routesFinal as &$route) {
if ($route[0] === '*') { if ($route[0] === '*') {
$route[0] = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD']; $route[0] = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD'];
} }
@@ -198,6 +200,10 @@ $dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r)
log_append('router.log', $warning); log_append('router.log', $warning);
} }
} }
if ($cache->enabled()) {
$cache->set('routes_final', serialize($routesFinal), 10 * 365 * 24 * 60 * 60); // 10 years / infinite
}
}, },
[ [
'cacheFile' => CACHE . 'route.cache', 'cacheFile' => CACHE . 'route.cache',
@@ -212,7 +218,7 @@ $found = true;
// old support for pages like /?subtopic=accountmanagement // old support for pages like /?subtopic=accountmanagement
$page = $_REQUEST['p'] ?? ($_REQUEST['subtopic'] ?? ''); $page = $_REQUEST['p'] ?? ($_REQUEST['subtopic'] ?? '');
if(!empty($page) && preg_match('/^[A-z0-9\-]+$/', $page)) { if(!empty($page) && preg_match('/^[A-z0-9\/\-]+$/', $page)) {
if (isset($_REQUEST['p'])) { // some plugins may require this if (isset($_REQUEST['p'])) { // some plugins may require this
$_REQUEST['subtopic'] = $_REQUEST['p']; $_REQUEST['subtopic'] = $_REQUEST['p'];
} }
@@ -221,9 +227,26 @@ if(!empty($page) && preg_match('/^[A-z0-9\-]+$/', $page)) {
require SYSTEM . 'compat/pages.php'; require SYSTEM . 'compat/pages.php';
} }
$file = loadPageFromFileSystem($page, $found); $foundRoute = false;
if(!$found) {
$file = false; $tmp = null;
if ($cache->enabled() && $cache->fetch('routes_final', $tmp)) {
$routesFinal = unserialize($tmp);
}
foreach ($routesFinal as $route) {
if ($page === $route[1]) {
$file = $route[2];
$foundRoute = true;
break;
}
}
if (!$foundRoute) {
$file = loadPageFromFileSystem($page, $found);
if(!$found) {
$file = false;
}
} }
} }
else { else {

View File

@@ -737,6 +737,18 @@ Sent by MyAAC,<br/>
'desc' => 'should country of user be automatically recognized by his IP? This makes an external API call to http://ipinfo.io', 'desc' => 'should country of user be automatically recognized by his IP? This makes an external API call to http://ipinfo.io',
'default' => true, 'default' => true,
], ],
'account_countries_most_popular' => [
'name' => 'Account Countries Most Popular',
'type' => 'text',
'desc' => 'Those countries will be display at the top of the list on the create account page. The short codes of countries can be found in file <i>system/countries.conf.php</i>',
'default' => 'pl,se,br,us,gb',
'callbacks' => [
'get' => function ($value) {
$tmp = array_map('trim', explode(',', $value));
return array_filter($tmp, function ($v) {return !empty($v); });
},
],
],
'characters_per_account' => [ 'characters_per_account' => [
'name' => 'Characters per Account', 'name' => 'Characters per Account',
'type' => 'number', 'type' => 'number',

View File

@@ -115,6 +115,11 @@ class Cache
return unserialize($value); return unserialize($value);
} }
// -1 for infinite cache
if ($ttl == -1) {
$ttl = 10 * 365 * 24 * 60 * 60; // 10 years should be enough
}
$value = $callback(); $value = $callback();
$cache->set($key, serialize($value), $ttl); $cache->set($key, serialize($value), $ttl);
return $value; return $value;

View File

@@ -27,6 +27,9 @@ class PHP
{ {
$var = var_export($var, true); $var = var_export($var, true);
ensureFolderExists($this->dir);
ensureIndexExists($this->dir);
// Write to temp file first to ensure atomicity // Write to temp file first to ensure atomicity
$tmp = $this->dir . "tmp_$key." . uniqid('', true) . '.tmp'; $tmp = $this->dir . "tmp_$key." . uniqid('', true) . '.tmp';
file_put_contents($tmp, '<?php $var = ' . $var . ';', LOCK_EX); file_put_contents($tmp, '<?php $var = ' . $var . ';', LOCK_EX);

View 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';
}
}

View File

@@ -9,6 +9,8 @@ use Symfony\Component\Console\Style\SymfonyStyle;
class MigrateCommand extends Command class MigrateCommand extends Command
{ {
use Env;
protected function configure(): void protected function configure(): void
{ {
$this->setName('migrate') $this->setName('migrate')
@@ -17,9 +19,19 @@ class MigrateCommand extends Command
protected function execute(InputInterface $input, OutputInterface $output): int protected function execute(InputInterface $input, OutputInterface $output): int
{ {
require SYSTEM . 'init.php'; $this->init();
$io = new SymfonyStyle($input, $output); $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'; require SYSTEM . 'migrate.php';
$io->success('Migrated to latest version (' . DATABASE_VERSION . ')'); $io->success('Migrated to latest version (' . DATABASE_VERSION . ')');

View File

@@ -10,6 +10,8 @@ use Symfony\Component\Console\Style\SymfonyStyle;
class MigrateRunCommand extends Command class MigrateRunCommand extends Command
{ {
use Env;
protected function configure(): void protected function configure(): void
{ {
$this->setName('migrate:run') $this->setName('migrate:run')
@@ -23,12 +25,12 @@ class MigrateRunCommand extends Command
protected function execute(InputInterface $input, OutputInterface $output): int protected function execute(InputInterface $input, OutputInterface $output): int
{ {
require SYSTEM . 'init.php';
$io = new SymfonyStyle($input, $output); $io = new SymfonyStyle($input, $output);
$ids = $input->getArgument('id'); $ids = $input->getArgument('id');
$this->init();
// pre-check // pre-check
// in case one of the migrations doesn't exist - we won't execute any of them // in case one of the migrations doesn't exist - we won't execute any of them
foreach ($ids as $id) { foreach ($ids as $id) {

View File

@@ -11,6 +11,8 @@ use Symfony\Component\Console\Style\SymfonyStyle;
class MigrateToCommand extends Command class MigrateToCommand extends Command
{ {
use Env;
protected function configure(): void protected function configure(): void
{ {
$this->setName('migrate:to') $this->setName('migrate:to')
@@ -32,7 +34,7 @@ class MigrateToCommand extends Command
return Command::FAILURE; return Command::FAILURE;
} }
$this->initEnv(); $this->init();
$currentVersion = Config::where('name', 'database_version')->first()->value; $currentVersion = Config::where('name', 'database_version')->first()->value;
if ($currentVersion > $versionDest) { if ($currentVersion > $versionDest) {
@@ -80,29 +82,4 @@ class MigrateToCommand extends Command
updateDatabaseConfig('database_version', ($_up ? $id : $id - 1)); 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';
}
} }

View File

@@ -13,6 +13,7 @@ class PluginDisableCommand extends Command
protected function configure(): void protected function configure(): void
{ {
$this->setName('plugin:disable') $this->setName('plugin:disable')
->setAliases(['plugin:deactivate'])
->setDescription('This command disables plugin') ->setDescription('This command disables plugin')
->addArgument('plugin-name', InputArgument::REQUIRED, 'Plugin that you want to disable'); ->addArgument('plugin-name', InputArgument::REQUIRED, 'Plugin that you want to disable');
} }

View File

@@ -13,6 +13,7 @@ class PluginEnableCommand extends Command
protected function configure(): void protected function configure(): void
{ {
$this->setName('plugin:enable') $this->setName('plugin:enable')
->setAliases(['plugin:activate'])
->setDescription('This command enables plugin') ->setDescription('This command enables plugin')
->addArgument('plugin-name', InputArgument::REQUIRED, 'Plugin that you want to enable'); ->addArgument('plugin-name', InputArgument::REQUIRED, 'Plugin that you want to enable');
} }

View File

@@ -13,6 +13,7 @@ class PluginUninstallCommand extends Command
protected function configure(): void protected function configure(): void
{ {
$this->setName('plugin:uninstall') $this->setName('plugin:uninstall')
->setAliases(['plugin:remove', 'plugin:delete'])
->setDescription('This command uninstalls plugin') ->setDescription('This command uninstalls plugin')
->addArgument('plugin-name', InputArgument::REQUIRED, 'Plugin that you want to uninstall'); ->addArgument('plugin-name', InputArgument::REQUIRED, 'Plugin that you want to uninstall');
} }

View File

@@ -76,10 +76,11 @@ class Items
public static function get($id) { public static function get($id) {
self::load(); 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); $item = self::get($id);
$attr = $item['attributes']; $attr = $item['attributes'];
@@ -112,15 +113,15 @@ class Items
$s .= 'an item of type ' . $item['id']; $s .= 'an item of type ' . $item['id'];
if(isset($attr['type']) && strtolower($attr['type']) == 'rune') { if(isset($attr['type']) && strtolower($attr['type']) == 'rune') {
$item = Spell::where('item_id', $id)->first(); $spell = Spell::where('item_id', $id)->first();
if($item) { if($spell) {
if($item->level > 0 && $item->maglevel > 0) { if($spell->level > 0 && $spell->maglevel > 0) {
$s .= '. ' . ($count > 1 ? "They" : "It") . ' can only be used by '; $s .= '. ' . ($count > 1 ? 'They' : 'It') . ' can only be used by ';
} }
$configVocations = config('vocations'); $configVocations = config('vocations');
if(!empty(trim($item->vocations))) { if(!empty(trim($spell->vocations))) {
$vocations = json_decode($item->vocations); $vocations = json_decode($spell->vocations);
if(count($vocations) > 0) { if(count($vocations) > 0) {
foreach($vocations as $voc => $show) { foreach($vocations as $voc => $show) {
$vocations[$configVocations[$voc]] = $show; $vocations[$configVocations[$voc]] = $show;
@@ -133,8 +134,39 @@ class Items
$s .= ' with'; $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; return $s;
} }
} }

View File

@@ -5,11 +5,15 @@ namespace MyAAC\Models;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
/** /**
* @property integer $premium_ends_at
* @property integer $premend
* @property integer $lastday * @property integer $lastday
* @property integer $premdays * @property integer $premdays
*/ */
class Account extends Model { class Account extends Model {
const GRATIS_PREMIUM_DAYS = 65535;
protected $table = 'accounts'; protected $table = 'accounts';
public $timestamps = false; public $timestamps = false;
@@ -33,32 +37,35 @@ class Account extends Model {
public function getPremiumDaysAttribute() public function getPremiumDaysAttribute()
{ {
if(isset($this->premium_ends_at) || isset($this->premend)) { if(isset($this->premium_ends_at) || isset($this->premend) ||
$col = isset($this->premium_ends_at) ? 'premium_ends_at' : 'premend'; (isCanary() && isset($this->lastday))) {
$ret = ceil(($this->{$col}- time()) / (24 * 60 * 60)); $col = (isset($this->premium_ends_at) ? 'premium_ends_at' : (isset($this->lastday) ? 'lastday' : 'premend'));
return $ret > 0 ? $ret : 0; $ret = ceil(($this->{$col} - time()) / (24 * 60 * 60));
return max($ret, 0);
} }
if($this->premdays == 0) { if($this->premdays == 0) {
return 0; return 0;
} }
if($this->premdays == 65535){ if($this->premdays == self::GRATIS_PREMIUM_DAYS){
return 65535; 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))); $ret = ceil($this->premdays - ((int)date("z", time()) + (365 * (date("Y", time()) - date("Y", $this->lastday))) - date("z", $this->lastday)));
return max($ret, 0); return max($ret, 0);
} }
public function getIsPremiumAttribute() public function getIsPremiumAttribute(): bool
{ {
if(isset($this->premium_ends_at)) { if(isset($this->premium_ends_at) || isset($this->premend) ||
return $this->premium_ends_at > time(); (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)) { if($this->premdays == self::GRATIS_PREMIUM_DAYS){
return $this->premend > time(); return true;
} }
return ($this->premdays - (date("z", time()) + (365 * (date("Y", time()) - date("Y", $this->lastday))) - date("z", $this->lastday)) > 0); return ($this->premdays - (date("z", time()) + (365 * (date("Y", time()) - date("Y", $this->lastday))) - date("z", $this->lastday)) > 0);

View File

@@ -9,6 +9,6 @@ class AccountAction extends Model {
public $timestamps = false; public $timestamps = false;
protected $fillable = ['account_id', 'ip', 'ipv6', 'date', 'action']; protected $fillable = ['account_id', 'ip', 'date', 'action'];
} }

View 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'];
}

View File

@@ -18,7 +18,16 @@ class Changelog extends Model {
public $timestamps = false; public $timestamps = false;
protected $fillable = [
'body', 'type', 'where',
'date', 'player_id', 'hide',
];
public function scopeIsPublic($query) { public function scopeIsPublic($query) {
$query->where('hide', '!=', 1); $query->where('hide', '!=', 1);
} }
public function player() {
return $this->belongsTo(Player::class);
}
} }

View 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',
];
}

View File

@@ -10,4 +10,9 @@ class Gallery extends Model {
public $timestamps = false; public $timestamps = false;
protected $fillable = [
'comment', 'image', 'thumb',
'author', 'ordering', 'hide',
];
} }

View 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'
];
}

View File

@@ -23,6 +23,8 @@ class Player extends Model {
public $timestamps = false; public $timestamps = false;
protected $guarded = [];
protected $casts = [ protected $casts = [
'worldid' => 'integer', 'worldid' => 'integer',
'sex' => 'integer', 'sex' => 'integer',

View File

@@ -513,6 +513,9 @@ class Plugins {
return false; return false;
} }
ensureFolderExists($cachePlugins = CACHE . 'plugins');
ensureIndexExists($cachePlugins);
self::$error = 'There was a problem with extracting zip archive.'; self::$error = 'There was a problem with extracting zip archive.';
$file_name = $plugin_temp_dir . $json_file; $file_name = $plugin_temp_dir . $json_file;
if(!file_exists($file_name)) { if(!file_exists($file_name)) {
@@ -549,21 +552,21 @@ class Plugins {
if(isset($plugin_json['require'])) { if(isset($plugin_json['require'])) {
$require = $plugin_json['require']; $require = $plugin_json['require'];
$myaac_satified = true; $myaac_satisfied = true;
if(isset($require['myaac_'])) { if(isset($require['myaac_'])) {
$require_myaac = $require['myaac_']; $require_myaac = $require['myaac_'];
if(!Semver::satisfies(MYAAC_VERSION, $require_myaac)) { if(!Semver::satisfies(MYAAC_VERSION, $require_myaac)) {
$myaac_satified = false; $myaac_satisfied = false;
} }
} }
else if(isset($require['myaac'])) { else if(isset($require['myaac'])) {
$require_myaac = $require['myaac']; $require_myaac = $require['myaac'];
if(version_compare(MYAAC_VERSION, $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 . "."; self::$error = "Your AAC version doesn't meet the requirement of this plugin. Required version is: " . $require_myaac . ", and you're using version " . MYAAC_VERSION . ".";
return false; return false;
} }

View File

@@ -248,7 +248,7 @@ class Settings implements \ArrayAccess
echo '<div class="input-group" id="show-hide-' . $key . '">'; 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') { 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>'; 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) { if ($rows < 2) {
$rows = 2; // always min 2 rows for textarea $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') { else if ($setting['type'] === 'options') {

View File

@@ -28,6 +28,8 @@ define('HOOK_CHARACTERS_AFTER_CHARACTERS', ++$i);
define('HOOK_LOGIN', ++$i); define('HOOK_LOGIN', ++$i);
define('HOOK_LOGIN_ATTEMPT', ++$i); define('HOOK_LOGIN_ATTEMPT', ++$i);
define('HOOK_LOGOUT', ++$i); define('HOOK_LOGOUT', ++$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_CHANGE_PASSWORD_POST', ++$i);
define('HOOK_ACCOUNT_CREATE_BEFORE_FORM', ++$i); define('HOOK_ACCOUNT_CREATE_BEFORE_FORM', ++$i);
define('HOOK_ACCOUNT_CREATE_BEFORE_BOXES', ++$i); define('HOOK_ACCOUNT_CREATE_BEFORE_BOXES', ++$i);

View File

@@ -145,13 +145,7 @@ function updateStatus() {
} }
$uptime = $status['uptime'] = $serverStatus->getUptime(); $uptime = $status['uptime'] = $serverStatus->getUptime();
$m = date('m', $uptime); $status['uptimeReadable'] = getStatusUptimeReadable($uptime);
$m = $m > 1 ? "$m months, " : ($m == 1 ? 'month, ' : '');
$d = date('d', $uptime);
$d = $d > 1 ? "$d days, " : ($d == 1 ? 'day, ' : '');
$h = date('H', $uptime);
$min = date('i', $uptime);
$status['uptimeReadable'] = "{$m}{$d}{$h}h {$min}m";
$status['monsters'] = $serverStatus->getMonstersCount(); $status['monsters'] = $serverStatus->getMonstersCount();
$status['motd'] = $serverStatus->getMOTD(); $status['motd'] = $serverStatus->getMOTD();

View File

@@ -9,23 +9,29 @@ Please enter your current password and a new password. For your security, please
<span>Current Password:</span> <span>Current Password:</span>
</td> </td>
<td> <td>
<input form="form" type="password" name="oldpassword" size="30" maxlength="29"> <input form="form" type="password" id="old_password" name="old_password" size="30" maxlength="29">
</td> </td>
</tr> </tr>
{{ hook('HOOK_ACCOUNT_CHANGE_PASSWORD_AFTER_OLD_PASSWORD') }}
<tr> <tr>
<td class="LabelV"> <td class="LabelV">
<span>New Password:</span> <span>New Password:</span>
</td> </td>
<td style="width:90%;"> <td style="width:90%;">
<input form="form" type="password" name="newpassword" size="30" maxlength="29"> <input form="form" type="password" id="new_password" name="new_password" size="30" maxlength="29">
</td> </td>
</tr> </tr>
{{ hook('HOOK_ACCOUNT_CHANGE_PASSWORD_AFTER_NEW_PASSWORD') }}
<tr> <tr>
<td class="LabelV"> <td class="LabelV">
<span>New Password Again:</span> <span>New Password Again:</span>
</td> </td>
<td> <td>
<input form="form" type="password" name="newpassword_confirm" size="30" maxlength="29"> <input form="form" type="password" id="new_password_confirm" name="new_password_confirm" size="30" maxlength="29">
</td> </td>
</tr> </tr>
</table> </table>

View File

@@ -0,0 +1,45 @@
Please enter your account Email address.<br/><br/>
{% set title = 'Resend Email' %}
{% set background = config('darkborder') %}
{% set content %}
<table style="width:100%;">
<tr>
<td class="LabelV" >
<span><label for="email">Email Address:</label></span>
</td>
<td style="width:90%;">
<input type="email" form="form" id="email" name="email" size="30" maxlength="50" autofocus/>
</td>
</tr>
</table>
{% endset %}
{% include 'tables.headline.html.twig' %}
<br/>
<table style="width:100%;">
<tr align="center">
<td>
<table border="0" cellspacing="0" cellpadding="0">
<tr>
<td style="border:0;">
<form id="form" action="{{ getLink('account/resend-email-verify') }}" method="post">
{{ csrf() }}
<input type="hidden" name="submit" value="1"/>
{{ include('buttons.submit.html.twig') }}
</form>
</td>
<tr>
</table>
</td>
<td>
<table border="0" cellspacing="0" cellpadding="0">
<tr>
<td style="border:0;">
<form action="{{ getLink('news') }}" method="post">
{{ include('buttons.back.html.twig') }}
</form>
</td>
</tr>
</table>
</td>
</tr>
</table>

View File

@@ -9,7 +9,7 @@
<table border="0" cellpadding="0" cellspacing="0" width="100%"><tr> <table border="0" cellpadding="0" cellspacing="0" width="100%"><tr>
<td><img src="{{ template_path }}/images/general/blank.gif" width="10" height="1" border="0"></td> <td><img src="{{ template_path }}/images/general/blank.gif" width="10" height="1" border="0"></td>
<td> <td>
{{ hook(constant('HOOK_CHARACTERS_BEFORE_INFORMATIONS')) }} {{ hook('HOOK_CHARACTERS_BEFORE_INFORMATIONS') }}
{% if canEdit %} {% if canEdit %}
<a href="{{ constant('ADMIN_URL') }}?p=players&id={{ player.getId() }}" title="Edit in Admin Panel" target="_blank"> <a href="{{ constant('ADMIN_URL') }}?p=players&id={{ player.getId() }}" title="Edit in Admin Panel" target="_blank">
<img src="images/edit.png"/>Edit <img src="images/edit.png"/>Edit
@@ -153,11 +153,11 @@
<td>{% if account.isPremium() %}Premium Account{% else %}Free Account{% endif %}</td> <td>{% if account.isPremium() %}Premium Account{% else %}Free Account{% endif %}</td>
</tr> </tr>
</table> </table>
{{ hook(constant('HOOK_CHARACTERS_AFTER_INFORMATIONS')) }} {{ hook('HOOK_CHARACTERS_AFTER_INFORMATIONS') }}
<br/> <br/>
<table border="0" width="100%"> <table border="0" width="100%">
<tr> <tr>
{{ hook(constant('HOOK_CHARACTERS_BEFORE_SKILLS')) }} {{ hook('HOOK_CHARACTERS_BEFORE_SKILLS') }}
{% if config.characters.skills %} {% if config.characters.skills %}
<!-- SKILLS --> <!-- SKILLS -->
@@ -179,7 +179,7 @@
<!-- SKILLS_END --> <!-- SKILLS_END -->
{% endif %} {% endif %}
{{ hook(constant('HOOK_CHARACTERS_AFTER_SKILLS')) }} {{ hook('HOOK_CHARACTERS_AFTER_SKILLS') }}
{% if quests_enabled %} {% if quests_enabled %}
<!-- QUESTS --> <!-- QUESTS -->
@@ -201,7 +201,7 @@
<!-- QUESTS_END --> <!-- QUESTS_END -->
{% endif %} {% endif %}
{{ hook(constant('HOOK_CHARACTERS_AFTER_QUESTS')) }} {{ hook('HOOK_CHARACTERS_AFTER_QUESTS') }}
{% if config.characters.equipment %} {% if config.characters.equipment %}
<!-- EQUIPMENT --> <!-- EQUIPMENT -->
@@ -239,11 +239,11 @@
<!-- EQUIPMENT_END --> <!-- EQUIPMENT_END -->
{% endif %} {% endif %}
{{ hook(constant('HOOK_CHARACTERS_AFTER_EQUIPMENT')) }} {{ hook('HOOK_CHARACTERS_AFTER_EQUIPMENT') }}
</tr> </tr>
</table> </table>
{{ hook(constant('HOOK_CHARACTERS_BEFORE_DEATHS')) }} {{ hook('HOOK_CHARACTERS_BEFORE_DEATHS') }}
{% if deaths|length > 0 %} {% if deaths|length > 0 %}
<!-- DEATHS --> <!-- DEATHS -->
@@ -283,7 +283,7 @@
<!-- FRAGS_END --> <!-- FRAGS_END -->
{% endif %} {% endif %}
{{ hook(constant('HOOK_CHARACTERS_BEFORE_SIGNATURE')) }} {{ hook('HOOK_CHARACTERS_BEFORE_SIGNATURE') }}
{% if setting('core.signature_enabled') %} {% if setting('core.signature_enabled') %}
<!-- SIGNATURE --> <!-- SIGNATURE -->
@@ -327,7 +327,7 @@
</table> </table>
<!-- SIGNATURE_END --> <!-- SIGNATURE_END -->
{% endif %} {% endif %}
{{ hook(constant('HOOK_CHARACTERS_AFTER_SIGNATURE')) }} {{ hook('HOOK_CHARACTERS_AFTER_SIGNATURE') }}
{% if not player.isHidden() %} {% if not player.isHidden() %}
{% set rows = 0 %} {% set rows = 0 %}
<!-- ACCOUNT_INFORMATION --> <!-- ACCOUNT_INFORMATION -->
@@ -377,7 +377,7 @@
</tr> </tr>
</table> </table>
<!-- ACCOUNT_INFORMATION_END --> <!-- ACCOUNT_INFORMATION_END -->
{{ hook(constant('HOOK_CHARACTERS_AFTER_ACCOUNT')) }} {{ hook('HOOK_CHARACTERS_AFTER_ACCOUNT') }}
<!-- CHARACTERS_LIST --> <!-- CHARACTERS_LIST -->
<br/><br/> <br/><br/>
<table border="0" cellspacing="1" cellpadding="4" width="100%"> <table border="0" cellspacing="1" cellpadding="4" width="100%">
@@ -421,7 +421,7 @@
</table> </table>
<!-- CHARACTERS_LIST_END --> <!-- CHARACTERS_LIST_END -->
{% endif %} {% endif %}
{{ hook(constant('HOOK_CHARACTERS_AFTER_CHARACTERS')) }} {{ hook('HOOK_CHARACTERS_AFTER_CHARACTERS') }}
{% if canEdit %} {% if canEdit %}
<a href="{{ constant('ADMIN_URL') }}?p=players&id={{ player.getId() }}" title="Edit in Admin Panel" target="_blank"> <a href="{{ constant('ADMIN_URL') }}?p=players&id={{ player.getId() }}" title="Edit in Admin Panel" target="_blank">
<img src="images/edit.png"/>Edit <img src="images/edit.png"/>Edit

View File

@@ -9,7 +9,7 @@
<div class="AttentionSign" style="background-image:url({{ template_path }}/images/content/attentionsign.gif);"></div> <div class="AttentionSign" style="background-image:url({{ template_path }}/images/content/attentionsign.gif);"></div>
<b>The Following Errors Have Occurred:</b><br/> <b>The Following Errors Have Occurred:</b><br/>
{% for error in errors %} {% for error in errors %}
<li>{{ error|striptags('<b>')|raw }}</li> <li>{{ error|striptags('<b><a>')|raw }}</li>
{% endfor %} {% endfor %}
</div> </div>
<div class="BoxFrameHorizontal" style="background-image:url({{ template_path }}/images/content/box-frame-horizontal.gif);"></div> <div class="BoxFrameHorizontal" style="background-image:url({{ template_path }}/images/content/box-frame-horizontal.gif);"></div>

View File

@@ -0,0 +1,7 @@
Hello {{ account }}!<br/>
<br/>
You requested to resend the verify Email on {{ config.lua.serverName }}!<br/>
<br/>
To verify your email address please click the link below:<br/>
{{ verify_url|raw }}

View File

@@ -101,7 +101,7 @@
<tr> <tr>
<td class="LabelV150"><b>Location Datacenter:</b></td> <td class="LabelV150"><b>Location Datacenter:</b></td>
<td>{{ setting('core.online_datacenter') }} <small>(Server date & time: - {{ "now"|date("d/m/Y H:i:s") }})</small></td> <td>{{ setting('core.online_datacenter')|raw }} <small>(Server date & time: - {{ "now"|date("d/m/Y H:i:s") }})</small></td>
</tr> </tr>
<tr> <tr>
<td class="LabelV150"><b>PvP Type:</b></td> <td class="LabelV150"><b>PvP Type:</b></td>

View File

@@ -101,6 +101,10 @@ $twig->addFunction($function);
$function = new TwigFunction('hook', function ($context, $hook, array $params = []) { $function = new TwigFunction('hook', function ($context, $hook, array $params = []) {
global $hooks; global $hooks;
if (config('hooks_debug')) {
note($hook);
}
if(is_string($hook)) { if(is_string($hook)) {
if (defined($hook)) { if (defined($hook)) {
$hook = constant($hook); $hook = constant($hook);

View File

@@ -27,26 +27,18 @@ if(isset($config['boxes']))
var loginStatus="<?php echo ($logged ? 'true' : 'false'); ?>"; var loginStatus="<?php echo ($logged ? 'true' : 'false'); ?>";
<?php <?php
if(PAGE !== 'news') { if(PAGE !== 'news') {
if(isset($_REQUEST['subtopic'])) { $tmp = str_replace('/', '_', isset($_REQUEST['subtopic']) ? escapeHtml($_REQUEST['subtopic']) : PAGE);
$tmp = escapeHtml($_REQUEST['subtopic']); $exp = explode('/', PAGE);
if($tmp === 'accountmanagement') { if(PAGE !== 'account/create' && PAGE !== 'account/lost' && isset($exp[1])) {
$tmp = 'accountmanage'; if ($exp[0] === 'account' && $exp[1] === 'lost') {
$tmp = 'account_lost';
} elseif ($exp[0] === 'account') {
$tmp = 'account_manage';
} else if ($exp[0] === 'news' && $exp[1] === 'archive') {
$tmp = 'news_archive';
} }
} else if (in_array($exp[0], ['characters', 'highscores', 'guilds', 'forum'])) {
else { $tmp = $exp[0];
$tmp = str_replace('/', '_', PAGE);
$exp = explode('/', PAGE);
if(PAGE !== 'account/create' && PAGE !== 'account/lost' && isset($exp[1])) {
if ($exp[0] === 'account' && $exp[1] === 'lost') {
$tmp = 'account_lost';
} elseif ($exp[0] === 'account') {
$tmp = 'account_manage';
} else if ($exp[0] === 'news' && $exp[1] === 'archive') {
$tmp = 'news_archive';
}
else if (in_array($exp[0], ['characters', 'highscores', 'guilds', 'forum'])) {
$tmp = $exp[0];
}
} }
} }
} }

View File

@@ -9,6 +9,8 @@
* @link https://my-aac.org * @link https://my-aac.org
*/ */
const IGNORE_SET_LAST_VISIT = true;
// we need some functions // we need some functions
require '../common.php'; require '../common.php';
require SYSTEM . 'functions.php'; require SYSTEM . 'functions.php';

View File

@@ -53,6 +53,9 @@
exit; exit;
} }
ensureFolderExists(SIGNATURES_CACHE);
ensureIndexExists(SIGNATURES_CACHE);
$cached = SIGNATURES_CACHE.$player->getId() . '.png'; $cached = SIGNATURES_CACHE.$player->getId() . '.png';
if(file_exists($cached) && (time() < (filemtime($cached) + (60 * setting('core.signature_cache_time'))))) if(file_exists($cached) && (time() < (filemtime($cached) + (60 * setting('core.signature_cache_time')))))
{ {

View File

@@ -1,4 +1,7 @@
<?php <?php
const IGNORE_SET_LAST_VISIT = true;
require '../common.php'; require '../common.php';
require SYSTEM . 'init.php'; require SYSTEM . 'init.php';
require SYSTEM . 'functions.php'; require SYSTEM . 'functions.php';

View File

@@ -12,6 +12,8 @@
use MyAAC\CreateCharacter; use MyAAC\CreateCharacter;
use MyAAC\Models\Account; use MyAAC\Models\Account;
const IGNORE_SET_LAST_VISIT = true;
// we need some functions // we need some functions
require '../common.php'; require '../common.php';
require SYSTEM . 'functions.php'; require SYSTEM . 'functions.php';