在 Xnova 這類基於 PHP 的網頁遊戲中,艦隊活動並非由定時任務驅動,而是採用「玩家請求觸發」的被動計算模式。每當用戶訪問頁面,common.php 都會執行檢查,掃描資料庫中是否有艦隊抵達目的地或返回起點。這種設計雖然簡單,但隨著玩家增長,每次請求都需全表掃描 fleets 表,效率極低。
// 檢查是否有到達目的地的艦隊
$_fleets = doquery("SELECT * FROM {{table}} WHERE 'fleet_start_time' <= '".time()."';", 'fleets');
// 循環處理每個艦隊
while ($row = mysql_fetch_array($_fleets)) {
$array = array(
'galaxy' => $row['fleet_start_galaxy'],
'system' => $row['fleet_start_system'],
'planet' => $row['fleet_start_planet'],
'planet_type' => $row['fleet_start_type']
);
$temp = FlyingFleetHandler($array);
}
// 檢查是否有返回出發地的艦隊
$_fleets = doquery("SELECT * FROM {{table}} WHERE 'fleet_end_time' <= '".time()."';", 'fleets');
while ($row = mysql_fetch_array($_fleets)) {
$array = array(
'galaxy' => $row['fleet_end_galaxy'],
'system' => $row['fleet_end_system'],
'planet' => $row['fleet_end_planet'],
'planet_type' => $row['fleet_end_type']
);
$temp = FlyingFleetHandler($array);
}
優化建議:應避免在 common.php 中全表掃描。可改為僅傳遞單一艦隊 ID 給處理函數,並建立索引優化查詢;或引入任務佇列(如 Gearman、Redis 列表)實現異步處理,將艦隊結算從 HTTP 請求中剝離。
該函數作為艦隊邏輯的總入口,採用表鎖確保數據一致性,根據 fleet_mission 任務類型分發至對應處理器:
// 鎖定相關表,防止併發衝突
doquery("LOCK TABLE {{table}}lunas WRITE, {{table}}rw WRITE, {{table}}errors WRITE, {{table}}messages WRITE, {{table}}fleets WRITE, {{table}}planets WRITE, {{table}}galaxy WRITE, {{table}}users WRITE", "");
// 複雜的 SQL 查詢獲取當前座標相關的所有艦隊
$QryFleet = "SELECT * FROM {{table}} WHERE ( ... 條件構建 ... ) AND ( `fleet_start_time` < '".time()."' OR `fleet_end_time` < '".time()."' );";
$fleetquery = doquery($QryFleet, 'fleets');
// 根據任務類型分發
while ($CurrentFleet = mysql_fetch_array($fleetquery)) {
switch ($CurrentFleet["fleet_mission"]) {
case 1: MissionCaseAttack($CurrentFleet); break; // 普通攻擊
case 2: /* ACS 攻擊,當前未啟用 */ break;
case 3: MissionCaseTransport($CurrentFleet); break; // 運輸
case 4: MissionCaseStay($CurrentFleet); break; // 派遣
case 5: MissionCaseStayAlly($CurrentFleet); break; // 聯合派遣 (ACS 防禦)
case 6: MissionCaseSpy($CurrentFleet); break; // 偵查
case 7: MissionCaseColonisation($CurrentFleet); break; // 殖民
case 8: MissionCaseRecycling($CurrentFleet); break; // 回收
case 9: MissionCaseDestruction($CurrentFleet); break; // 毀月
case 10: break; // 保留
case 15: MissionCaseExpedition($CurrentFleet); break; // 遠征/探險
default: doquery("DELETE FROM {{table}} WHERE `fleet_id` = '".$CurrentFleet['fleet_id']."';", 'fleets');
}
}
doquery("UNLOCK TABLES", "");
MissionCase* 函數專注單一任務邏輯,結構清晰,便於維護與擴展。default 分支刪除非法艦隊數據,體現防禦性編程思想。理解這段經典代碼,不僅能掌握早期瀏覽器遊戲的架構精髓,更能啟發現代高併發系統的設計思路。