From 69491b96bdf0d6d8a06a708f43e10bd16f834e09 Mon Sep 17 00:00:00 2001 From: Dan Hemberger Date: Thu, 19 Aug 2021 19:56:14 -0700 Subject: [PATCH 1/4] Fix bug sharing maps when all sectors are explored This was a result of the `$unvisitedSectors` array being empty, which caused the SQL query to use a `AND sector_id NOT IN ()` clause. This clause is now omitted if the array is empty. I suspect that this worked in the past due to the escaping mechanism in `escapeArray`, likely resulting in `AND sector_id NOT IN ('')` (see the `$autoQuotes` option, which was removed in 3b996d91fb5c4). --- src/engine/Default/alliance_share_maps_processing.php | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/engine/Default/alliance_share_maps_processing.php b/src/engine/Default/alliance_share_maps_processing.php index 07221e766..0f8a5ac89 100644 --- a/src/engine/Default/alliance_share_maps_processing.php +++ b/src/engine/Default/alliance_share_maps_processing.php @@ -10,7 +10,7 @@ $alliance_ids = array_diff($memberIDs, [$player->getAccountID()]); // end here if we are alone in the alliance -if (empty($alliance_ids)) { +if (count($alliance_ids) == 0) { create_error('Who exactly are you sharing maps with?'); } @@ -18,11 +18,14 @@ // delete all visited sectors from the table of all our alliance mates $db = Smr\Database::getInstance(); -$db->write('DELETE +$query = 'DELETE FROM player_visited_sector WHERE account_id IN (' . $db->escapeArray($alliance_ids) . ') - AND game_id = ' . $db->escapeNumber($player->getGameID()) . ' - AND sector_id NOT IN (' . $db->escapeArray($unvisitedSectors) . ')'); + AND game_id = ' . $db->escapeNumber($player->getGameID()); +if (count($unvisitedSectors) > 0) { + $query .= ' AND sector_id NOT IN (' . $db->escapeArray($unvisitedSectors) . ')'; +} +$db->write($query); // free some memory unset($unvisitedSectors); From 461ed5b864b022c64b2c552aeb55e74b0a24a75b Mon Sep 17 00:00:00 2001 From: Dan Hemberger Date: Fri, 20 Aug 2021 03:43:01 -0700 Subject: [PATCH 2/4] npc.php: fix error buying hardware Use `IFloor` instead of `floor` to compute the amount of each hardware to buy so that we have an int instead of a float. Fixes: > TypeError: doUNO(): Argument #2 ($amount) must be of type int, float given --- src/tools/npc/npc.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/npc/npc.php b/src/tools/npc/npc.php index 9bb1a9e9f..aaeaf4f92 100644 --- a/src/tools/npc/npc.php +++ b/src/tools/npc/npc.php @@ -459,11 +459,11 @@ function canWeUNO(AbstractSmrPlayer $player, bool $oppurtunisticOnly) : Page|fal foreach ($sector->getLocations() as $location) { if ($location->isHardwareSold()) { $hardwareSold = $location->getHardwareSold(); - if ($player->getNewbieTurns() > MIN_NEWBIE_TURNS_TO_BUY_CARGO && !$ship->hasMaxCargoHolds() && isset($hardwareSold[HARDWARE_CARGO]) && ($amount = floor(($player->getCredits() - MINUMUM_RESERVE_CREDITS) / Globals::getHardwareCost(HARDWARE_CARGO))) > 0) { // Buy cargo holds first if we have plenty of newbie turns left. + if ($player->getNewbieTurns() > MIN_NEWBIE_TURNS_TO_BUY_CARGO && !$ship->hasMaxCargoHolds() && isset($hardwareSold[HARDWARE_CARGO]) && ($amount = IFloor(($player->getCredits() - MINUMUM_RESERVE_CREDITS) / Globals::getHardwareCost(HARDWARE_CARGO))) > 0) { // Buy cargo holds first if we have plenty of newbie turns left. $hardwareID = HARDWARE_CARGO; } else { foreach ($hardwareArray as $hardwareArrayID) { - if (!$ship->hasMaxHardware($hardwareArrayID) && isset($hardwareSold[$hardwareArrayID]) && ($amount = floor(($player->getCredits() - MINUMUM_RESERVE_CREDITS) / Globals::getHardwareCost($hardwareArrayID))) > 0) { + if (!$ship->hasMaxHardware($hardwareArrayID) && isset($hardwareSold[$hardwareArrayID]) && ($amount = IFloor(($player->getCredits() - MINUMUM_RESERVE_CREDITS) / Globals::getHardwareCost($hardwareArrayID))) > 0) { $hardwareID = $hardwareArrayID; break; } From 9815538ee3dcd612c0bf85ec5dad9461a18011f6 Mon Sep 17 00:00:00 2001 From: Dan Hemberger Date: Fri, 20 Aug 2021 04:05:20 -0700 Subject: [PATCH 3/4] npc.php: clean up canWeUNO function The logic for deciding to buy hardware has been significantly simplified. --- src/tools/npc/npc.php | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/src/tools/npc/npc.php b/src/tools/npc/npc.php index aaeaf4f92..7854205b4 100644 --- a/src/tools/npc/npc.php +++ b/src/tools/npc/npc.php @@ -450,27 +450,24 @@ function canWeUNO(AbstractSmrPlayer $player, bool $oppurtunisticOnly) : Page|fal } $sector = $player->getSector(); - // We buy armour in preference to shields as it's cheaper. - // We buy cargo holds last if we have no newbie turns because we'd rather not die - $hardwareArray = array(HARDWARE_ARMOUR, HARDWARE_SHIELDS, HARDWARE_CARGO); - - $amount = 0; + if ($player->getNewbieTurns() > MIN_NEWBIE_TURNS_TO_BUY_CARGO) { + // Buy cargo holds first if we have plenty of newbie turns left. + $hardwareArray = [HARDWARE_CARGO, HARDWARE_ARMOUR, HARDWARE_SHIELDS]; + } else { + // We buy armour in preference to shields as it's cheaper. + // We buy cargo holds last if we have no newbie turns because we'd rather not die + $hardwareArray = [HARDWARE_ARMOUR, HARDWARE_SHIELDS, HARDWARE_CARGO]; + } foreach ($sector->getLocations() as $location) { - if ($location->isHardwareSold()) { - $hardwareSold = $location->getHardwareSold(); - if ($player->getNewbieTurns() > MIN_NEWBIE_TURNS_TO_BUY_CARGO && !$ship->hasMaxCargoHolds() && isset($hardwareSold[HARDWARE_CARGO]) && ($amount = IFloor(($player->getCredits() - MINUMUM_RESERVE_CREDITS) / Globals::getHardwareCost(HARDWARE_CARGO))) > 0) { // Buy cargo holds first if we have plenty of newbie turns left. - $hardwareID = HARDWARE_CARGO; - } else { - foreach ($hardwareArray as $hardwareArrayID) { - if (!$ship->hasMaxHardware($hardwareArrayID) && isset($hardwareSold[$hardwareArrayID]) && ($amount = IFloor(($player->getCredits() - MINUMUM_RESERVE_CREDITS) / Globals::getHardwareCost($hardwareArrayID))) > 0) { - $hardwareID = $hardwareArrayID; - break; - } - } + foreach ($hardwareArray as $hardwareID) { + if (!$location->isHardwareSold($hardwareID)) { + continue; } - if (isset($hardwareID)) { - $amount = min($ship->getType()->getMaxHardware($hardwareID) - $ship->getHardware($hardwareID), $amount); + $amountCanBuy = IFloor(($player->getCredits() - MINUMUM_RESERVE_CREDITS) / Globals::getHardwareCost($hardwareID)); + $amountNeeded = $ship->getType()->getMaxHardware($hardwareID) - $ship->getHardware($hardwareID); + $amount = min($amountCanBuy, $amountNeeded); + if ($amount > 0) { return doUNO($hardwareID, $amount, $sector->getSectorID()); } } From 98f8816034757384a0452de2ca6f6dab4795fb96 Mon Sep 17 00:00:00 2001 From: Dan Hemberger Date: Fri, 20 Aug 2021 04:43:21 -0700 Subject: [PATCH 4/4] Fix error displaying scout messages In the `displayGrouped` and `displayMessage` functions, we now return the constructed message (an array) instead of passing in the message box by reference and appending to it inside the functions. This fixes an issue with scout messages where the "GroupedMessages" element did not yet exist, but we were passing it by reference to the `displayMessage` function as if it were an array. This caused the following error: > TypeError: displayMessage(): Argument #1 ($messageBox) must be of type array, null given --- src/engine/Default/message_view.php | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/engine/Default/message_view.php b/src/engine/Default/message_view.php index 5feb359a8..5cb530ace 100644 --- a/src/engine/Default/message_view.php +++ b/src/engine/Default/message_view.php @@ -87,7 +87,7 @@ $template->unassign('NextPageHREF'); // always displaying all scout messages? } else { foreach ($dbResult->records() as $dbRecord) { - displayMessage($messageBox, $dbRecord->getInt('message_id'), $dbRecord->getInt('account_id'), $dbRecord->getInt('sender_id'), $player->getGameID(), $dbRecord->getString('message_text'), $dbRecord->getInt('send_time'), $dbRecord->getBoolean('msg_read'), $var['folder_id'], $player->getAccount()); + $messageBox['Messages'][] = displayMessage($dbRecord->getInt('message_id'), $dbRecord->getInt('account_id'), $dbRecord->getInt('sender_id'), $player->getGameID(), $dbRecord->getString('message_text'), $dbRecord->getInt('send_time'), $dbRecord->getBoolean('msg_read'), $var['folder_id'], $player->getAccount()); } } if (!USING_AJAX) { @@ -115,7 +115,7 @@ function displayScouts(array &$messageBox, SmrPlayer $player) : void { $totalUnread = $dbRecord->getInt('total_unread'); $message = 'Your forces have spotted ' . $sender->getBBLink() . ' passing your forces ' . $dbRecord->getInt('number') . ' ' . pluralise('time', $dbRecord->getInt('number')); $message .= ($totalUnread > 0) ? ' (' . $totalUnread . ' unread).' : '.'; - displayGrouped($messageBox, $sender, $message, $dbRecord->getInt('first'), $dbRecord->getInt('last'), $totalUnread > 0, $player->getAccount()); + $messageBox['Messages'][] = displayGrouped($sender, $message, $dbRecord->getInt('first'), $dbRecord->getInt('last'), $totalUnread > 0, $player->getAccount()); } // Now display individual messages in each group @@ -131,7 +131,7 @@ function displayScouts(array &$messageBox, SmrPlayer $player) : void { $groupBox =& $messageBox['GroupedMessages'][$dbRecord->getInt('sender_id')]; // Limit the number of messages in each group if (!isset($groupBox['Messages']) || count($groupBox['Messages']) < MESSAGE_SCOUT_GROUP_LIMIT) { - displayMessage($groupBox, $dbRecord->getInt('message_id'), $dbRecord->getInt('account_id'), $dbRecord->getInt('sender_id'), $player->getGameID(), $dbRecord->getString('message_text'), $dbRecord->getInt('send_time'), $dbRecord->getBoolean('msg_read'), MSG_SCOUT, $player->getAccount()); + $groupBox['Messages'][] = displayMessage($dbRecord->getInt('message_id'), $dbRecord->getInt('account_id'), $dbRecord->getInt('sender_id'), $player->getGameID(), $dbRecord->getString('message_text'), $dbRecord->getInt('send_time'), $dbRecord->getBoolean('msg_read'), MSG_SCOUT, $player->getAccount()); } } @@ -139,7 +139,7 @@ function displayScouts(array &$messageBox, SmrPlayer $player) : void { $messageBox['NumberMessages'] = $dbResult->getNumRecords(); } -function displayGrouped(array &$messageBox, SmrPlayer $sender, string $message_text, int $first, int $last, bool $star, SmrAccount $displayAccount) : void { +function displayGrouped(SmrPlayer $sender, string $message_text, int $first, int $last, bool $star, SmrAccount $displayAccount) : array { // Define a unique array so we can delete grouped messages $array = array( $sender->getAccountID(), @@ -154,10 +154,10 @@ function displayGrouped(array &$messageBox, SmrPlayer $sender, string $message_t $message['SenderDisplayName'] = $sender->getLinkedDisplayName(false); $message['SendTime'] = date($displayAccount->getDateTimeFormat(), $first) . " - " . date($displayAccount->getDateTimeFormat(), $last); $message['Text'] = $message_text; - $messageBox['Messages'][] = $message; + return $message; } -function displayMessage(array &$messageBox, int $message_id, int $receiver_id, int $sender_id, int $game_id, string $message_text, int $send_time, bool $msg_read, int $type, SmrAccount $displayAccount) : void { +function displayMessage(int $message_id, int $receiver_id, int $sender_id, int $game_id, string $message_text, int $send_time, bool $msg_read, int $type, SmrAccount $displayAccount) : array { $message = array(); $message['ID'] = $message_id; $message['Text'] = $message_text; @@ -201,6 +201,5 @@ function displayMessage(array &$messageBox, int $message_id, int $receiver_id, i $message['ReceiverDisplayName'] = create_link($container, $receiver->getDisplayName()); } - // Append the message to this box - $messageBox['Messages'][] = $message; + return $message; }