mirror of
https://github.com/Shadowss/TravianZ.git
synced 2026-06-28 00:24:23 +00:00
Merge branch 'master' of https://github.com/Shadowss/TravianZ
This commit is contained in:
Executable → Regular
+738
-286
File diff suppressed because it is too large
Load Diff
+233
-91
@@ -619,26 +619,25 @@ class MYSQLi_DB implements IDbConnection {
|
||||
References: lietuvis10
|
||||
***************************/
|
||||
|
||||
public function getBestOasisCropBonus($x, $y) {
|
||||
$x = (int)$x;
|
||||
$y = (int)$y;
|
||||
|
||||
// Adjust oasis type codes if your fork differs:
|
||||
// - 50% crop only: type IN (12)
|
||||
// - 25% crop (pure or mixed w/ wood/clay/iron): type IN (4,9,10,11)
|
||||
|
||||
$sql = "SELECT COALESCE(SUM(bonus), 0) AS total FROM (SELECT CASE
|
||||
WHEN o.type IN (12) THEN 50 WHEN o.type IN (4,9,10,11) THEN 25 ELSE 0
|
||||
END AS bonus FROM " . TB_PREFIX . "wdata w JOIN " . TB_PREFIX . "odata o ON o.wref = w.id
|
||||
WHERE w.fieldtype = 0 AND ABS(w.x - $x) <= 3 AND ABS(w.y - $y) <= 3
|
||||
AND o.type IN (12,4,9,10,11) -- only crop-giving oases ORDER BY bonus DESC LIMIT 3) t";
|
||||
public function getBestOasisCropBonus($x, $y) {
|
||||
$x = (int)$x;
|
||||
$y = (int)$y;
|
||||
|
||||
$q = mysqli_query($this->dblink, $sql);
|
||||
$row = mysqli_fetch_assoc($q);
|
||||
$total = (int)($row['total'] ?? 0);
|
||||
if ($total > 150) $total = 150; // safety cap
|
||||
return $total;
|
||||
}
|
||||
// Adjust oasis type codes if your fork differs:
|
||||
// - 50% crop only: type IN (12)
|
||||
// - 25% crop (pure or mixed w/ wood/clay/iron): type IN (4,9,10,11)
|
||||
$sql = "SELECT COALESCE(SUM(bonus), 0) AS total FROM (SELECT CASE
|
||||
WHEN o.type IN (12) THEN 50 WHEN o.type IN (4,9,10,11) THEN 25 ELSE 0
|
||||
END AS bonus FROM " . TB_PREFIX . "wdata w JOIN " . TB_PREFIX . "odata o ON o.wref = w.id
|
||||
WHERE w.fieldtype = 0 AND ABS(w.x - $x) <= 3 AND ABS(w.y - $y) <= 3 AND o.type IN (12,4,9,10,11)
|
||||
ORDER BY bonus DESC LIMIT 3) t";
|
||||
|
||||
$q = mysqli_query($this->dblink, $sql);
|
||||
$row = mysqli_fetch_assoc($q);
|
||||
$total = (int)($row['total'] ?? 0);
|
||||
if ($total > 150) $total = 150; // safety cap
|
||||
return $total;
|
||||
}
|
||||
|
||||
/***************************
|
||||
Function to process MYSQLi->fetch_all (Only exist in MYSQL)
|
||||
@@ -7014,94 +7013,237 @@ References: User ID/Message ID, Mode
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*** Build/rebuild the croppers precompute table from wdata. */
|
||||
|
||||
public function TotalCroppers(): int {
|
||||
$TBP = defined('TB_PREFIX') ? TB_PREFIX : 's1_';
|
||||
$WDATA = $TBP . 'wdata';
|
||||
|
||||
$res = mysqli_query($this->dblink, "SELECT COUNT(*) AS cnt FROM `$WDATA` WHERE fieldtype IN (1,6)");
|
||||
if (!$res) {
|
||||
throw new Exception('Count query failed: ' . mysqli_error($this->dblink));
|
||||
}
|
||||
|
||||
$row = mysqli_fetch_assoc($res);
|
||||
return (int)($row['cnt'] ?? 0);
|
||||
}
|
||||
|
||||
public function populateCroppers(int $countTotal = 0, bool $truncateFirst = false, int $batch = 20000, ?callable $reporter = null ): array {
|
||||
|
||||
@set_time_limit(0);
|
||||
@ini_set('memory_limit', '1G');
|
||||
|
||||
$TBP = defined('TB_PREFIX') ? TB_PREFIX : 's1_';
|
||||
$CROP_TABLE = $TBP . 'croppers';
|
||||
$WDATA = $TBP . 'wdata';
|
||||
|
||||
// Count once if caller didn't
|
||||
if ($countTotal <= 0) {
|
||||
$row = mysqli_fetch_assoc(mysqli_query($this->dblink,
|
||||
"SELECT COUNT(*) cnt FROM `$WDATA` WHERE fieldtype IN (1,6)"));
|
||||
$countTotal = (int)($row['cnt'] ?? 0);
|
||||
}
|
||||
|
||||
if ($truncateFirst) {
|
||||
if (!mysqli_query($this->dblink, "TRUNCATE TABLE `$CROP_TABLE`")) {
|
||||
return ['ok'=>false,'msg'=>'TRUNCATE failed: '.mysqli_error($this->dblink)];
|
||||
}
|
||||
}
|
||||
|
||||
// Session-level speed knobs (local to this connection)
|
||||
@mysqli_query($this->dblink, "SET innodb_flush_log_at_trx_commit=2");
|
||||
@mysqli_query($this->dblink, "SET sync_binlog=0");
|
||||
@mysqli_query($this->dblink, "SET unique_checks=0");
|
||||
@mysqli_query($this->dblink, "SET foreign_key_checks=0");
|
||||
|
||||
// Read big windows; write in safe slices to avoid max_allowed_packet
|
||||
if ($batch < 1000) $batch = 1000;
|
||||
if ($batch > 100000) $batch = 100000;
|
||||
if($countTotal < 1000) $sliceSize = 200;
|
||||
elseif($countTotal < 5000) $sliceSize = 500;
|
||||
elseif($countTotal > 5000) $sliceSize = 1000;
|
||||
|
||||
$total = 0;
|
||||
$lastId = 0;
|
||||
|
||||
// Cursor pagination (no OFFSET)
|
||||
while (true) {
|
||||
$res = mysqli_query(
|
||||
$this->dblink,
|
||||
"SELECT id AS wref, x, y, fieldtype
|
||||
FROM `$WDATA`
|
||||
WHERE fieldtype IN (1,6) AND id > $lastId
|
||||
ORDER BY id ASC
|
||||
LIMIT $batch"
|
||||
);
|
||||
if (!$res) {
|
||||
return ['ok'=>false,'msg'=>'SELECT failed: '.mysqli_error($this->dblink),'processed'=>$total,'target'=>$countTotal];
|
||||
}
|
||||
|
||||
$rows = [];
|
||||
while ($r = mysqli_fetch_assoc($res)) { $rows[] = $r; }
|
||||
if (!$rows) break;
|
||||
|
||||
mysqli_begin_transaction($this->dblink);
|
||||
|
||||
$n = count($rows);
|
||||
for ($i = 0; $i < $n; $i += $sliceSize) {
|
||||
$chunk = array_slice($rows, $i, $sliceSize);
|
||||
$values = [];
|
||||
|
||||
foreach ($chunk as $r) {
|
||||
$x = (int)$r['x'];
|
||||
$y = (int)$r['y'];
|
||||
|
||||
// Your existing helper:
|
||||
$bonus = (int)$this->getBestOasisCropBonus($x, $y);
|
||||
if ($bonus < 0) $bonus = 0;
|
||||
if ($bonus > 150) $bonus = 150;
|
||||
|
||||
$values[] = sprintf("(%d,%d,%d,%d,%d)",
|
||||
(int)$r['wref'], $x, $y, (int)$r['fieldtype'], $bonus
|
||||
);
|
||||
}
|
||||
|
||||
if ($values) {
|
||||
// ODKU is cheaper than REPLACE (no DELETE)
|
||||
$sql = "INSERT INTO `$CROP_TABLE`
|
||||
(`wref`,`x`,`y`,`fieldtype`,`best_oasis_bonus`)
|
||||
VALUES ".implode(',', $values)."
|
||||
ON DUPLICATE KEY UPDATE
|
||||
`x`=VALUES(`x`),
|
||||
`y`=VALUES(`y`),
|
||||
`fieldtype`=VALUES(`fieldtype`),
|
||||
`best_oasis_bonus`=VALUES(`best_oasis_bonus`)";
|
||||
if (!mysqli_query($this->dblink, $sql)) {
|
||||
mysqli_rollback($this->dblink);
|
||||
return ['ok'=>false,'msg'=>'INSERT failed: '.mysqli_error($this->dblink),'processed'=>$total,'target'=>$countTotal];
|
||||
}
|
||||
}
|
||||
|
||||
// progress after each slice
|
||||
$total += count($chunk);
|
||||
if ($reporter) {
|
||||
$pct = $countTotal ? min(100, (int)floor(($total / $countTotal) * 100)) : 0;
|
||||
$reporter($total, $countTotal, $pct);
|
||||
}
|
||||
}
|
||||
|
||||
mysqli_commit($this->dblink);
|
||||
|
||||
// advance cursor
|
||||
$lastId = (int)$rows[$n - 1]['wref'];
|
||||
}
|
||||
|
||||
// Restore checks (optional)
|
||||
@mysqli_query($this->dblink, "SET unique_checks=1");
|
||||
@mysqli_query($this->dblink, "SET foreign_key_checks=1");
|
||||
|
||||
// Analyze once at the end
|
||||
@mysqli_query($this->dblink, "ANALYZE TABLE `$CROP_TABLE`");
|
||||
|
||||
if ($reporter) { $reporter($total, $countTotal, 100); }
|
||||
return ['ok'=>true,'msg'=>'Croppers populated','processed'=>$total,'target'=>$countTotal];
|
||||
}
|
||||
|
||||
|
||||
// no need to cache, not used in any loops or more than once for each page load
|
||||
public function getAvailableExpansionTraining() {
|
||||
global $building, $session, $technology, $village;
|
||||
|
||||
$vilData = $this->getVillage($village->wid);
|
||||
$maxslots = (($vilData['exp1'] == 0 ? 1 : 0) + ($vilData['exp2'] == 0 ? 1 : 0) + ($vilData['exp3'] == 0 ? 1 : 0));
|
||||
$residence = $building->getTypeLevel(25);
|
||||
$palace = $building->getTypeLevel(26);
|
||||
$vilData = $this->getVillage($village->wid);
|
||||
$maxslots = (($vilData['exp1'] == 0 ? 1 : 0) + ($vilData['exp2'] == 0 ? 1 : 0) + ($vilData['exp3'] == 0 ? 1 : 0));
|
||||
$residence = $building->getTypeLevel(25);
|
||||
$palace = $building->getTypeLevel(26);
|
||||
|
||||
if($residence > 0) {
|
||||
$maxslots -= (3 - floor($residence / 10));
|
||||
}
|
||||
if($residence > 0) {
|
||||
$maxslots -= (3 - floor($residence / 10));
|
||||
}
|
||||
|
||||
if($palace > 0) {
|
||||
$maxslots -= (3 - floor(($palace - 5) / 5));
|
||||
}
|
||||
if($palace > 0) {
|
||||
$maxslots -= (3 - floor(($palace - 5) / 5));
|
||||
}
|
||||
|
||||
$q = "SELECT (u10+u20+u30) as R1, (u9+u19+u29) as R2 FROM " . TB_PREFIX . "units WHERE vref = ". (int) $village->wid;
|
||||
$result = mysqli_query($this->dblink,$q);
|
||||
$row = mysqli_fetch_array($result, MYSQLI_ASSOC);
|
||||
$settlers = $row['R1'];
|
||||
$chiefs = $row['R2'];
|
||||
// Units at home
|
||||
$q = "SELECT (u10+u20+u30) as R1, (u9+u19+u29) as R2
|
||||
FROM " . TB_PREFIX . "units
|
||||
WHERE vref = " . (int)$village->wid;
|
||||
$result = mysqli_query($this->dblink,$q);
|
||||
$row = mysqli_fetch_array($result, MYSQLI_ASSOC);
|
||||
$settlers = (int)$row['R1'];
|
||||
$chiefs = (int)$row['R2'];
|
||||
|
||||
$settlers += 3 * count($this->getMovement(5, $village->wid, 0));
|
||||
|
||||
$current_movement = $this->getMovement(3, $village->wid, 0);
|
||||
if(!empty($current_movement)) {
|
||||
foreach($current_movement as $build) {
|
||||
$settlers += $build['t10'];
|
||||
$chiefs += $build['t9'];
|
||||
}
|
||||
}
|
||||
// Movements
|
||||
$settlers += 3 * count($this->getMovement(5, $village->wid, 0));
|
||||
|
||||
$current_movement = $this->getMovement(4, $village->wid, 1);
|
||||
if(!empty($current_movement)) {
|
||||
foreach($current_movement as $build) {
|
||||
$settlers += $build['t10'];
|
||||
$chiefs += $build['t9'];
|
||||
}
|
||||
}
|
||||
$current_movement = $this->getMovement(3, $village->wid, 0);
|
||||
if(!empty($current_movement)) {
|
||||
foreach($current_movement as $build) {
|
||||
$settlers += (int)$build['t10'];
|
||||
$chiefs += (int)$build['t9'];
|
||||
}
|
||||
}
|
||||
|
||||
$q = "SELECT (u10+u20+u30) FROM " . TB_PREFIX . "enforcement WHERE `from` = ".(int) $village->wid;
|
||||
$result = mysqli_query($this->dblink,$q);
|
||||
$row = mysqli_fetch_row($result);
|
||||
if(!empty($row)) {
|
||||
foreach($row as $reinf) {
|
||||
$settlers += $reinf[0];
|
||||
}
|
||||
}
|
||||
$current_movement = $this->getMovement(4, $village->wid, 1);
|
||||
if(!empty($current_movement)) {
|
||||
foreach($current_movement as $build) {
|
||||
$settlers += (int)$build['t10'];
|
||||
$chiefs += (int)$build['t9'];
|
||||
}
|
||||
}
|
||||
|
||||
$q = "SELECT (u9+u19+u29) FROM " . TB_PREFIX . "enforcement WHERE `from` = ".(int) $village->wid;
|
||||
$result = mysqli_query($this->dblink,$q);
|
||||
$row = mysqli_fetch_row($result);
|
||||
if(!empty($row)) {
|
||||
foreach($row as $reinf) {
|
||||
$chiefs += $reinf[0];
|
||||
}
|
||||
}
|
||||
// FIX: Count ALL reinforcements properly (SUM over ALL rows)
|
||||
$q = "SELECT COALESCE(SUM(u10+u20+u30),0) AS s
|
||||
FROM " . TB_PREFIX . "enforcement
|
||||
WHERE `from` = " . (int)$village->wid;
|
||||
$result = mysqli_query($this->dblink,$q);
|
||||
$row = mysqli_fetch_array($result, MYSQLI_ASSOC);
|
||||
$settlers += (int)$row['s'];
|
||||
|
||||
$trainlist = $technology->getTrainingList(4);
|
||||
if(!empty($trainlist)) {
|
||||
foreach($trainlist as $train) {
|
||||
if($train['unit'] % 10 == 0) {
|
||||
$settlers += $train['amt'];
|
||||
}
|
||||
if($train['unit'] % 10 == 9) {
|
||||
$chiefs += $train['amt'];
|
||||
}
|
||||
}
|
||||
}
|
||||
$q = "SELECT COALESCE(SUM(u9+u19+u29),0) AS c
|
||||
FROM " . TB_PREFIX . "enforcement
|
||||
WHERE `from` = " . (int)$village->wid;
|
||||
$result = mysqli_query($this->dblink,$q);
|
||||
$row = mysqli_fetch_array($result, MYSQLI_ASSOC);
|
||||
$chiefs += (int)$row['c'];
|
||||
|
||||
$trappedTroops = $this->getPrisoners($village->wid, 1);
|
||||
if(!empty($trappedTroops)){
|
||||
foreach($trappedTroops as $trapped){
|
||||
$settlers += $trapped['t10'];
|
||||
$chiefs += $trapped['t9'];
|
||||
}
|
||||
}
|
||||
// Training queue (your existing logic)
|
||||
$trainlist = $technology->getTrainingList(4);
|
||||
if(!empty($trainlist)) {
|
||||
foreach($trainlist as $train) {
|
||||
if($train['unit'] % 10 == 0) {
|
||||
$settlers += (int)$train['amt'];
|
||||
}
|
||||
if($train['unit'] % 10 == 9) {
|
||||
$chiefs += (int)$train['amt'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$settlerslots = ($maxslots * 3) - ($chiefs * 3) - $settlers;
|
||||
$chiefslots = $maxslots - $chiefs - floor(($settlers + 2) / 3);
|
||||
// Trapped troops
|
||||
$trappedTroops = $this->getPrisoners($village->wid, 1);
|
||||
if(!empty($trappedTroops)){
|
||||
foreach($trappedTroops as $trapped){
|
||||
$settlers += (int)$trapped['t10'];
|
||||
$chiefs += (int)$trapped['t9'];
|
||||
}
|
||||
}
|
||||
|
||||
if(!$technology->getTech(($session->tribe - 1) * 10 + 9)) {
|
||||
$chiefslots = 0;
|
||||
}
|
||||
// Slot math (unchanged, but clamp to 0 to avoid negatives)
|
||||
$settlerslots = ($maxslots * 3) - ($chiefs * 3) - $settlers;
|
||||
$chiefslots = $maxslots - $chiefs - floor(($settlers + 2) / 3);
|
||||
|
||||
if(!$technology->getTech(($session->tribe - 1) * 10 + 9)) {
|
||||
$chiefslots = 0;
|
||||
}
|
||||
|
||||
if ($settlerslots < 0) $settlerslots = 0;
|
||||
if ($chiefslots < 0) $chiefslots = 0;
|
||||
|
||||
return ["chiefs" => $chiefslots, "settlers" => $settlerslots];
|
||||
}
|
||||
|
||||
return ["chiefs" => $chiefslots, "settlers" => $settlerslots];
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates how much artifacts affect troops speed, cranny efficency, etc.
|
||||
|
||||
@@ -1031,7 +1031,7 @@ define('CRANNY', 'Cranny');
|
||||
define('CURRENT_HIDDEN_UNITS', 'Currently hidden units per resource:');
|
||||
define('HIDDEN_UNITS_LEVEL', 'Hidden units per resource at level');
|
||||
define('UNITS', 'units');
|
||||
define('CRANNY_DESC', 'The cranny hides some of your resources in case the village gets attacked. These resources cannot get stolen.<br>At level 1 the cranny can hold 200 of each resource. The capacity of Gallic crannies is 1.5 times larger.<br>If a Teutonic hero attacks a village, crannies can hide only 80% of their normal capacity');
|
||||
define('CRANNY_DESC', 'The cranny hides some of your resources in case the village gets attacked. These resources cannot get stolen.<br>At level 1 the cranny can hold '.(100*((int)CRANNY_CAPACITY)).' of each resource. The capacity of Gallic crannies is 1.5 times larger.<br>If a Teutonic hero attacks a village, crannies can hide only 80% of their normal capacity');
|
||||
|
||||
define('TOWNHALL', 'Town Hall');
|
||||
define('CELEBRATIONS_COMMENCE_TOWNHALL', 'Celebrations can commence when the town hall is completed.');
|
||||
|
||||
Reference in New Issue
Block a user