Class CharacterItemFilterManager
_filter_item 資料表的查詢/寫入與其記憶體快取。
過濾設定以帳號(acc_id)為單位,故同帳號的所有角色共用同一份過濾清單:玩家只要設定一次,
之後該帳號任一角色擊殺怪物時,被過濾的道具皆不再掉落。被過濾的道具編號保存在 _filter_item
資料表(主鍵 (acc_id, item_id)),並於登入時(MapleCharacter.loadCharFromDB(int, MapleClient, boolean) /
MapleCharacter.ReconstructChr(CharacterTransfer, MapleClient, boolean))一次性載入到記憶體 Set 快取。
為何必須快取於記憶體:isFilterItem(int) 由
MapleMonsterKillManager 的掉落滾動(dropFromMonster)對每一筆掉落條目呼叫,
屬高頻熱路徑;若每次都查資料庫將嚴重拖慢掉落。因此本協作者於登入時把該帳號的過濾清單載入
執行緒安全的 Set,之後 isFilterItem 僅做記憶體
contains。新增/刪除(addFilterItem(int) /
subFilterItem(int))會同時更新資料庫與此快取,使後續掉落判定即時生效。
執行緒安全:讀取(isFilterItem,掉落/地圖執行緒)與寫入(add/sub,
NPC 腳本所在的玩家連線執行緒)可能並發,故快取採 ConcurrentHashMap.newKeySet()。
MapleCharacter 對外保留簽名完全相同的委派方法(addFilterItem /
subFilterItem / isFilterItem / getFilterItemInfo / getMapDropItemInfo),
因此遊戲內容腳本(如 scripts/special/0400_便利功能/_物品過濾.js)以
cm.getPlayer().addFilterItem(...) 等方式呼叫,完全不受協作者抽離影響。所有資料庫寫入經
Db 執行(僅關閉 Statement,不關閉共用 Connection),失敗時記錄 debug 並吞掉,
不影響遊戲流程。
-
Method Summary
Modifier and TypeMethodDescriptionvoidaddFilterItem(int itemId) 將指定道具加入本帳號的過濾清單(同步寫入資料庫與記憶體快取)。組出「目前過濾的道具」清單字串,供 NPC 對話框顯示(每個道具為可點選的連結,點選後可解除過濾)。組出「目前地圖上的掉落物」清單字串,供 NPC 對話框顯示(每個道具為可點選的連結,點選後可加入過濾)。booleanisFilterItem(int itemId) 查詢指定道具是否在本帳號的過濾清單中(記憶體快取查詢,掉落熱路徑使用)。void依角色所屬帳號 id 自_filter_item載入過濾道具清單到記憶體快取。voidsubFilterItem(int itemId) 將指定道具自本帳號的過濾清單移除(同步刪除資料庫列與記憶體快取項目)。
-
Method Details
-
loadFilterItems
public void loadFilterItems()依角色所屬帳號 id 自_filter_item載入過濾道具清單到記憶體快取。於帳號 id 已知後呼叫(
MapleCharacter.loadCharFromDB(int, MapleClient, boolean)的頻道伺服器分支、 以及換頻道的MapleCharacter.ReconstructChr(CharacterTransfer, MapleClient, boolean))。會先清空既有快取再重新載入,因此可安全地重複呼叫。 透過DatabaseConnection取得當前執行緒共用Connection執行唯讀查詢;發生例外時記錄 debug 並維持已載入到一半的內容(最壞情況退化為部分/不過濾,不影響其他流程)。 -
isFilterItem
public boolean isFilterItem(int itemId) 查詢指定道具是否在本帳號的過濾清單中(記憶體快取查詢,掉落熱路徑使用)。僅讀取
filterItems快取、不查資料庫;由MapleMonsterKillManager的dropFromMonster對每筆掉落條目呼叫,命中時該道具不掉落。楓幣掉落的條目 itemId 為0, 而過濾清單只會經由地圖掉落物(itemId > 50000)加入,故isFilterItem(0)恆為false, 不會誤過濾楓幣。- Parameters:
itemId- 道具編號- Returns:
true表示該道具被本帳號過濾(不應掉落);否則false
-
addFilterItem
public void addFilterItem(int itemId) 將指定道具加入本帳號的過濾清單(同步寫入資料庫與記憶體快取)。以
INSERT ... ON DUPLICATE KEY UPDATE寫入_filter_item(主鍵(acc_id, item_id)確保帳號內唯一、且防止並發重複),成功後加入記憶體快取使後續掉落判定即時生效。已在快取中時直接返回 (避免多餘的資料庫往返)。經Db.update(String, Object...)執行(僅關閉Statement,不關閉共用Connection);發生例外時記錄 debug 並吞掉。- Parameters:
itemId- 要過濾的道具編號
-
subFilterItem
public void subFilterItem(int itemId) 將指定道具自本帳號的過濾清單移除(同步刪除資料庫列與記憶體快取項目)。對
_filter_item以(acc_id, item_id)刪除對應列,並自記憶體快取移除,使該道具恢復正常掉落。 經Db.update(String, Object...)執行(僅關閉Statement,不關閉共用Connection);發生例外時記錄 debug 並吞掉。- Parameters:
itemId- 要解除過濾的道具編號
-
getFilterItemInfo
組出「目前過濾的道具」清單字串,供 NPC 對話框顯示(每個道具為可點選的連結,點選後可解除過濾)。讀取記憶體快取(依道具編號排序以確保顯示穩定),對每個道具產生
#L<id>#...#l連結 +#v<id>#圖示 +#z<id>#名稱的標記字串;連結的選擇索引即道具編號, 故腳本可直接以selection當道具編號呼叫subFilterItem(int)。清單為空時回傳提示字串。- Returns:
- 過濾清單的 NPC 標記字串;無任何過濾道具時回傳提示文字
-
getMapDropItemInfo
組出「目前地圖上的掉落物」清單字串,供 NPC 對話框顯示(每個道具為可點選的連結,點選後可加入過濾)。掃描角色目前地圖的所有掉落物(
MapleMapItem.getItemId()),略過非道具(itemId<= 50000,含楓幣)與不存在於道具資料(MapleItemInformationProvider.itemExists(int))者, 並對相同道具去重,對每個道具產生#L<id>#...#l連結;連結的選擇索引即道具編號,故腳本可直接以selection當道具編號呼叫addFilterItem(int)。地圖上沒有掉落物時回傳提示字串。- Returns:
- 地圖掉落物的 NPC 標記字串;地圖上無掉落物時回傳提示文字
-