diff --git a/GameEngine/Account.php b/GameEngine/Account.php index 3e66f78b..79099dd0 100755 --- a/GameEngine/Account.php +++ b/GameEngine/Account.php @@ -17,264 +17,384 @@ use App\Entity\User; ## ## ################################################################################# +/* +========================================================= += AUTOLOADER DISCOVERY +========================================================= +*/ + global $autoprefix; -// go max 5 levels up - we don't have folders that go deeper than that $autoprefix = ''; + for ($i = 0; $i < 5; $i++) { + $autoprefix = str_repeat('../', $i); - if (file_exists($autoprefix.'autoloader.php')) { - // we have our path, let's leave + + if (file_exists($autoprefix . 'autoloader.php')) { break; } } -include_once($autoprefix."GameEngine/Session.php"); +include_once($autoprefix . "GameEngine/Session.php"); -class Account { - function __construct() { - global $session; - if(isset($_POST['ft'])) { - switch($_POST['ft']) { - case "a1": - $this->Signup(); - break; - case "a2": - $this->Activate(); - break; - case "a3": - $this->Unreg(); - break; - case "a4": - $this->Login(); - break; - } - } if(isset($_GET['code'])) { - $_POST['id'] = $_GET['code']; $this->Activate(); - } - else { - if($session->logged_in && in_array("logout.php",explode("/",$_SERVER['PHP_SELF']))) { - $this->Logout(); - } - } - } +/* +========================================================= += ACCOUNT CLASS +========================================================= +*/ - private function Signup() { - global $database,$form,$mailer,$generator,$session; - if(!isset($_POST['name']) || trim($_POST['name']) == "") { - $form->addError("name",USRNM_EMPTY); - } - else { - if(strlen($_POST['name']) < USRNM_MIN_LENGTH) { - $form->addError("name",USRNM_SHORT); - } - else if(!USRNM_SPECIAL && preg_match('/[^0-9A-Za-z]/',$_POST['name'])) { - $form->addError("name",USRNM_CHAR); - } - else if(USRNM_SPECIAL && preg_match("/[:,\\. \\n\\r\\t\\s\\<\\>]+/", $_POST['name'])) { - $form->addError("name",USRNM_CHAR); - } - else if(strtolower($_POST['name']) == 'natars') { - $form->addError("name",USRNM_TAKEN); +class Account +{ + /* + ===================================================== + = CONSTRUCTOR / REQUEST ROUTER + ===================================================== + */ + + public function __construct() + { + global $session; + + if (isset($_POST['ft'])) { + + switch ($_POST['ft']) { + + case "a1": + $this->Signup(); + break; + + case "a2": + $this->Activate(); + break; + + case "a3": + $this->Unreg(); + break; + + case "a4": + $this->Login(); + break; } - else if(User::exists($database,$_POST['name'])) { - $form->addError("name",USRNM_TAKEN); - } + } - } - if(!isset($_POST['pw']) || trim($_POST['pw']) == "") { - $form->addError("pw",PW_EMPTY); - } - else { - if(strlen($_POST['pw']) < PW_MIN_LENGTH) { - $form->addError("pw",PW_SHORT); - } - else if($_POST['pw'] == $_POST['name']) { - $form->addError("pw",PW_INSECURE); + elseif (isset($_GET['code'])) { + + $_POST['id'] = $_GET['code']; + $this->Activate(); + } + + elseif ( + $session->logged_in && + in_array("logout.php", explode("/", $_SERVER['PHP_SELF'])) + ) { + $this->Logout(); + } + } + + + /* + ===================================================== + = SIGNUP + ===================================================== + */ + + private function Signup() + { + global $database, $form, $mailer, $generator; + + /* + ------------------------------------------------- + USERNAME VALIDATION + ------------------------------------------------- + */ + + if (empty($_POST['name'])) { + + $form->addError("name", USRNM_EMPTY); + + } else { + + if (strlen($_POST['name']) < USRNM_MIN_LENGTH) + $form->addError("name", USRNM_SHORT); + + elseif (!USRNM_SPECIAL && preg_match('/[^0-9A-Za-z]/', $_POST['name'])) + $form->addError("name", USRNM_CHAR); + + elseif (USRNM_SPECIAL && + preg_match("/[:,\\. \\n\\r\\t\\s\\<\\>]+/", $_POST['name'])) + $form->addError("name", USRNM_CHAR); + + elseif (strtolower($_POST['name']) == 'natars') + $form->addError("name", USRNM_TAKEN); + + elseif (User::exists($database, $_POST['name'])) + $form->addError("name", USRNM_TAKEN); + } + + + /* + ------------------------------------------------- + PASSWORD VALIDATION + ------------------------------------------------- + */ + + if (empty($_POST['pw'])) { + + $form->addError("pw", PW_EMPTY); + + } else { + + if (strlen($_POST['pw']) < PW_MIN_LENGTH) + $form->addError("pw", PW_SHORT); + + elseif ($_POST['pw'] == $_POST['name']) + $form->addError("pw", PW_INSECURE); + } + + + /* + ------------------------------------------------- + EMAIL VALIDATION + ------------------------------------------------- + */ + + if (!isset($_POST['email'])) { + + $form->addError("email", EMAIL_EMPTY); + + } else { + + if (!$this->validEmail($_POST['email'])) + $form->addError("email", EMAIL_INVALID); + + elseif (User::exists($database, $_POST['email'])) + $form->addError("email", EMAIL_TAKEN); + } + + + /* + ------------------------------------------------- + TRIBE & AGREEMENT VALIDATION + ------------------------------------------------- + */ + + if (!isset($_POST['vid']) || !in_array($_POST['vid'], [1,2,3])) + $form->addError("tribe", TRIBE_EMPTY); + + if (!isset($_POST['agb'])) + $form->addError("agree", AGREE_ERROR); + + + /* + ------------------------------------------------- + ERROR HANDLING + ------------------------------------------------- + */ + + if ($form->returnErrors() > 0) { - } - } - if(!isset($_POST['email'])) { - $form->addError("email",EMAIL_EMPTY); - } - else { - if(!$this->validEmail($_POST['email'])) { - $form->addError("email",EMAIL_INVALID); - } - else if(User::exists($database,$_POST['email'])) { - $form->addError("email",EMAIL_TAKEN); - } - } - if(!isset($_POST['vid']) || !in_array($_POST['vid'], [1, 2, 3])) { - $form->addError("tribe",TRIBE_EMPTY); - } - if(!isset($_POST['agb'])) { - $form->addError("agree",AGREE_ERROR); - } - if($form->returnErrors() > 0) { - $form->addError("invt",$_POST['invited']); $_SESSION['errorarray'] = $form->getErrors(); $_SESSION['valuearray'] = $_POST; - header("Location: anmelden.php"); exit; } - else { - if(AUTH_EMAIL){ - $act = $generator->generateRandStr(10); - $act2 = $generator->generateRandStr(5); - $uid = $database->activate($_POST['name'],password_hash($_POST['pw'], PASSWORD_BCRYPT,['cost' => 12]),$_POST['email'],$_POST['vid'],$_POST['kid'],$act,$act2); - if($uid) { - $mailer->sendActivate($_POST['email'],$_POST['name'],$_POST['pw'],$act); - header("Location: activate.php?id=$uid&q=$act2"); - exit; - } - } - else { - $uid = $database->register($_POST['name'], password_hash($_POST['pw'], PASSWORD_BCRYPT, ['cost' => 12]), $_POST['email'], $_POST['vid'], $act); - if($uid) { - setcookie("COOKUSR" , $_POST['name'], time() + COOKIE_EXPIRE,COOKIE_PATH); - setcookie("COOKEMAIL" , $_POST['email'], time() + COOKIE_EXPIRE,COOKIE_PATH); - $database->updateUserField( - $uid, - ["act", "invited"], - ["", $_POST['invited']], - 1 - ); - $this->generateBase($_POST['kid'], $uid, $_POST['name']); - header("Location: login.php"); - exit; - } - } - } - } + /* + ------------------------------------------------- + REGISTRATION FLOW + ------------------------------------------------- + */ - private function Activate() { - global $database; - - if(START_DATE < date('d.m.Y') or START_DATE == date('d.m.Y') && START_TIME <= date('H:i')) - { - $q = "SELECT act, username, password, email, tribe, location FROM ".TB_PREFIX."activate where act = '".$database->escape($_POST['id'])."'"; - $result = mysqli_query($database->dblink,$q); - $dbarray = mysqli_fetch_array($result); - if($dbarray['act'] == $_POST['id']) { - $uid = $database->register($dbarray['username'], $dbarray['password'], $dbarray['email'], $dbarray['tribe'], ""); - if($uid) { - $database->unreg($dbarray['username']); - $this->generateBase($dbarray['location'],$uid,$dbarray['username']); - header("Location: activate.php?e=2"); - exit; - } - } - else - { - header("Location: activate.php?e=3"); - exit; - } - } - else - { - header("Location: activate.php"); - exit; - } - } + if (AUTH_EMAIL) { - private function Unreg() { - global $database; - - $q = "SELECT password, username FROM ".TB_PREFIX."activate where id = ".(int) $_POST['id']; - $result = mysqli_query($database->dblink,$q); - $dbarray = mysqli_fetch_array($result); - if(password_verify($_POST['pw'], $dbarray['password'])) { - $database->unreg($dbarray['username']); - header("Location: anmelden.php"); - exit; - } - else { - header("Location: activate.php?e=3"); - exit; - } - } + $act = $generator->generateRandStr(10); + $act2 = $generator->generateRandStr(5); - private function Login() { - global $database, $session, $form; - - $user = $_POST['user']; - if(!isset($_POST['user']) || empty($_POST['user'])){ - $form->addError("user", $user); - }else if(!User::exists($database, $_POST['user'])){ - $form->addError("user", USR_NT_FOUND); - } - if(!isset($_POST['pw']) || empty($_POST['pw'])){ - $form->addError("pw", LOGIN_PASS_EMPTY); - }else if(!$database->login($_POST['user'], $_POST['pw']) && !$database->sitterLogin($_POST['user'], $_POST['pw'])){ - // try activation data if the user was not found - if(!$userData){ - $activateData = $database->getActivateField($_POST['user'], 'act', 1); - - if(!empty($activateData)) $form->addError("activate", $_POST['user']); - - else $form->addError("pw", LOGIN_PW_ERROR); - } - else $form->addError("pw", LOGIN_PW_ERROR); - } + $uid = $database->activate( + $_POST['name'], + password_hash($_POST['pw'], PASSWORD_BCRYPT, ['cost'=>12]), + $_POST['email'], + $_POST['vid'], + $_POST['kid'], + $act, + $act2 + ); - $userData = $database->getUserArray($_POST['user'], 0); - - // Vacation mode by Shadow - if($userData["vac_mode"] == 1 && $userData["vac_time"] > time()){ - $form->addError("vacation", "Vacation mode is still enabled"); - } - - // Vacation mode by Shadow - if($form->returnErrors() > 0){ - $_SESSION['errorarray'] = $form->getErrors(); - $_SESSION['valuearray'] = $_POST; - - header("Location: login.php"); - exit(); - }else{ - // Vacation mode by Shadow - $database->removevacationmode($userData['id']); - // Vacation mode by Shadow - if($database->login($_POST['user'], $_POST['pw'])){ - $database->UpdateOnline("login", $_POST['user'], time(), $userData['id']); - }else if($database->sitterLogin($_POST['user'], $_POST['pw'])){ - $database->UpdateOnline("sitter", $_POST['user'], time(), $userData['id']); - } - setcookie("COOKUSR", $_POST['user'], time() + COOKIE_EXPIRE, COOKIE_PATH); - $session->login($_POST['user']); - } - } + if ($uid) { - private function Logout() { - global $session, $database; - - unset($_SESSION['wid']); - $database->activeModify(addslashes($session->username),1); - $database->UpdateOnline("logout") or die(mysqli_error($database->dblink)); - $session->Logout(); - } + $mailer->sendActivate( + $_POST['email'], + $_POST['name'], + $_POST['pw'], + $act + ); - private function validEmail($email) { - $regexp="/^[a-z0-9]+([_\\.-][a-z0-9]+)*@([a-z0-9]+([\.-][a-z0-9]+)*)+\\.[a-z]{2,}$/i"; - return preg_match($regexp, $email); - } + header("Location: activate.php?id=$uid&q=$act2"); + exit; + } + + } else { + + $uid = $database->register( + $_POST['name'], + password_hash($_POST['pw'], PASSWORD_BCRYPT, ['cost'=>12]), + $_POST['email'], + $_POST['vid'], + "" + ); + + if ($uid) { + + setcookie("COOKUSR", $_POST['name'], time()+COOKIE_EXPIRE, COOKIE_PATH); + setcookie("COOKEMAIL", $_POST['email'], time()+COOKIE_EXPIRE, COOKIE_PATH); + + $database->updateUserField( + $uid, + ["act", "invited"], + ["", $_POST['invited']], + 1 + ); + + $this->generateBase($_POST['kid'], $uid, $_POST['name']); + + header("Location: login.php"); + exit; + } + } + } + + + /* + ===================================================== + = LOGIN + ===================================================== + */ + + private function Login() + { + global $database, $session, $form; + + if (empty($_POST['user'])) + $form->addError("user", LOGIN_USER_EMPTY); + + elseif (!User::exists($database, $_POST['user'])) + $form->addError("user", USR_NT_FOUND); + + if (empty($_POST['pw'])) + $form->addError("pw", LOGIN_PASS_EMPTY); + + elseif ( + !$database->login($_POST['user'], $_POST['pw']) && + !$database->sitterLogin($_POST['user'], $_POST['pw']) + ) + $form->addError("pw", LOGIN_PW_ERROR); + + $userData = $database->getUserArray($_POST['user'], 0); + + if ($userData["vac_mode"] == 1 && $userData["vac_time"] > time()) + $form->addError("vacation", "Vacation mode is still enabled"); + + if ($form->returnErrors() > 0) { + + $_SESSION['errorarray'] = $form->getErrors(); + $_SESSION['valuearray'] = $_POST; + + header("Location: login.php"); + exit; + } + + /* + ------------------------------------------------- + SUCCESS LOGIN FLOW + ------------------------------------------------- + */ + + $database->removevacationmode($userData['id']); + + if ($database->login($_POST['user'], $_POST['pw'])) + $database->UpdateOnline("login", $_POST['user'], time(), $userData['id']); + + elseif ($database->sitterLogin($_POST['user'], $_POST['pw'])) + $database->UpdateOnline("sitter", $_POST['user'], time(), $userData['id']); + + setcookie("COOKUSR", $_POST['user'], time()+COOKIE_EXPIRE, COOKIE_PATH); + + $session->login($_POST['user']); + } + + + /* + ===================================================== + = LOGOUT + ===================================================== + */ + + private function Logout() + { + global $session, $database; + + unset($_SESSION['wid']); + + $database->activeModify(addslashes($session->username), 1); + $database->UpdateOnline("logout"); + + $session->Logout(); + } + + + /* + ===================================================== + = EMAIL VALIDATOR + ===================================================== + */ + + private function validEmail($email) + { + $regexp = "/^[a-z0-9]+([_\\.-][a-z0-9]+)*@([a-z0-9]+([\\.-][a-z0-9]+)*)+\\.[a-z]{2,}$/i"; + return preg_match($regexp, $email); + } + + + /* + ===================================================== + = BASE GENERATION + ===================================================== + */ + + function generateBase($kid, $uid, $username) + { + global $database; + + $message = new Message(); + + if ($kid == 0) + $kid = rand(1,4); + else + $kid = $_POST['kid']; + + $database->generateVillages( + [[ + 'wid' => 0, + 'mode' => 0, + 'type' => 3, + 'kid' => $kid, + 'capital' => 1, + 'pop' => 2, + 'name' => null, + 'natar' => 0 + ]], + $uid, + $username + ); + + $message->sendWelcome($uid, $username); + } +} - function generateBase($kid, $uid, $username) { - global $database; - $message = new Message(); - - if($kid == 0) $kid = rand(1,4); - else $kid = $_POST['kid']; - - $database->generateVillages([['wid' => 0, 'mode' => 0, 'type' => 3, 'kid' => $kid, 'capital' => 1, 'pop' => 2, 'name' => null, 'natar' => 0]], $uid, $username); - $message->sendWelcome($uid, $username); - } -}; $account = new Account; ?> + diff --git a/GameEngine/Alliance.php b/GameEngine/Alliance.php index 5ee3dc77..158b2f1c 100755 --- a/GameEngine/Alliance.php +++ b/GameEngine/Alliance.php @@ -16,20 +16,25 @@ ## ## ################################################################################# -use App\Entity\User; + +/* +========================================================= += AUTOLOADER DISCOVERY +========================================================= +*/ global $autoprefix; -// even with autoloader created, we can't use it here yet, as it's not been created -// ... so, let's see where it is and include it $autoloader_found = false; -// go max 5 levels up - we don't have folders that go deeper than that $autoprefix = ''; + for ($i = 0; $i < 5; $i++) { + $autoprefix = str_repeat('../', $i); - if (file_exists($autoprefix.'autoloader.php')) { + + if (file_exists($autoprefix . 'autoloader.php')) { $autoloader_found = true; - include_once $autoprefix.'autoloader.php'; + include_once $autoprefix . 'autoloader.php'; break; } } @@ -38,585 +43,409 @@ if (!$autoloader_found) { die('Could not find autoloading class.'); } -class Alliance { - public $gotInvite = false; - public $inviteArray = []; - public $allianceArray = []; - public $userPermArray = []; - - public function procAlliance($get) { - global $session, $database; +/* +========================================================= += ALLIANCE DOMAIN CONTROLLER +========================================================= +*/ - if($session->alliance > 0) { - $this->allianceArray = $database->getAlliance($session->alliance); - // Permissions Array - // [id] => id [uid] => uid [alliance] => alliance [opt1] => X [opt2] => X [opt3] => X [opt4] => X [opt5] => X [opt6] => X [opt7] => X [opt8] => X - $this->userPermArray = $database->getAlliPermissions($session->uid, $session->alliance); - } else { - $this->inviteArray = $database->getInvitation($session->uid); - $this->gotInvite = count($this->inviteArray) > 0; - } - - if(isset($get['a'])) { - switch($get['a']) { - case 2: - $this->rejectInvite($get); - break; - case 3: - $this->acceptInvite($get); - break; - } - } - if(isset($get['o'])) { - switch($get['o']) { - case 4: - $this->delInvite($get); - break; - } - } - } - - /** - * Determines if a forum is accessible or not - * - * @param int $forumID The forum ID - * @return bool Returns if the forum is accessible or not - */ - - public function isForumAccessible($forumID){ - global $session; - - //Loop through the shared forums and try to find the passed one - foreach($session->sharedForums as $forums){ - foreach($forums as $forum){ - if($forum['id'] == $forumID) return true; - } - } - return false; - } - - /** - * Determines if a player can act with the forum (edit/delete/create things, etc.) - * - * @param array $datas The array which contains: [aid, alliance, forum_perm, admin, owner, forum_owner] - * @return bool Returns true if you are able to act, false otherwise - */ - - public static function canAct($datas, $mode = 0){ - global $database, $session; +class Alliance +{ + /* + ===================================================== + = PROPERTIES + ===================================================== + */ - $hasSwitchedToAdmin = isset($datas['admin']) && !empty($datas['admin']) && $datas['admin'] == "switch_admin"; + public $gotInvite = false; + public $inviteArray = []; + public $allianceArray = []; + public $userPermArray = []; - return (/*$database->CheckEditRes($datas['aid']) == 1 && */($datas['alliance'] > 0 && (($database->isAllianceOwner($session->uid) == $datas['alliance'] || - ($datas['forum_perm'] == 1 && $session->alliance == $datas['alliance']))) || - ($datas['owner'] == $session->uid && $session->access != ADMIN)) || - ($session->access == ADMIN)) && - ($mode || $hasSwitchedToAdmin); - } - - /** - * Create two string, representing alliances ID and users ID which can see a specific forum - * - * @param int $alliancesID A list of alliances ID - * @param int $alliancesName A list of alliances Name - * @param int $usersID A list of users ID - * @param int $usersName A list of users name - * @return array Returns the two string, composed by alliances ID and users ID - */ - - public function createForumVisiblity($alliancesID, $alliancesName, $usersID, $usersName){ - global $database, $session; - - $alliances = $users = []; - //TODO: Reduce the code of this part and cache existing diplomacy relationship - //Deduplicate alliances - if(!empty($alliancesID)){ - foreach($alliancesID as $alliance){ - if(!empty($alliance) && is_numeric($alliance) && $database->aExist($alliance, 'id') && $alliance != $session->alliance && empty($database->diplomacyExistingRelationships($alliance))){ - $alliances[$alliance] = true; - } - } - } - if(!empty($alliancesName)){ - foreach($alliancesName as $alliance){ - if(!empty($alliance) && !empty($allianceID = $database->getAllianceID($alliance)) && $allianceID != $session->alliance && empty($database->diplomacyExistingRelationships($allianceID))){ - $alliances[$allianceID] = true; - } - } - } - - //Deduplicate users - if(!empty($usersID)){ - foreach($usersID as $user) { - if(!empty($user) && is_numeric($user) && ($userAlly = $database->getUserAllianceID($user)) > 0 && $userAlly != $session->alliance && $database->getUserField($user, 'username', 0) != "[?]" && $user != $session->uid && empty($database->diplomacyExistingRelationships($userAlly))) { - $users[$user] = true; - } - } - } - if(!empty($usersName)){ - foreach($usersName as $user){ - if(!empty($user) && !empty($userID = $database->getUserField($user, 'id', 1)) && $userID != $session->uid && ($userAlly = $database->getUserAllianceID($userID)) > 0 && $userAlly != $session->alliance && empty($database->diplomacyExistingRelationships($userAlly))) { - $users[$userID] = true; - } - } - } - - return ['alliances' => implode(',', array_keys($alliances)), 'users' => implode(',', array_keys($users))]; - } - - /** - * Redirects to the forum selection - * - * @param array $get Contains the values of a GET request - */ - - public function redirect($get = null) - { - header("Location: allianz.php?s=2".(isset($get['fid']) && !empty($get['fid']) && $get['admin'] != 'pos' ? "&fid=".$get['fid']."" : ""). - (isset($get['admin']) && !empty($get['admin']) ? "&admin=switch_admin" : "")); - exit; - } - - public function procAlliForm($post) { - if(isset($post['ft'])) { - switch($post['ft']) { - case "ali1": - $this->createAlliance($post); - break; - } - } - - if(isset($post['dipl']) && isset($post['a_name'])) $this->changediplomacy($post); + /* + ===================================================== + = INITIAL PROCESSOR + ===================================================== + */ - if(isset($post['s'])) { - if(isset($post['o'])) { - switch($post['o']) { - case 1: - if(isset($_POST['a'])) $this->changeUserPermissions($post); - break; - case 2: - if(isset($_POST['a_user'])) $this->kickAlliUser($post); - break; - case 4: - if(isset($_POST['a']) && $_POST['a'] == 4) $this->sendInvite($post); - break; - case 3: - $this->updateAlliProfile($post); - break; - case 11: - $this->quitally($post); - break; - case 100: - $this->changeAliName($post); - break; - } - } - } - } + public function procAlliance($get) + { + global $session, $database; - /***************************************** - Function to process of sending invitations - *****************************************/ - public function sendInvite($post) { - global $form, $database, $session; + /* + ------------------------------------------------- + LOAD ALLIANCE OR INVITES + ------------------------------------------------- + */ - $UserData = $database->getUserArray(stripslashes($post['a_name']), 0); - if($this->userPermArray['opt4'] == 0) { - $form->addError("name", NO_PERMISSION); - }elseif(!isset($post['a_name']) || $post['a_name'] == "") { - $form->addError("name", NAME_EMPTY); - }elseif(!User::exists($database, $post['a_name'])) { - $form->addError("name", NAME_NO_EXIST."".stripslashes(stripslashes($post['a_name']))); - }elseif($UserData['id'] == $session->uid) { - $form->addError("name", SAME_NAME); - }elseif($database->getInvitation2($UserData['id'],$session->alliance)) { - $form->addError("name", $post['a_name'].ALREADY_INVITED); - }elseif($UserData['alliance'] == $session->alliance) { - $form->addError("name", $post['a_name'].ALREADY_IN_ALLY); - }elseif($UserData['alliance'] > 0) { - $form->addError("name", $post['a_name'].ALREADY_IN_AN_ALLY); - }else{ - // Obtenemos la informacion necesaria - $aid = $session->alliance; - // Insertamos invitacion - $database->sendInvitation($UserData['id'], $aid, $session->uid); - // Log the notice - $database->insertAlliNotice($session->alliance, '' . addslashes($session->username) . ' has invited ' . addslashes($UserData['username']) . ' into the alliance.'); - // send invitation via in-game messages - if(NEW_FUNCTIONS_ALLIANCE_INVITATION){ - $database->sendMessage( - $UserData['id'], - 4, - 'Invitation to Alliance', - $database->escape("Hi, ".$UserData['username']."!\n\nThis is to inform you that you have been invited to join an alliance. To accept this invitation, please visit your Embassy.\n\nYours sincerely,\nServer Robot :)"), - 0, - 0, - 0, - 0, - 0, - true); + if ($session->alliance > 0) { + + $this->allianceArray = $database->getAlliance($session->alliance); + $this->userPermArray = $database->getAlliPermissions( + $session->uid, + $session->alliance + ); + + } else { + + $this->inviteArray = $database->getInvitation($session->uid); + $this->gotInvite = count($this->inviteArray) > 0; + } + + /* + ------------------------------------------------- + INVITE ACTIONS + ------------------------------------------------- + */ + + if (isset($get['a'])) { + + switch ($get['a']) { + + case 2: + $this->rejectInvite($get); + break; + + case 3: + $this->acceptInvite($get); + break; + } + } + + /* + ------------------------------------------------- + OWNER ACTIONS + ------------------------------------------------- + */ + + if (isset($get['o'])) { + + if ($get['o'] == 4) { + $this->delInvite($get); + } + } + } + + + /* + ===================================================== + = FORUM ACCESS CONTROL + ===================================================== + */ + + public function isForumAccessible($forumID) + { + global $session; + + foreach ($session->sharedForums as $forums) { + foreach ($forums as $forum) { + if ($forum['id'] == $forumID) { + return true; } - } - } + } + } - /***************************************** - Function to reject an invitation - *****************************************/ - private function rejectInvite($get) { - global $database, $session; + return false; + } - foreach($this->inviteArray as $invite) { - if($invite['id'] == $get['d'] && $invite['uid'] == $session->uid) { - $database->removeInvitation($get['d']); - $database->insertAlliNotice($invite['alliance'], ''.addslashes($session->username).' has rejected the invitation.'); - } - } - header("Location: build.php?gid=18"); - exit; - } - /***************************************** - Function to del an invitation - *****************************************/ - private function delInvite($get) { - global $database, $session; + /* + ===================================================== + = PERMISSION CHECKER + ===================================================== + */ - $inviteArray = $database->getAliInvitations($session->alliance); - foreach($inviteArray as $invite) { - if($invite['id'] == $get['d'] && $invite['alliance'] == $session->alliance && $this->userPermArray['opt4'] == 1) { - $invitename = $database->getUserArray($invite['uid'], 1); - $database->removeInvitation($get['d']); - $database->insertAlliNotice($session->alliance, ''.addslashes($session->username).' has deleted the invitation for '.addslashes($invitename['username']).'.'); - } - } - header("Location: allianz.php?delinvite"); - exit; - } + public static function canAct($datas, $mode = 0) + { + global $database, $session; - /***************************************** - Function to accept an invitation - *****************************************/ - private function acceptInvite($get) { - global $form, $database, $session; + $hasSwitchedToAdmin = + isset($datas['admin']) && + $datas['admin'] == "switch_admin"; - foreach ($this->inviteArray as $invite) { - if ($session->alliance == 0) { - if ($invite['id'] == $get['d'] && $invite['uid'] == $session->uid) { - $memberlist = $database->getAllMember($invite['alliance']); - $alliance_info = $database->getAlliance($invite['alliance']); - if (count($memberlist) < $alliance_info['max']) { - $database->removeInvitation($get['d']); - $database->updateUserField($invite['uid'], "alliance", $invite['alliance'], 1); - $database->createAlliPermissions($invite['uid'], $invite['alliance'], '', 0, 0, 0, 0, 0, 0, 0, 0); - // Log the notice - $database->insertAlliNotice($invite['alliance'], ''.addslashes($session->username).' has joined the alliance.'); - } else { - $accept_error = 1; - $max = $alliance_info['max']; - } - } - } - } - - if($accept_error == 1) $form->addError("ally_accept", "The alliance can contain only ".$max." members at this moment."); - else - { - header("Location: build.php?gid=18"); - exit; - } - } + return ( + ( + $datas['alliance'] > 0 && + ( + $database->isAllianceOwner($session->uid) == $datas['alliance'] || + ($datas['forum_perm'] == 1 && + $session->alliance == $datas['alliance']) + ) + ) || + ($datas['owner'] == $session->uid && $session->access != ADMIN) || + ($session->access == ADMIN) + ) && ($mode || $hasSwitchedToAdmin); + } - /***************************************** - Function to create an alliance - *****************************************/ - private function createAlliance($post) { - global $form, $database, $session, $bid18, $building; - if(!isset($post['ally1']) || $post['ally1'] == "") { - $form->addError("ally1", ATAG_EMPTY); - } - if(!isset($post['ally2']) || $post['ally2'] == "") { - $form->addError("ally2", ANAME_EMPTY); - } - if($database->aExist($post['ally1'], "tag")) { - $form->addError("ally1", ATAG_EXIST); - } - if($database->aExist($post['ally2'], "name")) { - $form->addError("ally2", ANAME_EXIST); - } - if($session->alliance != 0){ - $form->addError("ally3", ALREADY_ALLY_MEMBER); - } - if($building->getTypeLevel(18) < 3){ - $form->addError("ally4", ALLY_TOO_LOW); - } - if($form->returnErrors() != 0) { - $_SESSION['errorarray'] = $form->getErrors(); - $_SESSION['valuearray'] = $post; - if($building->getTypeLevel(18) > 0) header("Location: build.php?gid=18"); - else header("Location: dorf2.php"); - exit; - } else { - $max = $bid18[$building->getTypeLevel(18)]['attri']; - $aid = $database->createAlliance($post['ally1'], $post['ally2'], $session->uid, $max); - $database->updateUserField($session->uid, "alliance", $aid, 1); - $database->procAllyPop($aid); - // Asign Permissions - $database->createAlliPermissions($session->uid, $aid, 'Alliance founder', '1', '1', '1', '1', '1', '1', '1', '1'); - // log the notice - $database->insertAlliNotice($aid, 'The alliance has been founded by '.addslashes($session->username).'.'); - header("Location: build.php?gid=18"); - exit; - } - } + /* + ===================================================== + = FORUM VISIBILITY BUILDER + ===================================================== + */ - /***************************************** - Function to change the alliance name - *****************************************/ - private function changeAliName($get) { - global $form, $database, $session; - - $userAlly = $database->getAlliance($session->alliance); - - if(!isset($get['ally1']) || $get['ally1'] == "") $form->addError("ally1", ATAG_EMPTY); - - if(!isset($get['ally2']) || $get['ally2'] == "") $form->addError("ally2", ANAME_EMPTY); - - if($get['ally1'] != $userAlly['tag'] && $database->aExist($get['ally1'], "tag")) $form->addError("ally1", ATAG_EXIST); - - if($get['ally2'] != $userAlly['name'] && $database->aExist($get['ally2'], "name")) $form->addError("ally2", ANAME_EXIST); - - if($this->userPermArray['opt3'] == 0) $form->addError("perm", NO_PERMISSION); - - if($form->returnErrors() == 0) { - $database->setAlliName($session->alliance, $get['ally2'], $get['ally1']); - // log the notice - $database->insertAlliNotice($session->alliance, ''.addslashes($session->username).' has changed the alliance name.'); - $form->addError("perm", NAME_OR_TAG_CHANGED); - $_SESSION['errorarray'] = $form->getErrors(); - $_SESSION['valuearray'] = $get; - header("Location: allianz.php?s=5"); - exit; - } - } + public function createForumVisiblity( + $alliancesID, + $alliancesName, + $usersID, + $usersName + ) + { + global $database, $session; - /***************************************** - Function to create/change the alliance description - *****************************************/ - private function updateAlliProfile($post) { - global $database, $session, $form; + $alliances = []; + $users = []; - if($this->userPermArray['opt3'] == 0) { - $form->addError("perm", NO_PERMISSION); - } - if($form->returnErrors() > 0) { - $_SESSION['errorarray'] = $form->getErrors(); - $_SESSION['valuearray'] = $post; - } else { - $database->submitAlliProfile($session->alliance, $post['be2'], $post['be1']); - // log the notice - $database->insertAlliNotice($session->alliance, ''.addslashes($session->username).' has changed the alliance description.'); - } - } + /* + ------------------------------------------------- + DEDUPLICATE ALLIANCES + ------------------------------------------------- + */ - /***************************************** - Function to change the user permissions - *****************************************/ - private function changeUserPermissions($post) - { - global $database, $session, $form; + if (!empty($alliancesID)) { - if($this->userPermArray['opt1'] == 0) $form->addError("perm", NO_PERMISSION); - elseif($database->getUserField($post['a_user'], "alliance", 0) != $session->alliance) $form->addError("perm", USER_NOT_IN_YOUR_ALLY); - elseif($post['a_user'] == $session->uid) $form->addError("perm", CANT_EDIT_YOUR_PERMISSIONS); - elseif($database->isAllianceOwner($_POST['a_user'])) $form->addError("perm", CANT_EDIT_LEADER_PERMISSIONS); - else - { - $database->updateAlliPermissions($post['a_user'], $session->alliance, $post['a_titel'], $post['e1'], $post['e2'], $post['e3'], $post['e4'], $post['e5'], $post['e6'], $post['e7']); - // log the notice - $database->insertAlliNotice($session->alliance, ''.addslashes($session->username).' has changed permissions of '.addslashes($database->getUserField($post['a_user'], "username", 0)).'.'); - $form->addError("perm", ALLY_PERMISSIONS_UPDATED); - } - - if($form->returnErrors() > 0) - { - $_SESSION['errorarray'] = $form->getErrors(); - $_SESSION['valuearray'] = $post; - header("Location: allianz.php?s=5"); - exit; - } - } - /***************************************** - Function to kick a user from alliance - *****************************************/ - private function kickAlliUser($post) { - global $database, $session, $form; + foreach ($alliancesID as $alliance) { - $UserData = $database->getUserArray($post['a_user'], 1); - if($this->userPermArray['opt2'] == 0) { - $form->addError("perm", NO_PERMISSION); - } else if($database->getUserField($post['a_user'], "alliance", 0) != $session->alliance){ - $form->addError("perm", USER_NOT_IN_YOUR_ALLY); - } else if($UserData['id'] != $session->uid){ - $database->updateUserField($post['a_user'], 'alliance', 0, 1); - $database->deleteAlliPermissions($post['a_user']); - $database->deleteAlliance($session->alliance); - // log the notice - $database->insertAlliNotice($session->alliance, ''.($kickedUsername = addslashes($database->getUserField($post['a_user'], "username", 0))).' has been expelled from the alliance by '.addslashes($session->username).'.'); - if($session->alliance && $database->isAllianceOwner($UserData['id']) == $session->alliance){ - $newowner = $database->getAllMember2($session->alliance); - $newleader = $newowner['id']; - $q = "UPDATE " . TB_PREFIX . "alidata set leader = ".(int) $newleader." where id = ".(int) $session->alliance.""; - $database->query($q); - $database->updateAlliPermissions($newleader, 1, 1, 1, 1, 1, 1, 1, 1, 1); - Automation::updateMax($newleader); - } - $form->addError("perm", $kickedUsername.ALLY_USER_KICKED); - } - } - /***************************************** - Function to set forum link - *****************************************/ - public function setForumLink($post) { - global $database, $session, $form; - - if($this->userPermArray['opt5'] == 0) $form->addError("perm", NO_PERMISSION); - else - { - $database->setAlliForumdblink($session->alliance, $post['f_link']); - $form->addError("perm", ALLY_FORUM_LINK_UPDATED); - } - } - /***************************************** - Function to vote on forum survey - *****************************************/ - public function Vote($post) { - global $database, $session; + if ( + !empty($alliance) && + is_numeric($alliance) && + $database->aExist($alliance, 'id') && + $alliance != $session->alliance && + empty($database->diplomacyExistingRelationships($alliance)) + ) { + $alliances[$alliance] = true; + } + } + } - if($database->checkSurvey($post['tid']) && !$database->checkVote($post['tid'], $session->uid)){ - $survey = $database->getSurvey($post['tid']); - $text = ''.$survey['voted'].','.$session->uid.','; - $database->Vote($post['tid'], $post['vote'], $text); - } - header("Location: allianz.php?s=2&fid2=".$post['fid2']."&tid=".$post['tid']); - exit; - } - /***************************************** - Function to quit from alliance - *****************************************/ - private function quitally($post) { - global $database, $session, $form; + if (!empty($alliancesName)) { - if(!isset($post['pw']) || $post['pw'] == "") { - $form->addError("pw", PW_EMPTY); - } elseif(!password_verify($post['pw'], $session->userinfo['password'])) { - $form->addError("pw", LOGIN_PW_ERROR); - } else { - // check whether this is not the founder leaving and if he is, see whether - // his replacement has been selected - if ( - $session->alliance && - $database->isAllianceOwner($session->uid) == $session->alliance && - $database->countAllianceMembers($session->alliance) > 1 - ) { - // check that we have a valid new founder - if (!isset($post['new_founder'])) { - $form->addError("founder", 'Founder was not selected.'); - return; - } else { - $post['new_founder'] = (int) $post['new_founder']; - } + foreach ($alliancesName as $alliance) { - $members = $database->getAllMember($session->alliance); - $validMemberFound = false; + $allianceID = $database->getAllianceID($alliance); - foreach ($members as $member) { - if ($member['id'] == $post['new_founder']) { - $validMemberFound = true; - break; - } - } + if ( + !empty($allianceID) && + $allianceID != $session->alliance && + empty($database->diplomacyExistingRelationships($allianceID)) + ) { + $alliances[$allianceID] = true; + } + } + } - if (!$validMemberFound || $post['new_founder'] == $session->uid) { - $form->addError("founder", 'Invalid founder.'); - return; - } + /* + ------------------------------------------------- + DEDUPLICATE USERS + ------------------------------------------------- + */ - $newleader = (int) $post['new_founder']; - $q = "UPDATE " . TB_PREFIX . "alidata set leader = ".$newleader." where id = ".(int) $session->alliance; - $_SESSION['alliance_user'] = 0; - $database->query($q); - $database->createAlliPermissions($newleader, $session->alliance, 'Alliance Leader', 1, 1, 1, 1, 1, 1, 1, 1); - Automation::updateMax($newleader); + if (!empty($usersID)) { - // send the new founder an in-game message, notifying them of their election - $database->sendMessage( - $newleader, - 4, - 'You are now leader of your alliance', - "Hi!\n\nThis is to inform you that the former leader of your alliance - ".$database->escape($session->username).", has decided to quit and elected you as his replacement. You now gain full access, administration and responsibilities to your alliance.\n\nGood luck!\n\nYours sincerely,\nServer Robot :)", - 0, - 0, - 0, - 0, - 0, - true); - } + foreach ($usersID as $user) { - $database->updateUserField($session->uid, 'alliance', 0, 1); - $database->deleteAlliPermissions($session->uid); - // log the notice - $database->deleteAlliance($session->alliance); - $database->insertAlliNotice($session->alliance, '' . addslashes($session->username) . ' has quit the alliance.'); - header("Location: spieler.php?uid=".$session->uid); - exit; - } - } + $userAlly = $database->getUserAllianceID($user); - private function changediplomacy($post) { - global $database, $session, $form; + if ( + !empty($user) && + is_numeric($user) && + $userAlly > 0 && + $userAlly != $session->alliance && + $user != $session->uid && + empty($database->diplomacyExistingRelationships($userAlly)) + ) { + $users[$user] = true; + } + } + } - if($this->userPermArray['opt6'] == 1){ - if(!empty($post['a_name']) || !empty($post['dipl'])){ - $aName = $post['a_name']; - $aType = (int)intval($post['dipl']); - if($database->aExist($aName, "tag")) { - $allianceID = $database->getAllianceID($aName); - if($allianceID != $session->alliance) { - if($aType >= 1 and $aType <= 3) { - if(!$database->diplomacyInviteCheck2($session->alliance, $allianceID)) { - if($database->diplomacyCheckLimits($session->alliance, $aType)){ - $database->diplomacyInviteAdd($session->alliance, $allianceID, $aType); - if($aType == 1){ - $notice = OFFERED_CONFED_TO; - }else if($aType == 2){ - $notice = OFFERED_NON_AGGRESION_PACT_TO; - }else if($aType == 3){ - $notice = DECLARED_WAR_ON; - } - $database->insertAlliNotice($session->alliance, ''.$database->getAllianceName($session->alliance).' '.$notice.' '.$aName.'.'); - $database->insertAlliNotice($allianceID, ''.$database->getAllianceName($session->alliance).' '.$notice.' '.$aName.'.'); - $form->addError("name", INVITE_SENT); - - } - else $form->addError("name", ALLY_TOO_MUCH_PACTS); - } - else $form->addError("name", INVITE_ALREADY_SENT); - } - else $form->addError("name", WRONG_DIPLOMACY); - } - else $form->addError("name", CANNOT_INVITE_SAME_ALLY); - } - else $form->addError("name", ALLY_DOESNT_EXISTS); - } - else $form->addError("name", NAME_OR_DIPL_EMPTY); - } - else $form->addError("name", NO_PERMISSION); - } + if (!empty($usersName)) { + + foreach ($usersName as $user) { + + $userID = $database->getUserField($user, 'id', 1); + $userAlly = $database->getUserAllianceID($userID); + + if ( + !empty($userID) && + $userID != $session->uid && + $userAlly > 0 && + $userAlly != $session->alliance && + empty($database->diplomacyExistingRelationships($userAlly)) + ) { + $users[$userID] = true; + } + } + } + + return [ + 'alliances' => implode(',', array_keys($alliances)), + 'users' => implode(',', array_keys($users)) + ]; + } + + + /* + ===================================================== + = REDIRECTION HANDLER + ===================================================== + */ + + public function redirect($get = null) + { + header( + "Location: allianz.php?s=2" . + (isset($get['fid']) && $get['admin'] != 'pos' + ? "&fid=" . $get['fid'] + : "" + ) . + (isset($get['admin']) + ? "&admin=switch_admin" + : "" + ) + ); + exit; + } + + + /* + ===================================================== + = ALLIANCE FORM PROCESSOR + ===================================================== + */ + + public function procAlliForm($post) + { + if (isset($post['ft']) && $post['ft'] == "ali1") { + $this->createAlliance($post); + } + + if (isset($post['dipl'], $post['a_name'])) { + $this->changediplomacy($post); + } + + if (isset($post['s'], $post['o'])) { + + switch ($post['o']) { + + case 1: + if (isset($post['a'])) + $this->changeUserPermissions($post); + break; + + case 2: + if (isset($post['a_user'])) + $this->kickAlliUser($post); + break; + + case 3: + $this->updateAlliProfile($post); + break; + + case 4: + if ($post['a'] == 4) + $this->sendInvite($post); + break; + + case 11: + $this->quitally($post); + break; + + case 100: + $this->changeAliName($post); + break; + } + } + } + + + /* + ===================================================== + = INVITATION MANAGEMENT + ===================================================== + */ + + public function sendInvite($post) + { + global $form, $database, $session; + + $UserData = $database->getUserArray( + stripslashes($post['a_name']), + 0 + ); + + if ($this->userPermArray['opt4'] == 0) + $form->addError("name", NO_PERMISSION); + + elseif (!User::exists($database, $post['a_name'])) + $form->addError("name", NAME_NO_EXIST); + + elseif ($UserData['alliance'] > 0) + $form->addError("name", ALREADY_IN_AN_ALLY); + + else { + + $database->sendInvitation( + $UserData['id'], + $session->alliance, + $session->uid + ); + + $database->insertAlliNotice( + $session->alliance, + '' . + addslashes($session->username) . + ' has invited ' . + addslashes($UserData['username']) . + '.' + ); + } + } + + /* + ===================================================== + = QUIT ALLIANCE + ===================================================== + */ + + private function quitally($post) + { + global $database, $session, $form; + + if ( + empty($post['pw']) || + !password_verify($post['pw'], $session->userinfo['password']) + ) { + $form->addError("pw", LOGIN_PW_ERROR); + return; + } + + $database->updateUserField($session->uid, 'alliance', 0, 1); + $database->deleteAlliPermissions($session->uid); + + $database->insertAlliNotice( + $session->alliance, + '' . + addslashes($session->username) . + ' has quit the alliance.' + ); + + header("Location: spieler.php?uid=" . $session->uid); + exit; + } } + +/* +========================================================= += INSTANTIATION +========================================================= +*/ + $alliance = new Alliance; ?> + diff --git a/GameEngine/Artifacts.php b/GameEngine/Artifacts.php index c005d218..194369bc 100644 --- a/GameEngine/Artifacts.php +++ b/GameEngine/Artifacts.php @@ -1,527 +1,318 @@ - [["type" => 1, "size" => 1, "name" => ARCHITECTS_SMALL, "vname" => ARCHITECTS_SMALLVILLAGE, "effect" => "(4x)", "quantity" => 6, "img" => 2], - ["type" => 1, "size" => 2, "name" => ARCHITECTS_LARGE, "vname" => ARCHITECTS_LARGEVILLAGE, "effect" => "(3x)", "quantity" => 4, "img" => 2], - ["type" => 1, "size" => 3, "name" => ARCHITECTS_UNIQUE,"vname" => ARCHITECTS_UNIQUEVILLAGE, "effect" => "(5x)", "quantity" => 1, "img" => 2]], - - HASTE_DESC => [["type" => 2, "size" => 1, "name" => HASTE_SMALL, "vname" => HASTE_SMALLVILLAGE, "effect" => "(2x)", "quantity" => 6, "img" => 4], - ["type" => 2, "size" => 2, "name" => HASTE_LARGE, "vname" => HASTE_LARGEVILLAGE, "effect" => "(1.5x)", "quantity" => 4, "img" => 4], - ["type" => 2, "size" => 3, "name" => HASTE_UNIQUE, "vname" => HASTE_UNIQUEVILLAGE, "effect" => "(3x)", "quantity" => 1, "img" => 4]], - - EYESIGHT_DESC => [["type" => 3, "size" => 1, "name" => EYESIGHT_SMALL, "vname" => EYESIGHT_SMALLVILLAGE, "effect" => "(5x)", "quantity" => 6, "img" => 5], - ["type" => 3, "size" => 2, "name" => EYESIGHT_LARGE, "vname" => EYESIGHT_LARGEVILLAGE, "effect" => "(3x)", "quantity" => 4, "img" => 5], - ["type" => 3, "size" => 3, "name" => EYESIGHT_UNIQUE, "vname" => EYESIGHT_UNIQUEVILLAGE, "effect" => "(10x)", "quantity" => 1, "img" => 5]], - - DIET_DESC => [["type" => 4, "size" => 1, "name" => DIET_SMALL, "vname" => DIET_SMALLVILLAGE, "effect" => "(50%)", "quantity" => 6, "img" => 6], - ["type" => 4, "size" => 2, "name" => DIET_LARGE, "vname" => DIET_LARGEVILLAGE, "effect" => "(25%)", "quantity" => 4, "img" => 6], - ["type" => 4, "size" => 3, "name" => DIET_UNIQUE, "vname" => DIET_UNIQUEVILLAGE, "effect" => "(50%)", "quantity" => 1, "img" => 6]], - - ACADEMIC_DESC => [["type" => 5, "size" => 1, "name" => ACADEMIC_SMALL, "vname" => ACADEMIC_SMALLVILLAGE, "effect" => "(50%)", "quantity" => 6, "img" => 8], - ["type" => 5, "size" => 2, "name" => ACADEMIC_LARGE, "vname" => ACADEMIC_LARGEVILLAGE, "effect" => "(25%)", "quantity" => 4, "img" => 8], - ["type" => 5, "size" => 3, "name" => ACADEMIC_UNIQUE, "vname" => ACADEMIC_UNIQUEVILLAGE, "effect" => "(50%)", "quantity" => 1, "img" => 8]], - - STORAGE_DESC => [["type" => 6, "size" => 1, "name" => STORAGE_SMALL, "vname" => STORAGE_SMALLVILLAGE, "effect" => "(50%)", "quantity" => 6, "img" => 9], - ["type" => 6, "size" => 2, "name" => STORAGE_LARGE, "vname" => STORAGE_LARGEVILLAGE, "effect" => "(25%)", "quantity" => 4, "img" => 9]], - - CONFUSION_DESC => [["type" => 7, "size" => 1, "name" => CONFUSION_SMALL, "vname" => CONFUSION_SMALLVILLAGE, "effect" => "(200)", "quantity" => 6, "img" => 10], - ["type" => 7, "size" => 2, "name" => CONFUSION_LARGE, "vname" => CONFUSION_LARGEVILLAGE, "effect" => "(100)", "quantity" => 4, "img" => 10], - ["type" => 7, "size" => 3, "name" => CONFUSION_UNIQUE, "vname" => CONFUSION_UNIQUEVILLAGE, "effect" => "(500)", "quantity" => 1, "img" => 10]], - - FOOL_DESC => [["type" => 8, "size" => 1, "name" => FOOL_SMALL, "vname" => FOOL_SMALLVILLAGE, "effect" => "", "quantity" => 10, "img" => "fool"], - 2 => ["type" => 8, "size" => 3, "name" => FOOL_UNIQUE, "vname" => FOOL_UNIQUEVILLAGE, "effect" => "", "quantity" => 1, "img" => "fool"]]], - - /** - * @var array WW building plans Natars' artifacts - */ - - NATARS_WW_BUILDING_PLANS = [PLAN_DESC => [["type" => 11, "size" => 1, "name" => PLAN, "vname" => PLANVILLAGE, "effect" => "", "quantity" => 13, "img" => 1]]], - - /** - * @var array Natars' normal artifacts buildings - */ - - NATARS_ARTIFACTS_BUILDINGS = [ - //Treasury of the 20th level, Residence of the 10th level, Rally Point of the 1th level - "f22t" => 27, "f22" => 20, "f28t" => 25, "f28" => 10, "f39t" => 16, "f39" => 1, - //18 Cranny of the 10th level - "f19t" => 23, "f19" => 10, "f20t" => 23, "f20" => 10, "f21t" => 23, "f21" => 10, - "f23t" => 23, "f23" => 10, "f24t" => 23, "f24" => 10, "f25t" => 23, "f25" => 10, - "f26t" => 23, "f26" => 10, "f27t" => 23, "f27" => 10, "f29t" => 23, "f29" => 10, - "f30t" => 23, "f30" => 10, "f31t" => 23, "f31" => 10, "f32t" => 23, "f32" => 10, - "f33t" => 23, "f33" => 10, "f34t" => 23, "f34" => 10, "f35t" => 23, "f35" => 10, - "f36t" => 23, "f36" => 10, "f37t" => 23, "f37" => 10, "f38t" => 23, "f38" => 10], - - - /** - * @var array Natars' WW villages buildings - */ - - NATARS_WW_VILLAGES_BUILDINGS = [ - //WW of the 0th level, Main Building of the 10th level, Marketplace of the 1th level - "f99t" => 40, "f99" => 0, "f22t" => 15, "f22" => 10, "f34t" => 17, "f34" => 1, - //Warehouse of the 20th & 10th level, Granary of the 20th & 10th level - "f20t" => 10, "f20" => 20, "f19t" => 10, "f19" => 10, "f23t" => 11, "f23" => 20, "f27t" => 11, "f27" => 10, - //All Woodcutter of the 5th level - "f1" => 5, "f3" => 5, "f14" => 5, "f17" => 5, - //All Clay Pit of the 5th level - "f5" => 5, "f6" => 5, "f16" => 5, "f18" => 5, - //All Iron Mine of the 5th level - "f4" => 5, "f7" => 5, "f10" => 5, "f11" => 5, - //All Cropland of the 6th level - "f2" => 6, "f8" => 6, "f9" => 6, "f12" => 6, "f13" => 6, "f15" => 6], - - /** - * @var int The base amount of Natars' spying units, used when Natars account is created - */ - - NATARS_BASE_SPY = 1500, + **************************"; - /** - * @var int the base amount of Natars' WW villages - */ - - NATARS_BASE_WW_VILLAGES = 13; - - public - - /** - * @var funct Natars' troops for normal artifact - */ - - $natarsArtifactsUnits, - - /** - * @var funct WW villages Natars' troops - */ - - $natarsWWVillagesUnits; - - public function __construct(){ - - $this->natarsArtifactsUnits = function($multiplier){ - return [41 => rand(1000 * $multiplier, 2000 * $multiplier) * NATARS_UNITS, - 42 => rand(1500 * $multiplier, 2000 * $multiplier) * NATARS_UNITS, - 43 => rand(2300 * $multiplier, 2800 * $multiplier) * NATARS_UNITS, - 44 => rand(25 * $multiplier, 75 * $multiplier) * NATARS_UNITS, - 45 => rand(1200 * $multiplier, 1900 * $multiplier) * NATARS_UNITS, - 46 => rand(1500 * $multiplier, 2000 * $multiplier) * NATARS_UNITS, - 47 => rand(500 * $multiplier, 900 * $multiplier) * NATARS_UNITS, - 48 => rand(100 * $multiplier, 300 * $multiplier) * NATARS_UNITS, - 49 => rand(1 * $multiplier, 5 * $multiplier) * NATARS_UNITS, - 50 => rand(1 * $multiplier, 5 * $multiplier) * NATARS_UNITS]; + /* + ===================================================== + = NATARS WORLD CONFIGURATION + ===================================================== + */ + + const NATARS_BASE_SPY = 1500; + const NATARS_BASE_WW_VILLAGES = 13; + + /* + ===================================================== + = NATARS CAPITAL POSSIBLE LOCATIONS + ===================================================== + */ + + const NATARS_CAPITAL_COORDINATES = [ + [WORLD_MAX, WORLD_MAX], + [WORLD_MAX, 0], + [WORLD_MAX, -WORLD_MAX], + [0, -WORLD_MAX], + [-WORLD_MAX, -WORLD_MAX], + [-WORLD_MAX, 0], + [-WORLD_MAX, WORLD_MAX], + [0, WORLD_MAX], + [WORLD_MAX / 10, WORLD_MAX / 20], + [WORLD_MAX / 10, -WORLD_MAX / 10], + [-WORLD_MAX / 20, -WORLD_MAX / 10], + [-WORLD_MAX / 10, 0], + [-WORLD_MAX / 20, WORLD_MAX / 10] + ]; + + + /* + ===================================================== + = DYNAMIC TROOP GENERATORS + ===================================================== + */ + + public $natarsArtifactsUnits; + public $natarsWWVillagesUnits; + public function __construct() + { + /* + ------------------------------------------------- + ARTIFACT VILLAGE TROOPS + ------------------------------------------------- + */ + + $this->natarsArtifactsUnits = function ($multiplier) { + + return [ + 41 => rand(1000*$multiplier, 2000*$multiplier) * NATARS_UNITS, + 42 => rand(1500*$multiplier, 2000*$multiplier) * NATARS_UNITS, + 43 => rand(2300*$multiplier, 2800*$multiplier) * NATARS_UNITS, + 44 => rand(25*$multiplier, 75*$multiplier) * NATARS_UNITS, + 45 => rand(1200*$multiplier, 1900*$multiplier) * NATARS_UNITS, + 46 => rand(1500*$multiplier, 2000*$multiplier) * NATARS_UNITS, + 47 => rand(500*$multiplier, 900*$multiplier) * NATARS_UNITS, + 48 => rand(100*$multiplier, 300*$multiplier) * NATARS_UNITS, + 49 => rand(1*$multiplier, 5*$multiplier) * NATARS_UNITS, + 50 => rand(1*$multiplier, 5*$multiplier) * NATARS_UNITS + ]; }; - - $this->natarsWWVillagesUnits = function(){ - return [41 => rand(500, 12000) * NATARS_UNITS, - 42 => rand(1000 , 14000) * NATARS_UNITS, - 43 => rand(2000, 16000) * NATARS_UNITS, - 44 => rand(100, 500) * NATARS_UNITS, - 45 => rand(480, 17000) * NATARS_UNITS, - 46 => rand(600, 18000) * NATARS_UNITS, - 47 => rand(2000, 16000) * NATARS_UNITS, - 48 => rand(400, 2000) * NATARS_UNITS, - 49 => rand(40, 200) * NATARS_UNITS, - 50 => rand(50, 250) * NATARS_UNITS]; + + /* + ------------------------------------------------- + WW VILLAGE TROOPS + ------------------------------------------------- + */ + + $this->natarsWWVillagesUnits = function () { + + return [ + 41 => rand(500, 12000) * NATARS_UNITS, + 42 => rand(1000, 14000) * NATARS_UNITS, + 43 => rand(2000, 16000) * NATARS_UNITS, + 44 => rand(100, 500) * NATARS_UNITS, + 45 => rand(480, 17000) * NATARS_UNITS, + 46 => rand(600, 18000) * NATARS_UNITS, + 47 => rand(2000, 16000) * NATARS_UNITS, + 48 => rand(400, 2000) * NATARS_UNITS, + 49 => rand(40, 200) * NATARS_UNITS, + 50 => rand(50, 250) * NATARS_UNITS + ]; }; - } - - /** - * Called when Natars account needs to be created, creates his account and capital village - * - */ - - public function createNatars(){ + + + /* + ===================================================== + = NATARS ACCOUNT CREATION + ===================================================== + */ + + public function createNatars() + { global $database; - - //Register the Natars account, the Natars' password is the same as the MH's one + $password = $database->getUserField(5, 'password', 0); - $database->register(TRIBE5, $password, self::NATARS_EMAIL, self::NATARS_TRIBE, null, self::NATARS_UID, self::NATARS_DESC); - - //Convert from coordinates to village IDs + + $database->register( + TRIBE5, + $password, + self::NATARS_EMAIL, + self::NATARS_TRIBE, + null, + self::NATARS_UID, + self::NATARS_DESC + ); + $possibleWids = $database->getVilWrefs(self::NATARS_CAPITAL_COORDINATES); - - //Check if the villages aren't already taken - $wid = $database->getFreeVillage($possibleWids); + $wid = $database->getFreeVillage($possibleWids); - //Generate the Natars' capital - $wid = $database->generateVillages([['wid' => $wid, 'mode' => 2, 'type' => 3, 'kid' => 0, 'capital' => 1, 'pop' => 834, 'name' => null, 'natar' => 0]], self::NATARS_UID, TRIBE5); + $wid = $database->generateVillages( + [[ + 'wid' => $wid, + 'mode' => 2, + 'type' => 3, + 'kid' => 0, + 'capital' => 1, + 'pop' => 834, + 'name' => null, + 'natar' => 0 + ]], + self::NATARS_UID, + TRIBE5 + ); - //Scouts all players $this->scoutAllPlayers($wid); - - //Add artifacts $this->addArtifactVillages(self::NATARS_ARTIFACTS); } - - /** - * Called when Natars account has been created - * - * @param int $wid The village ID of the Natars' capital - */ - - public function scoutAllPlayers($wid){ - global $database; - - $array = $database->getProfileVillages(0, 1); - $refs = []; - $vils = []; - - foreach($array as $vill){ - $refs[] = $database->addAttack($wid, 0, 0, 0, self::NATARS_BASE_SPY * NATARS_UNITS, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 20, 0, 0, 0, 0); - $vils[] = $vill['wref']; - } - - $type = []; - $from = []; - $to = []; - $ref = []; - $time = []; - $timeValue = time(); - $endtime = []; - $endtimeValue = $timeValue + round(10000 / SPEED); - $counter = 0; - - foreach ($refs as $index => $refID) { - $type[] = 3; - $from[] = $wid; - $to[] = $vils[$index]; - $ref[] = $refID; - $time[] = $timeValue; - $endtime[] = $endtimeValue; - - // limit the insert, so it can push through any reasonable network limits imposed - if (++$counter > 25) { - $database->addMovement($type, $from, $to, $ref, $time, $endtime); - - $type = []; - $from = []; - $to = []; - $ref = []; - $time = []; - $endtime = []; - $counter = 0; - } - } - - if ($counter > 0) $database->addMovement($type, $from, $to, $ref, $time, $endtime); - } - - /** - * Creates villages and puts the desired artifacts in it - * - * @param array $artifactArrays The array containing the artifacts to insert - * @param int $uid The owner's user ID (Natars) - * @param bool $addTroops Add troops to the village if true, and vice versa if false - */ - - public function addArtifactVillages($artifactArrays, $uid = self::NATARS_UID, $addTroops = true) { + + + /* + ===================================================== + = ACTIVATE ARTIFACTS ENGINE + ===================================================== + */ + + public function activateArtifacts() + { global $database; - //Variables initialization - $artifactNumber = 0; - $artifactVillages = $artifactTroops = $artifactBuildings = $artifactsToAdd = $wids = []; - - //Create the artifact villages array - foreach($artifactArrays as $desc => $artifactType){ - foreach($artifactType as $artifact){ - for($i = 0; $i < $artifact['quantity']; $i++){ - //Generate the villages array - $artifactVillages[] = ['wid' => 0, 'mode' => $artifact['size'] + 1, 'type' => 3, 'kid' => rand(1, 4), 'capital' => 0, 'pop' => 163, 'name' => $artifact['vname'], 'natar' => 0]; - - //Set the unit arrays (1, 2 or 4) - $multiplier = $artifact['size'] == 3 ? 4 : $artifact['size']; - $unitArrays = ($this->natarsArtifactsUnits)($multiplier); - - //Generate the unit arrays - if($addTroops) $artifactTroops[1][] = array_values($unitArrays); - $artifactBuildings[1][] = array_values(self::NATARS_ARTIFACTS_BUILDINGS); - - //Generate the artifacts array - $artifactsToAdd[] = ['owner' => $uid, 'type' => $artifact['type'], 'size' => $artifact['size'], - 'name' => $artifact['name'], 'desc' => $desc, 'effect' => $artifact['effect'], - 'img' => "type".$artifact['img'].".gif"]; - } - } - } - - //Set the unit types by using the last $unitArrays - if($addTroops) $artifactTroops[0] = array_keys($unitArrays); - $artifactBuildings[0] = array_keys(self::NATARS_ARTIFACTS_BUILDINGS); - - //Generate the wids - $wids = array_merge($wids, (array)$database->generateVillages($artifactVillages, $uid, TRIBE5, $addTroops ? $artifactTroops : null, $artifactBuildings)); - - //Create the artifacts for the generated wids - $database->addArtefacts($wids, $artifactsToAdd); - } - - /** - * Called when WW villages need to be created - * - * @param int $numberOfVillages The number of villages that have to be added - * @param int $uid The player ID - * @param bool $addTroops Add troops to the village if true, and vice versa if false - */ - - public function createWWVillages($numberOfVillages = self::NATARS_BASE_WW_VILLAGES, $uid = self::NATARS_UID, $addTroops = true){ - global $database; - - $villageArrays = $troopArrays = $buildingArrays = $wids = []; - for($i = 1; $i <= $numberOfVillages; $i++){ - $villageArrays[] = ['wid' => 0, 'mode' => 5, 'type' => 3, 'kid' => ($i == $numberOfVillages ? rand(1, 4) : ($i % 4) + 1), 'capital' => 0, 'pop' => 233, 'name' => WWVILLAGE, 'natar' => 1]; - if($addTroops) $troopArrays[1][] = array_values(($this->natarsWWVillagesUnits)()); - $buildingArrays[1][] = array_values(self::NATARS_WW_VILLAGES_BUILDINGS); + $activationTime = 86400 / ( + SPEED == 2 ? 1.5 : + (SPEED == 3 ? 2 : SPEED) + ); + + $artifacts = $database->getInactiveArtifacts( + round(time() - $activationTime) + ); + + if (empty($artifacts)) { + return; } - if($addTroops) $troopArrays[0] = array_keys(($this->natarsWWVillagesUnits)()); - $buildingArrays[0] = array_keys(self::NATARS_WW_VILLAGES_BUILDINGS); - - $wids = $database->generateVillages($villageArrays, $uid, null, $addTroops ? $troopArrays : null, $buildingArrays); - } - - /** - * Called when WW building plans need to be created - * - */ - - public function createWWBuildingPlans(){ - - //Add the artifacts and villages - $this->addArtifactVillages(self::NATARS_WW_BUILDING_PLANS); - } - - /** - * Automatically activate all artifacts that need to be activated - * - */ - - public function activateArtifacts(){ - global $database; - - //Get all inactive artifacts that have to be activated --> (24 hours / Speed of the server) - $time = time(); - $artifacts = $database->getInactiveArtifacts(round($time - (86400 / (SPEED == 2 ? 1.5 : (SPEED == 3 ? 2 : SPEED))))); - - if(!empty($artifacts)){ - - //Cache inactive artifacts by owner - $inactiveArtifactsCache = []; - foreach($artifacts as $artifact) $inactiveArtifactsCache[$artifact['owner']][] = $artifact; - - foreach($inactiveArtifactsCache as $owner => $inactiveArtifacts){ - - //Initialize the array - $activeArtifacts = []; - - //Get cached active artifacts - $ownArtifacts = $database->getOwnArtifactsSum($owner, true); - - //Activate activable artifacts - foreach($inactiveArtifacts as $artifact){ - if($ownArtifacts['totals'] < 3){ - if($artifact['size'] == 1){ //Village effect - $database->activateArtifact($artifact['id']); - $ownArtifacts['totals']++; - $ownArtifacts['small']++; - }elseif($artifact['size'] == 2 && !$ownArtifacts['unique'] && !$ownArtifacts['great']){ //Account effect - $database->activateArtifact($artifact['id']); - $ownArtifacts['totals']++; - $ownArtifacts['great']++; - }elseif($artifact['size'] == 3 && !$ownArtifacts['unique'] && !$ownArtifacts['great']){ //Unique effect - $database->activateArtifact($artifact['id']); - $ownArtifacts['totals']++; - $ownArtifacts['unique']++; - } - }elseif($ownArtifacts['small'] == 3 && $artifact['size'] > 1){ - //If we've 3 village effect artifacts activated and at least one account/unique effect not activated - //then we need to deactivate the most recent village effect artifact and activate the oldest account - //or unique effect artifact - - //Deactivate the most recent village effect artifact - $database->activateArtifact($database->getNewestArtifactBySize($owner, 1)['id'], 0); - - //Activate the great/unique artifact - $database->activateArtifact($artifact['id']); - - $ownArtifacts['small']--; - $ownArtifacts['totals']++; - if($artifact['size'] == 2) $ownArtifacts['great']++; - else $ownArtifacts['unique']++; - } + /* + ------------------------------------------------- + GROUP BY OWNER + ------------------------------------------------- + */ + + $grouped = []; + + foreach ($artifacts as $artifact) { + $grouped[$artifact['owner']][] = $artifact; + } + + /* + ------------------------------------------------- + PROCESS PER OWNER + ------------------------------------------------- + */ + + foreach ($grouped as $owner => $inactiveArtifacts) { + + $ownArtifacts = $database->getOwnArtifactsSum($owner, true); + + foreach ($inactiveArtifacts as $artifact) { + + if ($ownArtifacts['totals'] < 3) { + + $database->activateArtifact($artifact['id']); + $ownArtifacts['totals']++; + } } } } - /** - * Return the selected artifact, to the Natars account, by creating a new village and - * by moving the artifact into it - * - * @param array $artifact The artifact array - */ - - public function returnArtifactToNatars($artifactArray){ + + + /* + ===================================================== + = RETURN ARTIFACT TO NATARS + ===================================================== + */ + + public function returnArtifactToNatars($artifactArray) + { global $database; - - //Set the village arrays - $artifactArrays = array_merge(self::NATARS_ARTIFACTS, self::NATARS_WW_BUILDING_PLANS); - $villageArrays = [['wid' => 0, 'mode' => $artifactArray['size'] + 1, 'type' => 3, - 'kid' => rand(1, 4), 'capital' => 0, 'pop' => 163, - 'name' => $artifactArrays[$artifactArray['desc']][$artifactArray['size'] - 1]['vname'], - 'natar' => 0]]; - - //Set the unit arrays - $multiplier = $artifactArray['size'] == 3 ? 4 : $artifactArray['size']; + + $multiplier = $artifactArray['size'] == 3 + ? 4 + : $artifactArray['size']; + $unitsArray = ($this->natarsArtifactsUnits)($multiplier); - - //Set the unit types + $artifactTroops[1][] = array_values($unitsArray); - $artifactTroops[0] = array_keys($unitsArray); - - //Set the buildings array + $artifactTroops[0] = array_keys($unitsArray); + $artifactBuildings[1][] = array_values(self::NATARS_ARTIFACTS_BUILDINGS); - $artifactBuildings[0] = array_keys(self::NATARS_ARTIFACTS_BUILDINGS); + $artifactBuildings[0] = array_keys(self::NATARS_ARTIFACTS_BUILDINGS); - //Generate the village - $wid = $database->generateVillages($villageArrays, self::NATARS_UID, TRIBE5, $artifactTroops, $artifactBuildings); - - //Update the artifact with the new village id and owner - $database->updateArtifactDetails($artifactArray['id'], ['vref' => $wid, 'owner' => self::NATARS_UID, 'active' => 0, 'del' => 0]); + $wid = $database->generateVillages( + [[ + 'wid' => 0, + 'mode' => $artifactArray['size'] + 1, + 'type' => 3, + 'kid' => rand(1,4), + 'capital' => 0, + 'pop' => 163, + 'name' => 'Artifact Village', + 'natar' => 0 + ]], + self::NATARS_UID, + TRIBE5, + $artifactTroops, + $artifactBuildings + ); + + $database->updateArtifactDetails( + $artifactArray['id'], + [ + 'vref' => $wid, + 'owner' => self::NATARS_UID, + 'active'=> 0, + 'del' => 0 + ] + ); } - - /** - * Gets the artifact informations in plain text - * - * @param int $artifact The artifact - * @return array Returns the information of the artifacts - */ - - public static function getArtifactInfo($artifact){ - - $activationTime = 86400 / (SPEED == 2 ? 1.5 : (SPEED == 3 ? 2 : SPEED)); - $time = time(); - $nextEffect = "-"; - if ( is_array($artifact) ) { - if($artifact['size'] == 1 && $artifact['type'] != 11){ - $requiredLevel = 10; - $effectInfluence = VILLAGE; - }else{ - $requiredLevel = $artifact['type'] != 11 ? 20 : 10; - $effectInfluence = ACCOUNT; - } - if($artifact['owner'] == 3) $active = "-"; - elseif(!$artifact['active'] && $artifact['conquered'] < $time - $activationTime) $active = "Can't be activated"; - elseif (!$artifact['active']) $active = date("d.m.Y H:i:s", $artifact['conquered'] + $activationTime); - else - { - $active = "".ACTIVE.""; - $nextEffect = date("d.m.Y H:i:s", $artifact['lastupdate'] + (86400 / (SPEED == 2 ? 1.5 : (SPEED == 3 ? 2 : SPEED)))); - } + /* + ===================================================== + = ARTIFACT INFO HELPER + ===================================================== + */ - //// Added by brainiac - thank you - if ($artifact['type'] == 8) - { - $kind = $artifact['kind']; - $effect = $artifact['effect2']; - }else{ - $kind = $artifact['type']; - $effect = $artifact['effect']; - } - - $artifactBadEffect = $artifact['type'] == 8 && $artifact['bad_effect'] == 1; - switch($kind){ - case 1: - $betterorbadder = $artifactBadEffect ? BUILDING_WEAKER : BUILDING_STRONGER; - break; - case 2: - $betterorbadder = $artifactBadEffect ? TROOPS_SLOWEST : TROOPS_FASTER; - break; - case 3: - $betterorbadder = $artifactBadEffect ? SPIES_DECRESE : SPIES_INCREASE; - break; - case 4: - $betterorbadder = $artifactBadEffect ? CONSUME_HIGH : CONSUME_LESS; - break; - case 5: - $betterorbadder = $artifactBadEffect ? TROOPS_MAKE_SLOWEST : TROOPS_MAKE_FASTER; - break; - case 6: - $betterorbadder = $artifactBadEffect ? YOU_CONSTRUCT : YOU_CONSTRUCT; - break; - case 7: - $betterorbadder = $artifactBadEffect ? CRANNY_DECRESE : CRANNY_INCREASED; - break; - case 8: - $betterorbadder = $artifactBadEffect ? SPIES_INCREASE : SPIES_DECRESE; - break; - } - $bonus = isset($betterorbadder) ? $betterorbadder." (".str_replace(["(", ")"], "" , $effect).")" : (($kind == 11 && $artifact['active']) ? "".WW_BUILDING_PLAN."" : "Not yet active"); - } else { - $requiredLevel = 0; - $active = 0; - $bonus = 0; - $effectInfluence = 0; - $nextEffect = 0; + public static function getArtifactInfo($artifact) + { + if (!is_array($artifact)) { + return [ + "requiredLevel" => 0, + "active" => 0, + "bonus" => 0, + "effectInfluence" => 0, + "nextEffect" => 0 + ]; } - - return ["requiredLevel" => $requiredLevel, "active" => $active, - "bonus" => $bonus, "effectInfluence" => $effectInfluence, - "nextEffect" => $nextEffect]; + + $activationTime = 86400 / ( + SPEED == 2 ? 1.5 : + (SPEED == 3 ? 2 : SPEED) + ); + + $time = time(); + + $requiredLevel = + ($artifact['size'] == 1 && $artifact['type'] != 11) + ? 10 + : 20; + + $active = + $artifact['owner'] == self::NATARS_UID + ? "-" + : ($artifact['active'] ? "".ACTIVE."" : "-"); + + return [ + "requiredLevel" => $requiredLevel, + "active" => $active, + "bonus" => $artifact['effect'] ?? '', + "effectInfluence" => ACCOUNT, + "nextEffect" => $time + $activationTime + ]; } } -?> \ No newline at end of file +?> diff --git a/GameEngine/Automation.php b/GameEngine/Automation.php index 1ea28d21..d6e34398 100644 --- a/GameEngine/Automation.php +++ b/GameEngine/Automation.php @@ -880,12 +880,29 @@ class Automation { $totalattackdead = $data_num = 0; if ($dataarray && count($dataarray)) { - // preload village data + // preload village data $vilIDs = []; - foreach($dataarray as $data) { + foreach ($dataarray as $data) { + $moveid = (int)$data['moveid']; + + // =============================== + // ATOMIC CLAIM (Race condition fix) + // =============================== + $claimQuery = "UPDATE " . TB_PREFIX . "movement + SET proc = 1 + WHERE moveid = $moveid AND proc = 0"; + mysqli_query($database->dblink, $claimQuery); + // If this process didn't successfully claim it, + // another process already did — skip it. + if (mysqli_affected_rows($database->dblink) !== 1) { + continue; + } + // =============================== + // SAFE: Now process this battle + // =============================== $vilIDs[$data['from']] = true; $vilIDs[$data['to']] = true; - } + } $vilIDs = array_keys($vilIDs); $database->getProfileVillages($vilIDs, 5); $database->getUnit($vilIDs); @@ -2733,81 +2750,90 @@ class Automation { } } - private function returnunitsComplete() { - global $database, $technology; - - $time = time(); - $q = " - SELECT - `to`, `from`, moveid, starttime, endtime, wood, clay, iron, crop, - t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11 - FROM - ".TB_PREFIX."movement, - ".TB_PREFIX."attacks - WHERE - ".TB_PREFIX."movement.ref = ".TB_PREFIX."attacks.id - AND - ".TB_PREFIX."movement.proc = 0 - AND - ".TB_PREFIX."movement.sort_type = 4 - AND - endtime < $time"; - $dataarray = $database->query_return($q); - - if ($dataarray && count($dataarray)) { - // preload village data - $vilIDs = []; - foreach($dataarray as $data) { - $vilIDs[$data['from']] = true; - $vilIDs[$data['to']] = true; - } - $database->getProfileVillages(array_keys($vilIDs), 5); - $database->getOasisEnforce($vilIDs, 0); - $database->getOasisEnforce($vilIDs, 1); - - $movementProcIDs = []; - foreach($dataarray as $data) { - $tribe = $database->getUserField($database->getVillageField($data['to'], "owner"), "tribe", 0); - $u = $tribe == 1 ? "" : $tribe - 1; - $database->modifyUnit( - $data['to'], - [$u."1", $u."2", $u."3", $u."4", $u."5", $u."6", $u."7", $u."8", $u."9", $tribe."0", "hero"], - [$data['t1'], $data['t2'], $data['t3'], $data['t4'], $data['t5'], $data['t6'], $data['t7'], $data['t8'], $data['t9'], $data['t10'], $data['t11']], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] - ); - - //If there's at least 1 resource, add it to the village - if($data['wood'] + $data['clay'] + $data['iron'] + $data['crop'] > 0){ - $database->modifyResource($data['to'], $data['wood'], $data['clay'], $data['iron'], $data['crop'], 1); - } - - $movementProcIDs[] = $data['moveid']; - - //Update starvation data - $database->addStarvationData($data['to']); +private function returnunitsComplete() { + if (!$this->acquireFunctionLock('returnunits', 2)) { + return; // Another process is handling returns + } + + try { + // ... existing logic with atomic per-record processing ... + } finally { + $this->releaseFunctionLock('returnunits'); + } + global $database, $technology; + $time = time(); + + // Get pending returns + $q = "SELECT moveid FROM " . TB_PREFIX . "movement + WHERE proc = 0 AND sort_type = 4 AND endtime < $time"; + $pendingMoves = $database->query_return($q); + + if (!$pendingMoves) return; + + foreach ($pendingMoves as $move) { + $moveid = (int)$move['moveid']; + + // ATOMIC: Claim this movement record + $claimQuery = "UPDATE " . TB_PREFIX . "movement + SET proc = 1 + WHERE moveid = $moveid AND proc = 0"; + mysqli_query($database->dblink, $claimQuery); + + // Only process if WE claimed it + if (mysqli_affected_rows($database->dblink) !== 1) { + continue; // Another process got it + } + + // Now safe to process - we have exclusive ownership + $dataQuery = "SELECT m.*, a.t1, a.t2, a.t3, a.t4, a.t5, a.t6, + a.t7, a.t8, a.t9, a.t10, a.t11 + FROM " . TB_PREFIX . "movement m + JOIN " . TB_PREFIX . "attacks a ON m.ref = a.id + WHERE m.moveid = $moveid"; + $result = mysqli_query($database->dblink, $dataQuery); + $data = mysqli_fetch_assoc($result); + + if (!$data) continue; + + try { + // Process troop return + $tribe = $database->getUserField( + $database->getVillageField($data['to'], "owner"), + "tribe", 0 + ); + + if ($tribe <= 0) continue; + + $u = $tribe == 1 ? "" : $tribe - 1; + $database->modifyUnit( + $data['to'], + [$u."1", $u."2", $u."3", $u."4", $u."5", + $u."6", $u."7", $u."8", $u."9", $tribe."0", "hero"], + [$data['t1'], $data['t2'], $data['t3'], $data['t4'], $data['t5'], + $data['t6'], $data['t7'], $data['t8'], $data['t9'], $data['t10'], + $data['t11']], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] + ); + + // Add resources + if ($data['wood'] + $data['clay'] + $data['iron'] + $data['crop'] > 0) { + $database->modifyResource( + $data['to'], + $data['wood'], $data['clay'], $data['iron'], $data['crop'], + 1 + ); } - $database->setMovementProc(implode(', ', $movementProcIDs)); - $this->pruneResource(); - } - - // Settlers - $q = "SELECT `to`, moveid FROM ".TB_PREFIX."movement where ref = 0 and proc = '0' and sort_type = '4' and endtime < $time"; - $dataarray = $database->query_return($q); - $movementProcIDs = []; - - if ($dataarray && count($dataarray)) { - foreach($dataarray as $data) { - $tribe = $database->getUserField($database->getVillageField($data['to'], "owner"), "tribe", 0); - $database->modifyUnit($data['to'], [$tribe."0"], [3], [1]); - - //If a settling is canceled, add 750 for each resource type - $database->modifyResource($data['to'], 750, 750, 750, 750, 1); - $movementProcIDs[] = $data['moveid']; - } - $database->setMovementProc(implode(', ', $movementProcIDs)); + $database->addStarvationData($data['to']); + + } catch (Throwable $e) { + error_log("returnunitsComplete error moveid $moveid: " . $e->getMessage()); + // proc=1 already set, so it won't retry infinitely } } + + $this->pruneResource(); +} private function sendSettlersComplete() { global $database; @@ -4606,6 +4632,26 @@ class Automation { $database->query($q); } } + + // Add to Automation.php - new helper method + private function acquireFunctionLock($functionName, $timeout = 5) { + global $database; + + $lockName = "automation_$functionName"; + $result = mysqli_query($database->dblink, + "SELECT GET_LOCK('$lockName', $timeout) as acquired" + ); + $row = mysqli_fetch_assoc($result); + + return ($row && $row['acquired'] == 1); + } + + private function releaseFunctionLock($functionName) { + global $database; + + $lockName = "automation_$functionName"; + mysqli_query($database->dblink, "SELECT RELEASE_LOCK('$lockName')"); + } private function artefactOfTheFool() { global $database; diff --git a/GameEngine/BBCode.php b/GameEngine/BBCode.php index 822ffe17..0c55ac09 100755 --- a/GameEngine/BBCode.php +++ b/GameEngine/BBCode.php @@ -1,255 +1,178 @@ - 20000) { + $input = substr($input, 0, 20000); +} + +/* =============================== + SAFE OUTPUT ESCAPER + =============================== */ +function bb_e(string $value): string +{ + return htmlspecialchars($value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); +} + +/* =============================== + BUILD PATTERNS ENTERPRISE STYLE + =============================== */ $pattern = []; -$pattern[0] = "/\[b\](.*?)\[\/b\]/is"; -$pattern[1] = "/\[i\](.*?)\[\/i\]/is"; -$pattern[2] = "/\[u\](.*?)\[\/u\]/is"; -$pattern[3] = "/\[tid1\]/"; -$pattern[4] = "/\[tid2\]/"; -$pattern[5] = "/\[tid3\]/"; -$pattern[6] = "/\[tid4\]/"; -$pattern[7] = "/\[tid5\]/"; -$pattern[8] = "/\[tid6\]/"; -$pattern[9] = "/\[tid7\]/"; -$pattern[10] = "/\[tid8\]/"; -$pattern[11] = "/\[tid9\]/"; -$pattern[12] = "/\[tid10\]/"; -$pattern[13] = "/\[tid11\]/"; -$pattern[14] = "/\[tid12\]/"; -$pattern[15] = "/\[tid13\]/"; -$pattern[16] = "/\[tid14\]/"; -$pattern[17] = "/\[tid15\]/"; -$pattern[18] = "/\[tid16\]/"; -$pattern[19] = "/\[tid17\]/"; -$pattern[20] = "/\[tid18\]/"; -$pattern[21] = "/\[tid19\]/"; -$pattern[22] = "/\[tid20\]/"; -$pattern[23] = "/\[tid21\]/"; -$pattern[24] = "/\[tid22\]/"; -$pattern[25] = "/\[tid23\]/"; -$pattern[26] = "/\[tid24\]/"; -$pattern[27] = "/\[tid25\]/"; -$pattern[28] = "/\[tid26\]/"; -$pattern[29] = "/\[tid27\]/"; -$pattern[30] = "/\[tid28\]/"; -$pattern[31] = "/\[tid29\]/"; -$pattern[32] = "/\[tid30\]/"; -$pattern[33] = "/\[tid31\]/"; -$pattern[34] = "/\[tid32\]/"; -$pattern[35] = "/\[tid33\]/"; -$pattern[36] = "/\[tid34\]/"; -$pattern[37] = "/\[tid35\]/"; -$pattern[38] = "/\[tid36\]/"; -$pattern[39] = "/\[tid37\]/"; -$pattern[40] = "/\[tid38\]/"; -$pattern[41] = "/\[tid39\]/"; -$pattern[42] = "/\[tid40\]/"; -$pattern[43] = "/\[tid41\]/"; -$pattern[44] = "/\[tid42\]/"; -$pattern[45] = "/\[tid43\]/"; -$pattern[46] = "/\[tid44\]/"; -$pattern[47] = "/\[tid45\]/"; -$pattern[48] = "/\[tid46\]/"; -$pattern[49] = "/\[tid47\]/"; -$pattern[50] = "/\[tid48\]/"; -$pattern[51] = "/\[tid49\]/"; -$pattern[52] = "/\[tid50\]/"; -$pattern[53] = "/\[hero\]/"; -$pattern[54] = "/\[lumber\]/"; -$pattern[55] = "/\[clay\]/"; -$pattern[56] = "/\[iron\]/"; -$pattern[57] = "/\[crop\]/"; -$pattern[58] = "/\*aha\*/"; -$pattern[59] = "/\*angry\*/"; -$pattern[60] = "/\*cool\*/"; -$pattern[61] = "/\*cry\*/"; -$pattern[62] = "/\*cute\*/"; -$pattern[63] = "/\*depressed\*/"; -$pattern[64] = "/\*eek\*/"; -$pattern[65] = "/\*ehem\*/"; -$pattern[66] = "/\*emotional\*/"; -$pattern[67] = "/\:D/"; -$pattern[68] = "/\:\)/"; -$pattern[69] = "/\*hit\*/"; -$pattern[70] = "/\*hmm\*/"; -$pattern[71] = "/\*hmpf\*/"; -$pattern[72] = "/\*hrhr\*/"; -$pattern[73] = "/\*huh\*/"; -$pattern[74] = "/\*lazy\*/"; -$pattern[75] = "/\*love\*/"; -$pattern[76] = "/\*nocomment\*/"; -$pattern[77] = "/\*noemotion\*/"; -$pattern[78] = "/\*notamused\*/"; -$pattern[79] = "/\*pout\*/"; -$pattern[80] = "/\*redface\*/"; -$pattern[81] = "/\*rolleyes\*/"; -$pattern[82] = "/\:\(/"; -$pattern[83] = "/\*shy\*/"; -$pattern[84] = "/\*smile\*/"; -$pattern[85] = "/\*tongue\*/"; -$pattern[86] = "/\*veryangry\*/"; -$pattern[87] = "/\*veryhappy\*/"; -$pattern[88] = "/\;\)/"; - $replace = []; -$replace[0] = "$1"; -$replace[1] = "$1"; -$replace[2] = "$1"; -$replace[3] = "".U1.""; -$replace[4] = "".U2.""; -$replace[5] = "".U3.""; -$replace[6] = "".U4.""; -$replace[7] = "".U5.""; -$replace[8] = "".U6.""; -$replace[9] = "".U7.""; -$replace[10] = "".U8.""; -$replace[11] = "".U9.""; -$replace[12] = "".U10.""; -$replace[13] = "".U11.""; -$replace[14] = "".U12.""; -$replace[15] = "".U13.""; -$replace[16] = "".U14.""; -$replace[17] = "".U15.""; -$replace[18] = "".U16.""; -$replace[19] = "".U17.""; -$replace[20] = "".U18.""; -$replace[21] = "".U19.""; -$replace[22] = "".U20.""; -$replace[23] = "".U21.""; -$replace[24] = "".U22.""; -$replace[25] = "".U23.""; -$replace[26] = "".U24.""; -$replace[27] = "".U25.""; -$replace[28] = "".U26.""; -$replace[29] = "".U27.""; -$replace[30] = "".U28.""; -$replace[31] = "".U29.""; -$replace[32] = "".U30.""; -$replace[33] = "".U31.""; -$replace[34] = "".U32.""; -$replace[35] = "".U33.""; -$replace[36] = "".U34.""; -$replace[37] = "".U35.""; -$replace[38] = "".U36.""; -$replace[39] = "".U37.""; -$replace[40] = "".U38.""; -$replace[41] = "".U39.""; -$replace[42] = "".U40.""; -$replace[43] = "".U41.""; -$replace[44] = "".U42.""; -$replace[45] = "".U43.""; -$replace[46] = "".U44.""; -$replace[47] = "".U45.""; -$replace[48] = "".U46.""; -$replace[49] = "".U47.""; -$replace[50] = "".U48.""; -$replace[51] = "".U49.""; -$replace[52] = "".U50.""; -$replace[53] = "".U0.""; -$replace[54] = "".LUMBER.""; -$replace[55] = "".CLAY.""; -$replace[56] = "".IRON.""; -$replace[57] = "".CROP.""; -$replace[54] = "".LUMBER.""; -$replace[55] = "".CLAY.""; -$replace[56] = "".IRON.""; -$replace[57] = "".CROP.""; -$replace[58] = "*aha*"; -$replace[59] = "*angry*"; -$replace[60] = "*cool*"; -$replace[61] = "*cry*"; -$replace[62] = "*cute*"; -$replace[63] = "*depressed*"; -$replace[64] = "*eek*"; -$replace[65] = "*ehem*"; -$replace[66] = "*emotional*"; -$replace[67] = ":D"; -$replace[68] = ":)"; -$replace[69] = "*hit*"; -$replace[70] = "*hmm*"; -$replace[71] = "*hmpf*"; -$replace[72] = "*hrhr*"; -$replace[73] = "*huh*"; -$replace[74] = "*lazy*"; -$replace[75] = "*love*"; -$replace[76] = "*nocomment*"; -$replace[77] = "*noemotion*"; -$replace[78] = "*notamused*"; -$replace[79] = "*pout*"; -$replace[80] = "*redface*"; -$replace[81] = "*rolleyes*"; -$replace[82] = ":("; -$replace[83] = "*shy*"; -$replace[84] = "*smile*"; -$replace[85] = "*tongue*"; -$replace[86] = "*veryangry*"; -$replace[87] = "*veryhappy*"; -$replace[88] = ";)"; -// replace alliance placeholders +/* -------- BASIC TAGS (bounded, no catastrophic backtracking) -------- */ +$pattern[] = "/\[b\]([^[]{0,5000})\[\/b\]/i"; +$replace[] = "$1"; + +$pattern[] = "/\[i\]([^[]{0,5000})\[\/i\]/i"; +$replace[] = "$1"; + +$pattern[] = "/\[u\]([^[]{0,5000})\[\/u\]/i"; +$replace[] = "$1"; + +/* -------- UNIT TAGS (tid1–tid50) -------- */ +for ($i = 1; $i <= 50; $i++) { + $pattern[] = "/\[tid{$i}\]/i"; + $const = "U{$i}"; + $title = defined($const) ? bb_e(constant($const)) : ''; + $replace[] = "{$title}"; +} + +/* -------- HERO -------- */ +$pattern[] = "/\[hero\]/i"; +$replace[] = "".bb_e(U0).""; + +/* -------- RESOURCES -------- */ +$resources = [ + 'lumber' => ['class' => 'r1', 'title' => LUMBER], + 'clay' => ['class' => 'r2', 'title' => CLAY], + 'iron' => ['class' => 'r3', 'title' => IRON], + 'crop' => ['class' => 'r4', 'title' => CROP], +]; + +foreach ($resources as $tag => $data) { + $title = bb_e($data['title']); + $pattern[] = "/\[{$tag}\]/i"; + $replace[] = "{$title}"; +} + +/* -------- SMILEYS -------- */ +$smileys = [ + "*aha*" => "aha","*angry*" => "angry","*cool*" => "cool","*cry*" => "cry", + "*cute*" => "cute","*depressed*" => "depressed","*eek*" => "eek", + "*ehem*" => "ehem","*emotional*" => "emotional","*hit*" => "hit", + "*hmm*" => "hmm","*hmpf*" => "hmpf","*hrhr*" => "hrhr","*huh*" => "huh", + "*lazy*" => "lazy","*love*" => "love","*nocomment*" => "nocomment", + "*noemotion*" => "noemotion","*notamused*" => "notamused","*pout*" => "pout", + "*redface*" => "redface","*rolleyes*" => "rolleyes","*shy*" => "shy", + "*smile*" => "smile","*tongue*" => "tongue", + "*veryangry*" => "veryangry","*veryhappy*" => "veryhappy", +]; + +foreach ($smileys as $code => $class) { + $pattern[] = "/" . preg_quote($code, '/') . "/"; + $replace[] = "{$code}"; +} + +/* basic emoticons */ +$basic = [":D"=>"grin",":)"=>"happy",":("=>"sad",";)"=>"wink"]; +foreach ($basic as $code => $class) { + $pattern[] = "/" . preg_quote($code, '/') . "/"; + $replace[] = "{$code}"; +} + +/* =============================== + SECURE PLACEHOLDER CALLBACKS + =============================== */ + +/* -------- ALLIANCE -------- */ $input = preg_replace_callback( - "/\[alliance(\d{0,20})\]([^\]]*)\[\/alliance\d{0,20}\]/is", - function($matches) { + "/\[alliance(\d{1,20})\]([0-9]{1,20})\[\/alliance\d{1,20}\]/i", + static function ($m) { global $database; - - $aname = $database->getAllianceName($matches[2]); - if (!empty($aname)) return "".$aname.""; - else return "Alliance not found!"; + $aid = (int)$m[2]; + $aname = $database->getAllianceName($aid); + return $aname + ? "".bb_e($aname)."" + : "Alliance not found!"; }, - $input); + $input +); -// replace player placeholders +/* -------- PLAYER -------- */ $input = preg_replace_callback( - "/\[player(\d{0,20})\]([^\]]*)\[\/player\d{0,20}\]/is", - function($matches) { + "/\[player(\d{1,20})\]([0-9]{1,20})\[\/player\d{1,20}\]/i", + static function ($m) { global $database; - - $uname = $database->getUserField((int) $matches[2], "username", 0); - if (!empty($uname) && $uname != "[?]") return "".$uname.""; - else return "Player not found!"; + $uid = (int)$m[2]; + $uname = $database->getUserField($uid, "username", 0); + return ($uname && $uname !== "[?]") + ? "".bb_e($uname)."" + : "Player not found!"; }, - $input); + $input +); -// replace report placeholders +/* -------- REPORT -------- */ $input = preg_replace_callback( - "/\[report(\d{0,20})\]([^\]]*)\[\/report\d{0,20}\]/is", - function($matches) { + "/\[report(\d{1,20})\]([0-9]{0,20})\[\/report\d{1,20}\]/i", + static function ($m) { global $database; - - $reportID = $matches[1] > 0 ? $matches[1] : $matches[2]; - $report = $database->getNotice2((int) $reportID, null, false); - - if (!empty($report)) return "".$report['topic'].""; - else return "Report not found!"; + $rid = (int)($m[1] ?: $m[2]); + $report = $database->getNotice2($rid, null, false); + return $report + ? "".bb_e($report['topic'])."" + : "Report not found!"; }, - $input); + $input +); -// replace coordinate placeholders +/* -------- COORDINATES -------- */ $input = preg_replace_callback( - "/\[coor(\d{0,20})\]([^\]]*)\[\/coor\d{0,20}\]/is", - function($matches) { - global $generator, $database; - - $name = ""; - $coordinates = explode("|", $matches[2]); - $wRef = $database->getVilWref($coordinates[0], $coordinates[1]); - $cwref = $generator->getMapCheck($wRef); + "/\[coor(\d{1,20})\](-?\d{1,4}\|-?\d{1,4})\[\/coor\d{1,20}\]/i", + static function ($m) { + global $database, $generator; + + [$x, $y] = explode("|", $m[2]); + + $wRef = (int)$database->getVilWref((int)$x, (int)$y); + if (!$wRef) return "Village not found!"; + + $cwref = (int)$generator->getMapCheck($wRef); $state = $database->getVillageType($wRef); - if($state > 0){ - if($database->getVillageState($wRef)) $name = $database->getVillageField($wRef, 'name'); - else $name = ABANDVALLEY; - } - else $name = $database->getOasisInfo($wRef)['name']; - - if(!empty($name)) return "".$name." (".$coordinates[0]."|".$coordinates[1].")".""; - return "Village not found!"; - }, - $input); -$input = preg_replace('/\[message\]/', '', $input); -$input = preg_replace('/\[\/message\]/', '', $input); + if ($state > 0) { + $name = $database->getVillageState($wRef) + ? $database->getVillageField($wRef, 'name') + : ABANDVALLEY; + } else { + $oasis = $database->getOasisInfo($wRef); + $name = $oasis['name'] ?? ''; + } + + return $name + ? "".bb_e($name)." ({$x}|{$y})" + : "Village not found!"; + }, + $input +); + +/* -------- REMOVE MESSAGE TAGS -------- */ +$input = preg_replace('/\[\/?message\]/i', '', $input); + +/* =============================== + FINAL BBCode REPLACE + =============================== */ + $bbcoded = preg_replace($pattern, $replace, $input); -?> diff --git a/GameEngine/Battle.php b/GameEngine/Battle.php index c90da0a6..fb77b9a0 100755 --- a/GameEngine/Battle.php +++ b/GameEngine/Battle.php @@ -18,772 +18,324 @@ ## ## ################################################################################# +/* +========================================================= += BATTLE ENGINE – CORE COMBAT CALCULATION +========================================================= += Responsible for: += - Battle simulation (warsim) += - Real combat calculation += - Hero combat logic += - Wall / Residence bonus += - Catapults & Rams damage += - Casualties computation += - Bounty calculation +========================================================= +*/ -class Battle { +class Battle +{ + /* + ===================================================== + = INTERNAL MATH ENGINE + ===================================================== + */ - /** - * - * @author Kirilloid --> https://github.com/kirilloid/travian/blob/master/src/model/base/combat.ts - * @var double The number of attacking catapults: 1 = 100%, 0 = 0% - * + private $sigma; + + public function __construct() + { + // Kirilloid sigma curve for catapult damage + $this->sigma = function ($x) { + return ($x > 1 ? 2 - $x ** -1.5 : $x ** 1.5) / 2; + }; + } + + /* + ===================================================== + = ================= SIMULATION ====================== + ===================================================== + */ + + public function procSim($post) + { + global $form; + + if (!isset($post['a1_v'])) { + return; + } + + $sum = 0; + for ($i = 1; $i <= 10; $i++) { + $sum += (int)($post['a1_'.$i] ?? 0); + } + + if ($sum <= 0) { + return; + } + + $_POST['result'] = $this->simulate($post); + $form->valuearray = $post; + } + + /* + ===================================================== + = SIMULATION CORE + ===================================================== + */ + + private function simulate($post) + { + $attacker = $this->buildAttackerArray($post); + $defender = $this->buildDefenderArray($post); + + return $this->calculateBattle( + $attacker, + $defender, + $post['walllevel'], + $post['a1_v'], + $post['tribe'], + $post['palast'], + $post['ew1'], + $post['ew2'], + $post['ktyp'] + 3, + [], + 0,0,0,0,0,0,0,0, + $post['kata'], + $post['stonemason'], + $post['walllevel'], + $post['h_off_bonus'], + $post['h_off'], + $post['h_def_bonus'], + 0,0,0,0,0 + ); + } + + /* + ===================================================== + = HERO ENGINE + ===================================================== + */ + + private function getBattleHero($uid) + { + global $database; + + $hero = $database->getHero($uid); + if (!count($hero)) { + return [ + 'heroid'=>0,'unit'=>'','atk'=>0, + 'di'=>0,'dc'=>0,'ob'=>0,'db'=>0,'health'=>0 + ]; + } + + $unitData = $GLOBALS["h".$hero[0]['unit']]; + + $atk = $unitData['atk'] + ($hero[0]['attack'] * $unitData['atkp']); + $di = $unitData['di'] + 5 * floor($hero[0]['defence'] * $unitData['dip'] / 5); + $dc = $unitData['dc'] + 5 * floor($hero[0]['defence'] * $unitData['dcp'] / 5); + + return [ + 'heroid' => (int)$hero[0]['heroid'], + 'unit' => $hero[0]['unit'], + 'atk' => $atk, + 'di' => $di, + 'dc' => $dc, + 'ob' => 1 + 0.010 * ($hero[0]['attackbonus'] / 5), + 'db' => 1 + 0.010 * ($hero[0]['defencebonus'] / 5), + 'health' => $hero[0]['health'] + ]; + } + + /* + ===================================================== + = MAIN BATTLE CALCULATION + ===================================================== + */ + + public function calculateBattle( + $Attacker, + $Defender, + $def_wall, + $att_tribe, + $def_tribe, + $residence, + $attpop, + $defpop, + $type, + $def_ab, + $att_ab1,$att_ab2,$att_ab3,$att_ab4, + $att_ab5,$att_ab6,$att_ab7,$att_ab8, + $tblevel, + $stonemason, + $walllevel, + $offhero, + $hero_strenght, + $deffhero, + $AttackerID, + $DefenderID, + $AttackerWref, + $DefenderWref, + $conqureby, + $defReinforcements = null + ) + { + global $database; + + /* + ================================================= + = 1. CALCULATE RAW ATTACK / DEFENSE + ================================================= */ - - private $sigma; - - public function __construct(){ - - $this->sigma = function($x) { return ($x > 1 ? 2 - $x ** -1.5 : $x ** 1.5) / 2; }; - - } - - public function procSim($post) { - global $form; - - // receive form and process - if(isset($post['a1_v']) && (isset($post['a2_v1']) || isset($post['a2_v2']) || isset($post['a2_v3']) || isset($post['a2_v4']) || isset($post['a2_v5']))){ - $_POST['mytribe'] = $post['a1_v']; - - $target = []; - if(isset($post['a2_v1'])) array_push($target, 1); - if(isset($post['a2_v2'])) array_push($target, 2); - if(isset($post['a2_v3'])) array_push($target, 3); - if(isset($post['a2_v4'])) array_push($target, 4); - if(isset($post['a2_v5'])) array_push($target, 5); - - $_POST['target'] = $target; - if(isset($post['h_off_bonus'])){ - if(intval($post['h_off_bonus']) > 20) $post['h_off_bonus'] = 20; - } - else $post['h_off_bonus'] = 0; - - if(isset($post['h_def_bonus'])){ - if(intval($post['h_def_bonus']) > 20) $post['h_def_bonus'] = 20; - } - else $post['h_def_bonus'] = 0; - - $sum = 0; - for($i = 1; $i <= 10; $i++) $sum += (!empty($post['a1_'.$i]) ? $post['a1_'.$i] : 0); - - if($sum > 0){ - $post['palast'] = intval($post['palast']); - if($post['palast'] > 20) $post['palast'] = 20; - - for($i = 1; $i <= 5; $i++){ - if(isset($post['wall'.$i])){ - $post['wall'.$i] = intval($post['wall'.$i]); - if($post['wall'.$i] > 20) $post['wall'.$i] = 20; - elseif($post['wall'.$i] < 0) $post['wall'.$i] = 0; - $post['walllevel'] = $post['wall'.$i]; - } - } - $post['tribe'] = $target[0]; - $_POST['result'] = $this->simulate($post); - $newWallLevel = $_POST['result'][7]; - $oldWallLevel = $_POST['result'][8]; - - //If the wall level is reduce, we have to re-do the whole battle - if($newWallLevel != $oldWallLevel){ - $post['walllevel'] = $newWallLevel; - $_POST['result'] = $this->simulate($post); - - //Reset the datas - $_POST['result'][7] = $newWallLevel; - $_POST['result'][8] = $post['walllevel'] = $oldWallLevel; - } - - $form->valuearray = $post; - } - } - } - - private function getBattleHero($uid) { - global $database; - $heroarray = $database->getHero($uid); + $attackPoints = $this->calculateAttackPoints($Attacker, $att_tribe); + $defensePoints = $this->calculateDefensePoints($Defender); - if (!count($heroarray)) return ['heroid' => 0, 'unit' =>'','atk' => 0,'di' => 0,'dc' => 0,'ob' => 0,'db' => 0,'health' => 0]; + /* + ================================================= + = 2. WALL & RESIDENCE BONUS + ================================================= + */ - $herodata = $GLOBALS["h".$heroarray[0]['unit']]; - if(!isset($heroarray['health'])) $heroarray['health'] = 0; - $h_atk = $herodata['atk'] + ($heroarray[0]['attack'] * $herodata['atkp']); - $h_di = $herodata['di'] + 5 * floor($heroarray[0]['defence'] * $herodata['dip'] / 5); - $h_dc = $herodata['dc'] + 5 * floor($heroarray[0]['defence'] * $herodata['dcp'] / 5); - $h_ob = 1 + 0.010 * ($heroarray[0]['attackbonus'] / 5); - $h_db = 1 + 0.010 * ($heroarray[0]['defencebonus'] / 5); + $defensePoints = $this->applyWallBonus( + $defensePoints, + $def_wall, + $def_tribe, + $residence + ); - return ['heroid' => (int) $heroarray[0]['heroid'], 'unit' => $heroarray[0]['unit'], 'atk' => $h_atk, 'di' => $h_di, 'dc' => $h_dc, 'ob' => $h_ob, 'db' => $h_db, 'health' => $heroarray['health']]; - } + /* + ================================================= + = 3. FINAL RAP / RDP + ================================================= + */ - private function getBattleHeroSim($attbonus) { - $h_atk = 0; - $h_ob = 1 + 0.010 * $attbonus; + $rap = round($attackPoints); + $rdp = round($defensePoints); - return ['unit' => 16,'atk' => $h_atk,'ob' => $h_ob]; - } + $winner = $rap > $rdp; - private function simulate($post) { - //set the arrays with attacking and defending units - $attacker = ['u1' => 0, 'u2' => 0, 'u3' => 0, 'u4' => 0, 'u5' => 0, 'u6' => 0, 'u7' => 0, 'u8' => 0, 'u9' => 0, 'u10' => 0, 'u11' => 0, 'u12' => 0, 'u13' => 0, 'u14' => 0, 'u15' => 0, 'u16' => 0, 'u17' => 0, 'u18' => 0, 'u19' => 0, 'u20' => 0, 'u21' => 0, 'u22' => 0, 'u23' => 0, 'u24' => 0, - 'u25' => 0, 'u26' => 0, 'u27' => 0, 'u28' => 0, 'u29' => 0, 'u30' => 0, 'u31' => 0, 'u32' => 0, 'u33' => 0, 'u34' => 0, 'u35' => 0, 'u36' => 0, 'u37' => 0, 'u38' => 0, 'u39' => 0, 'u40' => 0, 'u41' => 0, 'u42' => 0, 'u43' => 0, 'u44' => 0, 'u45' => 0, 'u46' => 0, 'u47' => 0, 'u48' => 0, - 'u49' => 0, 'u50' => 0]; - $start = ($post['a1_v'] - 1) * 10 + 1; - $offhero = intval($post['h_off_bonus']); - $hero_strenght = intval($post['h_off']); - $deffhero = intval($post['h_def_bonus']); - for($i = $start, $index = 1; $i <= $start + 9; $i++, $index++) { - if(isset($post['a1_'.$index]) && !empty($post['a1_'.$index])) { - $attacker['u'.$i] = $post['a1_'.$index]; - } - else $attacker['u'.$i] = 0; - - if($index <=8 && isset($post['f1_'.$index]) && !empty($post['f1_'.$index])) { - ${'att_ab'.$index} = $post['f1_'.$index]; - } - else ${'att_ab'.$index} = 0; - } + /* + ================================================= + = 4. CASUALTY FACTOR + ================================================= + */ - $defender = []; - $defscout = 0; - //fix by ronix - for($i = 1;$i <= 50; $i++) { - if(isset($post['a2_'.$i]) && !empty($post['a2_'.$i])) { - $defender['u'.$i] = $post['a2_'.$i]; - $def_ab[$i] = $post['f2_'.$i]; - if($i == 4 || $i == 14 || $i == 23 || $i == 44){ - $defscout += $defender['u'.$i]; - } - - } - else { - $defender['u'.$i] = 0; - $def_ab[$i] = 0; - } - } - - $deftribe = $post['tribe']; - $wall = 0; + $ratio = $rap > 0 + ? pow(($rdp / $rap), 1.5) + : 1; - if(empty($post['kata'])) $post['kata'] = 0; + if ($ratio > 1) $ratio = 1; - // check scout - - $scout = 1; - for($i = $start; $i <= $start + 9 ; $i++) { - if($i == 4 || $i == 14 || $i == 23 || $i == 44){ - }else{ - if($attacker['u'.$i] > 0) { - $scout = 0; - break; - } - } - } - - $walllevel = $post['walllevel']; - $wall = $walllevel; - $palast = $post['palast']; - - if($scout == 1 && $defscout == 0) $walllevel = $wall = $palast = 0; - - if($scout == 1) $palast = 0; //no def point palace and residence when scout - - if(!$scout) return $this->calculateBattle($attacker,$defender,$wall,$post['a1_v'],$deftribe,$palast,$post['ew1'],$post['ew2'],$post['ktyp']+3,$def_ab,$att_ab1,$att_ab2,$att_ab3,$att_ab4,$att_ab5,$att_ab6,$att_ab7,$att_ab8,$post['kata'],$post['stonemason'],$walllevel,$offhero,$post['h_off'],$deffhero,0,0,0,0,0); - else return $this->calculateBattle($attacker,$defender,$wall,$post['a1_v'],$deftribe,$palast,$post['ew1'],$post['ew2'],1,$def_ab,$att_ab1,$att_ab2,$att_ab3,$att_ab4,$att_ab5,$att_ab6,$att_ab7,$att_ab8,$post['kata'],$post['stonemason'],$walllevel,0,0,0,0,0,0,0,0); - - } - - public function getTypeLevel($tid,$vid) { - global $village,$database; - - $keyholder = []; - $resourcearray = $database->getResourceLevel($vid); - - foreach(array_keys($resourcearray, $tid) as $key) { - if(strpos($key,'t')) { - $key = preg_replace("/[^0-9]/", '', $key); - array_push($keyholder, $key); - } - } - - $element = count($keyholder); - if($element >= 2) { - if($tid <= 4) { - $temparray = []; - for($i = 0; $i <= $element - 1; $i++){ - array_push($temparray, $resourcearray['f'.$keyholder[$i]]); - } - foreach ($temparray as $key => $val) { - if ($val == max($temparray)) - $target = $key; - } - } - else { - $target = 0; - for($i=1;$i<=$element-1;$i++) { - if($resourcearray['f'.$keyholder[$i]] > $resourcearray['f'.$keyholder[$target]]) { - $target = $i; - } - } - } - } - else if($element == 1) $target = 0; - else return 0; - - - if(!empty($keyholder[$target])) return $resourcearray['f'.$keyholder[$target]]; - else return 0; - } - - //1 raid 0 normal - function calculateBattle($Attacker, $Defender, $def_wall, $att_tribe, $def_tribe, $residence, $attpop, $defpop, $type, $def_ab, $att_ab1, $att_ab2, $att_ab3, $att_ab4, $att_ab5, $att_ab6, $att_ab7, $att_ab8, $tblevel, $stonemason, $walllevel, $offhero, $hero_strenght, $deffhero, $AttackerID, $DefenderID, $AttackerWref, $DefenderWref, $conqureby, $defReinforcements = null) { - global $bid34, $bid35, $database; - - // Define the array, with the units - $calvary = [4, 5, 6, 15, 16, 23, 24, 25, 26, 45, 46]; - $catapult = [8, 18, 28, 48]; - $rams = [7, 17, 27, 47]; - $catp = $ram = 0; - - // Array to return the result of the calculation back $result = []; - $involve = 0; - $winner = false; - - // at 0 all partial results - - //cap = Cavalry attack points - //ap = Infantry attack points - //cdp = Cavalry attack points - //dp = Infantry defense points - //rap = Result attack points - //rdp = Result defense points - //detected = Detected or not by defender spies - $cap = $ap = $dp = $cdp = $rap = $rdp = 0; - $detected = false; - - //Get involved artifacts - $attacker_artefact = $database->getArtifactsValueInfluence($AttackerID, $AttackerWref, 3, 1, false); - $defender_artefact = $database->getArtifactsValueInfluence($DefenderID, $DefenderWref, 3, 1, false); - $strongerbuildings = $database->getArtifactsValueInfluence($DefenderID, $DefenderWref, 1, 1, false); - $isWWVillage = $database->getVillageField($DefenderWref, 'natar'); - - if(isset($Attacker['uhero']) && $Attacker['uhero'] > 0){ - $atkhero = $this->getBattleHero($AttackerID); - } - if(isset($Defender['hero']) && $Defender['hero'] > 0){ - $defenderhero = $this->getBattleHero($DefenderID); - } - //own defender units - if ($type == 1) { - $datadefScout = $this->getDataDefScout($Defender, $def_ab, $defender_artefact); - $dp += $datadefScout['dp']; - $cdp += $datadefScout['cdp']; - $involve = $datadefScout['involve']; - if(!$detected && $datadefScout['detect']) $detected = $datadefScout['detect']; - }else{ - $datadef = $this->getDataDef($Defender, $def_ab); - $dp += $datadef['dp']; - $cdp += $datadef['cdp']; - $involve = $datadef['involve']; - if(isset($Defender['hero']) && $Defender['hero'] != 0){ - $units['Def_unit']['hero'] = $Defender['hero']; - $cdp += $defenderhero['dc']; - $dp += $defenderhero['di']; - $dp *= $defenderhero['db']; - $cdp *= $defenderhero['db']; - } - } - $DefendersAll = (!is_null($defReinforcements) ? $database->getEnforceVillage($DefenderWref, 0) : $defReinforcements); + $result['Attack_points'] = $rap; + $result['Defend_points'] = $rdp; + $result['Winner'] = $winner ? "attacker" : "defender"; + $result[1] = $ratio; + $result[2] = 1 - $ratio; - if(!empty($DefendersAll) && $DefenderWref > 0){ - // preload village IDs - $vilIDs = []; - foreach($DefendersAll as $defenders) { - $vilIDs[$defenders['from']] = true; - $vilIDs[$defenders['to']] = true; - } - $vilIDs = array_keys($vilIDs); - $database->getABTech($vilIDs); + /* + ================================================= + = 5. CASUALTIES + ================================================= + */ - foreach($DefendersAll as $defenders) { - for ($i = 1; $i <= 50; $i++) $def_ab[$i] = 0; - $fromvillage = $defenders['from']; + $result['casualties_attacker'] = + $this->calculateCasualties($Attacker, $ratio, $att_tribe); - $userdataCache[$fromvillage] = $database->getUserArray($database->getVillageField($fromvillage, "owner"), 1); + /* + ================================================= + = 6. BOUNTY + ================================================= + */ - $enforcetribe = $userdataCache[$fromvillage]["tribe"]; - $ud=($enforcetribe - 1) * 10; - if($defenders['from'] > 0) { //don't check nature tribe - $armory = $database->getABTech($defenders['from']); // Armory level every village enforcement - $def_ab[$ud + 1] = $armory['a1']; - $def_ab[$ud + 2] = $armory['a2']; - $def_ab[$ud + 3] = $armory['a3']; - $def_ab[$ud + 4] = $armory['a4']; - $def_ab[$ud + 5] = $armory['a5']; - $def_ab[$ud + 6] = $armory['a6']; - $def_ab[$ud + 7] = $armory['a7']; - $def_ab[$ud + 8] = $armory['a8']; - } - if ($type == 1) { - $datadefScout = $this->getDataDefScout($defenders, $def_ab, $defender_artefact); - $dp += $datadefScout['dp']; - $cdp += $datadefScout['cdp']; - $involve = $datadefScout['involve']; - if(!$detected && $datadefScout['detect']) $detected = $datadefScout['detect']; - }else{ - $datadef = $this->getDataDef($defenders, $def_ab); - $dp += $datadef['dp']; - $cdp += $datadef['cdp']; - $involve = $datadef['involve']; - } - $reinfowner = $database->getVillageField($fromvillage, "owner"); - $defhero = $this->getBattleHero($reinfowner); - - //calculate def hero from enforcement - if($defenders['hero'] != 0){ - $cdp += $defhero['dc']; - $dp += $defhero['di']; - $dp *= $defhero['db']; - $cdp *= $defhero['db']; - } - } - } - // Calculate the total number of points Attacker - $start = ($att_tribe - 1) * 10 + 1; - $end = $att_tribe * 10; - - if($att_tribe == 3) $abcount = 3; - else $abcount = 4; + $result['bounty'] = + $this->calculateBounty($Attacker, $result['casualties_attacker'], $att_tribe); - if($type == 1) {//scout - for($i = $start;$i <= $end; $i++) { - global ${'u'.$i}; - $j = $i - $start + 1; - if($Attacker['u'.$i] > 0 && ($i == 4 || $i == 14 || $i == 23 || $i == 44)){ - if(${'att_ab'.$abcount} > 0) { - $ap += round(35 + (35 + 300 * ${'u'.$i}['pop'] / 7) * (pow(1.007, ${'att_ab'.$abcount}) - 1), 4) * $Attacker['u'.$i]; - } - else $ap += $Attacker['u'.$i] * 35; - } - $involve += $Attacker['u'.$i]; - $units['Att_unit'][$i] = $Attacker['u'.$i]; - - } - $ap *= $attacker_artefact; - - }else{ //type=3 normal 4=raid - $abcount = 1; - for($i = $start; $i <= $end; $i++) { - global ${'u'.$i}; - $j = $i - $start + 1; - if($abcount <= 8 && ${'att_ab'.$abcount} > 0) { - if(in_array($i,$calvary)) { - $cap += round(${'u'.$i}['atk'] + (${'u'.$i}['atk'] + 300 * ${'u'.$i}['pop'] / 7) * (pow(1.007, ${'att_ab'.$abcount}) - 1), 4) * (int) $Attacker['u'.$i]; - }else{ - $ap += round(${'u'.$i}['atk'] + (${'u'.$i}['atk'] + 300 * ${'u'.$i}['pop'] / 7) * (pow(1.007, ${'att_ab'.$abcount}) - 1), 4) * (int) $Attacker['u'.$i]; - } - }else{ - if(in_array($i,$calvary)) $cap += (int) $Attacker['u'.$i]*${'u'.$i}['atk']; - else $ap += (int) $Attacker['u'.$i]*${'u'.$i}['atk']; - } - - $abcount += 1; - - // Points catapult the attacker - if(in_array($i, $catapult)) $catp += (int) $Attacker['u'.$i]; - - // Points of the Rams attacker - if(in_array($i, $rams)) $ram += (int) $Attacker['u'.$i]; - - $involve += (int) $Attacker['u'.$i]; - $units['Att_unit'][$i] = (int) $Attacker['u'.$i]; - } - if (isset($Attacker['uhero']) && $Attacker['uhero'] != 0){ - $units['Att_unit']['hero'] = $Attacker['uhero']; - $ap *= $atkhero['ob']; - $cap *= $atkhero['ob']; - $ap += $atkhero['atk']; - } - - if ($offhero > 0 || $hero_strenght > 0) { - $atkhero= $this->getBattleHeroSim($offhero); - $ap *= $atkhero['ob']; - $cap *= $atkhero['ob']; - $ap += $hero_strenght; - } - if ($deffhero > 0) { - $dfdhero = $this->getBattleHeroSim($deffhero); - $dp *= $dfdhero['ob']; - $cdp *= $dfdhero['ob']; - } - } - // Formula for calculating the bonus defensive wall and Residence - - if($def_wall > 0) { - // Set the factor calculation for the "wall" as the type of the civilization - // Factor = 1030 Wall Roman - // Factor = 1020 Wall Teuton - // Factor = 1025 Wall Goul - $factor = ($def_tribe == 1)? 1.030 : (($def_tribe == 2)? 1.020 : 1.025); - $wallMultiplier = round(pow($factor, $def_wall), 3); - // Defense infantry = Infantry * Wall (%) - // Defense calvary calvary = * Wall (%) - if ($dp > 0 || $cdp > 0){ - if($type == 1) { - $dp *= $wallMultiplier; - $dp += 10; - }else{ - $dp *= $wallMultiplier; - $cdp *= $wallMultiplier; - - // Calculation of the Basic defense bonus "Residence" - $dp += (2 * (pow($residence, 2)) + 10) * $wallMultiplier; - $cdp += (2 * (pow($residence, 2)) + 10) * $wallMultiplier; - } - }else{ - $dp = 10 * $wallMultiplier * $def_wall; - // Defense calvary calvary = * Wall (%) - $cdp = 10 * $wallMultiplier * $def_wall; - if($type != 1){ - // Calculation of the Basic defense bonus "Residence" - $dp += (2 * (pow($residence, 2)) + 10) * $wallMultiplier; - $cdp += (2 * (pow($residence, 2)) + 10) * $wallMultiplier; - }else{ - $dp += 10; - $cdp = 0; - } - } - }elseif($type != 1) { - - // Calculation of the Basic defense bonus "Residence" - $dp += (2 * (pow($residence, 2)) + 10); - $cdp += (2 * (pow($residence, 2)) + 10); - } - - // Formula for calculating Attacking Points (Infantry & Cavalry) - if($AttackerWref != 0){ - $rap = round(($ap + $cap) + (($ap + $cap) / 100 * (isset($bid35[$this->getTypeLevel(35, $AttackerWref)]) ? $bid35[$this->getTypeLevel(35, $AttackerWref)]['attri'] : 0))); - } - else $rap = round($ap + $cap); - - // Formula for calculating Defensive Points - if ($rap == 0) $rdp = round(($dp) + ($cdp)); - else $rdp = round(round($cap / $rap, 4) * ($cdp) + round($ap / $rap, 4) * ($dp)); - - // The Winner is....: - $result['Attack_points'] = $rap; - $result['Defend_points'] = $rdp; - $winner = ($rap > $rdp); - - // Formula for calculating the Morale bonus - // WW villages aren't affected by this bonus - if($attpop > $defpop && !$isWWVillage) { - $moralbonus = 1 / round(max(0.667, pow($defpop / $attpop, 0.2 * min(1, $rap / ($rdp > 0 ? $rdp : 1)))), 3); - } - else $moralbonus = 1.0; - - if($involve >= 1000 && $type != 1) $Mfactor = 2 * round((1.8592 - pow($involve, 0.015)), 4); - else $Mfactor = 1.5; - - if ($Mfactor < 1.2578) $Mfactor = 1.2578; - elseif ($Mfactor > 1.5) $Mfactor = 1.5; - - // Formula for calculating losses - // $type = 1 Scout, 2 Enforcement - // $type = 3 Normal, 4 Raid - if($type == 1){ - $holder = pow((($rdp * $moralbonus) / $rap), $Mfactor); - if($holder > 1) $holder = 1; - if ($rdp > $rap) $holder = 1; - - //Birds of Prey cannot die when scouting - //Spies cannot die if the attacked village has no defending spies - //Attacker result - $result[1] = ($att_tribe == 5 || !$detected) ? 0 : $holder; - - //Defender result - $result[2] = 0; - }else if($type == 4) { - $holder = ($winner) ? pow((($rdp * $moralbonus) / $rap), $Mfactor) : pow(($rap / ($rdp * $moralbonus)), $Mfactor); - $holder = $holder / (1 + $holder); - //Attacker result - $result[1] = $winner ? $holder : 1 - $holder; - //Defender result - $result[2] = $winner ? 1 - $holder : $holder; - $ram -= round($ram * $result[1] / 100); - $catp -= round($catp * $result[1] / 100); - }else if($type == 3){ - - // Attacker - $result[1] = ($winner) ? pow((($rdp * $moralbonus) / $rap), $Mfactor) : 1; - - if ($result[1] > 1){ - $result[1] = 1; - $winner = false; - $result['Winner'] = "defender"; - } - - // Defender - $result[2] = (!$winner) ? pow(($rap / ($rdp * $moralbonus)), $Mfactor) : 1; - - if ($result[1] == 1) $result[2] = pow(($rap / ($rdp * $moralbonus)), $Mfactor); - - if ($result[2] > 1) { - $result[2] = 1; - $result['Winner'] = "attacker"; - $winner = true; - } - - // If attacked with "Hero" - $ku = ($att_tribe - 1) * 10 + 9; - $kings = (int) $Attacker['u'.$ku]; - - $aviables = $kings - round($kings * (int) $result[1]); - if ($aviables > 0){ - switch($aviables){ - case 1: $fealthy = rand(20, 30); break; - case 2: $fealthy = rand(40, 60); break; - case 3: $fealthy = rand(60, 80); break; - case 4: $fealthy = rand(80, 100); break; - default: $fealthy = 100; break; - } - $result['hero_fealthy'] = $fealthy; - } - - $ram -= ($winner) ? round($ram * $result[1] / 100) : round($ram * $result[2] / 100); - $catp -= ($winner) ? round($catp * $result[1] / 100) : round($catp * $result[2] / 100); - } - - if($catp > 0 && $tblevel != 0) { - - //Catapults blacksmith upgrades - $upgrades = round(200 * pow(1.0205, $att_ab8)) / 200; - - //Buildings durability - $durability = ($stonemason > 0 ? $bid34[$stonemason]['attri'] / 100 : 1); - - //Calculates the catapults morale bonus - $catpMoraleBonus = min(max(($attpop / ($defpop > 0 ? $defpop : 1)) ** 0.3, 1), 3); - - //New level of the building (only for warsim.php) - $catapultsDamage = $this->calculateCatapultsDamage($catp, $upgrades, $durability, $rap / $rdp, $strongerbuildings, $catpMoraleBonus); - $result[3] = $this->calculateNewBuildingLevel($tblevel, $catapultsDamage); - $result[4] = $tblevel; - - //Results for Automation.php - $result['catapults']['upgrades'] = $upgrades; - $result['catapults']['durability'] = $durability; - $result['catapults']['attackDefenseRatio'] = $rap / $rdp; - $result['catapults']['strongerBuildings'] = $strongerbuildings; - $result['catapults']['moraleBonus'] = $catpMoraleBonus; - } - - if($ram > 0 && $walllevel != 0) { - - //Rams blacksmith upgrades - $upgrades = round(200 * pow(1.0205, $att_ab7)) / 200; - - //Building durability - $durability = ($stonemason > 0 ? $bid34[$stonemason]['attri'] / 100 : 1); - - // New level of the building (only for warsim.php) - $ramsDamage = $this->calculateCatapultsDamage($ram, $upgrades, $durability, $rap / $rdp, $strongerbuildings, 1); - $result[7] = $this->calculateNewBuildingLevel($walllevel, $ramsDamage); - $result[8] = $walllevel; - - // Results for Automation.php - $result['rams']['upgrades'] = $upgrades; - $result['rams']['durability'] = $durability; - $result['rams']['attackDefenseRatio'] = $rap / $rdp; - $result['rams']['strongerBuildings'] = $strongerbuildings; - $result['rams']['moraleBonus'] = 1; - } - - $result[6] = pow($rap / ($rdp * $moralbonus > 0 ? $rdp * $moralbonus : 1), $Mfactor); - $result['moralBonus'] = $moralbonus; - - $total_att_units = count($units['Att_unit']); - $start = intval(($att_tribe - 1) * 10 + 1); - $end = intval($att_tribe * 10); - - for($i = $start; $i <= $end; $i++){ - $y = $i - (($att_tribe - 1) * 10); - $result['casualties_attacker'][$y] = round($result[1] * $units['Att_unit'][$i]); - } - - if (isset($units['Att_unit']['hero']) && $units['Att_unit']['hero'] >0){ - - $_result = mysqli_query($database->dblink,"select heroid, health from " . TB_PREFIX . "hero where `dead`='0' and `heroid`=".(int) $atkhero['heroid']); - $fdb = mysqli_fetch_array($_result); - $hero_id = (int) $fdb['heroid']; - $hero_health = $fdb['health']; - $damage_health = round(100 * $result[1]); - - if ($hero_health <= $damage_health || $damage_health > 90){ - //hero die - $result['casualties_attacker'][11] = 1; - mysqli_query($database->dblink,"update " . TB_PREFIX . "hero set `dead` = 1, `health` = 0 where `heroid`=".(int) $hero_id); - }else{ - mysqli_query($database->dblink,"update " . TB_PREFIX . "hero set `health`=`health`-".(int) $damage_health." where `heroid`=".(int) $hero_id); - } - } - unset($_result, $fdb, $hero_id, $hero_health, $damage_health); - - - if (isset($units['Def_unit']['hero']) && $units['Def_unit']['hero'] >0){ - - $_result = mysqli_query($database->dblink,"select heroid, health from " . TB_PREFIX . "hero where `dead`='0' and `heroid`=".(int) $defenderhero['heroid']); - $fdb = mysqli_fetch_array($_result); - $hero_id = (int) $fdb['heroid']; - $hero_health = $fdb['health']; - $damage_health = round(100 * $result[2]); - if ($hero_health <= $damage_health || $damage_health > 90){ - //hero die - $result['deadherodef'] = 1; - mysqli_query($database->dblink,"update " . TB_PREFIX . "hero set `dead` = 1, `health` = 0 where `heroid`=".(int) $hero_id); - }else{ - $result['deadherodef'] = 0; - mysqli_query($database->dblink,"update " . TB_PREFIX . "hero set `health`=`health`-".(int) $damage_health." where `heroid`=".(int) $hero_id); - } - } - unset($_result, $fdb, $hero_id, $hero_health, $damage_health); - - if(!empty($DefendersAll)){ - $battleHeroesCache = []; - foreach($DefendersAll as $defenders) { - if($defenders['hero'] > 0) { - $battleHeroesCache[$defenders['from']] = $this->getBattleHero($database->getVillageField($defenders['from'],"owner")); - $heroarraydefender = $battleHeroesCache[$defenders['from']]; - $_result = mysqli_query($database->dblink,"select heroid, health from " . TB_PREFIX . "hero where `dead`='0' and `heroid`=".(int) $heroarraydefender['heroid']); - $fdb = mysqli_fetch_array($_result); - $hero_id = (int) $fdb['heroid']; - $hero_health = $fdb['health']; - $damage_health = round(100 * $result[2]); - if ($hero_health <= $damage_health || $damage_health > 90){ - //hero die - $result['deadheroref'][$defenders['id']] = 1; - mysqli_query($database->dblink,"update " . TB_PREFIX . "hero set `dead` = 1, `health` = 0 where `heroid`=".(int) $hero_id); - }else{ - $result['deadheroref'][$defenders['id']] = 0; - mysqli_query($database->dblink,"update " . TB_PREFIX . "hero set `health`=`health`-".(int) $damage_health." where `heroid`=".(int) $hero_id); - } - } - } - } - unset($_result, $fdb, $hero_id, $hero_health, $damage_health); - - - // Work out bounty - $start = ($att_tribe - 1) * 10 + 1; - $end = ($att_tribe * 10); - - $max_bounty = 0; - - for($i = $start; $i <= $end; $i++) { - $j = $i - $start + 1; - $y = $i -(($att_tribe - 1) * 10); - - $max_bounty += ((int) $Attacker['u'.$i] - (int) $result['casualties_attacker'][$y]) * (int) ${'u'.$i}['cap']; - } - - $result['bounty'] = $max_bounty; return $result; } - public function getDataDefScout($defenders, $def_ab, $defender_artefact) { - $abcount = 1; - $invol = $dp = $cdp = 0; - $detected = false; - - for($y = 4; $y <= 50; $y++) { - if($y == 4 || $y == 14 || $y == 23 || $y == 44){ - global ${'u'.$y}; + /* + ===================================================== + = ATTACK / DEFENSE HELPERS + ===================================================== + */ - if($defenders['u'.$y] > 0 && $def_ab[$y] > 0){ - $dp += round(20 + (20 + 300 * ${'u'.$y}['pop'] / 7) * (pow(1.007, $def_ab[$y]) - 1), 4) * $defenders['u'.$y] * $defender_artefact; - $detected = true; - }else{ - if($defenders['u'.$y] > 0){ - $dp += $defenders['u'.$y] * 20 * $defender_artefact; - $detected = true; - } - } - - $invol += $defenders['u'.$y]; //total troops - $units['Def_unit'][$y] = $defenders['u'.$y]; - } + private function calculateAttackPoints($Attacker, $tribe) + { + $start = ($tribe - 1) * 10 + 1; + $end = $tribe * 10; + + $points = 0; + + for ($i = $start; $i <= $end; $i++) { + global ${'u'.$i}; + $points += (int)$Attacker['u'.$i] * ${'u'.$i}['atk']; } - $datadef['dp'] = $dp; - $datadef['cdp'] = $cdp; - $datadef['detect'] = $detected; - $datadef['involve'] = $invol; - return $datadef; + return $points; } - public function getDataDef($defenders,$def_ab) { - $dp = $cdp = $invol = 0; - for($y = 1;$y <= 50; $y++) { - global ${'u'.$y}; - if ($defenders['u'.$y] > 0) { - if (!isset($def_ab[$y])) { - $def_ab[$y] = 0; - } - if ($def_ab[$y] > 0) { - $dp += round(${'u'.$y}['di'] + (${'u'.$y}['di'] + 300 * ${'u'.$y}['pop'] / 7) * (pow(1.007, $def_ab[$y]) - 1), 4) * $defenders['u'.$y]; - $cdp += round(${'u'.$y}['dc'] + (${'u'.$y}['dc'] + 300 * ${'u'.$y}['pop'] / 7) * (pow(1.007, $def_ab[$y]) - 1), 4) * $defenders['u'.$y]; - }else{ - $dp += $defenders['u'.$y] * ${'u'.$y}['di']; - $cdp += $defenders['u'.$y] * ${'u'.$y}['dc']; - } + private function calculateDefensePoints($Defender) + { + $points = 0; - } - $invol += $defenders['u'.$y]; //total troops - $units['Def_unit'][$y] = $defenders['u'.$y]; + for ($i = 1; $i <= 50; $i++) { + global ${'u'.$i}; + $points += (int)$Defender['u'.$i] * ${'u'.$i}['di']; } - $datadef['dp'] = $dp; - $datadef['cdp'] = $cdp; - $datadef['involve'] = $invol; - return $datadef; + + return $points; } - - /** - * @author Kirilloid --> https://github.com/kirilloid/travian/blob/master/src/model/base/combat.ts - * - * Calculates the new building level, after damaging it - * - * @param int $oldLevel The old building level - * @param float $damage The damage done by catapults - * @return int Returns the new building level - */ - - public function calculateNewBuildingLevel($oldLevel, $damage){ - $damage -= 0.5; - if ($damage < 0) return $oldLevel; - - while ($damage >= $oldLevel && $oldLevel) $damage -= $oldLevel--; - - return $oldLevel; + + private function applyWallBonus($defPoints, $wall, $tribe, $residence) + { + if ($wall <= 0) { + return $defPoints + (2 * pow($residence,2) + 10); + } + + $factor = ($tribe == 1) + ? 1.030 + : (($tribe == 2) ? 1.020 : 1.025); + + return $defPoints * pow($factor, $wall); } - - /** - * @author Kirilloid --> https://github.com/kirilloid/travian/blob/master/src/model/base/combat.ts - * - * Calculates the damage done by catapults - * - * @param int $catapultsQuantity The quantity of catapults which take part in the attack - * @param double $catapultsUpgrade The catapults upgrade multiplier, affected by the cataputls level in the blacksmith - * @param double $durability The building durability, affected by the stonemason's lodge - * @param double $ADRatio The attack points / defensive points ratio - * @param double $strongerBuildings The artifacts multiplier, which strengthens the building, affected by durability artifacts - * @param double $moraleBonus The defender morale bonus - * @return double Returns the damage done by catapults - */ - - public function calculateCatapultsDamage($catapultsQuantity, $catapultsUpgrade, $durability, $ADRatio, $strongerBuildings, $moraleBonus){ - $catapultsEfficiency = floor($catapultsQuantity / ($durability * $strongerBuildings)); - return 4 * ($this->sigma)($ADRatio) * $catapultsEfficiency * $catapultsUpgrade / $moraleBonus; + + private function calculateCasualties($Attacker, $ratio, $tribe) + { + $casualties = []; + + $start = ($tribe - 1) * 10 + 1; + $end = $tribe * 10; + + for ($i = $start; $i <= $end; $i++) { + $index = $i - (($tribe - 1) * 10); + $casualties[$index] = + round($ratio * (int)$Attacker['u'.$i]); + } + + return $casualties; } -}; + + private function calculateBounty($Attacker, $casualties, $tribe) + { + $start = ($tribe - 1) * 10 + 1; + $end = $tribe * 10; + + $bounty = 0; + + for ($i = $start; $i <= $end; $i++) { + global ${'u'.$i}; + $index = $i - (($tribe - 1) * 10); + + $alive = (int)$Attacker['u'.$i] - (int)$casualties[$index]; + + $bounty += $alive * (int)${'u'.$i}['cap']; + } + + return $bounty; + } +} $battle = new Battle; ?> diff --git a/GameEngine/Chat.php b/GameEngine/Chat.php index b71624c5..04e50c0e 100755 --- a/GameEngine/Chat.php +++ b/GameEngine/Chat.php @@ -4,6 +4,7 @@ ## --------------------------------------------------------------------------- ## ## Filename Chat.php ## ## Developed by: TTMMTT ## +## Refactored by: Shadow ## ## License: TravianZ Project ## ## Copyright: TravianZ (c) 2010-2025. All rights reserved. ## ## ## @@ -11,377 +12,196 @@ if (!isset($SAJAX_INCLUDED)) { - $GLOBALS['sajax_version'] = '0.12'; - $GLOBALS['sajax_debug_mode'] = 0; - $GLOBALS['sajax_export_list'] = array(); - $GLOBALS['sajax_request_type'] = 'GET'; - $GLOBALS['sajax_remote_uri'] = ''; - $GLOBALS['sajax_failure_redirect'] = ''; + $GLOBALS['sajax_version'] = '0.12'; + $GLOBALS['sajax_debug_mode'] = 0; + $GLOBALS['sajax_export_list'] = []; + $GLOBALS['sajax_request_type'] = 'GET'; + $GLOBALS['sajax_remote_uri'] = $_SERVER['REQUEST_URI'] ?? ''; + $GLOBALS['sajax_failure_redirect'] = ''; + /* ============================== + SECURITY HELPERS + ============================== */ - function sajax_init() { - } + function sajax_safe_string($value) { + return htmlspecialchars((string)$value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); + } - function sajax_get_my_uri() { - return $_SERVER["REQUEST_URI"]; - } - $sajax_remote_uri = sajax_get_my_uri(); + function sajax_validate_function($func_name) { + global $sajax_export_list; + return in_array($func_name, $sajax_export_list, true); + } + /* ============================== + CLIENT REQUEST HANDLER (HARDENED) + ============================== */ - function sajax_get_js_repr($value) { - $type = gettype($value); + function sajax_handle_client_request() { - if ($type == "boolean") { - return ($value) ? "Boolean(true)" : "Boolean(false)"; - } - elseif ($type == "integer") { - return "parseInt($value)"; - } - elseif ($type == "double") { - return "parseFloat($value)"; - } - elseif ($type == "array" || $type == "object" ) { + global $sajax_export_list; - $s = "{ "; - if ($type == "object") { - $value = get_object_vars($value); - } - foreach ($value as $k=>$v) { - $esc_key = sajax_esc($k); - if (is_numeric($k)) - $s .= "$k: " . sajax_get_js_repr($v) . ", "; - else - $s .= "\"$esc_key\": " . sajax_get_js_repr($v) . ", "; - } - if (count($value)) - $s = substr($s, 0, -2); - return $s . " }"; - } - else { - $esc_val = sajax_esc($value); - $s = "'$esc_val'"; - return $s; - } - } + $mode = ''; - function sajax_handle_client_request() { - global $sajax_export_list; + if (isset($_GET['rs'])) $mode = 'get'; + if (isset($_POST['rs'])) $mode = 'post'; - $mode = ""; + if (!$mode) return; - if (! empty($_GET["rs"])) - $mode = "get"; + header("Cache-Control: no-store, no-cache, must-revalidate"); + header("Pragma: no-cache"); - if (!empty($_POST["rs"])) - $mode = "post"; + $func_name = $mode === 'get' + ? (string)$_GET['rs'] + : (string)$_POST['rs']; - if (empty($mode)) - return; + $args = $mode === 'get' + ? ($_GET['rsargs'] ?? []) + : ($_POST['rsargs'] ?? []); - $target = ""; + if (!is_array($args)) { + $args = [$args]; + } - if ($mode == "get") { + if (!sajax_validate_function($func_name) || !function_exists($func_name)) { + echo "-:Function not callable"; + exit; + } - header ("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); - header ("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); + echo "+:"; + $result = call_user_func_array($func_name, $args); + echo "var res = " . trim(sajax_get_js_repr($result)) . "; res;"; + exit; + } - header ("Cache-Control: no-cache, must-revalidate"); - header ("Pragma: no-cache"); - $func_name = $_GET["rs"]; - if (! empty($_GET["rsargs"])) - $args = $_GET["rsargs"]; - else - $args = array(); - } - else { - $func_name = $_POST["rs"]; - if (! empty($_POST["rsargs"])) - $args = $_POST["rsargs"]; - else - $args = array(); - } + /* ============================== + SAFE JS ENCODER + ============================== */ - if (! in_array($func_name, $sajax_export_list)) - echo "-:$func_name not callable"; - else { - echo "+:"; - $result = call_user_func_array($func_name, $args); - echo "var res = " . trim(sajax_get_js_repr($result)) . "; res;"; - } - exit; - } + function sajax_get_js_repr($value) { - function sajax_get_common_js() { - global $sajax_debug_mode; - global $sajax_request_type; - global $sajax_remote_uri; - global $sajax_failure_redirect; + if (is_bool($value)) { + return $value ? "Boolean(true)" : "Boolean(false)"; + } - $t = strtoupper($sajax_request_type); - if ($t != "" && $t != "GET" && $t != "POST") - return "// Invalid type: $t.. \n\n"; + if (is_int($value)) { + return "parseInt($value)"; + } - ob_start(); - ?> + if (is_float($value)) { + return "parseFloat($value)"; + } - // remote scripting library - // (c) copyright 2005 modernmethod, inc - // edited by ttmtt - var sajax_debug_mode = ; - var sajax_request_type = ""; - var sajax_target_id = ""; - var sajax_failure_redirect = ""; + if (is_array($value) || is_object($value)) { - function sajax_debug(text) { - if (sajax_debug_mode) - alert(text); - } + $value = (array)$value; + $pairs = []; - function sajax_init_object() { - sajax_debug("sajax_init_object() called..") + foreach ($value as $k => $v) { + $k = sajax_safe_string($k); + $pairs[] = is_numeric($k) + ? "$k: " . sajax_get_js_repr($v) + : "\"$k\": " . sajax_get_js_repr($v); + } - var A; + return "{ " . implode(', ', $pairs) . " }"; + } - var msxmlhttp = new Array( - 'Msxml2.XMLHTTP.5.0', - 'Msxml2.XMLHTTP.4.0', - 'Msxml2.XMLHTTP.3.0', - 'Msxml2.XMLHTTP', - 'Microsoft.XMLHTTP'); - for (var i = 0; i < msxmlhttp.length; i++) { - try { - A = new ActiveXObject(msxmlhttp[i]); - } catch (e) { - A = null; - } - } + return "'" . sajax_safe_string($value) . "'"; + } - if(!A && typeof XMLHttpRequest != "undefined") - A = new XMLHttpRequest(); - if (!A) - sajax_debug("Could not create connection object."); - return A; - } + function sajax_export() { + global $sajax_export_list; + foreach (func_get_args() as $func) { + if (is_string($func)) { + $sajax_export_list[] = $func; + } + } + } - var sajax_requests = new Array(); - - function sajax_cancel() { - for (var i = 0; i < sajax_requests.length; i++) - sajax_requests[i].abort(); - } - - function sajax_do_call(func_name, args) { - var i, x, n; - var uri; - var post_data; - var target_id; - - sajax_debug("in sajax_do_call().." + sajax_request_type + "/" + sajax_target_id); - target_id = sajax_target_id; - if (typeof(sajax_request_type) == "undefined" || sajax_request_type == "") - sajax_request_type = "GET"; - - uri = ""; - if (sajax_request_type == "GET") { -// alert(args); - if (uri.indexOf("?") == -1) - uri += "?rs=" + escape(func_name); - else - uri += "&rs=" + escape(func_name); - uri += "&rst=" + escape(sajax_target_id); - uri += "&rsrnd=" + new Date().getTime(); - - for (i = 0; i < args.length-1; i++) { - uri += "&rsargs[]=" + args[i]; - } - post_data = null; - } - else if (sajax_request_type == "POST") { - post_data = "rs=" + escape(func_name); - post_data += "&rst=" + escape(sajax_target_id); - post_data += "&rsrnd=" + new Date().getTime(); - - for (i = 0; i < args.length-1; i++) - post_data = post_data + "&rsargs[]=" + escape(args[i]); - } - else { - alert("Illegal request type: " + sajax_request_type); - } - - x = sajax_init_object(); - if (x == null) { - if (sajax_failure_redirect != "") { - location.href = sajax_failure_redirect; - return false; - } else { - sajax_debug("NULL sajax object for user agent:\n" + navigator.userAgent); - return false; - } - } else { - x.open(sajax_request_type, uri, true); - // window.open(uri); - - sajax_requests[sajax_requests.length] = x; - - if (sajax_request_type == "POST") { - x.setRequestHeader("Method", "POST " + uri + " HTTP/1.1"); - x.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); - } - - x.onreadystatechange = function() { - if (x.readyState != 4) - return; - - sajax_debug("received " + x.responseText); - - var status; - var data; - var txt = x.responseText.replace(/^\s*|\s*$/g,""); - status = txt.charAt(0); - data = txt.substring(2); - - if (status == "") { - // let's just assume this is a pre-response bailout and let it slide for now - } else if (status == "-") - alert("Error: " + data); - else { - if (target_id != "") - document.getElementById(target_id).innerHTML = eval(data); - else { - try { - var callback; - var extra_data = false; - if (typeof args[args.length-1] == "object") { - callback = args[args.length-1].callback; - extra_data = args[args.length-1].extra_data; - } else { - callback = args[args.length-1]; - } - callback(eval(data), extra_data); - } catch (e) { - sajax_debug("Caught error " + e + ": Could not eval " + data ); - } - } - } - } - } - - sajax_debug(func_name + " uri = " + uri + "/post = " + post_data); - x.send(post_data); - sajax_debug(func_name + " waiting.."); - delete x; - return true; - } - - - - // wrapper for - - function x_() { - sajax_do_call("", - x_.arguments); - } - - escape($msg); -// $msg=htmlspecialchars($msg); - $name = addslashes($session->username); +function add_data($data) { - if ($msg != ""){ - $id_user = (int) $session->uid; - $alliance = $database->escape($session->alliance); - $now = time(); - echo $q = "INSERT into ".TB_PREFIX."chat (id_user,name,alli,date,msg) values ($id_user,'$name','$alliance','$now','$msg')"; - mysqli_query($database->dblink,$q); - } - } + global $session, $database; - function get_data() { - global $session,$database; + if (!$session->uid) return; - $alliance = $database->escape($session->alliance); - $query = mysqli_query($database->dblink,"select id_user, name, date, msg from ".TB_PREFIX."chat where alli='$alliance' order by id desc limit 0,13"); - while ($r = mysqli_fetch_array($query)) { - $dates = date("g:i",$r['date']); - $data .= "[{$dates}] {$r['name']}: {$r['msg']}
"; - } - return $data; - } + $msg = is_array($data) ? ($data[1] ?? '') : $data; + $msg = trim((string)$msg); - $sajax_request_type = "GET"; - sajax_init(); - sajax_export("add_data","get_data"); - sajax_handle_client_request(); + if ($msg === '') return; -?> + $id_user = (int)$session->uid; + $name = $database->escape($session->username); + $alliance = $database->escape($session->alliance); + $now = time(); + + $stmt = mysqli_prepare( + $database->dblink, + "INSERT INTO ".TB_PREFIX."chat (id_user, name, alli, date, msg) VALUES (?, ?, ?, ?, ?)" + ); + + if ($stmt) { + mysqli_stmt_bind_param($stmt, "issis", + $id_user, + $name, + $alliance, + $now, + $msg + ); + mysqli_stmt_execute($stmt); + mysqli_stmt_close($stmt); + } +} + +function get_data() { + + global $session, $database; + + $alliance = $database->escape($session->alliance); + + $stmt = mysqli_prepare( + $database->dblink, + "SELECT id_user, name, date, msg + FROM ".TB_PREFIX."chat + WHERE alli = ? + ORDER BY id DESC + LIMIT 13" + ); + + $data = ''; + + if ($stmt) { + mysqli_stmt_bind_param($stmt, "s", $alliance); + mysqli_stmt_execute($stmt); + $result = mysqli_stmt_get_result($stmt); + + while ($r = mysqli_fetch_assoc($result)) { + + $dates = date("H:i", (int)$r['date']); + $uid = (int)$r['id_user']; + + $username = sajax_safe_string($r['name']); + $message = sajax_safe_string($r['msg']); + + $data .= "[{$dates}] {$username}: {$message}
"; + } + + mysqli_stmt_close($stmt); + } + + return $data; +} + +/* ============================== + SAJAX BOOTSTRAP +============================== */ + +$sajax_request_type = "GET"; +sajax_export("add_data", "get_data"); +sajax_handle_client_request(); diff --git a/GameEngine/Database.php b/GameEngine/Database.php index e4f19f62..262de472 100755 --- a/GameEngine/Database.php +++ b/GameEngine/Database.php @@ -1037,6 +1037,24 @@ class MYSQLi_DB implements IDbConnection { $result = mysqli_query($this->dblink,$q); return $this->mysqli_fetch_all($result); } + + // Add to Database.php + function checkAttackRateLimit($uid, $maxPerMinute = 30) { + $uid = (int)$uid; + $oneMinuteAgo = time() - 60; + + // Count recent attacks from this user + $q = "SELECT COUNT(*) as cnt FROM " . TB_PREFIX . "movement m + JOIN " . TB_PREFIX . "vdata v ON m.from = v.wref + WHERE v.owner = $uid + AND m.sort_type = 3 + AND m.starttime > $oneMinuteAgo"; + + $result = mysqli_query($this->dblink, $q); + $row = mysqli_fetch_assoc($result); + + return ($row['cnt'] < $maxPerMinute); + } function getVrefField($ref, $field, $use_cache = true) { return $this->getVillage($ref, 0, $use_cache)[$field]; diff --git a/GameEngine/Form.php b/GameEngine/Form.php index 2196c091..2b7d2e4b 100755 --- a/GameEngine/Form.php +++ b/GameEngine/Form.php @@ -9,67 +9,107 @@ ## ## ################################################################################# -class Form { +class Form +{ + private array $errorarray = []; + public array $valuearray = []; + private int $errorcount = 0; - private $errorarray = array(); - public $valuearray = array(); - private $errorcount; + public function __construct() + { + if ( + isset($_SESSION['errorarray'], $_SESSION['valuearray']) && + is_array($_SESSION['errorarray']) && + is_array($_SESSION['valuearray']) + ) { - public function __construct() { - if(isset($_SESSION['errorarray']) && isset($_SESSION['valuearray'])) { - $this->errorarray = $_SESSION['errorarray']; - $this->valuearray = $_SESSION['valuearray']; - $this->errorcount = count($this->errorarray); + // Defensive copy (avoid reference issues) + $this->errorarray = $this->sanitizeArray($_SESSION['errorarray']); + $this->valuearray = $this->sanitizeArray($_SESSION['valuearray']); + $this->errorcount = count($this->errorarray); - unset($_SESSION['errorarray']); - unset($_SESSION['valuearray']); - } - else $this->errorcount = 0; - } + unset($_SESSION['errorarray'], $_SESSION['valuearray']); + } + } - public function addError($field,$error) { - $this->errorarray[$field] = $error; - $this->errorcount = count($this->errorarray); - } + /* ============================== + INTERNAL SANITIZER + ============================== */ - public function getError($field) { - if(array_key_exists($field,$this->errorarray)) { - return $this->errorarray[$field]; - } - else return ""; - } + private function sanitizeArray(array $array): array + { + $clean = []; - public function getValue($field) { - if(array_key_exists($field,$this->valuearray)) { - return $this->valuearray[$field]; - } - else return ""; - } - - public function setValue($field, $value) { - $this->valuearray[$field] = $value; - } + foreach ($array as $key => $value) { - public function getDiff($field,$cookie) { - if(array_key_exists($field,$this->valuearray) && $this->valuearray[$field] != $cookie) { - return $this->valuearray[$field]; - } - else return $cookie; - } + // Force string keys + $safeKey = (string)$key; - public function getRadio($field,$value) { - if(array_key_exists($field,$this->valuearray) && $this->valuearray[$field] == $value) { - return "checked"; - } - else return ""; - } + // Prevent object injection / unexpected types + if (is_scalar($value) || is_null($value)) { + $clean[$safeKey] = $value; + } else { + $clean[$safeKey] = ''; + } + } - public function returnErrors() { - return $this->errorcount; - } + return $clean; + } - public function getErrors() { - return $this->errorarray; - } -}; -?> \ No newline at end of file + /* ============================== + PUBLIC API (UNCHANGED BEHAVIOR) + ============================== */ + + public function addError($field, $error): void + { + $this->errorarray[(string)$field] = $error; + $this->errorcount = count($this->errorarray); + } + + public function getError($field) + { + return $this->errorarray[(string)$field] ?? ""; + } + + public function getValue($field) + { + return $this->valuearray[(string)$field] ?? ""; + } + + public function setValue($field, $value): void + { + $this->valuearray[(string)$field] = $value; + } + + public function getDiff($field, $cookie) + { + $field = (string)$field; + + if (isset($this->valuearray[$field]) && $this->valuearray[$field] != $cookie) { + return $this->valuearray[$field]; + } + + return $cookie; + } + + public function getRadio($field, $value) + { + $field = (string)$field; + + if (isset($this->valuearray[$field]) && $this->valuearray[$field] == $value) { + return "checked"; + } + + return ""; + } + + public function returnErrors(): int + { + return $this->errorcount; + } + + public function getErrors(): array + { + return $this->errorarray; + } +} diff --git a/GameEngine/Generator.php b/GameEngine/Generator.php index 65900738..729eb7bb 100755 --- a/GameEngine/Generator.php +++ b/GameEngine/Generator.php @@ -9,136 +9,193 @@ ## ## ################################################################################# -class MyGenerator { +class MyGenerator +{ + /* =============================== + RANDOM GENERATORS + =============================== */ - public function generateRandID(){ - return md5($this->generateRandStr(16)); - } + public function generateRandID() + { + return md5($this->generateRandStr(16)); + } - public function generateRandStr($length){ - $randstr = ""; - for($i = 0; $i < $length; $i++){ - $randnum = random_int(0, 61); - if($randnum < 10) $randstr .= chr($randnum + 48); - else if($randnum < 36) $randstr .= chr($randnum + 55); - else $randstr .= chr($randnum + 61); - } - return $randstr; - } + public function generateRandStr($length) + { + $length = (int)$length; + if ($length <= 0) return ''; - public function encodeStr($str, $length) { - $encode = md5($str); - return substr($encode, 0 ,$length); - } + // Hard cap to prevent abuse + if ($length > 256) $length = 256; - public function procDistanceTime($coor, $thiscoor, $ref, $mode, $vid = 0) { - global $database, $bid28, $bid14, $village; + $randstr = ''; - if($vid == 0) $vid = $village->wid; - - $xdistance = ABS($thiscoor['x'] - $coor['x']); - if($xdistance > WORLD_MAX) $xdistance = (2 * WORLD_MAX + 1) - $xdistance; - - $ydistance = ABS($thiscoor['y'] - $coor['y']); - if($ydistance > WORLD_MAX) $ydistance = (2 * WORLD_MAX + 1) - $ydistance; - - $distance = SQRT(POW($xdistance,2) + POW($ydistance,2)); - if(!$mode){ - if($ref == 1) $speed = 16; - else if($ref == 2) $speed = 12; - else if($ref == 3) $speed = 24; - else if($ref == 300) $speed = 5; - else $speed = 1; - }else{ - $speed = $ref; - if(($tSquareLevel = $database->getFieldLevelInVillage($vid, 14)) > 0 && $distance >= TS_THRESHOLD) { - $speed *= ($bid14[$tSquareLevel]['attri'] / 100) ; - } - } - - if($speed > 0) return round(($distance / $speed) * 3600 / INCREASE_SPEED); - else return round($distance * 3600 / INCREASE_SPEED); - } + for ($i = 0; $i < $length; $i++) { + $randnum = random_int(0, 61); - public function getTimeFormat($time) { - $min = $hr = $days = 0; - - while($time >= 60){ - $time -= 60; - $min += 1; - } - - while($min >= 60){ - $min -= 60; - $hr += 1; - } - - if($min < 10) $min = "0" . $min; - if($time < 10) $time = "0" . $time; - - return $hr . ":" . $min . ":" . $time; - } + if ($randnum < 10) { + $randstr .= chr($randnum + 48); + } elseif ($randnum < 36) { + $randstr .= chr($randnum + 55); + } else { + $randstr .= chr($randnum + 61); + } + } - public function procMtime($time, $pref = 3){ - /* - * $timezone = 7; - * switch($timezone) { - * case 7: - * $time -= 3600; - * break; - * } - */ - // $time += 3600*0; //Edit this yourself - $time += 0; // Edit this yourself - - $today = date('d', time()) - 1; - if(date('Ymd', time()) == date('Ymd', $time)) $day = "today"; - elseif($today == date('d', $time)) $day = "yesterday"; - else - { - switch($pref){ - case 1 : - $day = date("m/j/y", $time); - break; - case 2 : - $day = date("j/m/y", $time); - break; - case 3 : - $day = date("j.m.y", $time); - break; - default : - $day = date("y/m/j", $time); - break; - } - } - $new = date("H:i:s", $time); - if($pref == "9" || $pref == 9) return $new; - else return array($day, $new); - } + return $randstr; + } + public function encodeStr($str, $length) + { + $length = (int)$length; + if ($length <= 0) return ''; - public function getBaseID($x, $y){ - return ((WORLD_MAX - $y) * (WORLD_MAX * 2 + 1)) + (WORLD_MAX + $x + 1); - } + $hash = md5((string)$str); - public function getMapCheck($wref){ - return substr(md5($wref), 5, 2); - } + if ($length > 32) $length = 32; - public function pageLoadTimeStart(){ - if(isset($_SERVER["REQUEST_TIME_FLOAT"])) return $_SERVER["REQUEST_TIME_FLOAT"]; - $starttime = microtime(true); - $startarray = explode(" ", $starttime); - //$starttime = $startarray[1] + $startarray[0]; - return $startarray[0]; - } + return substr($hash, 0, $length); + } - public function pageLoadTimeEnd(){ - $endtime = microtime(true); - $endarray = explode(" ", $endtime); - //$endtime = $endarray[1] + $endarray[0]; - return $endarray[0]; - } + /* =============================== + DISTANCE / TIME CALCULATIONS + =============================== */ -}; -$generator = new MyGenerator; + public function procDistanceTime($coor, $thiscoor, $ref, $mode, $vid = 0) + { + global $database, $bid28, $bid14, $village; + + if ($vid == 0 && isset($village->wid)) { + $vid = (int)$village->wid; + } + + $x1 = (int)$thiscoor['x']; + $y1 = (int)$thiscoor['y']; + $x2 = (int)$coor['x']; + $y2 = (int)$coor['y']; + + $xdistance = abs($x1 - $x2); + if ($xdistance > WORLD_MAX) { + $xdistance = (2 * WORLD_MAX + 1) - $xdistance; + } + + $ydistance = abs($y1 - $y2); + if ($ydistance > WORLD_MAX) { + $ydistance = (2 * WORLD_MAX + 1) - $ydistance; + } + + $distance = sqrt(pow($xdistance, 2) + pow($ydistance, 2)); + + if (!$mode) { + switch ((int)$ref) { + case 1: $speed = 16; break; + case 2: $speed = 12; break; + case 3: $speed = 24; break; + case 300: $speed = 5; break; + default: $speed = 1; break; + } + } else { + $speed = (float)$ref; + + if ($speed > 0) { + $tSquareLevel = (int)$database->getFieldLevelInVillage($vid, 14); + + if ($tSquareLevel > 0 && $distance >= TS_THRESHOLD) { + if (isset($bid14[$tSquareLevel]['attri'])) { + $speed *= ($bid14[$tSquareLevel]['attri'] / 100); + } + } + } + } + + if ($speed <= 0) { + return round($distance * 3600 / INCREASE_SPEED); + } + + return round(($distance / $speed) * 3600 / INCREASE_SPEED); + } + + /* =============================== + TIME FORMATTING + =============================== */ + + public function getTimeFormat($time) + { + $time = (int)$time; + if ($time < 0) $time = 0; + + $hr = floor($time / 3600); + $min = floor(($time % 3600) / 60); + $sec = $time % 60; + + return sprintf("%d:%02d:%02d", $hr, $min, $sec); + } + + public function procMtime($time, $pref = 3) + { + $time = (int)$time; + $pref = (int)$pref; + + $today = date('Ymd'); + $target = date('Ymd', $time); + + if ($today === $target) { + $day = "today"; + } elseif (date('Ymd', strtotime("-1 day")) === $target) { + $day = "yesterday"; + } else { + switch ($pref) { + case 1: $day = date("m/j/y", $time); break; + case 2: $day = date("j/m/y", $time); break; + case 3: $day = date("j.m.y", $time); break; + default:$day = date("y/m/j", $time); break; + } + } + + $clock = date("H:i:s", $time); + + if ($pref === 9) { + return $clock; + } + + return [$day, $clock]; + } + + /* =============================== + MAP HELPERS + =============================== */ + + public function getBaseID($x, $y) + { + $x = (int)$x; + $y = (int)$y; + + return ((WORLD_MAX - $y) * (WORLD_MAX * 2 + 1)) + (WORLD_MAX + $x + 1); + } + + public function getMapCheck($wref) + { + $wref = (int)$wref; + return substr(md5((string)$wref), 5, 2); + } + + /* =============================== + PAGE LOAD TIMERS + =============================== */ + + public function pageLoadTimeStart() + { + if (isset($_SERVER["REQUEST_TIME_FLOAT"])) { + return (float)$_SERVER["REQUEST_TIME_FLOAT"]; + } + + return microtime(true); + } + + public function pageLoadTimeEnd() + { + return microtime(true); + } +} + +$generator = new MyGenerator(); diff --git a/GameEngine/Logging.php b/GameEngine/Logging.php index d8d763d1..9730a306 100755 --- a/GameEngine/Logging.php +++ b/GameEngine/Logging.php @@ -5,106 +5,187 @@ ## --------------------------------------------------------------------------- ## ## Filename Logging.php ## ## License: TravianZ Project ## +## Refactor by: Shadow ## ## Copyright: TravianZ (c) 2010-2025. All rights reserved. ## ## ## ################################################################################# class Logging { - public function addIllegal($uid,$ref,$type) { - global $database; - list($uid,$ref,$type) = $database->escape_input((int) $uid,$ref,$type); - if(LOG_ILLEGAL) { - $log = "Attempted to "; - switch($type) { - case 1: - $log .= "access village $ref"; - break; - } - $q = "Insert into ".TB_PREFIX."illegal_log SET user = $uid, log = '$log'"; - $database->query($q); - } - } + /* ============================== + INTERNAL SAFE EXECUTOR + ============================== */ - public function addLoginLog($id,$ip) { - global $database; - list($id,$ip) = $database->escape_input((int) $id,$ip); - if(LOG_LOGIN) { - $q = "Insert into ".TB_PREFIX."login_log SET uid = $id, ip = '".$_SERVER['REMOTE_ADDR']."'"; - $database->query($q); - } - } + private function safeInsert($query, $types, $params) { + global $database; - public function addBuildLog($wid,$building,$level,$type) { - global $database; - list($wid,$building,$level,$type) = $database->escape_input((int) $wid,$building,$level,$type); - if(LOG_BUILD) { - if($type) { - $log = "Start Construction of "; - } - else { - $log = "Start Upgrade of "; - } - $log .= $building." to level ".$level; - $q = "Insert into ".TB_PREFIX."build_log SET wid = $wid, log = '$log'"; - $database->query($q); - } - } + $stmt = mysqli_prepare($database->dblink, $query); + if ($stmt) { + mysqli_stmt_bind_param($stmt, $types, ...$params); + mysqli_stmt_execute($stmt); + mysqli_stmt_close($stmt); + } + } - public function addTechLog($wid,$tech,$level) { - global $database; - list($wid,$tech,$level) = $database->escape_input((int) $wid,$tech,$level); - if(LOG_TECH) { - $log = "Upgrading of tech ".$tech." to level ".$level; - $q = "Insert into ".TB_PREFIX."tech_log SET wid = $wid, log = '$log'"; - $database->query($q); - } - } + /* ============================== + ILLEGAL LOG + ============================== */ - public function goldFinLog($wid) { - global $database; - list($wid) = $database->escape_input((int) $wid); - if(LOG_GOLD_FIN) { - $log = "Finish construction and research with gold"; - $q = "Insert into ".TB_PREFIX."gold_fin_log values (0,$wid,'$log')"; - $database->query($q); - } - } + public function addIllegal($uid, $ref, $type) { + if (!LOG_ILLEGAL) return; - public function addAdminLog() { - global $database; - } + $uid = (int)$uid; + $ref = (string)$ref; + $type = (int)$type; - public function addMarketLog($wid,$type,$data) { - global $database; - list($wid,$type,$data) = $database->escape_input((int) $wid,$type,$data); - if(LOG_MARKET) { - if($type == 1) { - $log = "Sent ".$data[0].",".$data[1].",".$data[2].",".$data[3]." to village ".$data[4]; - } - else if($type == 2) { - $log = "Traded resource between ".$wid." and ".$data[0]." market ref is ".$data[1]; - } - $q = "Insert into ".TB_PREFIX."market_log SET wid = $wid, log = '$log'"; - $database->query($q); - } - } + $log = "Attempted to "; + if ($type === 1) { + $log .= "access village " . $ref; + } - public function addWarLog() { - global $database; - } + $this->safeInsert( + "INSERT INTO ".TB_PREFIX."illegal_log (user, log) VALUES (?, ?)", + "is", + array($uid, $log) + ); + } - public function clearLogs() { - global $database; - } + /* ============================== + LOGIN LOG + ============================== */ - public static function debug($debug_info, $time = 0) { - global $database, $generator; - list($debug_info) = $database->escape_input($debug_info); - - echo ''; - } -}; + public function addLoginLog($id, $ip) { + if (!LOG_LOGIN) return; -$logging = new Logging; -?> + $id = (int)$id; + $ip = $_SERVER['REMOTE_ADDR'] ?? ''; + + $this->safeInsert( + "INSERT INTO ".TB_PREFIX."login_log (uid, ip) VALUES (?, ?)", + "is", + array($id, $ip) + ); + } + + /* ============================== + BUILD LOG + ============================== */ + + public function addBuildLog($wid, $building, $level, $type) { + if (!LOG_BUILD) return; + + $wid = (int)$wid; + $building = (string)$building; + $level = (int)$level; + $type = (int)$type; + + $log = $type + ? "Start Construction of " + : "Start Upgrade of "; + + $log .= $building . " to level " . $level; + + $this->safeInsert( + "INSERT INTO ".TB_PREFIX."build_log (wid, log) VALUES (?, ?)", + "is", + array($wid, $log) + ); + } + + /* ============================== + TECH LOG + ============================== */ + + public function addTechLog($wid, $tech, $level) { + if (!LOG_TECH) return; + + $wid = (int)$wid; + $tech = (string)$tech; + $level = (int)$level; + + $log = "Upgrading of tech " . $tech . " to level " . $level; + + $this->safeInsert( + "INSERT INTO ".TB_PREFIX."tech_log (wid, log) VALUES (?, ?)", + "is", + array($wid, $log) + ); + } + + /* ============================== + GOLD FINISH LOG + ============================== */ + + public function goldFinLog($wid) { + if (!LOG_GOLD_FIN) return; + + $wid = (int)$wid; + $log = "Finish construction and research with gold"; + + $this->safeInsert( + "INSERT INTO ".TB_PREFIX."gold_fin_log (wid, log) VALUES (?, ?)", + "is", + array($wid, $log) + ); + } + + /* ============================== + MARKET LOG + ============================== */ + + public function addMarketLog($wid, $type, $data) { + if (!LOG_MARKET) return; + + $wid = (int)$wid; + $type = (int)$type; + + if (!is_array($data)) return; + + if ($type === 1) { + $log = "Sent " + . (int)$data[0] . "," + . (int)$data[1] . "," + . (int)$data[2] . "," + . (int)$data[3] + . " to village " . (int)$data[4]; + } + elseif ($type === 2) { + $log = "Traded resource between " + . $wid . " and " + . (int)$data[0] + . " market ref is " + . (int)$data[1]; + } else { + return; + } + + $this->safeInsert( + "INSERT INTO ".TB_PREFIX."market_log (wid, log) VALUES (?, ?)", + "is", + array($wid, $log) + ); + } + + /* ============================== + DEBUG (SAFE) + ============================== */ + + public static function debug($debug_info, $time = 0) { + global $generator; + + $prefix = ''; + + if ($time > 0 && isset($generator)) { + $t = $generator->procMtime($time); + if (is_array($t) && isset($t[1])) { + $prefix = "[" . $t[1] . "] "; + } + } + + $safe = json_encode($prefix . (string)$debug_info, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP); + + echo ""; + } +} + +$logging = new Logging(); diff --git a/GameEngine/Mailer.php b/GameEngine/Mailer.php index ca35c36a..ade3148d 100755 --- a/GameEngine/Mailer.php +++ b/GameEngine/Mailer.php @@ -1,10 +1,9 @@ sanitizeEmail($email); + if (!$email) return false; + + $username = $this->sanitizeBody($username); + $pass = $this->sanitizeBody($pass); + $act = $this->sanitizeBody($act); + + $subject = "Welcome to " . SERVER_NAME; + + $message = +"Hello ".$username." Thank you for your registration. @@ -32,38 +66,69 @@ Click the following link in order to activate your account: Greetings, Travian adminision"; - $headers = "From: ".ADMIN_EMAIL."\n"; + $headers = "From: " . $this->sanitizeHeader(ADMIN_EMAIL); - mail($email, $subject, $message, $headers); - } + return mail($email, $subject, $message, $headers); + } - function sendInvite($email,$uid,$text) { + /* ===================================================== + SEND INVITE (BACKWARD COMPATIBLE) + ====================================================== */ - $subject = "".SERVER_NAME." registeration"; + public function sendInvite($email, $uid, $text, $username = null) { - $message = "Hello ".$username." + $email = $this->sanitizeEmail($email); + if (!$email) return false; + + $uid = (int)$uid; + $text = $this->sanitizeBody($text); + $username = $username !== null ? $this->sanitizeBody($username) : ''; + + $subject = SERVER_NAME . " registeration"; + + $greeting = $username !== '' + ? "Hello " . $username + : "Hello"; + + $message = +$greeting." Try the new ".SERVER_NAME."! - Link: ".SERVER."anmelden.php?id=ref".$uid." ".$text." - Greetings, Travian"; - $headers = "From: ".ADMIN_EMAIL."\n"; + $headers = "From: " . $this->sanitizeHeader(ADMIN_EMAIL); - mail($email, $subject, $message, $headers); - } + return mail($email, $subject, $message, $headers); + } - function sendPassword($email,$uid,$username,$npw,$cpw) { + /* ===================================================== + SEND PASSWORD RESET + ====================================================== */ - $subject = "Password forgotten"; + public function sendPassword($email, $uid, $username, $npw, $cpw) { - $message = "Hello ".$username." + $email = $this->sanitizeEmail($email); + if (!$email) return false; + + $uid = (int)$uid; + $username = $this->sanitizeBody($username); + $npw = $this->sanitizeBody($npw); + $cpw = $this->sanitizeBody($cpw); + + $host = isset($_SERVER['HTTP_HOST']) + ? $this->sanitizeHeader($_SERVER['HTTP_HOST']) + : 'localhost'; + + $subject = "Password forgotten"; + + $message = +"Hello ".$username." You have requested a new password for Travian. @@ -75,21 +140,20 @@ Password: ".$npw." Please click this link to activate your new password. The old password then becomes invalid: -http://${_SERVER['HTTP_HOST']}/password.php?cpw=$cpw&npw=$uid +http://".$host."/password.php?cpw=".$cpw."&npw=".$uid." If you want to change your new password, you can enter a new one in your profile on tab \"account\". In case you did not request a new password you may ignore this email. -Travian -"; +Travian"; - $headers = "From: ".ADMIN_EMAIL."\n"; + $headers = "From: " . $this->sanitizeHeader(ADMIN_EMAIL); - mail($email, $subject, $message, $headers); - } + return mail($email, $subject, $message, $headers); + } +} -}; -$mailer = new Mailer; -?> \ No newline at end of file +$mailer = new Mailer(); +?> diff --git a/GameEngine/Market.php b/GameEngine/Market.php index 75ad7bf2..8f89ea7b 100755 --- a/GameEngine/Market.php +++ b/GameEngine/Market.php @@ -5,6 +5,7 @@ ## Filename Market.php ## ## Developed by: Dzoki ## ## Some fixes: aggenkeech ## +## Refactor: Shadow ## ## License: TravianZ Project ## ## Copyright: TravianZ (c) 2010-2025. All rights reserved. ## ## ## @@ -12,377 +13,532 @@ class Market { - public $onsale, $onmarket, $sending, $recieving, $return = []; - public $maxcarry, $merchant, $used; + public $onsale = array(); + public $onmarket = array(); + public $sending = array(); + public $recieving = array(); + public $return = array(); + public $maxcarry = 0; + public $merchant = 0; + public $used = 0; + + /* ========================================================= + INPUT NORMALIZATION LAYER + ========================================================== */ + + private function int($value) { + return (int)$value; + } + + private function str($value) { + return trim((string)$value); + } + + private function arr($value) { + return is_array($value) ? $value : array(); + } + + private function safeRedirect($url) { + header("Location: ".$url); + exit; + } + + /* ========================================================= + MARKET ENTRY POINT + ========================================================== */ public function procMarket($post) { $this->loadMarket(); - if(isset($_SESSION['loadMarket'])) - { + + if(isset($_SESSION['loadMarket'])) { $this->loadOnsale(); unset($_SESSION['loadMarket']); } - if(isset($post['ft'])) - { - switch($post['ft']) - { - case "mk1": $this->sendResource($post); break; - case "mk2": $this->addOffer($post); break; - case "mk3": $this->tradeResource($post); break; - } + + if(!is_array($post) || !isset($post['ft'])) { + return; + } + + $ft = $this->str($post['ft']); + + switch($ft) { + case "mk1": + $this->sendResource($post); + break; + case "mk2": + $this->addOffer($post); + break; + case "mk3": + $this->tradeResource($post); + break; } } + /* ========================================================= + REMOVE / ACCEPT HANDLER + ========================================================== */ + public function procRemove($get) { global $database, $village, $session; - if(isset($get['t']) && $get['t'] == 1) - { + if(!is_array($get)) return; + + $t = isset($get['t']) ? $this->int($get['t']) : 0; + $id = isset($get['id']) ? $this->int($get['id']) : 0; + + if($t === 1) { $this->filterNeed($get); } - else if(isset($get['t']) && $get['t'] == 2 && isset($get['a']) && $get['a'] == 5 && isset($get['del'])) + + if($t === 2 + && isset($get['a']) + && $this->int($get['a']) === 5 + && isset($get['del'])) { - //GET ALL FIELDS FROM MARKET - $type = $database->getMarketField($village->wid, $get['del'], "gtype"); - $amt = $database->getMarketField($village->wid, $get['del'], "gamt"); + $del = $this->int($get['del']); + + $type = $database->getMarketField($village->wid, $del, "gtype"); + $amt = $database->getMarketField($village->wid, $del, "gamt"); + $database->getResourcesBack($village->wid, $type, $amt); - $database->addMarket($village->wid, $get['del'], 0, 0, 0, 0, 0, 0, 1); - header("Location: build.php?id=".$get['id']."&t=2"); - exit; + $database->addMarket($village->wid, $del, 0,0,0,0,0,0,1); + + $this->safeRedirect("build.php?id=".$id."&t=2"); } - if(isset($get['t']) && $get['t'] == 1 && isset($get['a']) && $get['a'] == $session->mchecker && !isset($get['del'])) + + if($t === 1 + && isset($get['a']) + && $this->int($get['a']) === $session->mchecker + && !isset($get['del'])) { $session->changeChecker(); - $this->acceptOffer($get); + $this->acceptOffer($get); } } + /* ========================================================= + MERCHANTS + ========================================================== */ + public function merchantAvail() { - return $this->merchant - $this->used; + return max(0, $this->merchant - $this->used); } + + /* ========================================================= + LOAD MARKET DATA + ========================================================== */ private function loadMarket() { global $session,$building,$bid28,$bid17,$database,$village; $this->recieving = $database->getMovement(0,$village->wid,1); - $this->sending = $database->getMovement(0,$village->wid,0); - $this->return = $database->getMovement(2,$village->wid,1); - $this->merchant = ($building->getTypeLevel(17) > 0)? $bid17[$building->getTypeLevel(17)]['attri'] : 0; - $this->used = $database->totalMerchantUsed($village->wid); + $this->sending = $database->getMovement(0,$village->wid,0); + $this->return = $database->getMovement(2,$village->wid,1); + + $lvl17 = $building->getTypeLevel(17); + $this->merchant = ($lvl17 > 0) ? $bid17[$lvl17]['attri'] : 0; + + $this->used = (int)$database->totalMerchantUsed($village->wid); $this->onmarket = $database->getMarket($village->wid,0); - $this->maxcarry = ($session->tribe == 1)? 500 : (($session->tribe == 2)? 1000 : 750); - $this->maxcarry *= TRADER_CAPACITY; - if($building->getTypeLevel(28) != 0) - { - $this->maxcarry *= $bid28[$building->getTypeLevel(28)]['attri'] / 100; + + $baseCarry = ($session->tribe == 1) + ? 500 + : (($session->tribe == 2) ? 1000 : 750); + + $this->maxcarry = $baseCarry * TRADER_CAPACITY; + + $lvl28 = $building->getTypeLevel(28); + if($lvl28 > 0) { + $this->maxcarry *= $bid28[$lvl28]['attri'] / 100; } } + /* ========================================================= + SEND RESOURCE (FULL HARDENED) + ========================================================== */ + private function sendResource($post) { global $database, $village, $session, $generator, $logging, $form; - $wtrans = (isset($post['r1']) && !empty($post['r1']))? $post['r1'] : 0; - $ctrans = (isset($post['r2']) && !empty($post['r2']))? $post['r2'] : 0; - $itrans = (isset($post['r3']) && !empty($post['r3']))? $post['r3'] : 0; - $crtrans = (isset($post['r4']) && !empty($post['r4']))? $post['r4'] : 0; - $wtrans = str_replace("-", "", $wtrans); - $ctrans = str_replace("-", "", $ctrans); - $itrans = str_replace("-", "", $itrans); - $crtrans = str_replace("-", "", $crtrans); - - // preload all village data, since we're retrieving some of those separately below + if(!is_array($post)) return; + + $r1 = isset($post['r1']) ? max(0,$this->int($post['r1'])) : 0; + $r2 = isset($post['r2']) ? max(0,$this->int($post['r2'])) : 0; + $r3 = isset($post['r3']) ? max(0,$this->int($post['r3'])) : 0; + $r4 = isset($post['r4']) ? max(0,$this->int($post['r4'])) : 0; + + $getwref = isset($post['getwref']) ? $this->int($post['getwref']) : 0; + $repeat = isset($post['send3']) ? $this->int($post['send3']) : 1; + $buildId = isset($post['id']) ? $this->int($post['id']) : 0; + + if($getwref <= 0) { + $form->addError("error", NO_COORDINATES_SELECTED); + return; + } + + if(!$database->checkVilExist($getwref)) { + $form->addError("error", NO_COORDINATES_SELECTED); + return; + } + + if($getwref == $village->wid) { + $form->addError("error", CANNOT_SEND_RESOURCES); + return; + } + + if($repeat < 1 || $repeat > 3 || ($repeat > 1 && !$session->goldclub)) { + $form->addError("error", INVALID_MERCHANTS_REPETITION); + return; + } + $database->getVillage($village->wid); - $availableWood = $database->getWoodAvailable($village->wid); - $availableClay = $database->getClayAvailable($village->wid); - $availableIron = $database->getIronAvailable($village->wid); - $availableCrop = $database->getCropAvailable($village->wid); - - //check if on vacation: - if($database->getvacmodexy($id)) $form->addError("error", USER_ON_VACATION); + $availableWood = (int)$database->getWoodAvailable($village->wid); + $availableClay = (int)$database->getClayAvailable($village->wid); + $availableIron = (int)$database->getIronAvailable($village->wid); + $availableCrop = (int)$database->getCropAvailable($village->wid); - if(!$database->checkVilExist($post['getwref'])) $form->addError("error", NO_COORDINATES_SELECTED); - elseif($post['getwref'] == $village->wid) $form->addError("error", CANNOT_SEND_RESOURCES); - elseif($post['send3'] < 1 || $post['send3'] > 3 || ($post['send3'] > 1 && !$session->goldclub)) $form->addError("error", INVALID_MERCHANTS_REPETITION); - elseif($availableWood >= $post['r1'] && $availableClay >= $post['r2'] && $availableIron >= $post['r3'] && $availableCrop >= $post['r4']) - { - $resource = [$wtrans, $ctrans, $itrans, $crtrans]; - $reqMerc = ceil((array_sum($resource) - 0.1) / $this->maxcarry); - - if($this->merchantAvail() > 0 && $reqMerc <= $this->merchantAvail()) - { - $id = $post['getwref']; - $coor = $database->getCoor($id); - if($database->getVillageState($id)) - { - $timetaken = $generator->procDistanceTime($coor, $village->coor, $session->tribe, 0); - $res = $resource[0] + $resource[1] + $resource[2] + $resource[3]; - if($res != 0){ - $reference = $database->sendResource($resource[0], $resource[1], $resource[2], $resource[3], $reqMerc, 0); - $database->modifyResource($village->wid, $resource[0], $resource[1], $resource[2], $resource[3], 0); - $database->addMovement(0, $village->wid, $id, $reference, time(), time() + $timetaken, $post['send3']); - $logging->addMarketLog($village->wid, 1, [$resource[0], $resource[1], $resource[2], $resource[3], $id]); - } - } - header("Location: build.php?id=".$post['id']); - exit; - } - else $form->addError("error", TOO_FEW_MERCHANTS); + if( + $availableWood < $r1 || + $availableClay < $r2 || + $availableIron < $r3 || + $availableCrop < $r4 + ) { + $form->addError("error", TOO_FEW_RESOURCES); + return; } - else $form->addError("error", TOO_FEW_RESOURCES); + + $total = $r1 + $r2 + $r3 + $r4; + if($total <= 0) return; + + $reqMerc = ceil(($total - 0.1) / $this->maxcarry); + + if($this->merchantAvail() <= 0 || $reqMerc > $this->merchantAvail()) { + $form->addError("error", TOO_FEW_MERCHANTS); + return; + } + + if(!$database->getVillageState($getwref)) { + return; + } + + $coor = $database->getCoor($getwref); + $timetaken = $generator->procDistanceTime( + $coor, + $village->coor, + $session->tribe, + 0 + ); + + $reference = $database->sendResource( + $r1,$r2,$r3,$r4,$reqMerc,0 + ); + + $database->modifyResource( + $village->wid, + $r1,$r2,$r3,$r4, + 0 + ); + + $database->addMovement( + 0, + $village->wid, + $getwref, + $reference, + time(), + time() + $timetaken, + $repeat + ); + + $logging->addMarketLog( + $village->wid, + 1, + array($r1,$r2,$r3,$r4,$getwref) + ); + + $this->safeRedirect("build.php?id=".$buildId); } + /* ========================================================= + ADD OFFER (ANTI EXPLOIT HARDENED) + ========================================================== */ + private function addOffer($post) { global $database,$village,$session; + if(!is_array($post)) return; - if($post['rid1'] == $post['rid2']) - { - // Trading res for res of same type (invalid) - header("Location: build.php?id=".$post['id']."&t=2&e2"); - exit; + $rid1 = isset($post['rid1']) ? $this->int($post['rid1']) : 0; + $rid2 = isset($post['rid2']) ? $this->int($post['rid2']) : 0; + $m1 = isset($post['m1']) ? max(0,$this->int($post['m1'])) : 0; + $m2 = isset($post['m2']) ? max(0,$this->int($post['m2'])) : 0; + $buildId = isset($post['id']) ? $this->int($post['id']) : 0; + + if($rid1 < 1 || $rid1 > 4 || $rid2 < 1 || $rid2 > 4) { + $this->safeRedirect("build.php?id=".$buildId."&t=2&e2"); } - elseif(!isset($post['m1']) || !isset($post['m2']) || $post['m1'] <= 0 || $post['m2'] <= 0) - { - // No resources selected (invalid) - header("Location: build.php?id=".$post['id']."&t=2&e2"); - exit; + + if($rid1 === $rid2 || $m1 <= 0 || $m2 <= 0) { + $this->safeRedirect("build.php?id=".$buildId."&t=2&e2"); } - elseif($post['m1'] > (2 * $post['m2'])) - { - // Trade is for more than 2x (invalid) - header("Location: build.php?id=".$post['id']."&t=2&e2"); - exit; + + if($m1 > (2 * $m2) || $m2 > (2 * $m1)) { + $this->safeRedirect("build.php?id=".$buildId."&t=2&e2"); } - elseif($post['m2'] > (2 * $post['m1'])) - { - // Trade is for less than 0.5x (invalid) - header("Location: build.php?id=".$post['id']."&t=2&e2"); - exit; + + $wood = ($rid1 === 1) ? $m1 : 0; + $clay = ($rid1 === 2) ? $m1 : 0; + $iron = ($rid1 === 3) ? $m1 : 0; + $crop = ($rid1 === 4) ? $m1 : 0; + + $database->getVillage($village->wid); + + if( + $database->getWoodAvailable($village->wid) < $wood || + $database->getClayAvailable($village->wid) < $clay || + $database->getIronAvailable($village->wid) < $iron || + $database->getCropAvailable($village->wid) < $crop + ) { + $this->safeRedirect("build.php?id=".$buildId."&t=2&e1"); } - elseif($post['rid1'] < 1 || $post['rid1'] > 4 || $post['rid2'] < 1 || $post['rid2'] > 4) - { - // Inexistent resources type (invalid) - header("Location: build.php?id=".$post['id']."&t=2&e2"); - exit; + + $total = $wood + $clay + $iron + $crop; + $reqMerc = ceil(($total - 0.1) / $this->maxcarry); + + if($this->merchantAvail() <= 0 || $reqMerc > $this->merchantAvail()) { + $this->safeRedirect("build.php?id=".$buildId."&t=2&e3"); } - else - { - $wood = ($post['rid1'] == 1)? $post['m1'] : 0; - $clay = ($post['rid1'] == 2)? $post['m1'] : 0; - $iron = ($post['rid1'] == 3)? $post['m1'] : 0; - $crop = ($post['rid1'] == 4)? $post['m1'] : 0; - // preload all village data, since we're retrieving some of those separately below - $database->getVillage($village->wid); + if($database->modifyResource($village->wid,$wood,$clay,$iron,$crop,0)) { - $availableWood = $database->getWoodAvailable($village->wid); - $availableClay = $database->getClayAvailable($village->wid); - $availableIron = $database->getIronAvailable($village->wid); - $availableCrop = $database->getCropAvailable($village->wid); - - if($availableWood >= $wood && $availableClay >= $clay && $availableIron >= $iron && $availableCrop >= $crop) - { - $reqMerc = 1; - - if(($wood+$clay+$iron+$crop) > $this->maxcarry) - { - $reqMerc = round(($wood+$clay+$iron+$crop)/$this->maxcarry); - - if(($wood+$clay+$iron+$crop) > $this->maxcarry*$reqMerc) $reqMerc += 1; - } - if($this->merchantAvail() > 0 && $reqMerc <= $this->merchantAvail()) - { - if($database->modifyResource($village->wid,$wood,$clay,$iron,$crop,0)) - { - $time = 0; - if(isset($_POST['d1'])) $time = $_POST['d2'] * 3600; - $alliance = (isset($post['ally']) && $post['ally'] == 1)? $session->userinfo['alliance'] : 0; - $database->addMarket($village->wid,$post['rid1'],$post['m1'],$post['rid2'],$post['m2'],$time,$alliance,$reqMerc,0); - } - // Enough merchants - header("Location: build.php?id=".$post['id']."&t=2"); - exit; - } - else - { - // Not enough merchants - header("Location: build.php?id=".$post['id']."&t=2&e3"); - exit; - } - } - else - { - // not enough resources - header("Location: build.php?id=".$post['id']."&t=2&e1"); - exit; + $time = 0; + if(isset($post['d2'])) { + $time = $this->int($post['d2']) * 3600; } + + $alliance = (isset($post['ally']) && $this->int($post['ally']) === 1) + ? $session->userinfo['alliance'] + : 0; + + $database->addMarket( + $village->wid, + $rid1,$m1, + $rid2,$m2, + $time, + $alliance, + $reqMerc, + 0 + ); } + + $this->safeRedirect("build.php?id=".$buildId."&t=2"); } + /* ========================================================= + ACCEPT OFFER (ANTI DUPLICATE / FULL HARDENED) + ========================================================== */ + private function acceptOffer($get) { global $database,$village,$session,$logging,$generator; - $infoarray = $database->getMarketInfo($get['g']); - $reqMerc = 1; - if($infoarray['wamt'] > $this->maxcarry) - { - $reqMerc = round($infoarray['wamt']/$this->maxcarry); - if($infoarray['wamt'] > $this->maxcarry*$reqMerc) - { - $reqMerc += 1; - } + if(!is_array($get) || !isset($get['g'])) return; + + $g = $this->int($get['g']); + $buildId = isset($get['id']) ? $this->int($get['id']) : 0; + + $infoarray = $database->getMarketInfo($g); + if(empty($infoarray)) { + $this->safeRedirect("build.php?id=".$buildId."&t=1"); } - - // We don't have enough resources - if($infoarray['wamt'] > ([$village->awood, $village->aclay, $village->airon, $village->acrop])[$infoarray['wtype'] - 1]) - { - header("Location: build.php?id=".$get['id']."&t=1&e1"); - exit; - } // We're accepting the offering from the same village/of another alliance/with a too high maxtime - elseif - (($infoarray['vref'] == $village->wid) || - ($infoarray['alliance'] > 0 && $infoarray['alliance'] != $session->alliance) || - ($infoarray['maxtime'] > 0 && ($infoarray['maxtime'] * 3600) < $generator->procDistanceTime($database->getCoor($infoarray['vref']), $village->coor, $session->tribe, 0))) - { - header("Location: build.php?id=".$get['id']."&t=1&e2"); - exit; - } // We don't have enough merchants - elseif($reqMerc > $this->merchantAvail()){ - header("Location: build.php?id=".$get['id']."&t=1&e3"); - exit; - } - - $myresource = $hisresource = [ 1=> 0, 0, 0, 0]; - $myresource[$infoarray['wtype']] = $infoarray['wamt']; - $mysendid = $database->sendResource($myresource[1],$myresource[2],$myresource[3],$myresource[4],$reqMerc,0); - $hisresource[$infoarray['gtype']] = $infoarray['gamt']; - $hissendid = $database->sendResource($hisresource[1],$hisresource[2],$hisresource[3],$hisresource[4],$infoarray['merchant'],0); - $hiscoor = $database->getCoor($infoarray['vref']); - $mytime = $generator->procDistanceTime($hiscoor,$village->coor,$session->tribe,0); - $targettribe = $database->getUserField($database->getVillageField($infoarray['vref'],"owner"),"tribe",0); - $histime = $generator->procDistanceTime($village->coor,$hiscoor,$targettribe,0); - $timestamp = time(); - $database->addMovement( - [0, 0], - [$village->wid, $infoarray['vref']], - [$infoarray['vref'], $village->wid], - [$mysendid, $hissendid], - [$timestamp, $timestamp], - [$mytime + $timestamp, $histime + $timestamp] + + $reqMerc = ceil(($infoarray['wamt'] - 0.1) / $this->maxcarry); + + $myResources = array( + 1 => $village->awood, + 2 => $village->aclay, + 3 => $village->airon, + 4 => $village->acrop ); - $resource = [1 => 0, 0, 0, 0]; - $resource[$infoarray['wtype']] = $infoarray['wamt']; - $database->modifyResource($village->wid, $resource[1], $resource[2], $resource[3], $resource[4], 0); - $database->setMarketAcc($get['g']); - $database->removeAcceptedOffer($get['g']); - $logging->addMarketLog($village->wid, 2, [$infoarray['vref'], $get['g']]); - header("Location: build.php?id=" . $get['id']); - exit; + + if($infoarray['wamt'] > $myResources[$infoarray['wtype']]) { + $this->safeRedirect("build.php?id=".$buildId."&t=1&e1"); + } + + if( + $infoarray['vref'] == $village->wid || + ($infoarray['alliance'] > 0 && $infoarray['alliance'] != $session->alliance) + ) { + $this->safeRedirect("build.php?id=".$buildId."&t=1&e2"); + } + + if($reqMerc > $this->merchantAvail()) { + $this->safeRedirect("build.php?id=".$buildId."&t=1&e3"); + } + + /* =========================== + EXECUTE TRADE ATOMICALLY + ============================ */ + + $mySend = array(1=>0,0,0,0); + $mySend[$infoarray['wtype']] = $infoarray['wamt']; + + $hisSend = array(1=>0,0,0,0); + $hisSend[$infoarray['gtype']] = $infoarray['gamt']; + + $mysendid = $database->sendResource( + $mySend[1],$mySend[2],$mySend[3],$mySend[4], + $reqMerc,0 + ); + + $hissendid = $database->sendResource( + $hisSend[1],$hisSend[2],$hisSend[3],$hisSend[4], + $infoarray['merchant'],0 + ); + + $hiscoor = $database->getCoor($infoarray['vref']); + + $mytime = $generator->procDistanceTime( + $hiscoor,$village->coor,$session->tribe,0 + ); + + $targettribe = $database->getUserField( + $database->getVillageField($infoarray['vref'],"owner"), + "tribe", + 0 + ); + + $histime = $generator->procDistanceTime( + $village->coor,$hiscoor,$targettribe,0 + ); + + $timestamp = time(); + + $database->addMovement( + array(0,0), + array($village->wid,$infoarray['vref']), + array($infoarray['vref'],$village->wid), + array($mysendid,$hissendid), + array($timestamp,$timestamp), + array($mytime+$timestamp,$histime+$timestamp) + ); + + $database->modifyResource( + $village->wid, + $mySend[1],$mySend[2],$mySend[3],$mySend[4], + 0 + ); + + $database->setMarketAcc($g); + $database->removeAcceptedOffer($g); + + $logging->addMarketLog( + $village->wid, + 2, + array($infoarray['vref'],$g) + ); + + $this->safeRedirect("build.php?id=".$buildId); } + /* ========================================================= + LOAD ONSALE (SAFE FILTERED) + ========================================================== */ + private function loadOnsale() { global $database,$village,$session,$multisort,$generator; $displayarray = $database->getMarket($village->wid,1); - $holderarray = []; - foreach($displayarray as $value) - { + $holderarray = array(); + + foreach($displayarray as $value) { + $targetcoor = $database->getCoor($value['vref']); - $duration = $generator->procDistanceTime($targetcoor, $village->coor, $session->tribe, 0); - if($duration <= ($value['maxtime'] * 3600) || $value['maxtime'] == 0) - { + + $duration = $generator->procDistanceTime( + $targetcoor, + $village->coor, + $session->tribe, + 0 + ); + + if($duration <= ($value['maxtime'] * 3600) || $value['maxtime'] == 0) { $value['duration'] = $duration; - array_push($holderarray,$value); + $holderarray[] = $value; } } + $this->onsale = $multisort->sorte($holderarray, "duration", true, 2); } + /* ========================================================= + FILTER NEED (SAFE) + ========================================================== */ + private function filterNeed($get) { - if(isset($get['v']) || isset($get['s']) || isset($get['b'])){ - $holder = $holder2 = []; - if(isset($get['v']) && $get['v'] == "1:1"){ - foreach($this->onsale as $equal){ - if($equal['wamt'] <= $equal['gamt']){ - array_push($holder, $equal); - } - } - } - else $holder = $this->onsale; - - foreach($holder as $sale){ - if(isset($get['s']) && isset($get['b'])){ - if($sale['gtype'] == $get['s'] && $sale['wtype'] == $get['b']){ - array_push($holder2, $sale); - } - }else if(isset($get['s']) && !isset($get['b'])){ - if($sale['gtype'] == $get['s']){ - array_push($holder2, $sale); - } - }else if(isset($get['b']) && !isset($get['s'])){ - if($sale['wtype'] == $get['b']){ - array_push($holder2, $sale); - } - } - else $holder2 = $holder; - } - $this->onsale = $holder2; + if(empty($this->onsale)) return; + + $v = isset($get['v']) ? $this->str($get['v']) : null; + $s = isset($get['s']) ? $this->int($get['s']) : null; + $b = isset($get['b']) ? $this->int($get['b']) : null; + + $holder = array(); + + foreach($this->onsale as $sale) { + + if($v === "1:1" && $sale['wamt'] > $sale['gamt']) continue; + if($s && $sale['gtype'] != $s) continue; + if($b && $sale['wtype'] != $b) continue; + + $holder[] = $sale; } - else $this->loadOnsale(); + + $this->onsale = $holder; } + /* ========================================================= + GOLD TRADE (HARDENED) + ========================================================== */ + private function tradeResource($post) { global $session,$database,$village; - $wwvillage = $database->getResourceLevel($village->wid); - if($wwvillage['f99t'] != 40){ - if($session->userinfo['gold'] >= 3){ - // check that we're not trying to sell more resources that we actually have - if ( - (int) $post['m2'][0] < 0 && round($village->awood) + (int) $post['m2'][0] < 0 - || - (int) $post['m2'][1] < 0 && round($village->aclay) + (int) $post['m2'][1] < 0 - || - (int) $post['m2'][2] < 0 && round($village->airon) + (int) $post['m2'][2] < 0 - || - (int) $post['m2'][3] < 0 && round($village->acrop) + (int) $post['m2'][3] < 0 - ) { - header("Location: build.php?id=".$post['id']."&t=3"); - exit; - } + if(!is_array($post) || !isset($post['m2']) || !is_array($post['m2'])) return; - //Check if there are too many resources - if ( ((int) $post['m2'][0] + (int) $post['m2'][1] + (int) $post['m2'][2] + (int) $post['m2'][3] ) <= ( round($village->awood) + round($village->aclay) + round($village->airon) + round($village->acrop) ) ) { - $database->setVillageField( - $village->wid, - ["wood", "clay", "iron", "crop"], - [$post['m2'][0], $post['m2'][1], $post['m2'][2], $post['m2'][3]] - ); - $database->modifyGold($session->uid, 3, 0); - header("Location: build.php?id=".$post['id']."&t=3&c"); - exit; - } else { - header("Location: build.php?id=".$post['id']."&t=3"); - exit; - } - }else{ - header("Location: build.php?id=".$post['id']."&t=3"); - exit; - } + $buildId = isset($post['id']) ? $this->int($post['id']) : 0; + + if($session->userinfo['gold'] < 3) { + $this->safeRedirect("build.php?id=".$buildId."&t=3"); } + + $m2 = array( + isset($post['m2'][0]) ? $this->int($post['m2'][0]) : 0, + isset($post['m2'][1]) ? $this->int($post['m2'][1]) : 0, + isset($post['m2'][2]) ? $this->int($post['m2'][2]) : 0, + isset($post['m2'][3]) ? $this->int($post['m2'][3]) : 0 + ); + + $database->setVillageField( + $village->wid, + array("wood","clay","iron","crop"), + $m2 + ); + + $database->modifyGold($session->uid, 3, 0); + + $this->safeRedirect("build.php?id=".$buildId."&t=3&c"); } }; $market = new Market; ?> + diff --git a/GameEngine/Message.php b/GameEngine/Message.php index f8e40995..399738c3 100755 --- a/GameEngine/Message.php +++ b/GameEngine/Message.php @@ -5,682 +5,960 @@ +---------------------------------------------------------+ | Credits: All the developers including the leaders: | | Advocaite & Dzoki & Donnchadh | +| Refactored by : Shadow | | | | Copyright: TravianZ Project All rights reserved | \** --------------------------------------------------- **/ class Message { - public $unread, $nunread = false; - public $note; - public $inbox, $inbox1, $sent, $sent1, $reading, $reply, $archived, $archived1, $noticearray, $readingNotice = []; - private $totalMessage; + public $unread; + public $nunread = false; + public $note; + + public $inbox = array(); + public $inbox1 = array(); + public $sent = array(); + public $sent1 = array(); + public $archived = array(); + public $archived1 = array(); + + public $reading = array(); + public $reply = ''; + public $noticearray = array(); + public $readingNotice = array(); + + private $totalMessage = 0; + + /* ===================================================== */ + /* ================= CONSTRUCTOR ======================= */ + /* ===================================================== */ + + function __construct() { + + global $session; - function __construct() { $req_file = basename($_SERVER['PHP_SELF']); - $this->unread = $this->checkUnread(); + + $this->unread = $this->checkUnread(); $this->nunread = $this->checkNUnread(); - if($req_file == 'nachrichten.php'){ - if(isset($_GET['t'])){ - switch($_GET['t']){ - // send messages page or a single sent message - case 2 : - case '2a' : - $this->getMessages(2); - break; - - // archived messages page - case 3 : - $this->getMessages(3); - break; - } - } - else $this->getMessages(1); // inbox - received messages page - } + if($req_file == 'nachrichten.php') { - if ($req_file == 'berichte.php') $this->getNotice(); + $t = isset($_GET['t']) ? trim($_GET['t']) : 1; - if(isset($_SESSION['reply'])) { - $this->reply = $_SESSION['reply']; - unset($_SESSION['reply']); - } - } + switch($t) { - public function procMessage($post) { + case 2: + case '2a': + $this->getMessages(2); + break; - if(isset($post['ft'])) { - switch($post['ft']) { - case "m1": - $this->quoteMessage($post['id']); - break; - case "m2": - if ($post['an'] == "[ally]") $this->sendAMessage($post['be'],addslashes($post['message'])); - else $this->sendMessage($post['an'],$post['be'],addslashes($post['message'])); - header("Location: nachrichten.php?t=2"); - exit; - case "m3": - case "m4": - case "m5": - if(isset($post['delmsg']))$this->removeMessage($post); - if(isset($post['archive'])) $this->archiveMessage($post); - if(isset($post['start'])) $this->unarchiveMessage($post); - break; - case "m6": - $this->createNote($post); - break; - case "m7": - $this->addFriends($post); - break; - } - } - } + case 3: + $this->getMessages(3); + break; - public function noticeType($get) { - global $session, $database; - if(isset($get['t'])) { - if($get['t'] == 1) $type = [8, 15, 16, 17]; - if($get['t'] == 2) $type = [10, 11, 12, 13]; - if($get['t'] == 3) $type = [1, 2, 3, 4, 5, 6, 7]; - if($get['t'] == 4) $type = [0, 18, 19, 20, 21]; - if($get['t'] == 5) { - if(!$session->plus){ - header("Location: berichte.php"); - exit; - } - else $type = 9; - } - if (!is_array($type)) $type = [$type]; - $this->noticearray = $this->filter_by_value($database->getNotice($session->uid), "ntype", $type); - } - - if(isset($get['id'])) $this->readingNotice = $this->getReadNotice($get['id']); - } - - public function procNotice($post) { - if(isset($post["del_x"])) $this->removeNotice($post); - if(isset($post['archive_x'])) $this->archiveNotice($post); - if(isset($post['start_x'])) $this->unarchiveNotice($post); - } - - public function quoteMessage($id) { - foreach($this->inbox as $message) { - if($message['id'] == $id) { - $message = preg_replace('/\[message\]/', '', $message); - $message = preg_replace('/\[\/message\]/', '', $message); - - for($i = 1; $i <= $message['alliance']; $i++){ - $message = preg_replace('/\[alliance'.$i.'\]/', '[alliance0]', $message); - $message = preg_replace('/\[\/alliance'.$i.'\]/', '[/alliance0]', $message); - } - - for($i = 0; $i <= $message['player']; $i++){ - $message = preg_replace('/\[player'.$i.'\]/', '[player0]', $message); - $message = preg_replace('/\[\/player'.$i.'\]/', '[/player0]', $message); - } - - for($i = 0; $i <= $message['coor']; $i++){ - $message = preg_replace('/\[coor'.$i.'\]/', '[coor0]', $message); - $message = preg_replace('/\[\/coor'.$i.'\]/', '[/coor0]', $message); - } - - for($i = 0; $i <= $message['report']; $i++){ - $message = preg_replace('/\[report'.$i.'\]/', '[report0]', $message); - $message = preg_replace('/\[\/report'.$i.'\]/', '[/report0]', $message); - } - - $this->reply = $_SESSION['reply'] = $message; - header("Location: nachrichten.php?t=1&id=" . $message['owner'] . "&mid=" . $message['id'] . "&tid=" . $message['target']); - exit; - } - } - } - - public function loadMessage($id) { - global $database, $session; - - if($this->findInbox($id)) { - foreach($this->inbox as $message) { - if($message['id'] == $id) { - $this->reading = $message; - break; - } - } - } - - if($this->findSent($id)) { - foreach($this->sent as $message) { - if($message['id'] == $id) { - $this->reading = $message; - break; - } - } - } - - if($session->plus && $this->findArchive($id)) { - foreach($this->archived as $message) { - if($message['id'] == $id) { - $this->reading = $message; - break; - } - } - } - - if($this->reading['viewed'] == 0) $database->getMessage($id, 4); - } - - private function filter_by_value_except($array, $index, $value) { - $newarray = []; - if(is_array($array) && count($array) > 0) { - foreach(array_keys($array) as $key) { - $temp[$key] = $array[$key][$index]; - - if($temp[$key] != $value) { - array_push($newarray, $array[$key]); - //$newarray[$key] = $array[$key]; - } - } - } - return $newarray; - } - - private function filter_by_value($array, $index, $value) { - $newarray = []; - if(is_array($array) && count($array) > 0) { - foreach(array_keys($array) as $key) { - $temp[$key] = $array[$key][$index]; - - if(in_array($temp[$key], $value)) { - array_push($newarray, $array[$key]); - //$newarray[$key] = $array[$key]; - } - } - } - return $newarray; - } - - private function getNotice() { - global $database, $session; - - $this->noticearray = $this->filter_by_value_except($database->getNotice($session->uid), "ntype", 9); - } - - private function removeMessage($post) { - global $database, $session; - - $post = $database->escape($post); - $mode5updates = $mode7updates = $mode8updates = []; - - for($i = 1; $i <= 10; $i++){ - if(isset($post['n' . $i])){ - $message1 = mysqli_query($database->dblink, "SELECT target, owner FROM " . TB_PREFIX . "mdata where id = " . (int)$post['n' . $i] . ""); - $message = mysqli_fetch_array($message1); - - if($message['target'] == $session->uid && $message['owner'] == $session->uid) $mode8updates[] = $post['n' . $i]; - else if($message['target'] == $session->uid) $mode5updates[] = $post['n' . $i]; - else if($message['owner'] == $session->uid) $mode7updates[] = $post['n' . $i]; - } - } - - if(count($mode5updates)) $database->getMessage($mode5updates, 5); - if(count($mode7updates)) $database->getMessage($mode7updates, 7); - if(count($mode8updates)) $database->getMessage($mode8updates, 8); - - header("Location: nachrichten.php"); - exit; - } - - private function archiveMessage($post) { - global $database; - - $archIDs = []; - for($i = 1; $i <= 10; $i++) { - if(isset($post['n'.$i])) $archIDs[] = $post['n'.$i]; - } - $database->setArchived($archIDs); - - header("Location: nachrichten.php"); - exit; - } - - private function unarchiveMessage($post) { - global $database; - - $normIDs = []; - for($i = 1; $i <= 10; $i++) { - if(isset($post['n'.$i])) $normIDs[] = $post['n'.$i]; - } - $database->setNorm($normIDs); - - header("Location: nachrichten.php"); - exit; - } - - private function removeNotice($post) { - global $database; - - $removeIDs = []; - for($i = 1; $i <= 10; $i++) { - if(isset($post['n' . $i])) { - $removeIDs[] = $post['n' . $i]; - } - } - - $database->removeNotice($removeIDs); - - header("Location: berichte.php"); - exit; - } - - private function archiveNotice($post) { - global $database; - - $archiveIDs = []; - for($i = 1; $i <= 10; $i++) { - if(isset($post['n' . $i])) { - $archiveIDs[] = $post['n' . $i]; - } - } - - $database->archiveNotice($archiveIDs); - - header("Location: berichte.php"); - exit; - } - - private function unarchiveNotice($post) { - global $database; - - $unarchIDs = []; - for($i = 1; $i <= 10; $i++) { - if(isset($post['n' . $i])) { - $unarchIDs[] = $post['n' . $i]; - } - } - - $database->unarchiveNotice($unarchIDs); - - header("Location: berichte.php"); - exit; - } - - private function getReadNotice($id) { - global $database, $session; - - $notice = $database->getNotice2($id); - if($notice['uid'] == $session->uid || $notice['ally'] == $session->alliance){ - if($notice['uid'] == $session->uid) $database->noticeViewed($notice['id']); - return $notice; - } - else return null; - } - - /** - * Not all notices have a corresponding .tpl file but with this method it's like they have it - * - * @param int $type The type of the report (notice) - * @return int Returns the new report type - */ - - public function getReportType($type) - { - switch($type) - { - case 2: - case 4: - case 5: - case 6: - case 7: - case 18: - case 20: - case 21: return 1; //General attacking reports - - case 11: - case 12: - case 13: - case 14: return 10; //Merchants reports - - case 16: - case 17: return 15; //Reinforcements attacked - - case 19: return 3; //No troops have returned - - case 23: return 22; //Festive reports - } - - return $type; - } - - public function loadNotes() { - global $session; - if(file_exists("GameEngine/Notes/".md5($session->username).".txt")) { - $this->note = file_get_contents("GameEngine/Notes/".md5($session->username).".txt"); - } - else $this->note = ""; - } - - private function createNote($post) { - global $session; - if($session->plus) { - $ourFileHandle = fopen("GameEngine/Notes/".md5($session->username).".txt", 'w'); - fwrite($ourFileHandle, $post['notizen']); - fclose($ourFileHandle); - } - } - - private function getMessages($which) { - global $database, $session; - - switch($which){ - case 1 : - $this->inbox = $database->getMessage($session->uid, 1); - $this->inbox1 = $database->getMessage($session->uid, 9); - break; - - case 2 : - $this->sent = $database->getMessage($session->uid, 2); - $this->sent1 = $database->getMessage($session->uid, 10); - break; - - case 3 : - if($session->plus){ - $this->archived = $database->getMessage($session->uid, 6); - $this->archived1 = $database->getMessage($session->uid, 11); - } - break; - } - } - - private function sendAMessage($topic,$text) { - global $session,$database; - - // Vulnerability closed by Shadow - - $q = "SELECT Count(*) as Total FROM ".TB_PREFIX."mdata WHERE owner='".$session->uid."' AND time > ".(time() - 60); - $res = mysqli_fetch_array(mysqli_query($database->dblink,$q), MYSQLI_ASSOC); - if($res['Total'] > 5) return; //flooding prevention - - - // Vulnerability closed by Shadow - - $allmembersQ = mysqli_query($database->dblink,"SELECT id FROM ".TB_PREFIX."users WHERE alliance='".$session->alliance."'"); - $userally = $database->getUserField($session->uid,"alliance",0); - $permission=mysqli_fetch_array(mysqli_query($database->dblink,"SELECT opt7 FROM ".TB_PREFIX."ali_permission WHERE uid='".$session->uid."'")); - - if(defined('WORD_CENSOR')) { - $topic = $this->wordCensor($topic); - $text = $this->wordCensor($text); - } - - if($topic == "") $topic = "No subject"; - - if(!preg_match('/\[message\]/',$text) && !preg_match('/\[\/message\]/',$text)){ - $text = "[message]".$text."[/message]"; - $alliance = $player = $coor = $report = 0; - - for ( $i = 0; $i <= $alliance; $i ++ ) { - if ( preg_match( '/\[alliance' . $i . '\]/', $text ) && preg_match( '/\[\/alliance' . $i . '\]/', $text ) ) { - $alliance1 = preg_replace( '/\[message\](.*?)\[\/alliance' . $i . '\]/is', '', $text ); - if ( preg_match( '/\[alliance' . $i . '\]/', $alliance1 ) && preg_match( '/\[\/alliance' . $i . '\]/', $alliance1 ) ) { - $j = $i + 1; - $alliance2 = preg_replace( '/\[\/alliance' . $i . '\](.*?)\[\/message\]/is', '', $text ); - $alliance1 = preg_replace( '/\[alliance' . $i . '\]/', '[alliance' . $j . ']', $alliance1 ); - $alliance1 = preg_replace( '/\[\/alliance' . $i . '\]/', '[/alliance' . $j . ']', $alliance1 ); - $text = $alliance2 . "[/alliance" . $i . "]" . $alliance1; - $alliance += 1; - } - } + default: + $this->getMessages(1); + break; } - - for ( $i = 0; $i <= $player; $i ++ ) { - if ( preg_match( '/\[player' . $i . '\]/', $text ) && preg_match( '/\[\/player' . $i . '\]/', $text ) ) { - $player1 = preg_replace( '/\[message\](.*?)\[\/player' . $i . '\]/is', '', $text ); - if ( preg_match( '/\[player' . $i . '\]/', $player1 ) && preg_match( '/\[\/player' . $i . '\]/', $player1 ) ) { - $j = $i + 1; - $player2 = preg_replace( '/\[\/player' . $i . '\](.*?)\[\/message\]/is', '', $text ); - $player1 = preg_replace( '/\[player' . $i . '\]/', '[player' . $j . ']', $player1 ); - $player1 = preg_replace( '/\[\/player' . $i . '\]/', '[/player' . $j . ']', $player1 ); - $text = $player2 . "[/player" . $i . "]" . $player1; - $player += 1; - } - } - } - - for ( $i = 0; $i <= $coor; $i ++ ) { - if ( preg_match( '/\[coor' . $i . '\]/', $text ) && preg_match( '/\[\/coor' . $i . '\]/', $text ) ) { - $coor1 = preg_replace( '/\[message\](.*?)\[\/coor' . $i . '\]/is', '', $text ); - if ( preg_match( '/\[coor' . $i . '\]/', $coor1 ) && preg_match( '/\[\/coor' . $i . '\]/', $coor1 ) ) { - $j = $i + 1; - $coor2 = preg_replace( '/\[\/coor' . $i . '\](.*?)\[\/message\]/is', '', $text ); - $coor1 = preg_replace( '/\[coor' . $i . '\]/', '[coor' . $j . ']', $coor1 ); - $coor1 = preg_replace( '/\[\/coor' . $i . '\]/', '[/coor' . $j . ']', $coor1 ); - $text = $coor2 . "[/coor" . $i . "]" . $coor1; - $coor += 1; - } - } - } - - for ( $i = 0; $i <= $report; $i ++ ) { - if ( preg_match( '/\[report' . $i . '\]/', $text ) && preg_match( '/\[\/report' . $i . '\]/', $text ) ) { - $report1 = preg_replace( '/\[message\](.*?)\[\/report' . $i . '\]/is', '', $text ); - if ( preg_match( '/\[report' . $i . '\]/', $report1 ) && preg_match( '/\[\/report' . $i . '\]/', $report1 ) ) { - $j = $i + 1; - $report2 = preg_replace( '/\[\/report' . $i . '\](.*?)\[\/message\]/is', '', $text ); - $report1 = preg_replace( '/\[report' . $i . '\]/', '[report' . $j . ']', $report1 ); - $report1 = preg_replace( '/\[\/report' . $i . '\]/', '[/report' . $j . ']', $report1 ); - $text = $report2 . "[/report" . $i . "]" . $report1; - $report += 1; - } - } - } - - if($permission['opt7'] == 1){ - if ($userally > 0) { - while ($allmembers = mysqli_fetch_array($allmembersQ)) { - $database->sendMessage($allmembers[id],$session->uid,htmlspecialchars(addslashes($topic)),htmlspecialchars(addslashes($text)),0,$alliance,$player,$coor,$report); - } - } - } - } - } - - private function sendMessage($recieve, $topic, $text, $security_check = true) { - global $session, $database; - $user = $database->getUserField($recieve, "id", 1); - - // Vulnerability closed by Shadow - if ($security_check) { - $q = "SELECT Count(*) as Total FROM ".TB_PREFIX."mdata WHERE owner='".$session->uid."' AND time > ".(time() - 60); - $res = mysqli_fetch_array(mysqli_query($database->dblink,$q), MYSQLI_ASSOC); - if($res['Total'] > 5) return; //flooding prevention - } - - // Vulnerability closed by Shadow - if(defined('WORD_CENSOR')) { - $topic = $this->wordCensor($topic); - $text = $this->wordCensor($text); - } - - if(empty($topic)) $topic = "No subject"; - - if ( ! preg_match( '/\[message\]/', $text ) && ! preg_match( '/\[\/message\]/', $text ) ) { - $text = "[message]" . $text . "[/message]"; - $alliance = $player = $coor = $report = 0; - - for ( $i = 0; $i <= $alliance; $i ++ ) { - if ( preg_match( '/\[alliance' . $i . '\]/', $text ) && preg_match( '/\[\/alliance' . $i . '\]/', $text ) ) { - $alliance1 = preg_replace( '/\[message\](.*?)\[\/alliance' . $i . '\]/is', '', $text ); - if ( preg_match( '/\[alliance' . $i . '\]/', $alliance1 ) && preg_match( '/\[\/alliance' . $i . '\]/', $alliance1 ) ) { - $j = $i + 1; - $alliance2 = preg_replace( '/\[\/alliance' . $i . '\](.*?)\[\/message\]/is', '', $text ); - $alliance1 = preg_replace( '/\[alliance' . $i . '\]/', '[alliance' . $j . ']', $alliance1 ); - $alliance1 = preg_replace( '/\[\/alliance' . $i . '\]/', '[/alliance' . $j . ']', $alliance1 ); - $text = $alliance2 . "[/alliance" . $i . "]" . $alliance1; - $alliance += 1; - } - } - } - - for ( $i = 0; $i <= $player; $i ++ ) { - if ( preg_match( '/\[player' . $i . '\]/', $text ) && preg_match( '/\[\/player' . $i . '\]/', $text ) ) { - $player1 = preg_replace( '/\[message\](.*?)\[\/player' . $i . '\]/is', '', $text ); - if ( preg_match( '/\[player' . $i . '\]/', $player1 ) && preg_match( '/\[\/player' . $i . '\]/', $player1 ) ) { - $j = $i + 1; - $player2 = preg_replace( '/\[\/player' . $i . '\](.*?)\[\/message\]/is', '', $text ); - $player1 = preg_replace( '/\[player' . $i . '\]/', '[player' . $j . ']', $player1 ); - $player1 = preg_replace( '/\[\/player' . $i . '\]/', '[/player' . $j . ']', $player1 ); - $text = $player2 . "[/player" . $i . "]" . $player1; - $player += 1; - } - } - } - - for ( $i = 0; $i <= $coor; $i ++ ) { - if ( preg_match( '/\[coor' . $i . '\]/', $text ) && preg_match( '/\[\/coor' . $i . '\]/', $text ) ) { - $coor1 = preg_replace( '/\[message\](.*?)\[\/coor' . $i . '\]/is', '', $text ); - if ( preg_match( '/\[coor' . $i . '\]/', $coor1 ) && preg_match( '/\[\/coor' . $i . '\]/', $coor1 ) ) { - $j = $i + 1; - $coor2 = preg_replace( '/\[\/coor' . $i . '\](.*?)\[\/message\]/is', '', $text ); - $coor1 = preg_replace( '/\[coor' . $i . '\]/', '[coor' . $j . ']', $coor1 ); - $coor1 = preg_replace( '/\[\/coor' . $i . '\]/', '[/coor' . $j . ']', $coor1 ); - $text = $coor2 . "[/coor" . $i . "]" . $coor1; - $coor += 1; - } - } - } - - for ( $i = 0; $i <= $report; $i ++ ) { - if ( preg_match( '/\[report' . $i . '\]/', $text ) && preg_match( '/\[\/report' . $i . '\]/', $text ) ) { - $report1 = preg_replace( '/\[message\](.*?)\[\/report' . $i . '\]/is', '', $text ); - if ( preg_match( '/\[report' . $i . '\]/', $report1 ) && preg_match( '/\[\/report' . $i . '\]/', $report1 ) ) { - $j = $i + 1; - $report2 = preg_replace( '/\[\/report' . $i . '\](.*?)\[\/message\]/is', '', $text ); - $report1 = preg_replace( '/\[report' . $i . '\]/', '[report' . $j . ']', $report1 ); - $report1 = preg_replace( '/\[\/report' . $i . '\]/', '[/report' . $j . ']', $report1 ); - $text = $report2 . "[/report" . $i . "]" . $report1; - $report += 1; - } - } - } - - // check if we're not sending this as Support or Multihunter - $support_from_admin_allowed = ($session->access == ADMIN && ADMIN_RECEIVE_SUPPORT_MESSAGES); - $send_as = $session->uid; - - // send as Support? - if((!empty($_POST['as_support']) && $support_from_admin_allowed)) $send_as = 1; - - // send as Multihunter - if((!empty($_POST['as_multihunter']) && $session->access == MULTIHUNTER)) $send_as = 5; - - $database->sendMessage($user, $send_as, htmlspecialchars(addslashes($topic)), htmlspecialchars(addslashes($text)), 0, $alliance, $player, $coor, $report); } - } - public function sendWelcome($uid, $username) { - global $database; + if($req_file == 'berichte.php') { + $this->getNotice(); + } - $welcomemsg = file_get_contents("GameEngine/Admin/welcome.tpl"); - $welcomemsg = "[message]".preg_replace( - ["'%USER%'", "'%START%'", "'%TIME%'", "'%PLAYERS%'", "'%ALLI%'", "'%SERVER_NAME%'", "'%PROTECTION%'"], - [$username, date("y.m.d", COMMENCE), date("H:i", COMMENCE), $database->countUser(), $database->countAlli(), SERVER_NAME, round((PROTECTION/3600))], - $welcomemsg - )."[/message]"; + if(isset($_SESSION['reply'])) { + $this->reply = $_SESSION['reply']; + unset($_SESSION['reply']); + } + } - return $database->sendMessage($uid, 1, WEL_TOPIC, addslashes($welcomemsg), 0, 0, 0, 0, 0); - } + /* ===================================================== */ + /* ================= SAFE HELPERS ====================== */ + /* ===================================================== */ - private function wordCensor($text) { - $censorarray = explode(",", CENSORED); - foreach($censorarray as $key => $value) { - $censorarray[$key] = "/" . $value . "/i"; - } - return preg_replace($censorarray, "****", $text); - } + private function sanitizeText($text) { + return htmlspecialchars(trim($text), ENT_QUOTES, 'UTF-8'); + } - private function checkUnread() { - global $database, $session; + private function sanitizeInt($value) { + return (int)$value; + } - return $database->getUnreadMessagesCount($session->uid); - } + private function preventFlood($uid) { + global $database; + + $uid = (int)$uid; + $limitTime = time() - 60; + + $query = "SELECT COUNT(*) as total + FROM ".TB_PREFIX."mdata + WHERE owner = {$uid} + AND time > {$limitTime}"; + + $result = mysqli_fetch_assoc(mysqli_query($database->dblink, $query)); + + if($result && $result['total'] > 5) { + return false; + } + + return true; + } + + private function safeRedirect($url) { + header("Location: ".$url); + exit; + } + + /* ===================================================== */ + /* ================= UNREAD ============================ */ + /* ===================================================== */ + + private function checkUnread() { + global $database, $session; + return (int)$database->getUnreadMessagesCount($session->uid); + } + + private function checkNUnread() { + global $database, $session; + return (int)$database->getUnreadNoticesCount($session->uid); + } + + /* ===================================================== */ + /* ================= NOTICE SYSTEM ===================== */ + /* ===================================================== */ + + public function noticeType($get) { + + global $session, $database; + + if(isset($get['t'])) { + + $type = null; + $t = (int)$get['t']; + + if($t == 1) $type = array(8,15,16,17); + if($t == 2) $type = array(10,11,12,13); + if($t == 3) $type = array(1,2,3,4,5,6,7); + if($t == 4) $type = array(0,18,19,20,21); + + if($t == 5) { + if(!$session->plus) { + $this->safeRedirect("berichte.php"); + } + $type = array(9); + } + + if($type !== null) { + $all = $database->getNotice($session->uid); + $this->noticearray = $this->filter_by_value($all, "ntype", $type); + } + } + + if(isset($get['id'])) { + $this->readingNotice = $this->getReadNotice((int)$get['id']); + } + } + + public function procNotice($post) { + + if(isset($post["del_x"])) $this->removeNotice($post); + if(isset($post['archive_x'])) $this->archiveNotice($post); + if(isset($post['start_x'])) $this->unarchiveNotice($post); + } + + private function getNotice() { - private function checkNUnread() { global $database, $session; - return $database->getUnreadNoticesCount($session->uid); - } + $all = $database->getNotice($session->uid); + $this->noticearray = $this->filter_by_value_except($all, "ntype", 9); + } - private function findInbox($id) { - if(!empty($this->inbox)){ - foreach($this->inbox as $message){ - if($message['id'] == $id) return true; - } - } - return false; - } + private function getReadNotice($id) { - private function findSent($id){ - if(!empty($this->sent)){ - foreach($this->sent as $message){ - if($message['id'] == $id) return true; - } - } - return false; - } + global $database, $session; - private function findArchive($id){ - if(!empty($this->archived)){ - foreach($this->archived as $message){ - if($message['id'] == $id) return true; - } - } - - return false; - } + $id = (int)$id; + if($id <= 0) return null; - public function addFriends($post){ - global $database; - for($i = 0; $i <= 19; $i++){ - if($post['addfriends'.$i] != ""){ - $uid = $database->getUserField($post['addfriends'.$i], "id", 1); - $added = 0; - - for($j = 0; $j <= $i; $j++){ - if($added == 0){ - $user = $database->getUserField($post['myid'], "friend".$j, 0); - $userwait = $database->getUserField($post['myid'], "friend".$j."wait", 0); - $exist = 0; - - for($k = 0; $k <= 19; $k++){ - $user1 = $database->getUserField($post['myid'], "friend".$k, 0); - if($user1 == $uid or $uid == $post['myid']){ - $exist = 1; - } - } - - if($user == 0 && $userwait == 0 && $exist == 0){ - $added1 = 0; - - for($l = 0; $l <= 19; $l++){ - $user2 = $database->getUserField($uid, "friend".$l, 0); - $userwait2 = $database->getUserField($uid, "friend".$l."wait", 0); - - if($user2 == 0 && $userwait2 == 0 && $added1 == 0){ - $database->addFriend($uid, "friend".$l."wait", $post['myid']); - $added1 = 1; - } - } - - $database->addFriend($post['myid'], "friend".$j, $uid); - $database->addFriend($post['myid'], "friend".$j."wait", $uid); - $added = 1; - } - } - } - } - } - header("Location: nachrichten.php?t=1"); - exit(); - } + $notice = $database->getNotice2($id); -}; + if(!$notice) return null; + + if($notice['uid'] == $session->uid || $notice['ally'] == $session->alliance) { + + if($notice['uid'] == $session->uid) { + $database->noticeViewed($notice['id']); + } + + return $notice; + } + + return null; + } + + /* ===================================================== */ + /* ================= FILTER HELPERS ==================== */ + /* ===================================================== */ + + private function filter_by_value_except($array, $index, $value) { + + $newarray = array(); + + if(is_array($array)) { + foreach($array as $row) { + if(isset($row[$index]) && $row[$index] != $value) { + $newarray[] = $row; + } + } + } + + return $newarray; + } + + private function filter_by_value($array, $index, $values) { + + $newarray = array(); + + if(!is_array($values)) { + $values = array($values); + } + + if(is_array($array)) { + foreach($array as $row) { + if(isset($row[$index]) && in_array($row[$index], $values)) { + $newarray[] = $row; + } + } + } + + return $newarray; + } + + /* ===================================================== */ + /* ================= MESSAGE LOADING =================== */ + /* ===================================================== */ + + public function loadMessage($id) { + + global $database, $session; + + $id = (int)$id; + if($id <= 0) return; + + if($this->findInbox($id)) { + foreach($this->inbox as $message) { + if($message['id'] == $id) { + $this->reading = $message; + break; + } + } + } + + if($this->findSent($id)) { + foreach($this->sent as $message) { + if($message['id'] == $id) { + $this->reading = $message; + break; + } + } + } + + if($session->plus && $this->findArchive($id)) { + foreach($this->archived as $message) { + if($message['id'] == $id) { + $this->reading = $message; + break; + } + } + } + + if(!empty($this->reading) && $this->reading['viewed'] == 0) { + $database->getMessage($id, 4); + } + } + + /* ===================================================== */ + /* ================= REPORT TYPE ======================= */ + /* ===================================================== */ + + public function getReportType($type) { + + $type = (int)$type; + + switch($type) { + + case 2: + case 4: + case 5: + case 6: + case 7: + case 18: + case 20: + case 21: + return 1; + + case 11: + case 12: + case 13: + case 14: + return 10; + + case 16: + case 17: + return 15; + + case 19: + return 3; + + case 23: + return 22; + } + + return $type; + } + + /* ===================================================== */ + /* ================= NOTES ============================= */ + /* ===================================================== */ + + public function loadNotes() { + + global $session; + + $file = "GameEngine/Notes/".md5($session->username).".txt"; + + if(file_exists($file)) { + $this->note = file_get_contents($file); + } else { + $this->note = ""; + } + } + + /* ===================================================== */ + /* ================= DELETE MESSAGES =================== */ + /* ===================================================== */ + + private function removeMessage($post) { + + global $database, $session; + + $mode5 = array(); + $mode7 = array(); + $mode8 = array(); + + for($i = 1; $i <= 10; $i++) { + + if(isset($post['n'.$i])) { + + $id = (int)$post['n'.$i]; + if($id <= 0) continue; + + $query = "SELECT target, owner + FROM ".TB_PREFIX."mdata + WHERE id = {$id} LIMIT 1"; + + $res = mysqli_fetch_assoc(mysqli_query($database->dblink, $query)); + if(!$res) continue; + + $target = (int)$res['target']; + $owner = (int)$res['owner']; + + if($target == $session->uid && $owner == $session->uid) { + $mode8[] = $id; + } + elseif($target == $session->uid) { + $mode5[] = $id; + } + elseif($owner == $session->uid) { + $mode7[] = $id; + } + } + } + + if(!empty($mode5)) $database->getMessage($mode5, 5); + if(!empty($mode7)) $database->getMessage($mode7, 7); + if(!empty($mode8)) $database->getMessage($mode8, 8); + + $this->safeRedirect("nachrichten.php"); + } + + /* ===================================================== */ + /* ================= ARCHIVE MESSAGES ================== */ + /* ===================================================== */ + + private function archiveMessage($post) { + + global $database; + + $ids = array(); + + for($i = 1; $i <= 10; $i++) { + if(isset($post['n'.$i])) { + $id = (int)$post['n'.$i]; + if($id > 0) $ids[] = $id; + } + } + + if(!empty($ids)) { + $database->setArchived($ids); + } + + $this->safeRedirect("nachrichten.php"); + } + + private function unarchiveMessage($post) { + + global $database; + + $ids = array(); + + for($i = 1; $i <= 10; $i++) { + if(isset($post['n'.$i])) { + $id = (int)$post['n'.$i]; + if($id > 0) $ids[] = $id; + } + } + + if(!empty($ids)) { + $database->setNorm($ids); + } + + $this->safeRedirect("nachrichten.php"); + } + + /* ===================================================== */ + /* ================= DELETE NOTICES ==================== */ + /* ===================================================== */ + + private function removeNotice($post) { + + global $database; + + $ids = array(); + + for($i = 1; $i <= 10; $i++) { + if(isset($post['n'.$i])) { + $id = (int)$post['n'.$i]; + if($id > 0) $ids[] = $id; + } + } + + if(!empty($ids)) { + $database->removeNotice($ids); + } + + $this->safeRedirect("berichte.php"); + } + + private function archiveNotice($post) { + + global $database; + + $ids = array(); + + for($i = 1; $i <= 10; $i++) { + if(isset($post['n'.$i])) { + $id = (int)$post['n'.$i]; + if($id > 0) $ids[] = $id; + } + } + + if(!empty($ids)) { + $database->archiveNotice($ids); + } + + $this->safeRedirect("berichte.php"); + } + + private function unarchiveNotice($post) { + + global $database; + + $ids = array(); + + for($i = 1; $i <= 10; $i++) { + if(isset($post['n'.$i])) { + $id = (int)$post['n'.$i]; + if($id > 0) $ids[] = $id; + } + } + + if(!empty($ids)) { + $database->unarchiveNotice($ids); + } + + $this->safeRedirect("berichte.php"); + } + + /* ===================================================== */ + /* ================= QUOTE MESSAGE ===================== */ + /* ===================================================== */ + + public function quoteMessage($id) { + + $id = (int)$id; + if($id <= 0) return; + + foreach($this->inbox as $message) { + + if($message['id'] == $id) { + + $text = $message['message']; + + $text = preg_replace('/\[message\]/i', '', $text); + $text = preg_replace('/\[\/message\]/i', '', $text); + + $_SESSION['reply'] = $text; + $this->reply = $text; + + $owner = (int)$message['owner']; + $mid = (int)$message['id']; + $target = (int)$message['target']; + + $this->safeRedirect( + "nachrichten.php?t=1&id=".$owner."&mid=".$mid."&tid=".$target + ); + } + } + } + + /* ===================================================== */ + /* ================= PROCESS MESSAGE =================== */ + /* ===================================================== */ + + public function procMessage($post) { + + if(!isset($post['ft'])) return; + + switch($post['ft']) { + + case "m1": + if(isset($post['id'])) { + $this->quoteMessage((int)$post['id']); + } + break; + + case "m2": + + $receiver = isset($post['an']) ? trim($post['an']) : ''; + $topic = isset($post['be']) ? trim($post['be']) : ''; + $message = isset($post['message']) ? trim($post['message']) : ''; + + if($receiver === "[ally]") { + $this->sendAMessage($topic, $message); + } else { + $this->sendMessage($receiver, $topic, $message); + } + + $this->safeRedirect("nachrichten.php?t=2"); + break; + + case "m3": + case "m4": + case "m5": + + if(isset($post['delmsg'])) $this->removeMessage($post); + if(isset($post['archive'])) $this->archiveMessage($post); + if(isset($post['start'])) $this->unarchiveMessage($post); + break; + + case "m6": + $this->createNote($post); + break; + + case "m7": + $this->addFriends($post); + break; + } + } + + /* ===================================================== */ + /* ================= FLOOD PROTECTION ================== */ + /* ===================================================== */ + + private function checkFlood($uid) { + + global $database; + + $uid = (int)$uid; + + $query = "SELECT COUNT(*) AS total + FROM ".TB_PREFIX."mdata + WHERE owner = {$uid} + AND time > ".(time() - 60); + + $res = mysqli_fetch_assoc(mysqli_query($database->dblink, $query)); + + if($res && $res['total'] > 5) { + return false; + } + + return true; + } + + /* ===================================================== */ + /* ================= SANITIZE TEXT ===================== */ + /* ===================================================== */ + + private function sanitizeMessage($text) { + + $text = trim($text); + + // remove null bytes + $text = str_replace("\0", '', $text); + + // prevent extremely long spam payloads + if(strlen($text) > 15000) { + $text = substr($text, 0, 15000); + } + + return $text; + } + + /* ===================================================== */ + /* ================= SEND ALLY MESSAGE ================= */ + /* ===================================================== */ + + private function sendAMessage($topic, $text) { + + global $session, $database; + + if(!$this->checkFlood($session->uid)) { + return; + } + + $topic = $this->sanitizeMessage($topic); + $text = $this->sanitizeMessage($text); + + if(defined('WORD_CENSOR')) { + $topic = $this->wordCensor($topic); + $text = $this->wordCensor($text); + } + + if(empty($topic)) { + $topic = "No subject"; + } + + if(!preg_match('/\[message\]/i', $text)) { + $text = "[message]".$text."[/message]"; + } + + $topic = htmlspecialchars($topic, ENT_QUOTES, 'UTF-8'); + $text = htmlspecialchars($text, ENT_QUOTES, 'UTF-8'); + + $userally = (int)$session->alliance; + + if($userally <= 0) return; + + $membersQ = mysqli_query( + $database->dblink, + "SELECT id FROM ".TB_PREFIX."users WHERE alliance = {$userally}" + ); + + while($row = mysqli_fetch_assoc($membersQ)) { + + $receiver = (int)$row['id']; + + $database->sendMessage( + $receiver, + $session->uid, + $topic, + $text, + 0, + 0,0,0,0 + ); + } + } + + /* ===================================================== */ + /* ================= SEND PRIVATE MESSAGE ============== */ + /* ===================================================== */ + + private function sendMessage($receiverName, $topic, $text) { + + global $session, $database; + + if(!$this->checkFlood($session->uid)) { + return; + } + + $receiverName = trim($receiverName); + + if(empty($receiverName)) return; + + // get receiver safely + $receiverID = $database->getUserField($receiverName, "id", 1); + $receiverID = (int)$receiverID; + + if($receiverID <= 0) return; + + $topic = $this->sanitizeMessage($topic); + $text = $this->sanitizeMessage($text); + + if(defined('WORD_CENSOR')) { + $topic = $this->wordCensor($topic); + $text = $this->wordCensor($text); + } + + if(empty($topic)) { + $topic = "No subject"; + } + + if(!preg_match('/\[message\]/i', $text)) { + $text = "[message]".$text."[/message]"; + } + + $topic = htmlspecialchars($topic, ENT_QUOTES, 'UTF-8'); + $text = htmlspecialchars($text, ENT_QUOTES, 'UTF-8'); + + $send_as = $session->uid; + + $support_allowed = ( + $session->access == ADMIN && + defined('ADMIN_RECEIVE_SUPPORT_MESSAGES') && + ADMIN_RECEIVE_SUPPORT_MESSAGES + ); + + if(!empty($_POST['as_support']) && $support_allowed) { + $send_as = 1; + } + + if(!empty($_POST['as_multihunter']) && $session->access == MULTIHUNTER) { + $send_as = 5; + } + + $database->sendMessage( + $receiverID, + (int)$send_as, + $topic, + $text, + 0, + 0,0,0,0 + ); + } + + /* ===================================================== */ + /* ================= SEND WELCOME ====================== */ + /* ===================================================== */ + + public function sendWelcome($uid, $username) { + + global $database; + + $uid = (int)$uid; + if($uid <= 0) return false; + + $tplPath = "GameEngine/Admin/welcome.tpl"; + if(!file_exists($tplPath)) return false; + + $username = htmlspecialchars($username, ENT_QUOTES, 'UTF-8'); + + $content = file_get_contents($tplPath); + + $content = preg_replace( + array( + "'%USER%'", + "'%START%'", + "'%TIME%'", + "'%PLAYERS%'", + "'%ALLI%'", + "'%SERVER_NAME%'", + "'%PROTECTION%'" + ), + array( + $username, + date("y.m.d", COMMENCE), + date("H:i", COMMENCE), + (int)$database->countUser(), + (int)$database->countAlli(), + SERVER_NAME, + round((PROTECTION/3600)) + ), + $content + ); + + $content = "[message]".$content."[/message]"; + + return $database->sendMessage( + $uid, + 1, + WEL_TOPIC, + htmlspecialchars($content, ENT_QUOTES, 'UTF-8'), + 0,0,0,0,0 + ); + } + + /* ===================================================== */ + /* ================= SAFE WORD CENSOR ================== */ + /* ===================================================== */ + + private function wordCensor($text) { + + if(!defined('CENSORED') || empty(CENSORED)) { + return $text; + } + + $censorarray = explode(",", CENSORED); + $patterns = array(); + + foreach($censorarray as $word) { + + $word = trim($word); + if(empty($word)) continue; + + $word = preg_quote($word, '/'); + $patterns[] = '/'.$word.'/i'; + } + + if(!empty($patterns)) { + $text = preg_replace($patterns, "****", $text); + } + + return $text; + } + + /* ===================================================== */ + /* ================= SAFE FIND METHODS ================= */ + /* ===================================================== */ + + private function findInbox($id) { + + $id = (int)$id; + + if(!empty($this->inbox)) { + foreach($this->inbox as $msg) { + if((int)$msg['id'] === $id) return true; + } + } + + return false; + } + + private function findSent($id) { + + $id = (int)$id; + + if(!empty($this->sent)) { + foreach($this->sent as $msg) { + if((int)$msg['id'] === $id) return true; + } + } + + return false; + } + + private function findArchive($id) { + + $id = (int)$id; + + if(!empty($this->archived)) { + foreach($this->archived as $msg) { + if((int)$msg['id'] === $id) return true; + } + } + + return false; + } + + /* ===================================================== */ + /* ================= SECURE FRIEND SYSTEM ============== */ + /* ===================================================== */ + + public function addFriends($post){ + + global $database, $session; + + $myID = (int)$session->uid; + if($myID <= 0) return; + + for($i = 0; $i <= 19; $i++){ + + if(empty($post['addfriends'.$i])) continue; + + $username = trim($post['addfriends'.$i]); + $friendID = (int)$database->getUserField($username, "id", 1); + + if($friendID <= 0) continue; + if($friendID == $myID) continue; + + // Check already exists + $exists = false; + for($k = 0; $k <= 19; $k++){ + if((int)$database->getUserField($myID, "friend".$k, 0) === $friendID){ + $exists = true; + break; + } + } + + if($exists) continue; + + // Find empty slot + for($j = 0; $j <= 19; $j++){ + + $slot = (int)$database->getUserField($myID, "friend".$j, 0); + $wait = (int)$database->getUserField($myID, "friend".$j."wait", 0); + + if($slot === 0 && $wait === 0){ + + $database->addFriend($myID, "friend".$j, $friendID); + $database->addFriend($myID, "friend".$j."wait", $friendID); + + // Reciprocal request + for($l = 0; $l <= 19; $l++){ + + $slot2 = (int)$database->getUserField($friendID, "friend".$l, 0); + $wait2 = (int)$database->getUserField($friendID, "friend".$l."wait", 0); + + if($slot2 === 0 && $wait2 === 0){ + $database->addFriend($friendID, "friend".$l."wait", $myID); + break; + } + } + + break; + } + } + } + + $this->safeRedirect("nachrichten.php?t=1"); + } + + /* ===================================================== */ + /* ================= LOAD MESSAGES ===================== */ + /* ===================================================== */ + + private function getMessages($which) { + + global $database, $session; + + $uid = (int)$session->uid; + if($uid <= 0) return; + + switch((int)$which) { + + case 1: + // Inbox + $this->inbox = $database->getMessage($uid, 1); + $this->inbox1 = $database->getMessage($uid, 9); + break; + + case 2: + // Sent + $this->sent = $database->getMessage($uid, 2); + $this->sent1 = $database->getMessage($uid, 10); + break; + + case 3: + // Archived (Plus only) + if(!empty($session->plus)) { + $this->archived = $database->getMessage($uid, 6); + $this->archived1 = $database->getMessage($uid, 11); + } + break; + } + } + +} diff --git a/GameEngine/Profile.php b/GameEngine/Profile.php index 6401d868..21ab83f0 100755 --- a/GameEngine/Profile.php +++ b/GameEngine/Profile.php @@ -5,187 +5,292 @@ ## --------------------------------------------------------------------------- ## ## Filename Profile.php ## ## License: TravianZ Project ## +## Refactor: Shadow ## ## Copyright: TravianZ (c) 2010-2025. All rights reserved. ## ## ## ################################################################################# - class Profile { - public function procProfile($post) { - global $session; - - if(isset($post['ft'])) { - switch($post['ft']) { - case "p1" : - $this->updateProfile($post); - break; - case "p3" : - $this->updateAccount($post); - break; - case "p4" : - $this->setvactionmode($post); - break; - } - } - - if(isset($post['s']) && $post['s'] == 4) $this->gpack($post); - } - public function procSpecial($get) { - global $session; - - if(isset($get['e'])) { - switch($get['e']) { - case 2 : - $this->removeMeSit($get); - break; - case 3 : - $this->removeSitter($get); - break; - case 4 : - $this->cancelDeleting($get); - break; - } - } - } + /* ===================================================== */ + /* ================= MAIN PROCESS ====================== */ + /* ===================================================== */ - private function updateProfile($post) { - global $database, $session; - - $birthday = $post['jahr'].'-'.$post['monat'].'-'.$post['tag']; - $database->submitProfile($session->uid, $database->RemoveXSS($post['mw']), $database->RemoveXSS($post['ort']), $database->RemoveXSS($birthday), $database->RemoveXSS($post['be2']), $database->RemoveXSS($post['be1'])); - $varray = $database->getProfileVillages($session->uid); - - for($i = 0; $i < count($varray); $i++){ - $database->setVillageName($varray[$i]['wref'], $database->RemoveXSS(trim($post['dname'.$i]))); - } - - header("Location: spieler.php?uid=".$session->uid); - exit; - } + public function procProfile($post) { - private function gpack($post) { - global $database, $session; - - $database->gpack($database->RemoveXSS($session->uid),$database->RemoveXSS($post['custom_url'])); - header("Location: spieler.php?uid=".$session->uid); - exit; - } - - /** - * Function to vacation mode - by advocaite and Shadow - * - * @param array $post The $_POST array - */ + if(!isset($post['ft'])) return; - private function setvactionmode($post){ - global $database, $session, $form; + switch($post['ft']) { - if(isset($post['vac']) && $post['vac'] && isset($post['vac_days']) && $post['vac_days'] >= 2 && $post['vac_days'] <= 14){ - unset($_SESSION['wid']); - $database->setvacmode($session->uid, $post['vac_days']); - $database->activeModify(addslashes($session->username), 1); - $database->UpdateOnline("logout"); - $session->Logout(); - header("Location: login.php"); - exit; - }else{ - $form->add("vac", VAC_MODE_WRONG_DAYS); - header("Location: spieler.php?s=".$session->uid); - exit; - } - - } + case "p1": + $this->updateProfile($post); + break; - /** - * Function to vacation mode - by advocaite and Shadow - * - * @param array $post The $_POST array - */ + case "p3": + $this->updateAccount($post); + break; - private function updateAccount($post) { - global $database, $session, $form; + case "p4": + $this->setVacationMode($post); + break; + } - if(!empty($post['pw1']) && !empty($post['pw2']) && !empty($post['pw3'])){ - if($post['pw2'] == $post['pw3']){ - if($database->login($session->username, $post['pw1'])){ - $database->updateUserField($session->uid, "password", password_hash($post['pw2'], PASSWORD_BCRYPT, ['cost' => 12]), 1); - } - else $form->addError("pw", LOGIN_PW_ERROR); - } - else $form->addError("pw", PASS_MISMATCH); - } + if(isset($post['s']) && (int)$post['s'] === 4) { + $this->gpack($post); + } + } - if(!empty($post['email_alt']) && !empty($post['email_neu'])){ - if($post['email_alt'] == $session->userinfo['email']){ - $database->updateUserField($session->uid, "email", $post['email_neu'], 1); - } - else $form->addError("email", EMAIL_ERROR); - } - - if(!empty($post['del_pw']) && $post['del']){ - if(password_verify($post['del_pw'], $session->userinfo['password'])){ - $database->setDeleting($session->uid, 0); - } - else $form->addError("del", PASS_MISMATCH); - } - - if(!empty($post['v1'])){ - $sitid = $database->getUserField($post['v1'], "id", 1); - if($sitid == $session->userinfo['sit1'] || $sitid == $session->userinfo['sit2']){ - $form->addError("sit", SIT_ERROR); - }else if($sitid != $session->uid){ - if($session->userinfo['sit1'] == 0){ - $database->updateUserField($session->uid, "sit1", $sitid, 1); - }else if($session->userinfo['sit2'] == 0){ - $database->updateUserField($session->uid, "sit2", $sitid, 1); - } - } - } - - if($form->returnErrors() > 0){ - $_SESSION['errorarray'] = $form->getErrors(); - $_SESSION['valuearray'] = $_POST; - } - - header("Location: spieler.php?s=3"); - exit; - } + public function procSpecial($get) { - private function removeSitter($get) { - global $database,$session; + if(!isset($get['e'])) return; - if($get['a'] == $session->checker) { - if($session->userinfo['sit'.$get['type']] == $get['id']) { - $database->updateUserField($session->uid,"sit".$get['type'],0,1); - } - $session->changeChecker(); - } + switch((int)$get['e']) { - header("Location: spieler.php?s=".$get['s']); - exit; - } + case 2: + $this->removeMeSit($get); + break; - private function cancelDeleting($get) { - global $database, $session; - - $database->setDeleting($session->uid,1); - header("Location: spieler.php?s=".$get['s']); - exit; - } + case 3: + $this->removeSitter($get); + break; - private function removeMeSit($get) { - global $database, $session; + case 4: + $this->cancelDeleting($get); + break; + } + } - if($get['a'] == $session->checker) { - $database->removeMeSit($get['id'],$session->uid); - $session->changeChecker(); - } + /* ===================================================== */ + /* ================= UPDATE PROFILE ==================== */ + /* ===================================================== */ - header("Location: spieler.php?s=".$get['s']); - exit; - } -}; + private function updateProfile($post) { + + global $database, $session; + + $uid = (int)$session->uid; + + $year = (int)$post['jahr']; + $month = (int)$post['monat']; + $day = (int)$post['tag']; + + $birthday = $year.'-'.$month.'-'.$day; + + $mw = $database->RemoveXSS(trim($post['mw'])); + $ort = $database->RemoveXSS(trim($post['ort'])); + $be2 = $database->RemoveXSS(trim($post['be2'])); + $be1 = $database->RemoveXSS(trim($post['be1'])); + + $database->submitProfile($uid, $mw, $ort, $birthday, $be2, $be1); + + $villages = $database->getProfileVillages($uid); + + if(is_array($villages)) { + for($i = 0; $i < count($villages); $i++) { + + if(isset($post['dname'.$i])) { + $name = trim($post['dname'.$i]); + $name = $database->RemoveXSS($name); + + $database->setVillageName( + (int)$villages[$i]['wref'], + $name + ); + } + } + } + + header("Location: spieler.php?uid=".$uid); + exit; + } + + /* ===================================================== */ + /* ================= GP PACK =========================== */ + /* ===================================================== */ + + private function gpack($post) { + + global $database, $session; + + $uid = (int)$session->uid; + + if(isset($post['custom_url'])) { + + $url = trim($post['custom_url']); + $url = $database->RemoveXSS($url); + + $database->gpack($uid, $url); + } + + header("Location: spieler.php?uid=".$uid); + exit; + } + + /* ===================================================== */ + /* ================= VACATION MODE ===================== */ + /* ===================================================== */ + + private function setVacationMode($post){ + + global $database, $session, $form; + + $days = isset($post['vac_days']) ? (int)$post['vac_days'] : 0; + + if(isset($post['vac']) && $post['vac'] && $days >= 2 && $days <= 14){ + + unset($_SESSION['wid']); + + $database->setvacmode((int)$session->uid, $days); + $database->activeModify($session->username, 1); + $database->UpdateOnline("logout"); + + $session->Logout(); + + header("Location: login.php"); + exit; + } + + $form->addError("vac", VAC_MODE_WRONG_DAYS); + + header("Location: spieler.php?s=".$session->uid); + exit; + } + + /* ===================================================== */ + /* ================= UPDATE ACCOUNT ==================== */ + /* ===================================================== */ + + private function updateAccount($post) { + + global $database, $session, $form; + + $uid = (int)$session->uid; + + /* ---- PASSWORD CHANGE ---- */ + + if(!empty($post['pw1']) && !empty($post['pw2']) && !empty($post['pw3'])) { + + if($post['pw2'] === $post['pw3']) { + + if($database->login($session->username, $post['pw1'])) { + + $hash = password_hash($post['pw2'], PASSWORD_BCRYPT, array('cost' => 12)); + $database->updateUserField($uid, "password", $hash, 1); + + } else { + $form->addError("pw", LOGIN_PW_ERROR); + } + + } else { + $form->addError("pw", PASS_MISMATCH); + } + } + + /* ---- EMAIL CHANGE ---- */ + + if(!empty($post['email_alt']) && !empty($post['email_neu'])) { + + $newEmail = filter_var($post['email_neu'], FILTER_VALIDATE_EMAIL); + + if($post['email_alt'] === $session->userinfo['email'] && $newEmail) { + $database->updateUserField($uid, "email", $newEmail, 1); + } else { + $form->addError("email", EMAIL_ERROR); + } + } + + /* ---- ACCOUNT DELETE ---- */ + + if(!empty($post['del_pw']) && !empty($post['del'])) { + + if(password_verify($post['del_pw'], $session->userinfo['password'])) { + $database->setDeleting($uid, 0); + } else { + $form->addError("del", PASS_MISMATCH); + } + } + + /* ---- SITTER ADD ---- */ + + if(!empty($post['v1'])) { + + $sitID = (int)$database->getUserField($post['v1'], "id", 1); + + if($sitID > 0 && $sitID !== $uid) { + + if($sitID == $session->userinfo['sit1'] || + $sitID == $session->userinfo['sit2']) { + + $form->addError("sit", SIT_ERROR); + + } else { + + if((int)$session->userinfo['sit1'] === 0) { + $database->updateUserField($uid, "sit1", $sitID, 1); + } elseif((int)$session->userinfo['sit2'] === 0) { + $database->updateUserField($uid, "sit2", $sitID, 1); + } + } + } + } + + if($form->returnErrors() > 0) { + $_SESSION['errorarray'] = $form->getErrors(); + $_SESSION['valuearray'] = $_POST; + } + + header("Location: spieler.php?s=3"); + exit; + } + + /* ===================================================== */ + /* ================= REMOVE SITTER ===================== */ + /* ===================================================== */ + + private function removeSitter($get) { + + global $database, $session; + + $type = isset($get['type']) ? (int)$get['type'] : 0; + $id = isset($get['id']) ? (int)$get['id'] : 0; + + if(isset($get['a']) && $get['a'] == $session->checker) { + + if((int)$session->userinfo['sit'.$type] === $id) { + $database->updateUserField($session->uid, "sit".$type, 0, 1); + } + + $session->changeChecker(); + } + + header("Location: spieler.php?s=".(int)$get['s']); + exit; + } + + private function cancelDeleting($get) { + + global $database, $session; + + $database->setDeleting((int)$session->uid, 1); + + header("Location: spieler.php?s=".(int)$get['s']); + exit; + } + + private function removeMeSit($get) { + + global $database, $session; + + if(isset($get['a']) && $get['a'] == $session->checker) { + + $database->removeMeSit((int)$get['id'], (int)$session->uid); + $session->changeChecker(); + } + + header("Location: spieler.php?s=".(int)$get['s']); + exit; + } + +} $profile = new Profile; -?> diff --git a/GameEngine/Protection.php b/GameEngine/Protection.php index c295b420..442288c1 100755 --- a/GameEngine/Protection.php +++ b/GameEngine/Protection.php @@ -5,22 +5,97 @@ ## Filename Protection.php ## ## Developed by: SlimShady ## ## Edited by: Dzoki & Dixie ## +## Enterprise hardening by Shadow ## ## License: TravianZ Project ## ## Copyright: TravianZ (c) 2010-2025. All rights reserved. ## -## ## ################################################################################# -//heef npc uitzondering omdat die met speciaal $_post werken -if(isset($_POST)){ - if(!isset($_POST['ft'])){ - //$_POST = @array_map('mysqli_real_escape_string', $_POST); - $_POST = array_map('htmlspecialchars', $_POST); - } +/* +|-------------------------------------------------------------------------- +| Enterprise Superglobal Sanitizer +|-------------------------------------------------------------------------- +| - Does NOT corrupt numeric values +| - Recursive array support +| - Keeps rsargs intact +| - Does not break AJAX +| - Does not break NPC +| - Prevents XSS vectors +|-------------------------------------------------------------------------- +*/ + +if(!function_exists('secure_input_recursive')) { + + function secure_input_recursive($data) { + + if(is_array($data)) { + + $clean = array(); + + foreach($data as $key => $value) { + $clean[$key] = secure_input_recursive($value); + } + + return $clean; + } + + if(is_numeric($data)) { + return $data; + } + + if(is_string($data)) { + + // remove null bytes + $data = str_replace("\0", '', $data); + + // trim whitespace + $data = trim($data); + + // basic XSS protection + $data = htmlspecialchars($data, ENT_QUOTES, 'UTF-8'); + + return $data; + } + + return $data; + } +} + +/* +|-------------------------------------------------------------------------- +| Preserve rsargs (used by SAJAX) +|-------------------------------------------------------------------------- +*/ + +$rsargs_backup = null; + +if(isset($_GET['rsargs'])) { + $rsargs_backup = $_GET['rsargs']; +} + +/* +|-------------------------------------------------------------------------- +| Sanitize superglobals safely +|-------------------------------------------------------------------------- +*/ + +if(!empty($_POST)) { + $_POST = secure_input_recursive($_POST); +} + +if(!empty($_GET)) { + $_GET = secure_input_recursive($_GET); +} + +if(!empty($_COOKIE)) { + $_COOKIE = secure_input_recursive($_COOKIE); +} + +/* +|-------------------------------------------------------------------------- +| Restore rsargs if needed +|-------------------------------------------------------------------------- +*/ + +if($rsargs_backup !== null) { + $_GET['rsargs'] = $rsargs_backup; } - $rsargs=$_GET['rsargs']; -//$_GET = array_map('mysqli_real_escape_string', $_GET); -$_GET = array_map('htmlspecialchars', $_GET); - $_GET['rsargs']=$rsargs; -//$_COOKIE = array_map('mysqli_real_escape_string', $_COOKIE); -$_COOKIE = array_map('htmlspecialchars', $_COOKIE); -?> \ No newline at end of file diff --git a/GameEngine/Ranking.php b/GameEngine/Ranking.php index 008549e8..2a6b3dec 100755 --- a/GameEngine/Ranking.php +++ b/GameEngine/Ranking.php @@ -9,584 +9,678 @@ | Copyright: TravianZ Project All rights reserved | \** --------------------------------------------------- **/ - class Ranking { +class Ranking { - public $rankarray = []; - private $rlastupdate; + public $rankarray = array(); + private $rlastupdate = 0; - public function getRank() { - return $this->rankarray; - } + public function getRank() { + return $this->rankarray; + } - public function getUserRank($id) { - global $database; - - $ranking = $this->getRank(); - $users = "SELECT Count(*) as Total FROM " . TB_PREFIX . "users WHERE access < " . (INCLUDE_ADMIN ? "10" : "8"); - $users2 = mysqli_fetch_array(mysqli_query($database->dblink,$users), MYSQLI_ASSOC); - $users2 = $users2['Total']; - $users3 = $users2 + 1; - $myrank = 0; - if(count($ranking) > 0) { - for($i = 0;$i < $users3; $i++) { - if( isset( $ranking[$i]['userid'] ) ) { - if($ranking[$i]['userid'] == $id && $ranking[$i] != "pad") { - $myrank = $i; - } - } - } - } - return $myrank; - } + public function getUserRank($id) { + global $database; - public function procRankReq($get) { - global $village, $session; - if(isset($get['id'])) { - switch($get['id']) { - case 1: - $this->procRankArray(); - break; - case 8: - $this->procHeroRankArray(); - if($get['hero'] == 0) { - $this->getStart(1); - } else { - $this->getStart($this->searchRank($session->uid, "uid")); - } - break; - case 11: - $this->procRankRaceArray(1); - if($this->searchRank($session->uid, "userid") != 0){ - $this->getStart($this->searchRank($session->uid, "userid")); - }else{ - $this->getStart(1); - } - break; - case 12: - $this->procRankRaceArray(2); - if($this->searchRank($session->uid, "userid") != 0){ - $this->getStart($this->searchRank($session->uid, "userid")); - }else{ - $this->getStart(1); - } - break; - case 13: - $this->procRankRaceArray(3); - if($this->searchRank($session->uid, "userid") != 0){ - $this->getStart($this->searchRank($session->uid, "userid")); - }else{ - $this->getStart(1); - } - break; - case 31: - $this->procAttRankArray(); - $this->getStart($this->searchRank($session->uid, "userid")); - break; - case 32: - $this->procDefRankArray(); - $this->getStart($this->searchRank($session->uid, "userid")); - break; - case 2: - $this->procVRankArray(); - $this->getStart($this->searchRank($village->wid, "wref")); - break; - case 4: - $this->procARankArray(); - if($get['aid'] == 0) { - $this->getStart(1); - } else { - $this->getStart($this->searchRank($get['aid'], "id")); - } - break; - case 41: - $this->procAAttRankArray(); - if($get['aid'] == 0) { - $this->getStart(1); - } else { - $this->getStart($this->searchRank($get['aid'], "id")); - } - break; - case 42: - $this->procADefRankArray(); - if($get['aid'] == 0) { - $this->getStart(1); - } else { - $this->getStart($this->searchRank($get['aid'], "id")); - } - break; - } - } else { - $this->procRankArray(); - $this->getStart($this->searchRank($session->uid, "userid")); - } - } + $id = (int)$id; + $ranking = $this->getRank(); - public function procRank($post) { - if(isset($post['ft'])) { - switch($post['ft']) { - case "r1": - case "r11": - case "r12": - case "r13": - case "r31": - case "r32": - if(isset($post['rank']) && $post['rank'] != "") { - $this->getStart($post['rank']); - } - if(isset($post['name']) && $post['name'] != "") { - $this->getStart($this->searchRank(stripslashes($post['name']), "username")); - } - break; - case "r4": - case "r42": - case "r41": - if(isset($post['rank']) && $post['rank'] != "") { - $this->getStart($post['rank']); - } - if(isset($post['name']) && $post['name'] != "") { - $this->getStart($this->searchRank(stripslashes($post['name']), "tag")); - } - break; - case "r2": - case "r8": - if(isset($post['rank']) && $post['rank'] != "") { - $this->getStart($post['rank']); - } - if(isset($post['name']) && $post['name'] != "") { - $this->getStart($this->searchRank(stripslashes($post['name']), "name")); - } - break; - } - } - } + $usersQuery = "SELECT Count(*) as Total FROM " . TB_PREFIX . "users + WHERE access < " . (INCLUDE_ADMIN ? "10" : "8"); - private function getStart($search) { - $multiplier = 1; - if(!is_numeric($search)) { - $_SESSION['search'] = htmlspecialchars($search); - } else { - if($search > count($this->rankarray)) { - $search = count($this->rankarray) - 1; - } - while($search > (20 * $multiplier)) { - $multiplier += 1; - } - $start = 20 * $multiplier - 19 - 1; - $_SESSION['search'] = htmlspecialchars($search); - $_SESSION['start'] = htmlspecialchars($start); - } - } + $usersResult = mysqli_query($database->dblink, $usersQuery); + if(!$usersResult) return 0; - public function getAllianceRank($id) { - $this->procARankArray(); - while(1) { - if(count($this->rankarray) > 1) { - $key = key($this->rankarray); - if(isset ($this->rankarray[$key]["id"]) && $this->rankarray[$key]["id"] === $id) { - return $key; - break; - } else { - if(!next($this->rankarray)) { - return false; - break; - } - } - } else { - return 1; - } - } - } + $usersRow = mysqli_fetch_array($usersResult, MYSQLI_ASSOC); + $totalUsers = isset($usersRow['Total']) ? (int)$usersRow['Total'] : 0; - public function searchRank($name, $field) { - - while(1) { - //$key = key($this->rankarray); - for($key = 0; $key < count($this->rankarray); $key++){ - if($this->rankarray[$key]!="pad") { - if($this->rankarray[$key][$field] == $name) return $key; - } - } - if(!next($this->rankarray)) { - if($field != "userid") return $name; - else return 0; - } - - } - } + $limit = $totalUsers + 1; + $myrank = 0; - public function procRankArray() { - global $multisort, $database; - - if($GLOBALS['db']->countUser() > 0){ - $holder = array(); - if(SHOW_NATARS == True){ - $q = "SELECT " . TB_PREFIX . "users.id userid, " . TB_PREFIX . "users.username username, " . TB_PREFIX . "users.oldrank oldrank, " . TB_PREFIX . "users.alliance alliance, ( - - SELECT SUM( " . TB_PREFIX . "vdata.pop ) - FROM " . TB_PREFIX . "vdata - WHERE " . TB_PREFIX . "vdata.owner = userid - )totalpop, ( - - SELECT COUNT( " . TB_PREFIX . "vdata.wref ) - FROM " . TB_PREFIX . "vdata - WHERE " . TB_PREFIX . "vdata.owner = userid AND type != 99 - )totalvillages, ( - - SELECT " . TB_PREFIX . "alidata.tag - FROM " . TB_PREFIX . "alidata, " . TB_PREFIX . "users - WHERE " . TB_PREFIX . "alidata.id = " . TB_PREFIX . "users.alliance - AND " . TB_PREFIX . "users.id = userid - )allitag - FROM " . TB_PREFIX . "users - WHERE " . TB_PREFIX . "users.access < " . (INCLUDE_ADMIN ? "10" : "8") . " - AND (" . TB_PREFIX . "users.tribe <= 5 OR " . TB_PREFIX . "users.tribe = 5) - AND (" . TB_PREFIX . "users.id > 5 OR " . TB_PREFIX . "users.id = 3) - ORDER BY totalpop DESC, totalvillages DESC, userid DESC"; - } else { - $q = "SELECT " . TB_PREFIX . "users.id userid, " . TB_PREFIX . "users.username username, " . TB_PREFIX . "users.oldrank oldrank, " . TB_PREFIX . "users.alliance alliance, ( - - SELECT SUM( " . TB_PREFIX . "vdata.pop ) - FROM " . TB_PREFIX . "vdata - WHERE " . TB_PREFIX . "vdata.owner = userid - )totalpop, ( - - SELECT COUNT( " . TB_PREFIX . "vdata.wref ) - FROM " . TB_PREFIX . "vdata - WHERE " . TB_PREFIX . "vdata.owner = userid AND type != 99 - )totalvillages, ( - - SELECT " . TB_PREFIX . "alidata.tag - FROM " . TB_PREFIX . "alidata, " . TB_PREFIX . "users - WHERE " . TB_PREFIX . "alidata.id = " . TB_PREFIX . "users.alliance - AND " . TB_PREFIX . "users.id = userid - )allitag - FROM " . TB_PREFIX . "users - WHERE " . TB_PREFIX . "users.access < " . (INCLUDE_ADMIN ? "10" : "8") . " - AND " . TB_PREFIX . "users.tribe <= 3 - AND " . TB_PREFIX . "users.id > 5 - ORDER BY totalpop DESC, totalvillages DESC, userid DESC"; - } - - $datas = []; - - $result = (mysqli_query($database->dblink,$q)); - while($row = mysqli_fetch_assoc($result)) $datas[] = $row; - - if (count($datas)) { - foreach($datas as $result) { - $value['userid'] = $result['userid']; - $value['username'] = $result['username']; - $value['oldrank'] = $result['oldrank']; - $value['alliance'] = $result['alliance']; - $value['aname'] = $result['allitag']; - $value['totalpop'] = $result['totalpop']; - $value['totalvillage'] = $result['totalvillages']; - array_push($holder, $value); - } - } - - $newholder = ["pad"]; - foreach($holder as $key) array_push($newholder, $key); - - $this->rankarray = $newholder; - - } - } - - public function procRankRaceArray($race) { - global $multisort, $database; - $race = $database->escape((int) $race); - //$array = $GLOBALS['db']->getRanking(); - $holder = array(); - //$value['totalvillage'] = count($GLOBALS['db']->getVillagesID($value['id'])); - //$value['totalvillage'] = count($GLOBALS['db']->getVillagesID($value['id'])); - //$value['totalpop'] = $GLOBALS['db']->getVSumField($value['id'],"pop"); - //$value['aname'] = $GLOBALS['db']->getAllianceName($value['alliance']); - $q = "SELECT " . TB_PREFIX . "users.id userid, " . TB_PREFIX . "users.tribe tribe, " . TB_PREFIX . "users.username username," . TB_PREFIX . "users.alliance alliance, ( - - SELECT SUM( " . TB_PREFIX . "vdata.pop ) - FROM " . TB_PREFIX . "vdata - WHERE " . TB_PREFIX . "vdata.owner = userid - )totalpop, ( - - SELECT COUNT( " . TB_PREFIX . "vdata.wref ) - FROM " . TB_PREFIX . "vdata - WHERE " . TB_PREFIX . "vdata.owner = userid AND type != 99 - )totalvillages, ( - - SELECT " . TB_PREFIX . "alidata.tag - FROM " . TB_PREFIX . "alidata, " . TB_PREFIX . "users - WHERE " . TB_PREFIX . "alidata.id = " . TB_PREFIX . "users.alliance - AND " . TB_PREFIX . "users.id = userid - )allitag - FROM " . TB_PREFIX . "users - WHERE " . TB_PREFIX . "users.tribe = $race AND " . TB_PREFIX . "users.access < " . (INCLUDE_ADMIN ? "10" : "8") . " - AND " . TB_PREFIX . "users.id > 5 - ORDER BY totalpop DESC, totalvillages DESC, userid DESC"; - - - $result = (mysqli_query($database->dblink,$q)); - while($row = mysqli_fetch_assoc($result)) { - $datas[] = $row; - } - - if(mysqli_num_rows($result)) { - - - foreach($datas as $result) { - $value['userid'] = $result['userid']; - $value['username'] = $result['username']; - $value['alliance'] = $result['alliance']; - $value['aname'] = $result['allitag']; - $value['totalpop'] = $result['totalpop']; - $value['totalvillage'] = $result['totalvillages']; - //SELECT (SELECT SUM(".TB_PREFIX."vdata.pop) FROM ".TB_PREFIX."vdata WHERE ".TB_PREFIX."vdata.owner = 2) totalpop, (SELECT COUNT(".TB_PREFIX."vdata.wref) FROM ".TB_PREFIX."vdata WHERE ".TB_PREFIX."vdata.owner = 2) totalvillages, (SELECT ".TB_PREFIX."alidata.tag FROM ".TB_PREFIX."alidata WHERE ".TB_PREFIX."alidata.id = ".TB_PREFIX."users.alliance AND ".TB_PREFIX."users.id = 2); - array_push($holder, $value); - } - } else { - $value['userid'] = 0; - $value['username'] = "No User"; - $value['alliance'] = ""; - $value['aname'] = ""; - $value['totalpop'] = ""; - $value['totalvillage'] = ""; - array_push($holder, $value); - } - //$holder = $multisort->sorte($holder, "'totalvillage'", false, 2, "'totalpop'", false, 2); - $newholder = array("pad"); - foreach($holder as $key) { - array_push($newholder, $key); - } - $this->rankarray = $newholder; - } - - public function procAttRankArray() { - global $multisort, $database; - //$array = $GLOBALS['db']->getRanking(); - $holder = array(); - - //$value['totalvillage'] = count($GLOBALS['db']->getVillagesID($value['id'])); - //$value['totalpop'] = $GLOBALS['db']->getVSumField($value['id'],"pop"); - $q = "SELECT " . TB_PREFIX . "users.id userid, " . TB_PREFIX . "users.username username, " . TB_PREFIX . "users.apall, ( - - SELECT COUNT( " . TB_PREFIX . "vdata.wref ) - FROM " . TB_PREFIX . "vdata - WHERE " . TB_PREFIX . "vdata.owner = userid AND type != 99 - )totalvillages, ( - - SELECT SUM( " . TB_PREFIX . "vdata.pop ) - FROM " . TB_PREFIX . "vdata - WHERE " . TB_PREFIX . "vdata.owner = userid - )pop - FROM " . TB_PREFIX . "users - WHERE " . TB_PREFIX . "users.apall >=0 AND " . TB_PREFIX . "users.access < " . (INCLUDE_ADMIN ? "10" : "8") . " AND " . TB_PREFIX . "users.tribe <= 3 - AND " . TB_PREFIX . "users.id > 5 - ORDER BY " . TB_PREFIX . "users.apall DESC, pop DESC, userid DESC"; - $result = mysqli_query($database->dblink,$q) or die(mysqli_error($database->dblink)); - while($row = mysqli_Fetch_assoc($result)) { - $datas[] = $row; - } - - foreach($datas as $key => $row) { - $value['userid'] = $row['userid']; - $value['username'] = $row['username']; - $value['totalvillages'] = $row['totalvillages']; - $value['id'] = $row['userid']; - $value['totalpop'] = $row['pop']; - $value['apall'] = $row['apall']; - array_push($holder, $value); - printf("\n\n", $value['username'], $value['totalvillages'], $value['totalpop'], $value['apall']); - } - - //$holder = $multisort->sorte($holder, "'ap'", false, 2, "'totalvillages'", false, 2, "'ap'", false, 2); - $newholder = array("pad"); - foreach($holder as $key) { - array_push($newholder, $key); - } - $this->rankarray = $newholder; - } - - public function procDefRankArray() { - global $database; - //global $GLOBALS['db'], $multisort; - //$array = $GLOBALS['db']->getRanking(); - $holder = array(); - $q = "SELECT " . TB_PREFIX . "users.id userid, " . TB_PREFIX . "users.username username, " . TB_PREFIX . "users.dpall, ( - - SELECT COUNT( " . TB_PREFIX . "vdata.wref ) - FROM " . TB_PREFIX . "vdata - WHERE " . TB_PREFIX . "vdata.owner = userid AND type != 99 - )totalvillages, ( - - SELECT SUM( " . TB_PREFIX . "vdata.pop ) - FROM " . TB_PREFIX . "vdata - WHERE " . TB_PREFIX . "vdata.owner = userid - )pop - FROM " . TB_PREFIX . "users - WHERE " . TB_PREFIX . "users.dpall >=0 AND " . TB_PREFIX . "users.access < " . (INCLUDE_ADMIN ? "10" : "8") . " AND " . TB_PREFIX . "users.tribe <= 3 - AND " . TB_PREFIX . "users.id > 5 - ORDER BY " . TB_PREFIX . "users.dpall DESC, pop DESC, userid DESC"; - $result = mysqli_query($database->dblink,$q) or die(mysqli_error($database->dblink)); - while($row = mysqli_Fetch_assoc($result)) { - $datas[] = $row; - } - - foreach($datas as $key => $row) { - $value['userid'] = $row['userid']; - $value['username'] = $row['username']; - $value['totalvillages'] = $row['totalvillages']; - $value['id'] = $row['userid']; - $value['totalpop'] = $row['pop']; - $value['dpall'] = $row['dpall']; - array_push($holder, $value); - - } - - //$holder = $multisort->sorte($holder, "'dpall'", false, 2, "'totalvillage'", false, 2, "'dpall'", false, 2); - $newholder = array("pad"); - foreach($holder as $key) { - array_push($newholder, $key); - } - $this->rankarray = $newholder; - } - - public function procVRankArray() { - global $multisort; - $array = $GLOBALS['db']->getVRanking(); - $holder = array(); - foreach($array as $value) { - $coor = $GLOBALS['db']->getCoor($value['wref']); - $value['x'] = $coor['x']; - $value['y'] = $coor['y']; - $value['user'] = $GLOBALS['db']->getUserField($value['owner'], "username", 0); - - array_push($holder, $value); - } - $holder = $multisort->sorte($holder, "x", true, 2, "y", true, 2, "pop", false, 2); - $newholder = array("pad"); - foreach($holder as $key) { - array_push($newholder, $key); - } - $this->rankarray = $newholder; - } - - public function procARankArray() { - global $multisort, $database; - $array = $GLOBALS['db']->getARanking(); - $holder = array(); - - foreach($array as $value) { - $memberlist = $GLOBALS['db']->getAllMember($value['id']); - $totalpop = 0; - - $memberIDs = []; - foreach($memberlist as $member) { - $memberIDs[] = $member['id']; + if(!empty($ranking)) { + for($i = 0; $i < $limit; $i++) { + if(isset($ranking[$i]['userid']) && $ranking[$i] !== "pad") { + if((int)$ranking[$i]['userid'] === $id) { + $myrank = $i; + break; } - $data = $database->getVSumField($memberIDs,"pop"); + } + } + } - if (count($data)) { - foreach ($data as $row) { - $totalpop += $row['Total']; + return $myrank; + } + + public function procRankReq($get) { + global $village, $session; + + if(isset($get['id'])) { + + $id = (int)$get['id']; + + switch($id) { + + case 1: + $this->procRankArray(); + break; + + case 8: + $this->procHeroRankArray(); + if(isset($get['hero']) && (int)$get['hero'] !== 0) { + $this->getStart($this->searchRank($session->uid, "uid")); + } else { + $this->getStart(1); + } + break; + + case 11: + case 12: + case 13: + $this->procRankRaceArray($id - 10); + $rank = $this->searchRank($session->uid, "userid"); + $this->getStart($rank !== 0 ? $rank : 1); + break; + + case 31: + $this->procAttRankArray(); + $this->getStart($this->searchRank($session->uid, "userid")); + break; + + case 32: + $this->procDefRankArray(); + $this->getStart($this->searchRank($session->uid, "userid")); + break; + + case 2: + $this->procVRankArray(); + $this->getStart($this->searchRank($village->wid, "wref")); + break; + + case 4: + case 41: + case 42: + if($id == 4) $this->procARankArray(); + if($id == 41) $this->procAAttRankArray(); + if($id == 42) $this->procADefRankArray(); + + $aid = isset($get['aid']) ? (int)$get['aid'] : 0; + if($aid === 0) { + $this->getStart(1); + } else { + $this->getStart($this->searchRank($aid, "id")); + } + break; + } + + } else { + $this->procRankArray(); + $this->getStart($this->searchRank($session->uid, "userid")); + } + } + + public function procRank($post) { + + if(!isset($post['ft'])) return; + + $ft = $post['ft']; + + if(isset($post['rank']) && $post['rank'] !== "") { + $this->getStart((int)$post['rank']); + } + + if(isset($post['name']) && $post['name'] !== "") { + + $name = stripslashes($post['name']); + + switch($ft) { + case "r1": + case "r11": + case "r12": + case "r13": + case "r31": + case "r32": + $this->getStart($this->searchRank($name, "username")); + break; + + case "r4": + case "r42": + case "r41": + $this->getStart($this->searchRank($name, "tag")); + break; + + case "r2": + case "r8": + $this->getStart($this->searchRank($name, "name")); + break; + } + } + } + + private function getStart($search) { + + if(!is_numeric($search)) { + $_SESSION['search'] = htmlspecialchars($search, ENT_QUOTES, 'UTF-8'); + return; + } + + $search = (int)$search; + $count = count($this->rankarray); + + if($count <= 1) return; + + if($search > $count) { + $search = $count - 1; + } + + $multiplier = 1; + + while($search > (20 * $multiplier)) { + $multiplier++; + } + + $start = (20 * $multiplier) - 19 - 1; + + $_SESSION['search'] = htmlspecialchars($search, ENT_QUOTES, 'UTF-8'); + $_SESSION['start'] = htmlspecialchars($start, ENT_QUOTES, 'UTF-8'); + } + + public function getAllianceRank($id) { + + $id = (int)$id; + $this->procARankArray(); + + if(count($this->rankarray) <= 1) return 1; + + foreach($this->rankarray as $key => $row) { + if($row !== "pad" && isset($row['id']) && (int)$row['id'] === $id) { + return $key; + } + } + + return false; + } + + public function searchRank($name, $field) { + + if(empty($this->rankarray)) return 0; + + foreach($this->rankarray as $key => $row) { + if($row !== "pad" && isset($row[$field])) { + if($row[$field] == $name) { + return $key; + } + } + } + + return ($field !== "userid") ? $name : 0; + } + public function procRankArray() { + global $database; + + if($GLOBALS['db']->countUser() <= 0) { + $this->rankarray = array("pad"); + return; + } + + $holder = array(); + + if(SHOW_NATARS == true) { + + $q = "SELECT u.id userid, u.username username, u.oldrank oldrank, + u.alliance alliance, + + (SELECT SUM(v.pop) FROM ".TB_PREFIX."vdata v WHERE v.owner = u.id) totalpop, + + (SELECT COUNT(v.wref) FROM ".TB_PREFIX."vdata v + WHERE v.owner = u.id AND v.type != 99) totalvillages, + + (SELECT a.tag FROM ".TB_PREFIX."alidata a + WHERE a.id = u.alliance) allitag + + FROM ".TB_PREFIX."users u + WHERE u.access < ".(INCLUDE_ADMIN ? "10" : "8")." + AND (u.tribe <= 5 OR u.tribe = 5) + AND (u.id > 5 OR u.id = 3) + ORDER BY totalpop DESC, totalvillages DESC, userid DESC"; + + } else { + + $q = "SELECT u.id userid, u.username username, u.oldrank oldrank, + u.alliance alliance, + + (SELECT SUM(v.pop) FROM ".TB_PREFIX."vdata v WHERE v.owner = u.id) totalpop, + + (SELECT COUNT(v.wref) FROM ".TB_PREFIX."vdata v + WHERE v.owner = u.id AND v.type != 99) totalvillages, + + (SELECT a.tag FROM ".TB_PREFIX."alidata a + WHERE a.id = u.alliance) allitag + + FROM ".TB_PREFIX."users u + WHERE u.access < ".(INCLUDE_ADMIN ? "10" : "8")." + AND u.tribe <= 3 + AND u.id > 5 + ORDER BY totalpop DESC, totalvillages DESC, userid DESC"; + } + + $result = mysqli_query($database->dblink, $q); + if(!$result) { + $this->rankarray = array("pad"); + return; + } + + while($row = mysqli_fetch_assoc($result)) { + + $value = array(); + $value['userid'] = (int)$row['userid']; + $value['username'] = $row['username']; + $value['oldrank'] = (int)$row['oldrank']; + $value['alliance'] = (int)$row['alliance']; + $value['aname'] = $row['allitag']; + $value['totalpop'] = (int)$row['totalpop']; + $value['totalvillage'] = (int)$row['totalvillages']; + + $holder[] = $value; + } + + $newholder = array("pad"); + foreach($holder as $row) { + $newholder[] = $row; + } + + $this->rankarray = $newholder; + } + public function procRankRaceArray($race) { + global $database; + + $race = (int)$race; + $holder = array(); + + $q = "SELECT u.id userid, u.tribe tribe, u.username username, + u.alliance alliance, + + (SELECT SUM(v.pop) FROM ".TB_PREFIX."vdata v + WHERE v.owner = u.id) totalpop, + + (SELECT COUNT(v.wref) FROM ".TB_PREFIX."vdata v + WHERE v.owner = u.id AND v.type != 99) totalvillages, + + (SELECT a.tag FROM ".TB_PREFIX."alidata a + WHERE a.id = u.alliance) allitag + + FROM ".TB_PREFIX."users u + WHERE u.tribe = $race + AND u.access < ".(INCLUDE_ADMIN ? "10" : "8")." + AND u.id > 5 + ORDER BY totalpop DESC, totalvillages DESC, userid DESC"; + + $result = mysqli_query($database->dblink, $q); + + if($result && mysqli_num_rows($result) > 0) { + + while($row = mysqli_fetch_assoc($result)) { + + $value = array(); + $value['userid'] = (int)$row['userid']; + $value['username'] = $row['username']; + $value['alliance'] = (int)$row['alliance']; + $value['aname'] = $row['allitag']; + $value['totalpop'] = (int)$row['totalpop']; + $value['totalvillage'] = (int)$row['totalvillages']; + + $holder[] = $value; + } + + } else { + + $holder[] = array( + 'userid' => 0, + 'username' => "No User", + 'alliance' => "", + 'aname' => "", + 'totalpop' => "", + 'totalvillage' => "" + ); + } + + $newholder = array("pad"); + foreach($holder as $row) { + $newholder[] = $row; + } + + $this->rankarray = $newholder; + } + public function procAttRankArray() { + global $database; + + $holder = array(); + + $q = "SELECT u.id userid, u.username username, u.apall, + + (SELECT COUNT(v.wref) FROM ".TB_PREFIX."vdata v + WHERE v.owner = u.id AND v.type != 99) totalvillages, + + (SELECT SUM(v.pop) FROM ".TB_PREFIX."vdata v + WHERE v.owner = u.id) pop + + FROM ".TB_PREFIX."users u + WHERE u.apall >= 0 + AND u.access < ".(INCLUDE_ADMIN ? "10" : "8")." + AND u.tribe <= 3 + AND u.id > 5 + ORDER BY u.apall DESC, pop DESC, userid DESC"; + + $result = mysqli_query($database->dblink, $q); + + if(!$result) { + $this->rankarray = array("pad"); + return; + } + + while($row = mysqli_fetch_assoc($result)) { + + $value = array(); + $value['userid'] = (int)$row['userid']; + $value['username'] = $row['username']; + $value['totalvillages'] = (int)$row['totalvillages']; + $value['id'] = (int)$row['userid']; + $value['totalpop'] = (int)$row['pop']; + $value['apall'] = (int)$row['apall']; + + $holder[] = $value; + + // păstrăm debug comment original (nu afectează logica) + printf("\n\n", + $value['username'], + $value['totalvillages'], + $value['totalpop'], + $value['apall'] + ); + } + + $newholder = array("pad"); + foreach($holder as $row) { + $newholder[] = $row; + } + + $this->rankarray = $newholder; + } + public function procDefRankArray() { + global $database; + + $holder = array(); + + $q = "SELECT u.id userid, u.username username, u.dpall, + + (SELECT COUNT(v.wref) FROM ".TB_PREFIX."vdata v + WHERE v.owner = u.id AND v.type != 99) totalvillages, + + (SELECT SUM(v.pop) FROM ".TB_PREFIX."vdata v + WHERE v.owner = u.id) pop + + FROM ".TB_PREFIX."users u + WHERE u.dpall >= 0 + AND u.access < ".(INCLUDE_ADMIN ? "10" : "8")." + AND u.tribe <= 3 + AND u.id > 5 + ORDER BY u.dpall DESC, pop DESC, userid DESC"; + + $result = mysqli_query($database->dblink, $q); + + if(!$result) { + $this->rankarray = array("pad"); + return; + } + + while($row = mysqli_fetch_assoc($result)) { + + $value = array(); + $value['userid'] = (int)$row['userid']; + $value['username'] = $row['username']; + $value['totalvillages'] = (int)$row['totalvillages']; + $value['id'] = (int)$row['userid']; + $value['totalpop'] = (int)$row['pop']; + $value['dpall'] = (int)$row['dpall']; + + $holder[] = $value; + } + + $newholder = array("pad"); + foreach($holder as $row) { + $newholder[] = $row; + } + + $this->rankarray = $newholder; + } + public function procVRankArray() { + global $multisort; + + $array = $GLOBALS['db']->getVRanking(); + $holder = array(); + + if(!is_array($array)) { + $this->rankarray = array("pad"); + return; + } + + foreach($array as $value) { + + $coor = $GLOBALS['db']->getCoor($value['wref']); + + if(!is_array($coor)) { + $coor = array('x' => 0, 'y' => 0); + } + + $value['x'] = isset($coor['x']) ? (int)$coor['x'] : 0; + $value['y'] = isset($coor['y']) ? (int)$coor['y'] : 0; + $value['user'] = $GLOBALS['db']->getUserField($value['owner'], "username", 0); + + $holder[] = $value; + } + + if(is_array($holder) && count($holder) > 0) { + $holder = $multisort->sorte($holder, "x", true, 2, "y", true, 2, "pop", false, 2); + } + + $newholder = array("pad"); + foreach($holder as $row) { + $newholder[] = $row; + } + + $this->rankarray = $newholder; + } + public function procARankArray() { + global $multisort, $database; + + $array = $GLOBALS['db']->getARanking(); + $holder = array(); + + if(!is_array($array)) { + $this->rankarray = array("pad"); + return; + } + + foreach($array as $value) { + + $memberlist = $GLOBALS['db']->getAllMember($value['id']); + $totalpop = 0; + + if(!is_array($memberlist)) { + $memberlist = array(); + } + + $memberIDs = array(); + foreach($memberlist as $member) { + if(isset($member['id'])) { + $memberIDs[] = (int)$member['id']; + } + } + + if(count($memberIDs) > 0) { + + $data = $database->getVSumField($memberIDs, "pop"); + + if(is_array($data)) { + foreach($data as $row) { + if(isset($row['Total'])) { + $totalpop += (int)$row['Total']; } } + } + } - $value['players'] = count($memberlist); - $value['totalpop'] = $totalpop; - if(!isset($value['avg'])) { - $value['avg'] = @round($totalpop / count($memberlist)); - } else { - $value['avg'] = 0; - } + $value['players'] = count($memberlist); + $value['totalpop'] = $totalpop; - array_push($holder, $value); - } - $holder = $multisort->sorte($holder, "totalpop", false, 2); - $newholder = array("pad"); - foreach($holder as $key) { - array_push($newholder, $key); - } - $this->rankarray = $newholder; - } + if(count($memberlist) > 0) { + $value['avg'] = (int)round($totalpop / count($memberlist)); + } else { + $value['avg'] = 0; + } - public function procHeroRankArray() { - global $multisort; - $array = $GLOBALS['db']->getHeroRanking(); - $holder = array(); - foreach($array as $value) { - $value['owner'] = $GLOBALS['db']->getUserField($value['uid'], "username", 0); - $value['level']; - $value['name']; - $value['uid']; + $holder[] = $value; + } - array_push($holder, $value); - } - $holder = $multisort->sorte($holder, "experience", false, 2); - $newholder = array("pad"); - foreach($holder as $key) { - array_push($newholder, $key); - } - $this->rankarray = $newholder; - } + if(is_array($holder) && count($holder) > 0) { + $holder = $multisort->sorte($holder, "totalpop", false, 2); + } - public function procAAttRankArray() { - global $multisort; - $array = $GLOBALS['db']->getARanking(); - $holder = array(); - foreach($array as $value) { - $memberlist = $GLOBALS['db']->getAllMember($value['id']); - $totalap = 0; - foreach($memberlist as $member) { - $totalap += $member['ap']; - } - $value['players'] = count($memberlist); - $value['totalap'] = $totalap; - if($value['avg'] > 0) { - $value['avg'] = round($totalap / count($memberlist)); - } else { - $value['avg'] = 0; - } + $newholder = array("pad"); + foreach($holder as $row) { + $newholder[] = $row; + } - array_push($holder, $value); - } - $holder = $multisort->sorte($holder, "Aap", false, 2); - $newholder = array("pad"); - foreach($holder as $key) { - array_push($newholder, $key); - } - $this->rankarray = $newholder; - } + $this->rankarray = $newholder; + } + public function procHeroRankArray() { + global $multisort; - public function procADefRankArray() { - global $multisort; - $array = $GLOBALS['db']->getARanking(); - $holder = array(); - foreach($array as $value) { - $memberlist = $GLOBALS['db']->getAllMember($value['id']); - $totaldp = 0; - foreach($memberlist as $member) { - $totaldp += $member['dp']; - } - $value['players'] = count($memberlist); - $value['totaldp'] = $totaldp; - if($value['avg'] > 0) { - $value['avg'] = round($totalap / count($memberlist)); - } else { - $value['avg'] = 0; - } + $array = $GLOBALS['db']->getHeroRanking(); + $holder = array(); - array_push($holder, $value); - } - $holder = $multisort->sorte($holder, "Adp", false, 2); - $newholder = array("pad"); - foreach($holder as $key) { - array_push($newholder, $key); - } - $this->rankarray = $newholder; - } - } - ; + if(!is_array($array)) { + $this->rankarray = array("pad"); + return; + } - $ranking = new Ranking; + foreach($array as $value) { + + $value['owner'] = $GLOBALS['db']->getUserField($value['uid'], "username", 0); + + $holder[] = $value; + } + + if(count($holder) > 0) { + $holder = $multisort->sorte($holder, "experience", false, 2); + } + + $newholder = array("pad"); + foreach($holder as $row) { + $newholder[] = $row; + } + + $this->rankarray = $newholder; + } + public function procAAttRankArray() { + global $multisort; + + $array = $GLOBALS['db']->getARanking(); + $holder = array(); + + if(!is_array($array)) { + $this->rankarray = array("pad"); + return; + } + + foreach($array as $value) { + + $memberlist = $GLOBALS['db']->getAllMember($value['id']); + $totalap = 0; + + if(!is_array($memberlist)) { + $memberlist = array(); + } + + foreach($memberlist as $member) { + if(isset($member['ap'])) { + $totalap += (int)$member['ap']; + } + } + + $value['players'] = count($memberlist); + $value['totalap'] = $totalap; + + if(count($memberlist) > 0) { + $value['avg'] = (int)round($totalap / count($memberlist)); + } else { + $value['avg'] = 0; + } + + $holder[] = $value; + } + + if(count($holder) > 0) { + $holder = $multisort->sorte($holder, "Aap", false, 2); + } + + $newholder = array("pad"); + foreach($holder as $row) { + $newholder[] = $row; + } + + $this->rankarray = $newholder; + } + public function procADefRankArray() { + global $multisort; + + $array = $GLOBALS['db']->getARanking(); + $holder = array(); + + if(!is_array($array)) { + $this->rankarray = array("pad"); + return; + } + + foreach($array as $value) { + + $memberlist = $GLOBALS['db']->getAllMember($value['id']); + $totaldp = 0; + + if(!is_array($memberlist)) { + $memberlist = array(); + } + + foreach($memberlist as $member) { + if(isset($member['dp'])) { + $totaldp += (int)$member['dp']; + } + } + + $value['players'] = count($memberlist); + $value['totaldp'] = $totaldp; + + if(count($memberlist) > 0) { + $value['avg'] = (int)round($totaldp / count($memberlist)); // FIX BUG (era $totalap) + } else { + $value['avg'] = 0; + } + + $holder[] = $value; + } + + if(count($holder) > 0) { + $holder = $multisort->sorte($holder, "Adp", false, 2); + } + + $newholder = array("pad"); + foreach($holder as $row) { + $newholder[] = $row; + } + + $this->rankarray = $newholder; + } + } + ; + + $ranking = new Ranking; ?> diff --git a/GameEngine/Session.php b/GameEngine/Session.php index 8d4d0235..abdc0117 100755 --- a/GameEngine/Session.php +++ b/GameEngine/Session.php @@ -8,26 +8,25 @@ mb_internal_encoding("UTF-8"); // Add for utf8 varriables. ## -= YOU MAY NOT REMOVE OR CHANGE THIS NOTICE =- ## ## --------------------------------------------------------------------------- ## ## Project: TravianZ ## -## Version: 22.06.2015 ## +## Version: 22.06.2015 ## ## Filename Session.php ## ## Developed by: Mr.php , Advocaite , brainiacX , yi12345 , Shadow , ronix ## -## Fixed by: Shadow - STARVATION , HERO FIXED COMPL. ## -## Fixed by: InCube - double troops ## +## Fixed by: Shadow - STARVATION , HERO FIXED COMPL. ## +## Fixed by: InCube - double troops ## +## Refactored TravianZ Enterprise Hardened Core by Shadow ## ## License: TravianZ Project ## ## Copyright: TravianZ (c) 2010-2015. All rights reserved. ## -## URLs: http://travian.shadowss.ro ## -## Source code: https://github.com/Shadowss/TravianZ ## +## URLs: http://travian.shadowss.ro ## +## Source code: https://github.com/Shadowss/TravianZ ## ## ## ################################################################################# global $autoprefix; -// go max 5 levels up - we don't have folders that go deeper than that $autoprefix = ''; for ($i = 0; $i < 5; $i++) { $autoprefix = str_repeat('../', $i); if (file_exists($autoprefix.'autoloader.php')) { - // we have our path, let's leave break; } } @@ -38,6 +37,7 @@ if(!file_exists($autoprefix.'GameEngine/config.php')) { } $script_name = ($_SERVER['REQUEST_URI'] == 'karte.php') ? 'karte' : $_SERVER['REQUEST_URI']; + include_once ("Battle.php"); include_once ("Data/buidata.php"); include_once ("Data/cp.php"); @@ -60,324 +60,440 @@ include_once ("Profile.php"); class Session { - private $time; - var $logged_in = false; - var $referrer, $url; - var $username, $uid, $access, $plus, $tribe, $isAdmin, $alliance, $gold, $oldrank, $gpack, $goldclub; - var $bonus = 0; - var $bonus1 = 0; - var $bonus2 = 0; - var $bonus3 = 0; - var $bonus4 = 0; - var $timer = 0; - var $sharedForums = []; - var $checker, $mchecker; - public $userinfo = []; - private $userarray = []; - var $villages = []; + private $time; + var $logged_in = false; + var $referrer, $url; + var $username, $uid, $access, $plus, $tribe, $isAdmin, $alliance, $gold, $oldrank, $gpack, $goldclub; + var $bonus = 0; + var $bonus1 = 0; + var $bonus2 = 0; + var $bonus3 = 0; + var $bonus4 = 0; + var $timer = 0; + var $sharedForums = array(); + var $checker, $mchecker; + public $userinfo = array(); + private $userarray = array(); + var $villages = array(); - function __construct() { - global $database; //TienTN fix + function __construct() { + global $database; - $this->time = time(); - if (!isset($_SESSION)) { - session_start(); - } + $this->time = time(); - $this->logged_in = $this->checkLogin(); + if (session_status() == PHP_SESSION_NONE) { + session_start(); + } - if($this->logged_in && TRACK_USR) $database->updateActiveUser($this->username, $this->time); - - if(isset($_SESSION['url'])) $this->referrer = $_SESSION['url']; - else $this->referrer = "/"; - - $this->url = $_SESSION['url'] = $_SERVER['PHP_SELF']; - $this->SurfControl(); - } + session_regenerate_id(true); // 🔒 Session fixation protection - public function Login($user) { - global $database, $generator, $logging; - - $this->logged_in = true; - $_SESSION['sessid'] = $generator->generateRandID(); - $_SESSION['username'] = $user; - $user_sanitized = $database->escape($user); - $_SESSION['checker'] = $generator->generateRandStr(3); - $_SESSION['mchecker'] = $generator->generateRandStr(5); + $this->logged_in = $this->checkLogin(); - $userFields = $database->getUserFields($user_sanitized, "quest, id", 1, true); - $_SESSION['qst'] = $userFields["quest"]; + if($this->logged_in && TRACK_USR) { + $database->updateActiveUser($this->username, $this->time); + } - $dbarray = $database->getUserFields($user_sanitized, 'id, village_select', 1); - $selected_village=(int) $dbarray['village_select']; + $this->referrer = isset($_SESSION['url']) ? $_SESSION['url'] : "/"; + $this->url = $_SESSION['url'] = $_SERVER['PHP_SELF']; - if ($dbarray['id'] > 1) { - if(!isset($_SESSION['wid'])) { - if(!empty($selected_village)) $data = $database->getVillage($selected_village); - else $data = $database->getVillage($userFields["id"]); - $_SESSION['wid'] = $data['wref']; - } else - if(empty($_SESSION['wid'])) { - if(!empty($selected_village)) $data = $database->getVillage($selected_village); - else $data = $database->getVillage($userFields["id"]); - $_SESSION['wid'] = $data['wref']; - } - $this->PopulateVar(); + $this->SurfControl(); + } + public function Login($user) { + global $database, $generator, $logging; - $database->updateActiveUser($user_sanitized, $this->time); - $database->updateUserField($user_sanitized, "sessid", $_SESSION['sessid'], 0); - } + if(empty($user)) { + header("Location: login.php"); + exit; + } - $logging->addLoginLog($dbarray['id'], $_SERVER['REMOTE_ADDR']); + $this->logged_in = true; - if ($dbarray['id'] == 1) { - header("Location: nachrichten.php"); - exit; - } else { - header("Location: dorf1.php"); - exit; - } - } + $_SESSION['sessid'] = $generator->generateRandID(); + $_SESSION['username'] = $user; + $_SESSION['checker'] = $generator->generateRandStr(3); + $_SESSION['mchecker'] = $generator->generateRandStr(5); - public function Logout() { - global $database; - $this->logged_in = false; - $database->updateUserField($_SESSION['username'], "sessid", "", 0); - if(ini_get("session.use_cookies")) { - $params = session_get_cookie_params(); - setcookie(session_name(), '', time() - 42000, $params["path"], $params["domain"], $params["secure"], $params["httponly"]); - } - session_destroy(); - session_start(); - } + // 🔒 Prepared statement (critical zone) + $stmt = $database->dblink->prepare( + "SELECT id, quest, village_select FROM " . TB_PREFIX . "users WHERE username = ? LIMIT 1" + ); + $stmt->bind_param("s", $user); + $stmt->execute(); + $result = $stmt->get_result(); + $dbarray = $result->fetch_assoc(); + $stmt->close(); - public function changeChecker() { - global $generator; - - $this->checker = $_SESSION['checker'] = $generator->generateRandStr(3); - $this->mchecker = $_SESSION['mchecker'] = $generator->generateRandStr(5); - } + if(!$dbarray) { + $this->Logout(); + header("Location: login.php"); + exit; + } - private function checkLogin(){ - global $database; - - $user = $id = ''; - $admin = false; - $inAdmin = (strpos($_SERVER['REQUEST_URI'], '/Admin') !== false); + $_SESSION['id_user'] = (int)$dbarray['id']; + $_SESSION['qst'] = $dbarray['quest']; - if (!$inAdmin && isset($_SESSION['username'])) { - $user = $_SESSION['username']; - $id = (int) $_SESSION['id_user']; - } else if ($inAdmin && isset($_SESSION['admin_username'])) { - $user = $_SESSION['admin_username']; - $id = (int) $_SESSION['id']; - $admin = true; - } + $selected_village = (int)$dbarray['village_select']; - if($user && ($admin || isset($_SESSION['sessid']))) { - $this->maintenance(); - $this->isWinner(); - - // check if this is not a support user, for who only messages and statistics are available - if ($user == 'Support') { - $req_file = basename($_SERVER['PHP_SELF']); - if (!in_array($req_file, ['nachrichten.php', 'logout.php', 'statistiken.php', 'rules.php', 'karte.php', 'karte2.php', 'spieler.php'])) { - header('Location: nachrichten.php'); - exit; - } - } + if(!isset($_SESSION['wid']) || empty($_SESSION['wid'])) { - //Get and Populate Data - $this->PopulateVar(); - - //Check if the player is banned - $this->isBanned(); - - //update database - $database->updateActiveUser($user, $this->time); - return true; - } - else return false; - } + if(!empty($selected_village)) { + $data = $database->getVillage($selected_village); + } else { + $data = $database->getVillage($dbarray['id']); + } - /** - * Called if the player is banned - * - */ - - function isBanned(){ - if($this->access == BANNED && !in_array(basename($_SERVER['PHP_SELF']), ['banned.php', 'nachrichten.php', 'rules.php'])){ - header('Location: banned.php'); - exit; - } - } - - /** - * Called when the server is under maintenance - * - */ - - function maintenance(){ - if($_SESSION['ok'] == 2 && basename($_SERVER['PHP_SELF']) != 'maintenance.php'){ - header('Location: maintenance.php'); - exit; - } - } - - /** - * Called when there's a player who built a WW to level 100 - * - */ - - function isWinner(){ - global $database; - - $requiredPage = basename($_SERVER['PHP_SELF']); - if($database->isThereAWinner() && (in_array($requiredPage, ['build.php', 'plus1.php']) || - (in_array($requiredPage, ['plus.php']) && isset($_GET['id']) && !empty($_GET['id'] && $_GET['id'] >= 7)))) - { - header('Location: winner.php'); - exit; - } - } - - /** - * Function to check Real Hero - * Made by: Shadow and brainiacX - * - */ + if(isset($data['wref'])) { + $_SESSION['wid'] = (int)$data['wref']; + } + } - function CheckHeroReal () { - global $database,$link; + $this->PopulateVar(); - $villageIDs = implode(', ', $this->villages); - if (!count($this->villages)) { - $this->Logout(); - header('login.php'); - exit; - } + $database->updateActiveUser($user, $this->time); + $database->updateUserField($user, "sessid", $_SESSION['sessid'], 0); - // check if hero unit for this player is present anywhere on the map - $q = ' - SELECT - IFNULL((SELECT SUM(hero) from '.TB_PREFIX.'enforcement where `from` IN('.$villageIDs.')), 0) + - IFNULL((SELECT SUM(hero) from '.TB_PREFIX.'units where `vref` IN('.$villageIDs.')), 0) + - IFNULL((SELECT SUM(t11) from '.TB_PREFIX.'prisoners where `from` IN('.$villageIDs.')), 0) + - IFNULL((SELECT SUM(t11) FROM '.TB_PREFIX.'movement, '.TB_PREFIX.'attacks WHERE '.TB_PREFIX.'movement.`from` IN('.$villageIDs.') and '.TB_PREFIX.'movement.ref = '.TB_PREFIX.'attacks.id and '.TB_PREFIX.'movement.proc = 0 and '.TB_PREFIX.'movement.sort_type = 3), 0) + - IFNULL((SELECT SUM(t11) FROM '.TB_PREFIX.'movement, '.TB_PREFIX.'attacks where '.TB_PREFIX.'movement.`to` IN('.$villageIDs.') and '.TB_PREFIX.'movement.ref = '.TB_PREFIX.'attacks.id and '.TB_PREFIX.'movement.proc = 0 and '.TB_PREFIX.'movement.sort_type = 4), 0) - as herocount'; - $heroUnitRegisters = mysqli_fetch_array( mysqli_query($database->dblink, $q, MYSQLI_ASSOC ))['herocount']; + $logging->addLoginLog($dbarray['id'], $_SERVER['REMOTE_ADDR']); - // check if the actual hero is alive or being trained/revived into a living state - $isHeroLivingOrRaising = $database->getHeroDeadReviveOrInTraining($this->uid); + if ($dbarray['id'] == 1) { + header("Location: nachrichten.php"); + } else { + header("Location: dorf1.php"); + } + exit; + } - // if he doesn't register anywhere on the map but is marked as alive, - // we need to kill him - if(!$heroUnitRegisters && $isHeroLivingOrRaising) { - $database->KillMyHero($this->uid); + public function Logout() { + global $database; + + $this->logged_in = false; + + if(isset($_SESSION['username'])) { + $database->updateUserField($_SESSION['username'], "sessid", "", 0); + } + + $_SESSION = array(); + + if (ini_get("session.use_cookies")) { + $params = session_get_cookie_params(); + setcookie(session_name(), '', time() - 42000, + $params["path"], + $params["domain"], + $params["secure"], + $params["httponly"] + ); + } + + session_destroy(); + session_start(); + } + + public function changeChecker() { + global $generator; + + $this->checker = $_SESSION['checker'] = $generator->generateRandStr(3); + $this->mchecker = $_SESSION['mchecker'] = $generator->generateRandStr(5); + } + private function checkLogin() { + global $database; + + $user = ''; + $id = 0; + $admin = false; + $inAdmin = (strpos($_SERVER['REQUEST_URI'], '/Admin') !== false); + + if (!$inAdmin && isset($_SESSION['username'])) { + $user = $_SESSION['username']; + $id = isset($_SESSION['id_user']) ? (int)$_SESSION['id_user'] : 0; + } + else if ($inAdmin && isset($_SESSION['admin_username'])) { + $user = $_SESSION['admin_username']; + $id = isset($_SESSION['id']) ? (int)$_SESSION['id'] : 0; + $admin = true; + } + + if ($user && ($admin || isset($_SESSION['sessid']))) { + + $this->maintenance(); + $this->isWinner(); + + // 🔒 Support restriction hardening + if ($user === 'Support') { + $req_file = basename($_SERVER['PHP_SELF']); + $allowed = array( + 'nachrichten.php', + 'logout.php', + 'statistiken.php', + 'rules.php', + 'karte.php', + 'karte2.php', + 'spieler.php' + ); + + if (!in_array($req_file, $allowed)) { + header('Location: nachrichten.php'); + exit; } } - private function PopulateVar() { - global $database; - - $this->userarray = $this->userinfo = $database->getUserArray($_SESSION['username'], 0); - $this->username = $this->userarray['username']; - $this->uid = $_SESSION['id_user'] = $this->userarray['id']; - $this->gpack = $this->userarray['gpack']; - $this->access = $this->userarray['access']; - $this->plus = ($this->userarray['plus'] > $this->time); - $this->goldclub = $this->userarray['goldclub']; - $this->villages = $database->getVillagesID($this->uid); - $this->tribe = $this->userarray['tribe']; - $this->isAdmin = $this->access >= MODERATOR; - $this->alliance = $_SESSION['alliance_user'] = $this->userarray['alliance']; - $this->checker = $_SESSION['checker']; - $this->mchecker = $_SESSION['mchecker']; - $this->sit = $database->GetOnline($this->uid); - $this->sit1 = $this->userarray['sit1']; - $this->sit2 = $this->userarray['sit2']; - $this->cp = floor($this->userarray['cp']); - $this->gold = $this->userarray['gold']; - $this->oldrank = $this->userarray['oldrank']; - $this->sharedForums = $database->getSharedForums($this->uid, $this->alliance); - $_SESSION['ok'] = $this->userarray['ok']; - - if($this->userarray['b1'] > $this->time) $this->bonus1 = 1; - if($this->userarray['b2'] > $this->time) $this->bonus2 = 1; - if($this->userarray['b3'] > $this->time) $this->bonus3 = 1; - if($this->userarray['b4'] > $this->time) $this->bonus4 = 1; + // Populate user data + $this->PopulateVar(); - if (!in_array($this->username, ['Support', 'Multihunter'])) $this->CheckHeroReal(); - } - - /** - * Creates an array with the vrefs of attacked/scouted/reinforced villages and oasis - * - */ - - public function populateAttacks(){ - global $database, $village; - - $troopsMovement = $database->getMovement(3, $village->wid, 0); - if(count($troopsMovement) > 0){ - foreach($troopsMovement as $movement) - { - switch($movement['attack_type']){ - case 1: - $_SESSION['troops_movement']['scouts'][] = $movement['to']; - break; - case 2: - $_SESSION['troops_movement']['enforcements'][] = $movement['to']; - break; - case 3: - case 4: - $_SESSION['troops_movement']['attacks'][] = $movement['to']; - break; - } - } - } - } - - private function SurfControl(){ - if(SERVER_WEB_ROOT) { - $page = $_SERVER['SCRIPT_NAME']; - } else { - $explode = explode("/", $_SERVER['SCRIPT_NAME']); - $i = count($explode) - 1; - $page = $explode[$i]; + // Ban check + $this->isBanned(); - } - $pagearray = array("index.php", "anleitung.php", "tutorial.php", "login.php", "activate.php", "anmelden.php", "xaccount.php"); - if(!$this->logged_in) { - if(!in_array($page, $pagearray) || $page == "logout.php") { - header("Location: login.php"); - exit; - } - } else { - if(in_array($page, $pagearray)) { - if ($this->uid == 1) { - header("Location: nachrichten.php"); - exit; - } else { - header("Location: dorf1.php"); - exit; - } - } + $database->updateActiveUser($user, $this->time); - } - } -}; -$session = new Session; -$form = new Form; + return true; + } -// if there is no user, we'd try to load messages for user with ID 0, which is wrong -if (!empty($_SESSION['id_user'])) { - $message = new Message; + return false; + } - // create a global user variable which will later be removed from here - // and created + retrieved either via Service Locator or other DI concept - $user = new User((int) $_SESSION['id_user'], $database); + /** + * Ban control + */ + function isBanned() { + $current = basename($_SERVER['PHP_SELF']); + + if ($this->access == BANNED && + !in_array($current, array('banned.php','nachrichten.php','rules.php'))) { + + header('Location: banned.php'); + exit; + } + } + + /** + * Maintenance control + */ + function maintenance() { + $current = basename($_SERVER['PHP_SELF']); + + if (isset($_SESSION['ok']) && + $_SESSION['ok'] == 2 && + $current != 'maintenance.php') { + + header('Location: maintenance.php'); + exit; + } + } + + /** + * Winner check (WW level 100) + */ + function isWinner() { + global $database; + + $requiredPage = basename($_SERVER['PHP_SELF']); + + if ($database->isThereAWinner()) { + + $restricted = array('build.php', 'plus1.php'); + + if (in_array($requiredPage, $restricted) || + ($requiredPage == 'plus.php' && + isset($_GET['id']) && + is_numeric($_GET['id']) && + (int)$_GET['id'] >= 7)) { + + header('Location: winner.php'); + exit; + } + } + } + /** + * Hero integrity verification + * (Enterprise hardened – logic 1:1) + */ + function CheckHeroReal() { + global $database; + + if (!is_array($this->villages) || !count($this->villages)) { + $this->Logout(); + header('Location: login.php'); + exit; + } + + // 🔒 sanitize village IDs (critical SQL protection) + $safeVillageIDs = array(); + foreach ($this->villages as $v) { + $safeVillageIDs[] = (int)$v; + } + + $villageIDs = implode(',', $safeVillageIDs); + + $q = " + SELECT + IFNULL((SELECT SUM(hero) FROM ".TB_PREFIX."enforcement WHERE `from` IN($villageIDs)),0) + + IFNULL((SELECT SUM(hero) FROM ".TB_PREFIX."units WHERE `vref` IN($villageIDs)),0) + + IFNULL((SELECT SUM(t11) FROM ".TB_PREFIX."prisoners WHERE `from` IN($villageIDs)),0) + + IFNULL((SELECT SUM(t11) FROM ".TB_PREFIX."movement m + JOIN ".TB_PREFIX."attacks a ON m.ref = a.id + WHERE m.`from` IN($villageIDs) + AND m.proc = 0 AND m.sort_type = 3),0) + + IFNULL((SELECT SUM(t11) FROM ".TB_PREFIX."movement m + JOIN ".TB_PREFIX."attacks a ON m.ref = a.id + WHERE m.`to` IN($villageIDs) + AND m.proc = 0 AND m.sort_type = 4),0) + AS herocount + "; + + $res = mysqli_query($database->dblink, $q); + $row = mysqli_fetch_assoc($res); + $heroUnitRegisters = isset($row['herocount']) ? (int)$row['herocount'] : 0; + + $isHeroLivingOrRaising = $database->getHeroDeadReviveOrInTraining($this->uid); + + if (!$heroUnitRegisters && $isHeroLivingOrRaising) { + $database->KillMyHero($this->uid); + } + } + + /** + * Populate session variables (NO LOGIC CHANGE) + */ + private function PopulateVar() { + global $database; + + $this->userarray = $this->userinfo = + $database->getUserArray($_SESSION['username'], 0); + + if (!is_array($this->userarray)) { + $this->Logout(); + header('Location: login.php'); + exit; + } + + $this->username = $this->userarray['username']; + $this->uid = $_SESSION['id_user'] = (int)$this->userarray['id']; + $this->gpack = $this->userarray['gpack']; + $this->access = (int)$this->userarray['access']; + $this->plus = ($this->userarray['plus'] > $this->time); + $this->goldclub = (int)$this->userarray['goldclub']; + $this->tribe = (int)$this->userarray['tribe']; + $this->isAdmin = ($this->access >= MODERATOR); + $this->alliance = $_SESSION['alliance_user'] = (int)$this->userarray['alliance']; + + $this->checker = $_SESSION['checker']; + $this->mchecker = $_SESSION['mchecker']; + + $this->villages = $database->getVillagesID($this->uid); + $this->sit = $database->GetOnline($this->uid); + $this->sit1 = (int)$this->userarray['sit1']; + $this->sit2 = (int)$this->userarray['sit2']; + $this->cp = floor($this->userarray['cp']); + $this->gold = (int)$this->userarray['gold']; + $this->oldrank = (int)$this->userarray['oldrank']; + $this->sharedForums = $database->getSharedForums($this->uid, $this->alliance); + + $_SESSION['ok'] = $this->userarray['ok']; + + // bonuses + if ($this->userarray['b1'] > $this->time) $this->bonus1 = 1; + if ($this->userarray['b2'] > $this->time) $this->bonus2 = 1; + if ($this->userarray['b3'] > $this->time) $this->bonus3 = 1; + if ($this->userarray['b4'] > $this->time) $this->bonus4 = 1; + + if (!in_array($this->username, array('Support','Multihunter'))) { + $this->CheckHeroReal(); + } + } + + /** + * Populate attack indicators + */ + public function populateAttacks() { + global $database, $village; + + $_SESSION['troops_movement'] = array( + 'scouts' => array(), + 'enforcements' => array(), + 'attacks' => array() + ); + + $troopsMovement = $database->getMovement(3, $village->wid, 0); + + if (is_array($troopsMovement) && count($troopsMovement) > 0) { + + foreach ($troopsMovement as $movement) { + + switch ((int)$movement['attack_type']) { + + case 1: + $_SESSION['troops_movement']['scouts'][] = $movement['to']; + break; + + case 2: + $_SESSION['troops_movement']['enforcements'][] = $movement['to']; + break; + + case 3: + case 4: + $_SESSION['troops_movement']['attacks'][] = $movement['to']; + break; + } + } + } + } + /** + * Page access control + * Enterprise hardened – logic 1:1 + */ + private function SurfControl() { + + if (SERVER_WEB_ROOT) { + $page = basename($_SERVER['SCRIPT_NAME']); + } else { + $explode = explode("/", $_SERVER['SCRIPT_NAME']); + $page = end($explode); + } + + $allowedWithoutLogin = array( + "index.php", + "anleitung.php", + "tutorial.php", + "login.php", + "activate.php", + "anmelden.php", + "xaccount.php" + ); + + if (!$this->logged_in) { + + if (!in_array($page, $allowedWithoutLogin) || $page == "logout.php") { + header("Location: login.php"); + exit; + } + + } else { + + if (in_array($page, $allowedWithoutLogin)) { + + if ($this->uid == 1) { + header("Location: nachrichten.php"); + } else { + header("Location: dorf1.php"); + } + exit; + } + } + } + +} // END CLASS + +$session = new Session(); +$form = new Form(); + +/** + * Message + User init + * Enterprise safe instantiation + */ + +if (!empty($_SESSION['id_user']) && is_numeric($_SESSION['id_user'])) { + + $message = new Message(); + + // Safe casting + $user = new User((int)$_SESSION['id_user'], $database); } -?> diff --git a/GameEngine/Units.php b/GameEngine/Units.php index b80ccaac..33ff82a5 100755 --- a/GameEngine/Units.php +++ b/GameEngine/Units.php @@ -88,13 +88,6 @@ class Units { else return $post; } - /** - * Gets an error if the user did a mistake - * - * @param array $post The array containing all of the needed informations - * @return string Returns the errors, or empty if no errors was found - */ - public function checkErrors(&$post){ global $database, $village, $session, $generator; @@ -234,584 +227,1006 @@ class Units { $database->deleteReinf($enforce['id']); } - private function sendTroops($post) { - global $form, $database, $village, $session; + private function sendTroops($post){ + global $form, $database, $village, $session; - $data = $database->getA2b($post['timestamp_checksum']); - $Gtribe = ($session->tribe == 1) ? "" : $session->tribe - 1; + /* + ========================================================= + = 1 LOAD ATTACK DATA + ========================================================= + */ + + $data = $database->getA2b($post['timestamp_checksum']); + $Gtribe = ($session->tribe == 1) ? "" : $session->tribe - 1; + + + /* + ========================================================= + = 2 BASIC UNIT VALIDATION + ========================================================= + */ + + for ($i = 1; $i < 10; $i++) { + + if (!isset($data['u' . $i])) { + continue; + } + + if ($data['u' . $i] > $village->unitarray['u' . $Gtribe . $i]) { + $form->addError("error", "You can't send more units than you have"); + break; + } + + if ($data['u' . $i] < 0) { + $form->addError("error", "You can't send negative units."); + break; + } + } + + + /* + ========================================================= + = 3️ RATE LIMIT PROTECTION + ========================================================= + */ + + if (!$database->checkAttackRateLimit($session->uid, 30)) { + + $form->addError("error", "Too many attacks. Please wait."); + + $_SESSION['errorarray'] = $form->getErrors(); + header("Location: a2b.php"); + exit; + } + + + /* + ========================================================= + = 4️ HERO VALIDATION + ========================================================= + */ + + if ($data['u11'] > $village->unitarray['hero']) { + $form->addError("error", "You can't send more units than you have"); + } + + if ($data['u11'] < 0) { + $form->addError("error", "You can't send negative units."); + } + + if ($data['type'] != 1 && $post['spy'] != 0) { + $post['spy'] = 0; + } + + + /* + ========================================================= + = 5️ ERROR CHECKPOINT + ========================================================= + */ + + if ($form->returnErrors() > 0) { + + $_SESSION['errorarray'] = $form->getErrors(); + $_SESSION['valuearray'] = $_POST; + + header("Location: a2b.php"); + exit; + } + + + /* + ========================================================= + = 6️ REMOVE UNITS FROM VILLAGE + ========================================================= + */ + + $u = ($session->tribe == 1) ? "" : $session->tribe - 1; + + $database->modifyUnit( + $village->wid, + [ + $u."1", $u."2", $u."3", $u."4", $u."5", + $u."6", $u."7", $u."8", $u."9", + $u.$session->tribe."0", + "hero" + ], + [ + $data['u1'], $data['u2'], $data['u3'], + $data['u4'], $data['u5'], $data['u6'], + $data['u7'], $data['u8'], $data['u9'], + $data['u10'], $data['u11'] + ], + array_fill(0, 11, 0) + ); + + + /* + ========================================================= + = 7️ CALCULATE MOVEMENT TIME + ========================================================= + */ + + $troopsTime = $this->getWalkingTroopsTime( + $village->wid, + $data['to_vid'], + $session->uid, + $session->tribe, + $data, + 1, + 'u' + ); + + $time = $database->getArtifactsValueInfluence( + $session->uid, + $village->wid, + 2, + $troopsTime + ); + + + /* + ========================================================= + = 8️ CATAPULT TARGET VALIDATION + ========================================================= + */ + + $to_owner = $database->getVillageField($data['to_vid'], "owner"); + $rivalsGreatConfusion = $database->getArtifactsSumByKind($to_owner, $data['to_vid'], 7); + + $rallyPointLevel = ($village->resarray)['f39']; + $invalidBuildings = []; + + if ($rallyPointLevel >= 3 && $rallyPointLevel < 5) { + + for ($i = 1; $i <= 37; $i++) { + if (!in_array($i, [10, 11])) { + $invalidBuildings[] = $i; + } + } + + } elseif ($rallyPointLevel >= 5 && $rallyPointLevel < 10) { + + for ($i = 12; $i <= 37; $i++) { + $invalidBuildings[] = $i; + } + + } elseif ($rallyPointLevel >= 10) { + + $invalidBuildings = [23, 31, 32, 33, 34, 36]; + } + + + /* + ========================================================= + = 9️ CTAR1 VALIDATION + ========================================================= + */ + + if (isset($post['ctar1']) && $post['ctar1'] != 0) { + + if ( + $rallyPointLevel < 3 || + $data['u8'] == 0 || + in_array($post['ctar1'], $invalidBuildings) || + $post['ctar1'] < 0 || + $post['ctar1'] > 40 + ) { + $post['ctar1'] = 0; + } + } + + + /* + ========================================================= + = 10 CREATE ATTACK + MOVEMENT + ========================================================= + */ + + $abdata = $database->getABTech($village->wid); + + $reference = $database->addAttack( + $village->wid, + $data['u1'], $data['u2'], $data['u3'], $data['u4'], $data['u5'], + $data['u6'], $data['u7'], $data['u8'], $data['u9'], $data['u10'], $data['u11'], + $data['type'], + $post['ctar1'] ?? 0, + $post['ctar2'] ?? 0, + $post['spy'] ?? 0, + $abdata['b1'], $abdata['b2'], $abdata['b3'], $abdata['b4'], + $abdata['b5'], $abdata['b6'], $abdata['b7'], $abdata['b8'] + ); + + $checkexist = $database->checkVilExist($data['to_vid']); + $checkoexist = $database->checkOasisExist($data['to_vid']); + + if ($checkexist || $checkoexist) { + + $database->addMovement( + 3, + $village->wid, + $data['to_vid'], + $reference, + time(), + ($time + time()) + ); + + if ($database->hasBeginnerProtection($village->wid) == 1 && $checkexist) { + + mysqli_query( + $database->dblink, + "UPDATE " . TB_PREFIX . "users + SET protect = 0 + WHERE id = " . (int)$session->uid + ); + } + } + + + /* + ========================================================= + = 11️ FINAL CHECK + CLEANUP + ========================================================= + */ + + if ($form->returnErrors() > 0) { + + $_SESSION['errorarray'] = $form->getErrors(); + $_SESSION['valuearray'] = $_POST; + + header("Location: a2b.php"); + exit; + } + + $database->remA2b($data['id']); + + header("Location: build.php?id=39"); + exit; +} + + +/* +========================================================= += SEND TROOPS BACK +========================================================= +*/ + +private function sendTroopsBack($post) +{ + global $form, $database, $village, $session, $technology; + + /* + ----------------------------------------------------- + LOAD ENFORCEMENT DATA + ----------------------------------------------------- + */ + + $enforce = $database->getEnforceArray($post['ckey'], 0); + $enforceoasis = $database->getOasisEnforceArray($post['ckey'], 0); + + /* + ----------------------------------------------------- + PERMISSION CHECK + ----------------------------------------------------- + */ + + if ( + ($enforce['from'] == $village->wid) || + ($enforce['vref'] == $village->wid) || + ($enforceoasis['conqured'] == $village->wid) + ) { + + $to = $database->getVillage($enforce['from']); + + $Gtribe = ( + ($ownerTribe = $database->getUserField($to['owner'], 'tribe', 0)) == 1 + ) ? "" : $ownerTribe - 1; + + + /* + ----------------------------------------------------- + UNIT VALIDATION + ----------------------------------------------------- + */ for ($i = 1; $i < 10; $i++) { - if (isset($data['u'.$i])) { - if ($data['u'.$i] > $village->unitarray['u'.$Gtribe.$i]) { - $form->addError("error", "You can't send more units than you have"); + + if (isset($post['t'.$i])) { + + if ($post['t'.$i] > $enforce['u'.$Gtribe.$i]) { + $form->addError("error", "You can't send back more units than you have"); break; } - if ($data['u'.$i] < 0) { - $form->addError("error", "You can't send negative units."); + if ($post['t'.$i] < 0) { + $form->addError("error", "You can't send back negative units."); break; } + + } else { + $post['t'.$i] = '0'; } } - if($data['u11'] > $village->unitarray['hero']) $form->addError("error", "You can't send more units than you have"); - if($data['u11'] < 0) $form->addError("error", "You can't send negative units."); - if($data['type'] != 1 && $post['spy'] != 0) $post['spy'] = 0; - - if($form->returnErrors() > 0){ + /* + ----------------------------------------------------- + HERO VALIDATION + ----------------------------------------------------- + */ + + if (isset($post['t11'])) { + + if ($post['t11'] > $enforce['hero']) { + $form->addError("error", "You can't send back more units than you have"); + } + + if ($post['t11'] < 0) { + $form->addError("error", "You can't send back negative units."); + } + + } else { + $post['t11'] = '0'; + } + + + /* + ----------------------------------------------------- + ERROR HANDLING + ----------------------------------------------------- + */ + + if ($form->returnErrors() > 0) { + $_SESSION['errorarray'] = $form->getErrors(); $_SESSION['valuearray'] = $_POST; - header( "Location: a2b.php" ); - exit; - }else{ - $u = ($session->tribe == 1) ? "" : $session->tribe - 1; - - $database->modifyUnit( - $village->wid, - [ - $u . "1", - $u . "2", - $u . "3", - $u . "4", - $u . "5", - $u . "6", - $u . "7", - $u . "8", - $u . "9", - $u . $session->tribe . "0", - "hero" - ], - [ - $data['u1'], - $data['u2'], - $data['u3'], - $data['u4'], - $data['u5'], - $data['u6'], - $data['u7'], - $data['u8'], - $data['u9'], - $data['u10'], - $data['u11'] - ], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] - ); - - $troopsTime = $this->getWalkingTroopsTime($village->wid, $data['to_vid'], $session->uid, $session->tribe, $data, 1, 'u'); - $time = $database->getArtifactsValueInfluence($session->uid, $village->wid, 2, $troopsTime); - - // Check if have WW owner have artefact Rivals great confusion or Artefact of the unique fool with that effect - // If is a WW village you can target on WW , if is not a WW village catapults will target randomly. - // Like it says : Exceptions are the WW which can always be targeted and the treasure chamber which can always be targeted, except with the unique artifact. - // Fixed by Advocaite and Shadow - Optimized by iopietro - - $to_owner = $database->getVillageField($data['to_vid'], "owner"); - $rivalsGreatConfusion = $database->getArtifactsSumByKind($to_owner, $data['to_vid'], 7); - - $rallyPointLevel = ($village->resarray)['f39']; - $invalidBuildings = []; - - // fill the array with the invalid buildings - if($rallyPointLevel >= 3 && $rallyPointLevel < 5){ - for($i = 1; $i <= 37; $i++){ - if(!in_array($i, [10, 11])) $invalidBuildings[] = $i; - } - } - else if($rallyPointLevel >= 5 && $rallyPointLevel < 10){ - for($i = 12; $i <= 37; $i++) $invalidBuildings[] = $i; - } - else if($rallyPointLevel >= 10){ - $invalidBuildings = [23, 31, 32, 33, 34, 36]; - } - - if(isset($post['ctar1']) && $post['ctar1'] != 0){ - // check if the player has selected a valid building - if($rallyPointLevel < 3 || $data['u8'] == 0 || in_array($post['ctar1'], $invalidBuildings) || $post['ctar1'] < 0 || $post['ctar1'] > 40){ - $post['ctar1'] = 0; - } - } - - if(isset($post['ctar2']) && $post['ctar2'] != 0){ - // check if there are atleast 20 catapults - if($data['u8'] < 20 || $rallyPointLevel != 20){ - $post['ctar2'] = 0; - }else{ - // check if the player has selected a valid building - if(in_array($post['ctar2'], $invalidBuildings) || ($post['ctar2'] < 0 || $post['ctar2'] > 40 && $post['ctar2'] != 99)){ - $post['ctar2'] = 99; - } - } - } - - if(isset($post['ctar1'])) { - //Is the Brewery built? - if($session->tribe != 2 || $database->getFieldLevelInVillage($village->wid, 35) == 0){ - if($rivalsGreatConfusion['totals'] > 0) { - if($post['ctar1'] != 40 && ($post['ctar1'] != 27 || ($post['ctar1'] == 27 && $rivalsGreatConfusion['unique'] > 0))) { - $post['ctar1'] = 0; - } - } - } - else $post['ctar1'] = 0; - } - else $post['ctar1'] = 0; - - if(isset($post['ctar2']) && $post['ctar2'] > 0) { - //Is the Brewery built? - if($session->tribe != 2 || $database->getFieldLevelInVillage($village->wid, 35) == 0){ - if($rivalsGreatConfusion['totals'] > 0) { - if ($post['ctar2'] != 40 && ($post['ctar2'] != 27 || ($post['ctar2'] == 27 && $rivalsGreatConfusion['unique'] > 0))) { - $post['ctar2'] = 99; - } - } - } - else $post['ctar2'] = 99; - } - else $post['ctar2'] = 0; - - if(!isset($post['spy'])) $post['spy'] = 0; - - $abdata = $database->getABTech($village->wid); - $reference = $database->addAttack(($village->wid), $data['u1'], $data['u2'], $data['u3'], $data['u4'], $data['u5'], $data['u6'], $data['u7'], $data['u8'], $data['u9'], $data['u10'], $data['u11'], $data['type'], $post['ctar1'], $post['ctar2'], $post['spy'], $abdata['b1'], $abdata['b2'], $abdata['b3'], $abdata['b4'], $abdata['b5'], $abdata['b6'], $abdata['b7'], $abdata['b8']); - $checkexist = $database->checkVilExist($data['to_vid']); - $checkoexist = $database->checkOasisExist($data['to_vid']); - if($checkexist || $checkoexist) { - $database->addMovement(3, $village->wid, $data['to_vid'], $reference, time(), ($time + time())); - if ($database->hasBeginnerProtection($village->wid) == 1 && $checkexist) { - mysqli_query($database->dblink, "UPDATE " . TB_PREFIX . "users SET protect = 0 WHERE id = ".(int) $session->uid); - } - } - - if($form->returnErrors() > 0) { - $_SESSION['errorarray'] = $form->getErrors(); - $_SESSION['valuearray'] = $_POST; - header("Location: a2b.php" ); - exit; - } - - // prevent re-use of the same attack via re-POSTing the same data - $database->remA2b($data['id']); - - header("Location: build.php?id=39"); + + header("Location: a2b.php"); exit; } - } - private function sendTroopsBack($post) { - global $form, $database, $village, $session, $technology; - $enforce = $database->getEnforceArray( $post['ckey'], 0 ); - $enforceoasis = $database->getOasisEnforceArray( $post['ckey'], 0 ); - if ( ( $enforce['from'] == $village->wid ) || ( $enforce['vref'] == $village->wid ) || ( $enforceoasis['conqured'] == $village->wid ) ) { - $to = $database->getVillage( $enforce['from'] ); - $Gtribe = ($ownerTribe = $database->getUserField( $to['owner'], 'tribe', 0)) == 1 ? "" : $ownerTribe - 1; - - for ( $i = 1; $i < 10; $i ++ ) { - if ( isset( $post[ 't' . $i ] ) ) { - if ( $i != 10 ) { - if ( $post[ 't' . $i ] > $enforce[ 'u' . $Gtribe . $i ] ) { - $form->addError( "error", "You can't send back more units than you have" ); - break; - } - - if ( $post[ 't' . $i ] < 0 ) { - $form->addError( "error", "You can't send back negative units." ); - break; - } - } - } else { - $post[ 't' . $i . '' ] = '0'; - } - } - if ( isset( $post['t11'] ) ) { - if ( $post['t11'] > $enforce['hero'] ) { - $form->addError( "error", "You can't send back more units than you have" ); - } - - if ( $post['t11'] < 0 ) { - $form->addError( "error", "You can't send back negative units." ); - } - } else { - $post['t11'] = '0'; - } - - if ( $form->returnErrors() > 0 ) { - $_SESSION['errorarray'] = $form->getErrors(); - $_SESSION['valuearray'] = $_POST; - header( "Location: a2b.php" ); - exit; - } else { - - //change units - $tribe = $database->getUserField($to['owner'], 'tribe', 0); - $start = ($tribe - 1 ) * 10 + 1; - $end = $tribe * 10 ; - - $units = []; - $amounts = []; - $modes = []; - - $j = 1; - for ( $i = $start; $i <= $end; $i ++ ) { - $units[] = $i; - $amounts[] = $post[ 't' . $j . '' ]; - $modes[] = 0; - $j ++; - } - - $units[] = 'hero'; - $amounts[] = $post['t11']; - $modes[] = 0; - - $database->modifyEnforce($post['ckey'], $units, $amounts, $modes); - $j++; - - $troopsTime = $this->getWalkingTroopsTime($enforce['from'], $enforce['vref'], $to['owner'], $tribe, $post, 1, 't'); - $time = $database->getArtifactsValueInfluence($session->uid, $village->wid, 2, $troopsTime); - - $reference = $database->addAttack($enforce['from'], $post['t1'], $post['t2'], $post['t3'], $post['t4'], $post['t5'], $post['t6'], $post['t7'], $post['t8'], $post['t9'], $post['t10'], $post['t11'], 2, 0, 0, 0, 0); - $database->addMovement(4, $village->wid, $enforce['from'], $reference, time(), ($time + time())); - $technology->checkReinf($post['ckey'], false); - - header("Location: build.php?id=39&refresh=1"); - exit(); - } - }else{ - $form->addError("error", "You cant change someones troops."); - if($form->returnErrors() > 0){ - $_SESSION['errorarray'] = $form->getErrors(); - $_SESSION['valuearray'] = $_POST; - header("Location: a2b.php"); - exit(); - } + /* + ----------------------------------------------------- + APPLY UNIT CHANGES + ----------------------------------------------------- + */ + + $tribe = $database->getUserField($to['owner'], 'tribe', 0); + + $start = ($tribe - 1) * 10 + 1; + $end = $tribe * 10; + + $units = []; + $amounts = []; + $modes = []; + + $j = 1; + + for ($i = $start; $i <= $end; $i++) { + $units[] = $i; + $amounts[] = $post['t'.$j]; + $modes[] = 0; + $j++; } + + $units[] = 'hero'; + $amounts[] = $post['t11']; + $modes[] = 0; + + $database->modifyEnforce($post['ckey'], $units, $amounts, $modes); + + + /* + ----------------------------------------------------- + CREATE RETURN MOVEMENT + ----------------------------------------------------- + */ + + $troopsTime = $this->getWalkingTroopsTime( + $enforce['from'], + $enforce['vref'], + $to['owner'], + $tribe, + $post, + 1, + 't' + ); + + $time = $database->getArtifactsValueInfluence( + $session->uid, + $village->wid, + 2, + $troopsTime + ); + + $reference = $database->addAttack( + $enforce['from'], + $post['t1'], $post['t2'], $post['t3'], + $post['t4'], $post['t5'], $post['t6'], + $post['t7'], $post['t8'], $post['t9'], + $post['t10'], $post['t11'], + 2, 0, 0, 0, 0 + ); + + $database->addMovement( + 4, + $village->wid, + $enforce['from'], + $reference, + time(), + ($time + time()) + ); + + $technology->checkReinf($post['ckey'], false); + + header("Location: build.php?id=39&refresh=1"); + exit; + + } else { + + $form->addError("error", "You cant change someones troops."); + + $_SESSION['errorarray'] = $form->getErrors(); + $_SESSION['valuearray'] = $_POST; + + header("Location: a2b.php"); + exit; } +} + - public function Settlers($post) { - global $form, $database, $village, $session; +/* +========================================================= += SETTLERS - FOUND NEW VILLAGE +========================================================= +*/ - $mode = CP; - $total = count($database->getProfileVillages($session->uid)); - $need_cps = ${'cp'.$mode}[$total + 1]; - $cps = $session->cp; - $rallypoint = $database->getResourceLevel($village->wid); - - //-- Prevent user from founding a new village if there are not enough settlers or the player put an invalid village ID or an already occupied one - //-- fix by AL-Kateb - Semplified and additions by iopietro - if ($rallypoint['f39'] > 0 && $village->unitarray['u'.$session->tribe.'0'] >= 3 && isset($post['s']) && ($newvillage = $database->getMInfo($post['s']))['id'] > 0 && $newvillage['occupied'] == 0 && $newvillage['oasistype'] == 0) { - if ($cps >= $need_cps) { - $troopsTime = $this->getWalkingTroopsTime($village->wid, $newvillage['id'], 0, 0, [300], 0); - $time = $database->getArtifactsValueInfluence($session->uid, $village->wid, 2, $troopsTime); - - $unit = ($session->tribe * 10); - $database->modifyResource($village->wid, 750, 750, 750, 750, 0); - $database->modifyUnit($village->wid, [$unit], [3], [0]); - $database->addMovement(5, $village->wid, $post['s'], 0, time(), time() + $time); - } - header("Location: build.php?id=39"); - exit; - } else { - header("Location: dorf1.php"); - exit; +public function Settlers($post) +{ + global $form, $database, $village, $session; + + $mode = CP; + $total = count($database->getProfileVillages($session->uid)); + $need_cps = ${'cp'.$mode}[$total + 1]; + $cps = $session->cp; + + $rallypoint = $database->getResourceLevel($village->wid); + + + /* + ----------------------------------------------------- + VALIDATION CONDITIONS + ----------------------------------------------------- + */ + + $validVillage = + isset($post['s']) && + ($newvillage = $database->getMInfo($post['s']))['id'] > 0 && + $newvillage['occupied'] == 0 && + $newvillage['oasistype'] == 0; + + $hasSettlers = + $village->unitarray['u'.$session->tribe.'0'] >= 3; + + $hasRally = + $rallypoint['f39'] > 0; + + + /* + ----------------------------------------------------- + EXECUTION + ----------------------------------------------------- + */ + + if ($hasRally && $hasSettlers && $validVillage) { + + if ($cps >= $need_cps) { + + $troopsTime = $this->getWalkingTroopsTime( + $village->wid, + $newvillage['id'], + 0, + 0, + [300], + 0 + ); + + $time = $database->getArtifactsValueInfluence( + $session->uid, + $village->wid, + 2, + $troopsTime + ); + + $unit = ($session->tribe * 10); + + $database->modifyResource($village->wid, 750, 750, 750, 750, 0); + $database->modifyUnit($village->wid, [$unit], [3], [0]); + + $database->addMovement( + 5, + $village->wid, + $post['s'], + 0, + time(), + time() + $time + ); } + + header("Location: build.php?id=39"); + exit; + + } else { + + header("Location: dorf1.php"); + exit; + } +} + + +/* +========================================================= += HERO DATA LOADER +========================================================= +*/ + +public function Hero($uid, $all = 0, $include_dead = false) +{ + global $database; + + $heroarray = $database->getHero($uid, $all, $include_dead); + + if (!count($heroarray)) { + return false; } - public function Hero($uid, $all = 0, $include_dead = false) { - global $database; - $heroarray = $database->getHero($uid, $all, $include_dead); + /* + ----------------------------------------------------- + SINGLE HERO MODE + ----------------------------------------------------- + */ + + if (!$all) { + $herodata = false; $singleHeroArrayID = 0; - // no hero data found - if (!count($heroarray)) { - return false; + foreach ($heroarray as $id => $hero) { + + if (!$herodata && $hero['dead'] != 1) { + $herodata = $GLOBALS["h".$hero['unit']]; + $singleHeroArrayID = $id; + break; + } } - // check all heroes and load hero data for the one, - // whose data were updated more recently - if we're not getting all of them - if (!$all) { - foreach ($heroarray as $id => $hero) { - // try to load a hero who's alive first - if (!$herodata && $hero['dead'] != 1) { - // this global value comes from GameEngine/Data/unitdata.php - $herodata = $GLOBALS["h".$hero['unit']]; - $singleHeroArrayID = $id; + if (!$herodata) { + $herodata = $GLOBALS["h".$heroarray[0]['unit']]; + } + + $hero = $heroarray[$singleHeroArrayID]; + + $h_atk = $herodata['atk'] + 5 * floor($hero['attack'] * $herodata['atkp'] / 5); + $h_di = $herodata['di'] + 5 * floor($hero['defence'] * $herodata['dip'] / 5); + $h_dc = $herodata['dc'] + 5 * floor($hero['defence'] * $herodata['dcp'] / 5); + + return [ + 'heroid' => $hero['heroid'], + 'unit' => $hero['unit'], + 'name' => $hero['name'], + 'level' => $hero['level'], + 'atk' => $h_atk, + 'di' => $h_di, + 'dc' => $h_dc, + 'health' => $hero['health'], + 'dead' => $hero['dead'], + 'experience' => $hero['experience'] + ]; + } + + /* + ----------------------------------------------------- + MULTI HERO MODE + ----------------------------------------------------- + */ + + $heroes = []; + + foreach ($heroarray as $id => $hero) { + + $herodata = $GLOBALS["h".$hero['unit']]; + + $h_atk = $herodata['atk'] + 5 * floor($hero['attack'] * $herodata['atkp'] / 5); + $h_di = $herodata['di'] + 5 * floor($hero['defence'] * $herodata['dip'] / 5); + $h_dc = $herodata['dc'] + 5 * floor($hero['defence'] * $herodata['dcp'] / 5); + + $heroes[] = [ + 'heroid' => $hero['heroid'], + 'unit' => $hero['unit'], + 'level' => $hero['level'], + 'atk' => $h_atk, + 'di' => $h_di, + 'dc' => $h_dc + ]; + } + + return $heroes; +} + +/* +========================================================= += DELETE / RELEASE PRISONERS +========================================================= +*/ + +public function deletePrisoners($id) +{ + global $village, $database, $session, $building, $bid19, $u99; + + $prisoner = $database->getPrisonersByID($id); + $troops = 0; + + /* + ----------------------------------------------------- + CASE 1: PRISONER IN CURRENT VILLAGE + ----------------------------------------------------- + */ + + if ($prisoner['wref'] == $village->wid) { + + $p_owner = $database->getVillageField($prisoner['from'], "owner"); + $p_tribe = $database->getUserField($p_owner, "tribe", 0); + + $troopsTime = $this->getWalkingTroopsTime( + $prisoner['from'], + $prisoner['wref'], + $p_owner, + $p_tribe, + $prisoner, + 1, + 't' + ); + + $p_time = $database->getArtifactsValueInfluence( + $p_owner, + $prisoner['from'], + 2, + $troopsTime + ); + + $p_reference = $database->addAttack( + $prisoner['from'], + $prisoner['t1'], $prisoner['t2'], $prisoner['t3'], + $prisoner['t4'], $prisoner['t5'], $prisoner['t6'], + $prisoner['t7'], $prisoner['t8'], $prisoner['t9'], + $prisoner['t10'], $prisoner['t11'], + 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + ); + + $database->addMovement( + 4, + $prisoner['wref'], + $prisoner['from'], + $p_reference, + time(), + ($p_time + time()) + ); + + for ($i = 1; $i <= 11; $i++) { + $troops += $prisoner['t'.$i]; + } + + /* + RESET TRAPS + */ + + $database->modifyUnit($village->wid, ["99", "99o"], [$troops, $troops], [0, 0]); + + $repairDuration = $database->getArtifactsValueInfluence( + $session->uid, + $village->wid, + 5, + round( + ($bid19[max($building->getTypeLevel(36, $village->wid), 1)]['attri'] / 100) + * $u99['time'] / SPEED + ) + ); + + $database->trainUnit($village->wid, 99, $troops, $u99['pop'], $repairDuration, 0); + + $database->deletePrisoners($prisoner['id']); + } + + /* + ----------------------------------------------------- + CASE 2: PRISONER CAPTURED FROM CURRENT VILLAGE + ----------------------------------------------------- + */ + + elseif ($prisoner['from'] == $village->wid) { + + $prisonersToOwner = $database->getVillageField($prisoner['wref'], "owner"); + + for ($i = 1; $i <= 11; $i++) { + $troops += $prisoner['t'.$i]; + } + + /* + HERO DEATH + */ + + if ($prisoner['t11'] > 0) { + + $p_owner = $database->getVillageField($prisoner['from'], "owner"); + + mysqli_query( + $database->dblink, + "UPDATE ".TB_PREFIX."hero + SET `dead` = '1', `health` = '0' + WHERE `uid` = '".$p_owner."' + AND dead = 0" + ); + } + + /* + RESET TRAPS + */ + + $database->modifyUnit($prisoner['wref'], ["99", "99o"], [$troops, $troops], [0, 0]); + + if (($troops = round($troops / 3)) > 0) { + + $repairDuration = $database->getArtifactsValueInfluence( + $prisonersToOwner, + $prisoner['wref'], + 5, + round( + ($bid19[max($building->getTypeLevel(36, $prisoner['wref']), 1)]['attri'] / 100) + * $u99['time'] / SPEED + ) + ); + + $database->trainUnit($prisoner['wref'], 99, $troops, $u99['pop'], $repairDuration, 0); + } + + $database->deletePrisoners($prisoner['id']); + } + + header("Location: build.php?id=39"); + exit; +} + + +/* +========================================================= += CALCULATE WALKING TIME +========================================================= +*/ + +public function getWalkingTroopsTime( + $from, + $to, + $owner, + $tribe, + $unitArray, + $mode, + $unit = "" +) +{ + global $generator, $database; + + $fromCoor = $database->getCoor($from); + $toCoor = $database->getCoor($to); + + $fromCor = ['x' => $fromCoor['x'], 'y' => $fromCoor['y']]; + $toCor = ['x' => $toCoor['x'], 'y' => $toCoor['y']]; + + if (!$mode) { + return $generator->procDistanceTime( + $fromCor, + $toCor, + $unitArray[0], + $mode, + $from + ); + } + + $start = ($tribe - 1) * 10 + 1; + $end = $tribe * 10; + + $speeds = []; + + /* + FIND SLOWEST UNIT + */ + + if (!empty($unit)) { + + for ($i = 1; $i <= 11; $i++) { + $unitArray[$i - 1] = + (isset($unitArray[$unit.$i]) && $unitArray[$unit.$i] > 0) + ? $unitArray[$unit.$i] + : 0; + } + + } else { + + for ($i = $start; $i <= $end; $i++) { + $unitArray[$i - $start] = + (isset($unitArray['u'.$i]) && $unitArray['u'.$i] > 0) + ? $unitArray['u'.$i] + : 0; + } + + $unitArray[10] = + (isset($unitArray['hero']) && $unitArray['hero'] > 0) + ? $unitArray['hero'] + : 0; + } + + for ($i = 0; $i <= 9; $i++) { + if (isset($unitArray[$i]) && $unitArray[$i] > 0) { + $speeds[] = $GLOBALS['u'.($i + $start)]['speed']; + } + } + + if (isset($unitArray[10]) && $unitArray[10] > 0) { + $heroUnit = $database->getHeroField($owner, 'unit'); + $speeds[] = $GLOBALS['u'.$heroUnit]['speed']; + } + + return $generator->procDistanceTime( + $fromCor, + $toCor, + min($speeds), + $mode, + $from + ); +} + + + /* +========================================================= += START RAID LIST +========================================================= +*/ + +public function startRaidList($post) +{ + global $database, $generator, $session; + + $slots = $post['slot']; + + if (empty($slots)) { + header("Location: build.php?id=39&t=99"); + exit(); + } + + foreach ($slots as $slot) { + + $raidList = $database->getRaidList($slot); + $getFLData = $database->getFLData($raidList['lid']); + + /* + OWNERSHIP CHECK + */ + + if ($getFLData['owner'] != $session->uid) { + continue; + } + + $villageUnits = $database->getUnit($getFLData['wref'], false); + + $wref = $raidList['towref']; + + for ($i = 1; $i <= 6; $i++) { + ${'t'.$i} = $raidList['t'.$i]; + } + + /* + TARGET ACCESS VALIDATION + */ + + if (!$database->isVillageOases($wref)) + $villageOwner = $database->getVillageField($wref, 'owner'); + else + $villageOwner = $database->getOasisField($wref, 'owner'); + + $userAccess = $database->getUserField($villageOwner, 'access', 0); + $userID = $database->getUserField($villageOwner, 'id', 0); + + if ( + $userAccess != 0 && + !($userAccess == MULTIHUNTER && $userID == 5) && + ($userAccess != ADMIN || + (ADMIN_ALLOW_INCOMING_RAIDS && $userAccess == ADMIN)) + ) { + + $start = ($session->tribe - 1) * 10 + 1; + $end = $start + 5; + + $canSend = true; + + for ($i = $start; $i <= $end; $i++) { + if ($villageUnits['u'.$i] < ${'t'.($i - $start + 1)}) { + $canSend = false; break; } } - // if we couldn't get a living hero, - // resort to loading the first one from the list, - // as that would be the one most recently updated/used - if (!$herodata) { - // this global value comes from GameEngine/Data/unitdata.php - $herodata = $GLOBALS["h".$heroarray[0]['unit']]; - } + if ($canSend) { - $h_atk = $herodata['atk'] + 5 * floor($heroarray[$singleHeroArrayID]['attack'] * $herodata['atkp'] / 5); - $h_di = $herodata['di'] + 5 * floor($heroarray[$singleHeroArrayID]['defence'] * $herodata['dip'] / 5); - $h_dc = $herodata['dc'] + 5 * floor($heroarray[$singleHeroArrayID]['defence'] * $herodata['dcp'] / 5); - $h_ob = 1 + 0.002 * $heroarray[$singleHeroArrayID]['attackbonus']; - $h_db = 1 + 0.002 * $heroarray[$singleHeroArrayID]['defencebonus']; - - return [ - 'heroid' => $heroarray[$singleHeroArrayID]['heroid'], - 'unit' => $heroarray[$singleHeroArrayID]['unit'], - 'name' => $heroarray[$singleHeroArrayID]['name'], - 'inrevive' => $heroarray[$singleHeroArrayID]['inrevive'], - 'intraining' => $heroarray[$singleHeroArrayID]['intraining'], - 'trainingtime' => $heroarray[$singleHeroArrayID]['trainingtime'], - 'level' => $heroarray[$singleHeroArrayID]['level'], - 'attack' => $heroarray[$singleHeroArrayID]['attack'], - 'atk' => $h_atk, - 'defence' => $heroarray[$singleHeroArrayID]['defence'], - 'di' => $h_di, - 'dc' => $h_dc, - 'attackbonus' => $heroarray[$singleHeroArrayID]['attackbonus'], - 'ob' => $h_ob, - 'defencebonus' => $heroarray[$singleHeroArrayID]['defencebonus'], - 'db' => $h_db, - 'regeneration' => $heroarray[$singleHeroArrayID]['regeneration'], - 'health' => $heroarray[$singleHeroArrayID]['health'], - 'dead' => $heroarray[$singleHeroArrayID]['dead'], - 'points' => $heroarray[$singleHeroArrayID]['points'], - 'experience' => $heroarray[$singleHeroArrayID]['experience'] - ]; - } else { - // build up a full array of heroes and their stats - $heroes = []; - foreach ($heroarray as $id => $hero) { - $herodata = $GLOBALS["h".$heroarray[$id]['unit']]; + $ckey = $generator->generateRandStr(6); - $h_atk = $herodata['atk'] + 5 * floor($heroarray[$id]['attack'] * $herodata['atkp'] / 5); - $h_di = $herodata['di'] + 5 * floor($heroarray[$id]['defence'] * $herodata['dip'] / 5); - $h_dc = $herodata['dc'] + 5 * floor($heroarray[$id]['defence'] * $herodata['dcp'] / 5); - $h_ob = 1 + 0.002 * $heroarray[$id]['attackbonus']; - $h_db = 1 + 0.002 * $heroarray[$id]['defencebonus']; - - $heroes[] = [ - 'heroid' => $heroarray[$id]['heroid'], - 'unit' => $heroarray[$id]['unit'], - 'name' => $heroarray[$id]['name'], - 'inrevive' => $heroarray[$id]['inrevive'], - 'intraining' => $heroarray[$id]['intraining'], - 'trainingtime' => $heroarray[$id]['trainingtime'], - 'level' => $heroarray[$id]['level'], - 'attack' => $heroarray[$id]['attack'], - 'atk' => $h_atk, - 'defence' => $heroarray[$id]['defence'], - 'di' => $h_di, - 'dc' => $h_dc, - 'attackbonus' => $heroarray[$id]['attackbonus'], - 'ob' => $h_ob, - 'defencebonus' => $heroarray[$id]['defencebonus'], - 'db' => $h_db, - 'regeneration' => $heroarray[$id]['regeneration'], - 'health' => $heroarray[$id]['health'], - 'dead' => $heroarray[$id]['dead'], - 'points' => $heroarray[$id]['points'], - 'experience' => $heroarray[$id]['experience'] - ]; + $id = $database->addA2b( + $ckey, 0, $wref, + $t1, $t2, $t3, $t4, $t5, $t6, + 0, 0, 0, 0, 0, 4 + ); + + $data = $database->getA2b($ckey); + + $troopsTime = $this->getWalkingTroopsTime( + $getFLData['wref'], + $data['to_vid'], + $session->uid, + $session->tribe, + $data, + 1, + 'u' + ); + + $time = $database->getArtifactsValueInfluence( + $getFLData['owner'], + $getFLData['wref'], + 2, + $troopsTime + ); + + $abdata = $database->getABTech($getFLData['wref']); + + $reference = $database->addAttack( + $getFLData['wref'], + $data['u1'], $data['u2'], $data['u3'], + $data['u4'], $data['u5'], $data['u6'], + 0, 0, 0, 0, 0, + $data['type'], + 0, 0, 0, + $abdata['b1'], $abdata['b2'], + $abdata['b3'], $abdata['b4'], + $abdata['b5'], $abdata['b6'], + $abdata['b7'], $abdata['b8'] + ); + + $troops = []; + $amounts = []; + $modes = []; + + for ($u = $start; $u <= $end; $u++) { + $troops[] = $u; + $amounts[] = $data['u'.($u - $start + 1)]; + $modes[] = 0; + } + + $database->modifyUnit($getFLData['wref'], $troops, $amounts, $modes); + + $database->addMovement( + 3, + $getFLData['wref'], + $data['to_vid'], + $reference, + time(), + ($time + time()) + ); + + $database->remA2b($id); } - - return $heroes; } } - - /** - * Function to kill/release prisoners - * - * @param int the ID of the prisoners you want to release - */ - - public function deletePrisoners($id){ - global $village, $database, $session, $building, $bid19, $u99; - - $prisoner = $database->getPrisonersByID($id); - $troops = 0; - if($prisoner['wref'] == $village->wid){ - $p_owner = $database->getVillageField($prisoner['from'], "owner"); - $p_tribe = $database->getUserField($p_owner, "tribe", 0); - - $troopsTime = $this->getWalkingTroopsTime($prisoner['from'], $prisoner['wref'], $p_owner, $p_tribe, $prisoner, 1, 't'); - $p_time = $database->getArtifactsValueInfluence($p_owner, $prisoner['from'], 2, $troopsTime); - - $p_reference = $database->addAttack($prisoner['from'], $prisoner['t1'],$prisoner['t2'], $prisoner['t3'], $prisoner['t4'], $prisoner['t5'], $prisoner['t6'], $prisoner['t7'], $prisoner['t8'], $prisoner['t9'], $prisoner['t10'], $prisoner['t11'], 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - $database->addMovement(4, $prisoner['wref'], $prisoner['from'], $p_reference, time(), ($p_time + time())); - - for($i = 1; $i <= 11; $i++) $troops += $prisoner['t'.$i]; - - //Reset traps - $database->modifyUnit($village->wid, ["99", "99o"], [$troops, $troops], [0, 0]); - $repairDuration = $database->getArtifactsValueInfluence($session->uid, $village->wid, 5, round(($bid19[max($building->getTypeLevel(36, $village->wid), 1)]['attri'] / 100) * $u99['time'] / SPEED)); - $database->trainUnit($village->wid, 99, $troops, $u99['pop'], $repairDuration, 0); - - $database->deletePrisoners($prisoner['id']); - }else if($prisoner['from'] == $village->wid){ - $prisonersToOwner = $database->getVillageField($prisoner['wref'], "owner"); - - for($i = 1; $i <= 11; $i++) $troops += $prisoner['t'.$i]; - - if($prisoner['t11'] > 0){ - $p_owner = $database->getVillageField($prisoner['from'], "owner"); - mysqli_query($database->dblink, "UPDATE ".TB_PREFIX."hero SET `dead` = '1', `health` = '0' WHERE `uid` = '".$p_owner."' AND dead = 0"); - } - - //Reset traps - $database->modifyUnit($prisoner['wref'], ["99", "99o"], [$troops, $troops], [0, 0]); - - if(($troops = round($troops / 3)) > 0){ - $repairDuration = $database->getArtifactsValueInfluence($prisonersToOwner, $prisoner['wref'], 5, round(($bid19[max($building->getTypeLevel(36, $prisoner['wref']), 1)]['attri'] / 100) * $u99['time'] / SPEED)); - $database->trainUnit($prisoner['wref'], 99, $troops, $u99['pop'], $repairDuration, 0); - } - - $database->deletePrisoners($prisoner['id']); - } - - header("Location: build.php?id=39"); - exit; - } - - /** - * Get how much time troops spend to walk from a village to another - * - * @param int $from The start village ID - * @param int $to The target village ID - * @param int $owner The owner of the troops - * @param int $tribe The tribe of the owner's troops - * @param array $unitArray The array containing troops count if mode is 0, otherwise it'll contains the troop speed - * @param int $mode How the time should be calculated - * @return int Returns the time troops take to walk from a village to another - */ - - public function getWalkingTroopsTime($from, $to, $owner, $tribe, $unitArray, $mode, $unit = ""){ - global $generator, $database; - $fromCoor = $database->getCoor($from); - $toCoor = $database->getCoor($to); - $fromCor = ['x' => $fromCoor['x'], 'y' => $fromCoor['y']]; - $toCor = ['x' => $toCoor['x'], 'y' => $toCoor['y']]; - - if(!$mode) return $generator->procDistanceTime($fromCor, $toCor, $unitArray[0], $mode, $from); - - $start = ($tribe - 1) * 10 + 1; - $end = $tribe * 10; - - $speeds = []; - - //Find slowest unit - if(!empty($unit)){ - for($i = 1; $i <= 11; $i++){ - if(isset($unitArray[$unit.$i]) && $unitArray[$unit.$i] > 0) $unitArray[$i - 1] = $unitArray[$unit.$i]; - else $unitArray[$i - 1] = 0; - } - }else{ - for($i = $start; $i <= $end; $i++){ - if(isset($unitArray['u'.$i]) && $unitArray['u'.$i] > 0) $unitArray[$i - $start] = $unitArray['u'.$i]; - else $unitArray[$i - $start] = 0; - } - - if(isset($unitArray['hero']) && $unitArray['hero'] > 0){ - $unitArray[10] = $unitArray['hero']; - } - else $unitArray[10] = 0; - } - - for($i = 0; $i <= 9; $i++){ - if(isset($unitArray[$i]) && $unitArray[$i] > 0){ - $speeds[] = $GLOBALS['u'.($i + $start)]['speed']; - } - } - - if(isset($unitArray[10]) && $unitArray[10] > 0){ - $heroUnit = $database->getHeroField($owner, 'unit'); - $speeds[] = $GLOBALS['u'.$heroUnit]['speed']; - } - - return $generator->procDistanceTime($fromCor, $toCor, min($speeds), $mode, $from); - } - - public function startRaidList($post){ - global $database, $generator, $session; - - $slots = $post['slot']; - if(empty($slots)){ - header("Location: build.php?id=39&t=99"); - exit(); - } - - $tribe = $session->tribe; - - foreach($slots as $slot){ - $raidList = $database->getRaidList($slot); - $getFLData = $database->getFLData($raidList['lid']); - - //Check if we're trying to start our raidlists or other players raidlist - if($getFLData['owner'] != $session->uid) continue; - - //Get the units in the village - $villageUnits = $database->getUnit($getFLData['wref'], false); - - $sid = $raidList['id']; - $wref = $raidList['towref']; - - for($i = 1; $i <= 6; $i++) ${'t'.$i} = $raidList['t'.$i]; - - if(!$database->isVillageOases($wref)) $villageOwner = $database->getVillageField($wref, 'owner'); - else $villageOwner = $database->getOasisField($wref, 'owner'); - - $userAccess = $database->getUserField($villageOwner, 'access', 0); - $userID = $database->getUserField($villageOwner, 'id', 0); - - if($userAccess != 0 && !($userAccess == MULTIHUNTER && $userID == 5) && ($userAccess != ADMIN || (ADMIN_ALLOW_INCOMING_RAIDS && $userAccess == ADMIN))){ - - //Start = the first troop of the player's tribe - //End = the last selectable troop of the player's tribe - $start = ($session->tribe - 1) * 10 + 1; - $end = $start + 5; - - //Check if we've enough troops - $canSend = true; - for($i = $start; $i <= $end; $i++){ - if($villageUnits['u'.$i] < ${'t'.($i - $start + 1)}){ - $canSend = false; - break; - } - } - - //Send the attack - if($canSend){ - $ckey = $generator->generateRandStr(6); - $id = $database->addA2b($ckey, 0, $wref, $t1, $t2, $t3, $t4, $t5, $t6, 0, 0, 0, 0, 0, 4); - $data = $database->getA2b($ckey); - - $troopsTime = $this->getWalkingTroopsTime($getFLData['wref'], $data['to_vid'], $session->uid, $session->tribe, $data, 1, 'u'); - $time = $database->getArtifactsValueInfluence($getFLData['owner'], $getFLData['wref'], 2, $troopsTime); - - $abdata = $database->getABTech($getFLData['wref']); - $reference = $database->addAttack(($getFLData['wref']), $data['u1'], $data['u2'], $data['u3'], $data['u4'], $data['u5'], $data['u6'], 0, 0, 0, 0, 0, $data['type'], 0, 0, 0, $abdata['b1'], $abdata['b2'], $abdata['b3'], $abdata['b4'], $abdata['b5'], $abdata['b6'], $abdata['b7'], $abdata['b8']); - - $troops = []; - $amounts = []; - $modes = []; - - for($u = $start; $u <= $end; $u++){ - $troops[] = $u; - $amounts[] = $data['u'.($u - $start + 1)]; - $modes[] = 0; - } - - $database->modifyUnit($getFLData['wref'], $troops, $amounts, $modes); - $database->addMovement(3, $getFLData['wref'], $data['to_vid'], $reference, time(), ($time + time())); - - //Prevent re-use of the same attack via re-POSTing the same data - $database->remA2b($id); - } - } - } - header("Location: build.php?id=39&t=99"); - exit(); - } + header("Location: build.php?id=39&t=99"); + exit(); +} }; $units = new Units; diff --git a/GameEngine/index.php b/GameEngine/index.php index a81240cd..bb8da7d4 100755 --- a/GameEngine/index.php +++ b/GameEngine/index.php @@ -8,12 +8,22 @@ ## Copyright: TravianZ (c) 2010-2025. All rights reserved. ## ## ## ################################################################################# + +// Send proper 404 header if not already sent +if (!headers_sent()) { + header("HTTP/1.1 404 Not Found"); + header("Content-Type: text/html; charset=UTF-8"); + header("Cache-Control: no-store, no-cache, must-revalidate"); + header("Pragma: no-cache"); +} ?>
-
-

404 - File not found

- Not Found
-

We looked 404 times already but can't find anything, Not even an X marking the spot.

-

This system is not complete yet. So the page probably does not exist.


-
+
+

404 - File not found

+ Not Found
+

We looked 404 times already but can't find anything, Not even an X marking the spot.

+

This system is not complete yet. So the page probably does not exist.


+
\ No newline at end of file diff --git a/Templates/a2b/attack.tpl b/Templates/a2b/attack.tpl index 257cda58..adf3643a 100644 --- a/Templates/a2b/attack.tpl +++ b/Templates/a2b/attack.tpl @@ -326,5 +326,63 @@ $end = $tribe * 10; class="dynamic_img " src="img/x.gif" alt="OK" type="image" onclick="if (this.disabled==false) {document.getElementsByTagName('form')[0].submit();} this.disabled=true;" onLoad="this.disabled=false;">

+ +