Some full fixes before final v11 release

Some full fixes before final v11 release
This commit is contained in:
novgorodschi catalin
2026-07-23 11:20:01 +03:00
parent 62b39f4d34
commit 9a3f26bc93
7 changed files with 116 additions and 43 deletions
@@ -329,6 +329,10 @@ trait AutomationAccountMaintenance {
$database->cacheResourceLevels(array_keys($vilIDs));
foreach($villages as $village){
// HOTFIX warning "$attri undefined": $attri se seteaza doar daca satul are
// un camp tip 18 (Stonemason); fara initializare, valoarea "scapa" din satul
// anterior (rezultatul final era acelasi, fiind un max, dar cu warning in log)
$attri = 0;
$field = $database->getResourceLevel($village['wref'], false);
for($i = 19; $i <= 40; $i++){
if($field['f'.$i.'t'] == 18){
@@ -495,9 +495,14 @@ trait AutomationBattleResolution {
$expArray = $database->getVillageFields($from['wref'], 'exp1, exp2, exp3');
$villexp = ($expArray['exp1'] == 0) ? 0 : (($expArray['exp2'] == 0) ? 1 : (($expArray['exp3'] == 0) ? 2 : 3));
// HOTFIX "$cp0 undefined" (acelasi tipar ca FIX U1 din Units.php): tabelele $cp0..$cpN
// vin din Data/cp.php, incarcat pana acum doar de Session.php - deci pe traseul de CRON
// (fara Session) verificarea de CP la cucerire era OCOLITA silentios. Data/cp.php e
// acum inclus si in Automation.php; gardul ?? PHP_INT_MAX ramane fail-closed daca
// tabelul lipseste totusi (fara date de CP nu se poate cuceri), identic cu Settlers().
$mode = CP;
$cp_mode = $GLOBALS['cp' . $mode];
$need_cps = $cp_mode[count($varray1) + 1];
$cp_mode = $GLOBALS['cp' . $mode] ?? [];
$need_cps = $cp_mode[count($varray1) + 1] ?? PHP_INT_MAX;
$user_cps = $database->getUserArray($from['owner'], 1)['cp'];
if ($user_cps < $need_cps) {
@@ -323,50 +323,81 @@ trait AutomationVillageUpkeep {
private function updateStore() {
global $database, $bid10, $bid38, $bid11, $bid39;
$result = mysqli_query($database->dblink, 'SELECT * FROM `' . TB_PREFIX . 'fdata`');
// HOTFIX deadlock (log 20-23 iul): rutina scria toata vdata intr-o SINGURA
// tranzactie lunga, tinand lock-uri pe multe randuri => coliziuni fatale cu
// scrierile jucatorilor. Doua schimbari: (1) commit in transe de 200 de randuri
// (ferestre de lock scurte), (2) reincercare de maximum 3 ori la deadlock / lock
// timeout. Rutina e idempotenta (recalculeaza maxstore/maxcrop de la zero), deci
// o rulare partiala e inofensiva - urmatorul tick o completeaza.
for ($attempt = 1; $attempt <= 3; $attempt++) {
try {
$result = mysqli_query($database->dblink, 'SELECT * FROM `' . TB_PREFIX . 'fdata`');
mysqli_begin_transaction($database->dblink);
while ($row = mysqli_fetch_assoc($result))
{
$ress = $crop = 0;
for ($i = 19; $i < 40; ++$i)
{
//Warehouse
if ($row['f' . $i . 't'] == 10)
$pending = 0;
mysqli_begin_transaction($database->dblink);
while ($row = mysqli_fetch_assoc($result))
{
$ress += ((isset($bid10[$row['f' . $i]]) && isset($bid10[$row['f' . $i]]['attri'])) ? $bid10[$row['f' . $i]]['attri'] * STORAGE_MULTIPLIER : 0);
}
$ress = $crop = 0;
for ($i = 19; $i < 40; ++$i)
{
//Warehouse
if ($row['f' . $i . 't'] == 10)
{
$ress += ((isset($bid10[$row['f' . $i]]) && isset($bid10[$row['f' . $i]]['attri'])) ? $bid10[$row['f' . $i]]['attri'] * STORAGE_MULTIPLIER : 0);
}
//Great warehouse
if ($row['f' . $i . 't'] == 38)
{
$ress += ((isset($bid38[$row['f' . $i]]) && isset($bid38[$row['f' . $i]]['attri'])) ? $bid38[$row['f' . $i]]['attri'] * STORAGE_MULTIPLIER : 0);
}
//Great warehouse
if ($row['f' . $i . 't'] == 38)
{
$ress += ((isset($bid38[$row['f' . $i]]) && isset($bid38[$row['f' . $i]]['attri'])) ? $bid38[$row['f' . $i]]['attri'] * STORAGE_MULTIPLIER : 0);
}
//Granary
if ($row['f' . $i . 't'] == 11)
{
$crop += ((isset($bid11[$row['f' . $i]]) && isset($bid11[$row['f' . $i]]['attri'])) ? $bid11[$row['f' . $i]]['attri'] * STORAGE_MULTIPLIER : 0);
}
//Granary
if ($row['f' . $i . 't'] == 11)
{
$crop += ((isset($bid11[$row['f' . $i]]) && isset($bid11[$row['f' . $i]]['attri'])) ? $bid11[$row['f' . $i]]['attri'] * STORAGE_MULTIPLIER : 0);
}
//Great granary
if ($row['f' . $i . 't'] == 39)
{
$crop += ((isset($bid39[$row['f' . $i]]) && isset($bid39[$row['f' . $i]]['attri'])) ? $bid39[$row['f' . $i]]['attri'] * STORAGE_MULTIPLIER : 0);
//Great granary
if ($row['f' . $i . 't'] == 39)
{
$crop += ((isset($bid39[$row['f' . $i]]) && isset($bid39[$row['f' . $i]]['attri'])) ? $bid39[$row['f' . $i]]['attri'] * STORAGE_MULTIPLIER : 0);
}
}
// no need for update, since we didn't find any warehouses or granaries
// and maximums would have been set to correct values inside prune* functions already
if ($ress == 0 && $crop == 0) continue;
// maxstore nor maxcrop can go below the minimum threshold
if ($ress < STORAGE_BASE) $ress = STORAGE_BASE;
if ($crop < STORAGE_BASE) $crop = STORAGE_BASE;
mysqli_query($database->dblink,'UPDATE `' . TB_PREFIX . 'vdata` SET `maxstore` = ' . (int) $ress . ', `maxcrop` = ' . (int) $crop . ' WHERE `wref` = ' . (int) $row['vref']);
// commit in transe: tranzactii scurte = ferestre de lock mici
if (++$pending >= 200) {
mysqli_commit($database->dblink);
mysqli_begin_transaction($database->dblink);
$pending = 0;
}
}
}
// no need for update, since we didn't find any warehouses or granaries
// and maximums would have been set to correct values inside prune* functions already
if ($ress == 0 && $crop == 0) continue;
// maxstore nor maxcrop can go below the minimum threshold
if ($ress < STORAGE_BASE) $ress = STORAGE_BASE;
if ($crop < STORAGE_BASE) $crop = STORAGE_BASE;
mysqli_query($database->dblink,'UPDATE `' . TB_PREFIX . 'vdata` SET `maxstore` = ' . (int) $ress . ', `maxcrop` = ' . (int) $crop . ' WHERE `wref` = ' . (int) $row['vref']);
}
mysqli_commit($database->dblink);
return;
} catch (mysqli_sql_exception $e) {
if (!in_array((int) $e->getCode(), [1213, 1205], true)) {
throw $e; // orice alta eroare ramane fatala, ca inainte
}
try { mysqli_rollback($database->dblink); } catch (mysqli_sql_exception $ignored) {}
if ($attempt === 3) {
// dupa 3 incercari renuntam la ACEST tick fara sa-l omoram;
// urmatorul tick reia calculul de la zero
error_log('Automation::updateStore: deadlock persistent dupa 3 incercari, amanat pentru tick-ul urmator');
return;
}
usleep(150000 * $attempt);
}
}
}
private function regenerateOasisTroops() {