Class MapleClient
- All Implemented Interfaces:
Serializable
本類別代表一條由 MapleServerHandler 在連線建立時掛上 CLIENT_KEY channel 屬性的 Netty 連線,
持有底層 Channel、收送兩組 MapleAESOFB 加解密器,以及帳號/封鎖/頻道等狀態;
其登入狀態以 LOGIN_* 與 CASH_SHOP_TRANSITION/CHANGE_CHANNEL 等 byte 常數構成狀態機,
跨 LoginServer/ChannelServer/CashShopServer 流轉。職責與主要協作者:
- 持有目前操控的
MapleCharacter(player),並提供登入/登出、頻道轉移與斷線清理。 - 快取 per-client 的 GraalJS 腳本引擎(
engines,ScriptEngine)與 reactor 腳本鎖,供scripting.*管理器取用。 - 透過
DatabaseConnection載入/更新帳號資料,並以npc_mutex/login_mutex等鎖序列化關鍵互動。
- See Also:
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprotected static final class角色名稱與編號的不可變配對。 -
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final byte登入狀態機常數:正轉移至商城伺服器的過渡狀態。static final byte登入狀態機常數:自商城伺服器返回的過渡狀態。static final byte登入狀態機常數:頻道切換中的過渡狀態。static final io.netty.util.AttributeKey<MapleClient> Netty channel 屬性鍵:連線建立時由MapleServerHandler將對應的MapleClient掛在此鍵上,後續封包處理皆透過channel.attr(CLIENT_KEY)取回本連線。static final int帳號預設可建立的角色欄位數量。static final byte登入狀態機常數:停留在角色選擇畫面。static final byte登入狀態機常數:已登入商城伺服器。static final byte登入狀態機常數:已完成登入並進入遊戲頻道。static final byte登入狀態機常數:已登入交易(MTS)伺服器。static final byte登入狀態機常數:尚未登入(初始狀態)。static final byte登入狀態機常數:登入伺服器與頻道伺服器之間的過渡狀態(轉移期間視為未完全登入)。static final byte登入狀態機常數:停留在伺服器(世界)選擇畫面。shortstatic final byte登入狀態機常數:正轉移至交易(MTS)伺服器的過渡狀態。static final byte登入狀態機常數:自交易(MTS)伺服器返回的過渡狀態。 -
Constructor Summary
ConstructorsConstructorDescriptionMapleClient(MapleAESOFB send, MapleAESOFB receive, io.netty.channel.Channel session) 建立一條玩家連線,綁定收送兩組加解密器與底層 Netty channel。 -
Method Summary
Modifier and TypeMethodDescriptionvoidbanMacs()封鎖本帳號目前所有已知的 MAC 位址。static final void將給定的多個 MAC 位址寫入 MAC 封鎖名單(macbans)。static booleanbanSingleMacs(String macData) 將單一 MAC 位址加入封鎖名單。boolean判斷距離上次點擊 NPC 是否已超過防連點冷卻(500 毫秒)。booleancanMakeCharacter(int serverId) 判斷本帳號在指定世界是否仍有空餘角色欄位可建立新角色。final booleancheckBirthDate(int date) 比對輸入日期是否與本帳號記錄的生日相符。final boolean驗證本連線目前的來源 IP 是否與資料庫記錄的SessionIP相符,且帳號未被封鎖。boolean驗證輸入的二次密碼是否正確,並在需要時就地升級其雜湊格式。void清除本連線快取的帳號相關資訊,重置為未登入的初始狀態。voidcreatedChar(int id) 將新建立的角色編號加入本連線的授權清單,使其可立即被選用登入。final void將本連線的偵錯資訊附加到給定的字串建構器。final intdeleteCharacter(int cid) 刪除指定角色,並一併清除其在各資料表中的所有關聯資料。final voiddisconnect(boolean RemoveInChannelServer, boolean fromCS) 中斷本連線(非伺服器關閉情境)。final voiddisconnect(boolean RemoveInChannelServer, boolean fromCS, boolean shutdown) 完整中斷本連線:存檔角色、清理跨伺服器協作狀態並釋放資源。static final intfindAccIdForCharacterName(String charName) 依角色名稱查詢其所屬的帳號編號。intReturns 0 on success, a state to be used forLoginPacket.getLoginFailed(int)otherwise.static booleanFullyunban(String charname) 對指定角色的帳號執行完整解封(帳號封鎖 + IP/MAC 封鎖)。boolean為此帳號在目前世界增加一個角色欄位。intgetAccID()取得本連線綁定的帳號編號。final String取得此連線的登入帳號名稱。byte取得本帳號的封鎖原因代碼。final int取得此連線目前所在的頻道編號。final ChannelServer取得此連線目前所在頻道對應的ChannelServer實例。int取得此帳號在目前世界可用的角色欄位數。final String取得此連線記錄的主要網卡 MAC 位址。boolean判斷此連線是否已被標記為待關閉。final Timestamp查詢此帳號的建立時間。final byte取得此帳號的性別。final ScheduledFuture<?> 取得此連線目前的閒置逾時排程任務。final long取得最後一次送出 ping 封包的時間戳記。final long取得最後一次收到客戶端 pong 回應的時間戳記。final int取得最近一次量測的網路延遲。final LockgetLock()取得此 client 的通用互斥鎖(公平鎖)。final byte自資料庫查詢本帳號的即時登入狀態,並一併更新生日快取與本機loggedIn旗標。static final StringgetLogMessage(MapleCharacter cfor, String message) 產生一則含角色身分前綴的記錄訊息(無參數格式化)。static final StringgetLogMessage(MapleCharacter cfor, String message, Object... parms) 產生一則含角色身分前綴並套用參數格式化的記錄訊息。static final StringgetLogMessage(MapleClient cfor, String message) 產生一則含連線身分前綴的記錄訊息(無參數格式化)。static final StringgetLogMessage(MapleClient cfor, String message, Object... parms) 產生一則含連線身分前綴並套用參數格式化的記錄訊息(其餘多載皆收斂至此)。getMacs()取得此連線回報的所有 MAC 位址集合。final Lock取得此 client 的 NPC 互動鎖。取得此連線目前操控的角色實體。final ReentrantLockgetReactorScriptLock(int reactorId) Track B C4:取得此 client 對應reactorId的ReentrantLock。final MapleAESOFB取得接收封包用的 AES-OFB 解密器。int查詢並回傳此帳號的獎勵等級。final ScriptEnginegetScriptEngine(String name) 依名稱取得先前快取的ScriptEngine。final String取得此帳號的第二組密碼(防護密碼)。final MapleAESOFB取得送出封包用的 AES-OFB 加密器。final io.netty.channel.Channel取得此連線底層的 Netty channel。final String取得本連線對端的 IP 位址(去除埠號部分)。取得本帳號暫時封鎖(tempban)的到期時間。取得此連線的暫存 IP 位址。intgetVip()查詢並回傳此帳號的 VIP 等級。final intgetWorld()取得此連線所屬的世界(World)編號。boolean檢查目前連線來源 IP 是否在 IP 封鎖名單(ipbans)中。boolean檢查本連線蒐集到的任一 MAC 位址是否在 MAC 封鎖名單(macbans)中。booleanisBanned()判斷此帳號是否處於被封鎖狀態。booleanisBannedIP(String ip) 檢查指定 IP 是否在 IP 封鎖名單(ipbans)中。booleanisBannedMac(String mac) 檢查指定的 MAC 位址是否在 MAC 封鎖名單(macbans)中。boolean判斷此連線是否已登入商城伺服器。final booleanisGm()判斷此帳號是否為 GM(管理員)帳號。boolean判斷伺服器是否以本機(localhost)模式運行。boolean判斷此連線目前是否處於已登入狀態(依本機快取旗標,不查詢資料庫)。boolean判斷此連線是否處於「已登入但尚未進入遊戲」階段(伺服器選擇或角色選擇畫面)。boolean判斷此連線是否處於受監控狀態。boolean判斷此連線目前是否接受處理封包。voidloadAccountData(int accountID) 自資料庫載入指定帳號的基本資料並填入本連線狀態。loadCharacterNames(int serverId) 載入本帳號在指定世界下所有角色的名稱清單。loadCharacterNamesByAccId(int accId) 載入指定帳號底下所有角色的名稱。final List<MapleCharacter> loadCharacters(int serverId) 載入本帳號在指定世界(伺服器)下的所有角色,供角色選擇畫面使用。voidloadNecessaryAccInfoByCharID(int charid) 依角色編號回填此連線所需的基本帳號資訊。int以帳號與密碼進行登入驗證,並依結果更新本連線的帳號狀態。final booleanlogin_Auth(int id) 檢查指定角色是否屬於本連線的授權清單(防止以非本帳號角色登入)。final void標記已收到客戶端的 pong 回應,更新最後 pong 時間為目前時間。final voidremovalTask(boolean shutdown) 在玩家離線前對其角色執行清理與狀態收尾。void清除上次 NPC 點擊時間,立即解除防連點冷卻。final voidremoveScriptEngine(String name) 從快取移除指定名稱的ScriptEngine。voidsendPacket(byte[] packet) 將已組裝完成的封包寫入此連線並送出。final voidsendPing()送出 ping 封包並排程逾時檢查。voidsetAccID(int id) 設定本連線綁定的帳號編號。final voidsetAccountName(String accountName) 設定此連線的登入帳號名稱。final voidsetChannel(int channel) 設定此連線目前所在的頻道編號。void記錄一次 NPC 點擊時間,啟動防連點冷卻。final voidsetGender(byte gender) 設定此帳號的性別。final voidsetIdleTask(ScheduledFuture<?> idleTask) 設定此連線的閒置逾時排程任務。void設定本連線目前的 MAC 位址(僅更新記憶體欄位,不寫入資料庫)。voidsetMonitored(boolean m) 設定此連線是否受監控。voidsetPlayer(MapleCharacter player) 設定此連線目前操控的角色實體。voidsetReceiving(boolean m) 設定此連線是否接受處理封包。voidsetRewardLevel(int reward) 設定此帳號的獎勵等級並立即寫回資料庫。final voidsetScriptEngine(String name, ScriptEngine e) 以指定名稱快取一個ScriptEngine。final voidsetSecondPassword(String secondPassword) 設定此帳號的第二組密碼(防護密碼)。void設定此連線的暫存 IP 位址。voidsetVip(int vip) 設定此帳號的 VIP 等級並立即寫回資料庫。final voidsetWorld(int world) 設定此連線所屬的世界(World)編號。static final byte依角色名稱解除其所屬帳號的封鎖。static byte依角色名稱解除其帳號最近登入 IP 的封鎖。static final byteunbanIPMacs(String charname) 依角色名稱解除其帳號的 IP 與 MAC 封鎖。static final byte依角色名稱解除其帳號的「地獄封鎖」(hellban)。final void因帳號於他處重複登入而強制斷線並關閉連線。final voidupdateCharacterCards(Map<Integer, Integer> cids) 依據指定的「欄位位置 → 角色編號」對應,重建本帳號的角色卡(character cards)資料表。final void將本連線目前的性別欄位寫回資料庫(accounts.gender)。final voidupdateLoginState(int newstate, String SessionID) 更新本帳號的登入狀態,並同步寫回資料庫與本機快取旗標。voidupdateMacs(String macData) 將本帳號的 MAC 清單寫回資料庫(accounts.macs)。final void將本連線目前的二次密碼以加鹽 SHA-512 重新雜湊後寫回資料庫(accounts.2ndpassword/salt2)。
-
Field Details
-
LOGIN_NOTLOGGEDIN
public static final transient byte LOGIN_NOTLOGGEDIN登入狀態機常數:尚未登入(初始狀態)。寫入accounts.loggedin並透過updateLoginState(int, String)切換。- See Also:
-
LOGIN_SERVER_TRANSITION
public static final transient byte LOGIN_SERVER_TRANSITION登入狀態機常數:登入伺服器與頻道伺服器之間的過渡狀態(轉移期間視為未完全登入)。- See Also:
-
LOGIN_LOGGEDIN
public static final transient byte LOGIN_LOGGEDIN登入狀態機常數:已完成登入並進入遊戲頻道。- See Also:
-
LOGIN_SERVERLIST
public static final transient byte LOGIN_SERVERLIST登入狀態機常數:停留在伺服器(世界)選擇畫面。- See Also:
-
CASH_SHOP_TRANSITION
public static final transient byte CASH_SHOP_TRANSITION登入狀態機常數:正轉移至商城伺服器的過渡狀態。- See Also:
-
LOGIN_CS_LOGGEDIN
public static final transient byte LOGIN_CS_LOGGEDIN登入狀態機常數:已登入商城伺服器。- See Also:
-
CHANGE_CHANNEL
public static final transient byte CHANGE_CHANNEL登入狀態機常數:頻道切換中的過渡狀態。- See Also:
-
MAPLE_TRADE_TRANSITION
public static final transient byte MAPLE_TRADE_TRANSITION登入狀態機常數:正轉移至交易(MTS)伺服器的過渡狀態。- See Also:
-
LOGIN_MTS_LOGGEDIN
public static final transient byte LOGIN_MTS_LOGGEDIN登入狀態機常數:已登入交易(MTS)伺服器。- See Also:
-
CASH_SHOP_TRANSITION_LEAVE
public static final transient byte CASH_SHOP_TRANSITION_LEAVE登入狀態機常數:自商城伺服器返回的過渡狀態。- See Also:
-
MAPLE_TRADE_TRANSITION_LEAVE
public static final transient byte MAPLE_TRADE_TRANSITION_LEAVE登入狀態機常數:自交易(MTS)伺服器返回的過渡狀態。- See Also:
-
LOGIN_CHARLIST
public static final transient byte LOGIN_CHARLIST登入狀態機常數:停留在角色選擇畫面。- See Also:
-
DEFAULT_CHARSLOT
public static final int DEFAULT_CHARSLOT帳號預設可建立的角色欄位數量。- See Also:
-
CLIENT_KEY
Netty channel 屬性鍵:連線建立時由MapleServerHandler將對應的MapleClient掛在此鍵上,後續封包處理皆透過channel.attr(CLIENT_KEY)取回本連線。 -
loginAttempt
public transient short loginAttempt
-
-
Constructor Details
-
MapleClient
建立一條玩家連線,綁定收送兩組加解密器與底層 Netty channel。由
MapleServerHandler於連線建立時建構,隨後完成 AES-OFB 握手並將本實例 掛上CLIENT_KEYchannel 屬性。- Parameters:
send- 送出封包用的MapleAESOFB加密器receive- 接收封包用的MapleAESOFB解密器session- 底層的 NettyChannel
-
-
Method Details
-
getReceiveCrypto
-
getSendCrypto
-
getSession
public final io.netty.channel.Channel getSession()取得此連線底層的 Netty channel。- Returns:
- 底層的
Channel
-
getLock
-
getNPCLock
-
getReactorScriptLock
Track B C4:取得此 client 對應reactorId的ReentrantLock。GraalJS 下ReactorScriptManager.act(MapleClient, MapleReactor)以此序列化「同一 (client, reactorId)」的並發進入 (per-client 引擎共用一條 GraalJS Context、禁多執行緒並發);不同 reactorId 仍並行。回傳ReentrantLock以容忍腳本同執行緒重入 act()(rm.hitReactor 同 rid 回呼,目前無腳本如此,純防禦)。 -
getPlayer
取得此連線目前操控的角色實體。- Returns:
- 目前的
MapleCharacter;在角色選擇完成之前(仍在登入/角色清單階段)為null
-
setPlayer
設定此連線目前操控的角色實體。- Parameters:
player- 欲綁定的MapleCharacter,可為null(例如斷線清理時清空)
-
createdChar
public void createdChar(int id) 將新建立的角色編號加入本連線的授權清單,使其可立即被選用登入。- Parameters:
id- 新建立角色的角色編號
-
login_Auth
public final boolean login_Auth(int id) 檢查指定角色是否屬於本連線的授權清單(防止以非本帳號角色登入)。- Parameters:
id- 欲驗證的角色編號- Returns:
- 若該角色已在授權清單中則為
true
-
loadCharacters
載入本帳號在指定世界(伺服器)下的所有角色,供角色選擇畫面使用。會自資料庫讀取每個角色(
MapleCharacter.loadCharFromDB(int, MapleClient, boolean))並載入其角色卡資料, 同時把每個角色的等級/職業記入charInfo以供更新角色卡,並補登未在授權清單中的角色。 屬於高成本操作(逐角色查詢,原始碼註記待最佳化)。- Parameters:
serverId- 世界(伺服器)編號- Returns:
- 該帳號於此世界的
MapleCharacter清單;無角色時為空清單
-
updateCharacterCards
依據指定的「欄位位置 → 角色編號」對應,重建本帳號的角色卡(character cards)資料表。會寫入資料庫(透過共用的
ThreadLocal連線):先刪除本帳號既有的所有角色卡列, 再逐一插入新對應;只插入符合CharacterCardFactory.canHaveCard(int, int)條件的角色。 若charInfo為空(無角色)則直接返回。SQL 失敗僅記錄而不拋出。- Parameters:
cids- 欄位位置(key)對應到角色編號(value)的對照表
-
canMakeCharacter
public boolean canMakeCharacter(int serverId) 判斷本帳號在指定世界是否仍有空餘角色欄位可建立新角色。會查詢資料庫取得該世界現有角色數,與
getCharacterSlots()比較。- Parameters:
serverId- 世界(伺服器)編號- Returns:
- 現有角色數小於可用欄位數時為
true
-
loadCharacterNames
-
isLoggedIn_beforeInGame
public boolean isLoggedIn_beforeInGame()判斷此連線是否處於「已登入但尚未進入遊戲」階段(伺服器選擇或角色選擇畫面)。會經由
getLoginState()查詢資料庫取得即時登入狀態。- Returns:
- 登入狀態為
LOGIN_SERVERLIST或LOGIN_CHARLIST時為true
-
isCSLoggedIn
public boolean isCSLoggedIn()判斷此連線是否已登入商城伺服器。會經由
getLoginState()查詢資料庫取得即時登入狀態。- Returns:
- 登入狀態為
LOGIN_CS_LOGGEDIN時為true
-
isLoggedIn
public boolean isLoggedIn()判斷此連線目前是否處於已登入狀態(依本機快取旗標,不查詢資料庫)。- Returns:
loggedIn旗標為真且已綁定有效帳號編號(accId >= 0)時為true
-
getTempBanCalendar
-
getBanReason
public byte getBanReason()取得本帳號的封鎖原因代碼。- Returns:
- 封鎖原因代碼(
byte)
-
hasBannedIP
public boolean hasBannedIP()檢查目前連線來源 IP 是否在 IP 封鎖名單(ipbans)中。會查詢資料庫,比對方式為前綴
LIKE(涵蓋以該 IP 開頭的封鎖網段)。- Returns:
- 該 IP 命中任一封鎖規則時為
true;查詢失敗時為false
-
isBannedMac
檢查指定的 MAC 位址是否在 MAC 封鎖名單(macbans)中。會查詢資料庫。全零位址(
00-00-00-00-00-00)或長度不為 17 的字串視為無效,直接回傳false。- Parameters:
mac- 欲查驗的 MAC 位址字串- Returns:
- 該 MAC 命中封鎖名單時為
true;無效或查詢失敗時為false
-
hasBannedMac
public boolean hasBannedMac()檢查本連線蒐集到的任一 MAC 位址是否在 MAC 封鎖名單(macbans)中。以本連線目前的
macs集合動態組出IN (...)查詢比對資料庫; 集合為空時直接回傳false。- Returns:
- 任一 MAC 命中封鎖名單時為
true;無 MAC 或查詢失敗時為false
-
banMacs
public void banMacs()封鎖本帳號目前所有已知的 MAC 位址。必要時先自資料庫載入帳號的 MAC 清單(
accounts.macs),再委派banMacs(String[])寫入macbans。SQL 失敗僅記錄而不拋出。 -
banMacs
將給定的多個 MAC 位址寫入 MAC 封鎖名單(macbans)。會寫入資料庫:先讀取
macfilters過濾規則,凡符合任一過濾正則的 MAC 會被跳過、 其餘逐筆插入;因 UNIQUE 鍵造成的重複插入失敗會被刻意忽略。SQL 失敗僅記錄而不拋出。- Parameters:
macs- 欲封鎖的 MAC 位址陣列
-
isBannedIP
檢查指定 IP 是否在 IP 封鎖名單(ipbans)中。會查詢資料庫,比對方式為前綴
LIKE(涵蓋以該 IP 開頭的封鎖網段)。- Parameters:
ip- 欲查驗的 IP 位址字串- Returns:
- 該 IP 命中任一封鎖規則時為
true;查詢失敗時為false
-
finishLogin
public int finishLogin()Returns 0 on success, a state to be used forLoginPacket.getLoginFailed(int)otherwise.- Returns:
- The state of the login.
-
clearInformation
public void clearInformation()清除本連線快取的帳號相關資訊,重置為未登入的初始狀態。重設帳號名稱、帳號編號、二次密碼/鹽值、GM 旗標、登入旗標、封鎖原因、暫封時間與性別, 並清空
charInfo。僅作用於本機記憶體狀態,不寫入資料庫。 -
loadAccountData
public void loadAccountData(int accountID) 自資料庫載入指定帳號的基本資料並填入本連線狀態。會查詢
accounts表,讀取 VIP、二次密碼/鹽值、GM 旗標、性別與 MAC; 若存在二次密碼則以LoginCrypto.rand_r還原。例外僅記錄而不拋出。- Parameters:
accountID- 欲載入的帳號編號
-
login
以帳號與密碼進行登入驗證,並依結果更新本連線的帳號狀態。會查詢並可能寫入資料庫:自
accounts讀取密碼雜湊、鹽值、封鎖狀態、VIP、GM、性別等, 支援多種雜湊格式(legacy、SHA-1、加鹽 SHA-512)並在需要時就地升級密碼雜湊(UPDATE accounts); 已封鎖(非 GM)回傳封鎖碼,banned == -1時呼叫unban()解封。 驗證成功(0)時會先ChannelServer.forceRemovePlayerByAccId(MapleClient, int)踢除既有連線並把登入狀態重設為LOGIN_NOTLOGGEDIN,最後設定loggedIn為真。- Parameters:
login- 帳號名稱pwd- 明文密碼ipMacBanned- 呼叫端先行判定的 IP/MAC 封鎖旗標- Returns:
- 登入結果代碼:
0成功;3已封鎖;4密碼/Session 不符;5帳號不存在(預設值)
-
CheckSecondPassword
驗證輸入的二次密碼是否正確,並在需要時就地升級其雜湊格式。支援 legacy、SHA-1 與加鹽 SHA-512 三種格式;若命中前兩者會以加鹽 SHA-512 重新雜湊並 寫回
accounts(資料庫寫入)。升級寫入失敗時回傳false。- Parameters:
in- 玩家輸入的明文二次密碼- Returns:
- 二次密碼正確時為
true
-
unban
依角色名稱解除其所屬帳號的封鎖。會查詢資料庫由
characters反查accountid,再對accounts執行解封(banned = 0、清空banreason)。- Parameters:
charname- 角色名稱- Returns:
0解封成功;-1查無此角色;-2過程發生 SQL 例外
-
setMacs
設定本連線目前的 MAC 位址(僅更新記憶體欄位,不寫入資料庫)。- Parameters:
macData- MAC 位址字串
-
updateMacs
將本帳號的 MAC 清單寫回資料庫(accounts.macs)。SQL 失敗僅記錄而不拋出。
- Parameters:
macData- 欲儲存的 MAC 清單字串
-
setAccID
public void setAccID(int id) 設定本連線綁定的帳號編號。- Parameters:
id- 帳號編號
-
getAccID
public int getAccID()取得本連線綁定的帳號編號。- Returns:
- 帳號編號;尚未登入時為
-1
-
updateLoginState
更新本帳號的登入狀態,並同步寫回資料庫與本機快取旗標。會寫入資料庫:更新
accounts的loggedin、SessionIP與lastlogin。 隨後重算本機loggedIn/serverTransition旗標——各種「過渡」狀態 (商城/交易/頻道切換/登入伺服器轉移)會將serverTransition設為真且loggedIn設為偽;LOGIN_NOTLOGGEDIN則兩者皆清為偽。SQL 失敗僅記錄而不拋出。- Parameters:
newstate- 新的登入狀態(LOGIN_*/過渡常數之一)SessionID- 寫入的 Session IP 字串
-
updateGender
public final void updateGender()將本連線目前的性別欄位寫回資料庫(accounts.gender)。SQL 失敗僅記錄而不拋出。
-
updateSecondPassword
public final void updateSecondPassword()將本連線目前的二次密碼以加鹽 SHA-512 重新雜湊後寫回資料庫(accounts.2ndpassword/salt2)。SQL 失敗僅記錄而不拋出。
-
getLoginState
public final byte getLoginState()自資料庫查詢本帳號的即時登入狀態,並一併更新生日快取與本機loggedIn旗標。會讀取
accounts的loggedin、lastlogin、banned與生日; 若帳號不存在或已封鎖,會關閉底層 session 並拋出DatabaseException。 對於各種「過渡」狀態,若lastlogin距今逾 20 秒(連線逾時)會就地把狀態重設為LOGIN_NOTLOGGEDIN(含一次updateLoginState(int, String)寫入)。- Returns:
- 目前的登入狀態(
byte) - Throws:
DatabaseException- 帳號不存在、已封鎖,或查詢發生 SQL 例外時
-
checkBirthDate
public final boolean checkBirthDate(int date) 比對輸入日期是否與本帳號記錄的生日相符。比對的是
birthday快取欄位,其值在最近一次getLoginState()查詢時被更新。- Parameters:
date- 欲比對的生日(整數格式,如yyyyMMdd)- Returns:
- 與帳號生日相符時為
true
-
removalTask
public final void removalTask(boolean shutdown) 在玩家離線前對其角色執行清理與狀態收尾。此方法會大量變更角色與地圖狀態:取消所有 buff/debuff;處理進行中的結婚任務狀態; 在監獄地圖時結算剩餘監禁秒數;標記角色待移除;通知所屬活動實例玩家離線;關閉或保留其玩家商店; 清空通訊員;針對特定 Boss 地圖在伺服器關閉時重置任務時間、或在仍存活時登記斷線;最後將角色自地圖移除。 任何
Throwable皆會被攔截並寫入錯誤檔,不向外拋出。- Parameters:
shutdown- 是否為伺服器關閉流程觸發;影響商店關閉方式與 Boss 地圖任務時間的處理
-
disconnect
public final void disconnect(boolean RemoveInChannelServer, boolean fromCS) 中斷本連線(非伺服器關閉情境)。等同於以
shutdown = false呼叫disconnect(boolean, boolean, boolean)。- Parameters:
RemoveInChannelServer- 是否一併自頻道伺服器(或商城)的玩家儲存中移除此玩家fromCS- 是否由商城伺服器情境發起
-
disconnect
public final void disconnect(boolean RemoveInChannelServer, boolean fromCS, boolean shutdown) 完整中斷本連線:存檔角色、清理跨伺服器協作狀態並釋放資源。此方法有大量副作用與跨伺服器效果:先呼叫
removalTask(boolean)收尾並saveToDB存檔; 透過World處理通訊員離開、組隊上下線與隊長轉移、好友上下線、公會與家族的線上狀態; 依fromCS與World.Find.findChannel(int)結果判斷實際所在伺服器(必要時改以正確情境重呼自己); 視RemoveInChannelServer自頻道伺服器或商城玩家儲存移除此玩家;最後在非過渡且仍登入時把登入狀態 重設為LOGIN_NOTLOGGEDIN,並清空 per-client 腳本引擎快取(engines.clear())。 例外會被攔截、記錄並寫入錯誤檔。- Parameters:
RemoveInChannelServer- 是否一併自頻道伺服器(或商城)的玩家儲存中移除此玩家fromCS- 是否由商城伺服器情境發起shutdown- 是否為伺服器關閉流程觸發;為真時僅存檔並提前返回,略過跨伺服器離線處理
-
getSessionIPAddress
-
CheckIPAddress
public final boolean CheckIPAddress()驗證本連線目前的來源 IP 是否與資料庫記錄的SessionIP相符,且帳號未被封鎖。會查詢資料庫(
accounts)。未綁定帳號(accId < 0)時回傳false; 已封鎖則判定不可登入。查詢發生 SQL 例外時保守地回傳true(記錄但不阻擋)。- Returns:
- IP 相符且未封鎖時為
true;不符或已封鎖時為false
-
DebugMessage
將本連線的偵錯資訊附加到給定的字串建構器。輸出對端位址、連線是否啟用/開啟、是否已設定
CLIENT_KEY屬性、是否已登入,以及是否已綁定角色。- Parameters:
sb- 用於收集偵錯文字的StringBuilder
-
getChannel
public final int getChannel()取得此連線目前所在的頻道編號。- Returns:
- 頻道編號;登入伺服器階段或尚未指派時為初始值
-
getChannelServer
取得此連線目前所在頻道對應的ChannelServer實例。- Returns:
- 對應頻道的
ChannelServer;若該頻道未啟動則可能為null
-
deleteCharacter
public final int deleteCharacter(int cid) 刪除指定角色,並一併清除其在各資料表中的所有關聯資料。此方法會大量寫入資料庫(透過共用的
ThreadLocal連線):先驗證角色屬於本帳號 (accountid必須相符),處理公會與家族的離隊,接著對characters及 二十餘張關聯表(道具、技能、好友、任務、傳送點、拍賣等)逐一執行刪除。 視伺服器設定log_delchr寫入刪除角色記錄檔,並在玩家開啟 GM 監聽時對所有 GM 廣播封包。- Parameters:
cid- 欲刪除角色的角色編號- Returns:
- 結果代碼:
0表示刪除成功;9表示查無此角色(或不屬於本帳號);22表示角色為公會會長無法刪除;10表示刪除過程發生例外
-
getGender
public final byte getGender()取得此帳號的性別。- Returns:
- 性別代碼(
0為男性、1為女性)
-
setGender
public final void setGender(byte gender) 設定此帳號的性別。- Parameters:
gender- 性別代碼(0為男性、1為女性)
-
getSecondPassword
-
setSecondPassword
設定此帳號的第二組密碼(防護密碼)。- Parameters:
secondPassword- 欲設定的第二組密碼
-
getAccountName
-
setAccountName
-
setChannel
public final void setChannel(int channel) 設定此連線目前所在的頻道編號。- Parameters:
channel- 頻道編號
-
getWorld
public final int getWorld()取得此連線所屬的世界(World)編號。- Returns:
- 世界編號
-
setWorld
public final void setWorld(int world) 設定此連線所屬的世界(World)編號。- Parameters:
world- 世界編號
-
getLatency
public final int getLatency()取得最近一次量測的網路延遲。以最後一次收到 pong 的時間減去最後一次送出 ping 的時間計算; 若結果為負值(pong 尚未回應),
sendPing()排程的逾時檢查會將連線斷開。- Returns:
- 延遲毫秒數
-
getLastPong
public final long getLastPong()取得最後一次收到客戶端 pong 回應的時間戳記。- Returns:
- 時間戳記(
System.currentTimeMillis()毫秒)
-
getLastPing
public final long getLastPing()取得最後一次送出 ping 封包的時間戳記。- Returns:
- 時間戳記(
System.currentTimeMillis()毫秒)
-
pongReceived
public final void pongReceived()標記已收到客戶端的 pong 回應,更新最後 pong 時間為目前時間。由處理 pong 封包的處理器呼叫,用於計算
網路延遲。 -
sendPing
public final void sendPing()送出 ping 封包並排程逾時檢查。記錄送出時間後,立即將 ping 封包寫入連線;接著於
PingTimer排程一個延遲約兩分鐘的任務, 屆時若延遲仍為負值(代表尚未收到 pong),便斷開並關閉此連線。 注意客戶端的閒置時間會額外疊加在此逾時之上。 -
getLogMessage
產生一則含連線身分前綴的記錄訊息(無參數格式化)。- Parameters:
cfor- 來源連線;為null時不附加身分前綴message- 記錄訊息內容- Returns:
- 已附加角色/帳號前綴的記錄字串
-
getLogMessage
產生一則含角色身分前綴的記錄訊息(無參數格式化)。- Parameters:
cfor- 來源角色;為null時不附加身分前綴message- 記錄訊息內容- Returns:
- 已附加角色/帳號前綴的記錄字串
-
getLogMessage
產生一則含角色身分前綴並套用參數格式化的記錄訊息。訊息中的每個
{}佔位符會依序以parms的字串值取代。- Parameters:
cfor- 來源角色;為null時不附加身分前綴message- 含{}佔位符的記錄訊息範本parms- 依序填入佔位符的參數- Returns:
- 已附加角色/帳號前綴且完成格式化的記錄字串
-
getLogMessage
產生一則含連線身分前綴並套用參數格式化的記錄訊息(其餘多載皆收斂至此)。當
cfor不為null時,依序附加角色名稱與 cid(角色存在時)以及帳號名稱 (帳號存在時)作為前綴;接著將訊息中的每個{}佔位符依序以parms的字串值取代。- Parameters:
cfor- 來源連線;為null時不附加身分前綴message- 含{}佔位符的記錄訊息範本parms- 依序填入佔位符的參數- Returns:
- 已附加角色/帳號前綴且完成格式化的記錄字串
-
findAccIdForCharacterName
依角色名稱查詢其所屬的帳號編號。透過共用
ThreadLocal連線查詢characters資料表。- Parameters:
charName- 角色名稱- Returns:
- 對應的帳號編號;查無此角色或查詢發生例外時回傳
-1
-
getClientMac
-
getMacs
取得此連線回報的所有 MAC 位址集合。- Returns:
- 不可修改的 MAC 位址集合(
Collections.unmodifiableSet(Set))
-
isBanned
public boolean isBanned()判斷此帳號是否處於被封鎖狀態。GM 帳號永遠視為未封鎖。
- Returns:
- 若帳號被封鎖且非 GM 則為
true,否則為false
-
isGm
public final boolean isGm()判斷此帳號是否為 GM(管理員)帳號。- Returns:
- 為 GM 則回傳
true
-
setScriptEngine
以指定名稱快取一個ScriptEngine。腳本引擎以每個
MapleClient為單位快取,供 NPC/任務等腳本重複使用; 連線斷開時整個快取會被清空。- Parameters:
name- 快取鍵(通常為腳本路徑)e- 欲快取的腳本引擎
-
getScriptEngine
依名稱取得先前快取的ScriptEngine。- Parameters:
name- 快取鍵(通常為腳本路徑)- Returns:
- 對應的腳本引擎;若尚未快取則為
null
-
removeScriptEngine
從快取移除指定名稱的ScriptEngine。用於令下次取用該腳本時重新讀取檔案(例如指令腳本的自動刷新)。
- Parameters:
name- 快取鍵(通常為腳本路徑)
-
getIdleTask
取得此連線目前的閒置逾時排程任務。- Returns:
- 閒置任務的
ScheduledFuture;未排程時可能為null
-
setIdleTask
設定此連線的閒置逾時排程任務。- Parameters:
idleTask- 閒置任務的ScheduledFuture
-
unLockDisconnect
public final void unLockDisconnect()因帳號於他處重複登入而強制斷線並關閉連線。會向客戶端送出重複登入提示封包(
serverNotice),呼叫disconnect,並另起一條執行緒延遲約三秒後關閉 session (讓提示有時間送達)。 -
getCharacterSlots
public int getCharacterSlots()取得此帳號在目前世界可用的角色欄位數。GM 帳號固定回傳
15。一般帳號優先回傳已快取的值以節省查詢;快取為預設值時才查詢character_slots資料表,若該帳號/世界尚無紀錄則順帶寫入一筆預設列(資料庫副作用)。- Returns:
- 可建立的角色欄位數
-
gainCharacterSlot
public boolean gainCharacterSlot()為此帳號在目前世界增加一個角色欄位。當前欄位數達上限
15時不予增加。成功時會更新character_slots資料表 (資料庫副作用)。- Returns:
- 成功增加回傳
true;已達上限或更新失敗回傳false
-
unbanIP
依角色名稱解除其帳號最近登入 IP 的封鎖。查出該角色的帳號與
sessionIP後,自ipbans資料表移除對應 IP(資料庫副作用)。- Parameters:
charname- 角色名稱- Returns:
- 成功解除的 IP 筆數(通常為
1);查無角色或帳號回傳-1; 發生 SQL 例外回傳-2
-
unbanIPMacs
依角色名稱解除其帳號的 IP 與 MAC 封鎖。查出該角色帳號的
sessionIP與macs後,分別自ipbans與macbans資料表移除對應紀錄(資料庫副作用);macs以", "分隔,逐一處理。- Parameters:
charname- 角色名稱- Returns:
- 已解除的項目類別數(IP 與 MAC 各計一);查無角色或帳號回傳
-1; 發生 SQL 例外回傳-2
-
unHellban
依角色名稱解除其帳號的「地獄封鎖」(hellban)。查出該角色帳號的
email與sessionIP後,將accounts資料表中 凡 email 相符(或 IP 相符,若有)的所有帳號之banned與banreason清除 (資料庫副作用,可能影響多個共用 email/IP 的帳號)。- Parameters:
charname- 角色名稱- Returns:
- 成功回傳
0;查無角色或帳號回傳-1;發生 SQL 例外回傳-2
-
isMonitored
public boolean isMonitored()判斷此連線是否處於受監控狀態。- Returns:
- 受監控則回傳
true
-
setMonitored
public void setMonitored(boolean m) 設定此連線是否受監控。- Parameters:
m-true表示啟用監控
-
isReceiving
public boolean isReceiving()判斷此連線目前是否接受處理封包。- Returns:
- 接受封包則回傳
true
-
setReceiving
public void setReceiving(boolean m) 設定此連線是否接受處理封包。斷線流程會先設為
false以停止後續封包處理。- Parameters:
m-true表示接受封包
-
canClickNPC
public boolean canClickNPC()判斷距離上次點擊 NPC 是否已超過防連點冷卻(500 毫秒)。- Returns:
- 已可再次點擊 NPC 則回傳
true
-
setClickedNPC
public void setClickedNPC()記錄一次 NPC 點擊時間,啟動防連點冷卻。- See Also:
-
removeClickedNPC
public void removeClickedNPC()清除上次 NPC 點擊時間,立即解除防連點冷卻。- See Also:
-
getCreated
查詢此帳號的建立時間。透過共用
ThreadLocal連線查詢accounts資料表的createdat欄位。- Returns:
- 帳號建立時間;查無此帳號時回傳
null - Throws:
DatabaseException- 查詢過程發生 SQL 例外時
-
getTempIP
-
setTempIP
-
isLocalhost
public boolean isLocalhost()判斷伺服器是否以本機(localhost)模式運行。- Returns:
- 取自
ServerConstants.Use_Localhost的設定值
-
setVip
public void setVip(int vip) 設定此帳號的 VIP 等級並立即寫回資料庫。更新
accounts資料表的vip欄位(資料庫副作用);寫入失敗僅記錄除錯訊息、不拋出例外。- Parameters:
vip- VIP 等級
-
getVip
public int getVip()查詢並回傳此帳號的 VIP 等級。每次呼叫都會查詢
accounts資料表並更新內部快取欄位;查詢失敗時回傳上次的快取值。- Returns:
- VIP 等級
-
setRewardLevel
public void setRewardLevel(int reward) 設定此帳號的獎勵等級並立即寫回資料庫。更新
accounts資料表的reward欄位(資料庫副作用);寫入失敗僅記錄除錯訊息、不拋出例外。- Parameters:
reward- 獎勵等級
-
getRewardLevel
public int getRewardLevel()查詢並回傳此帳號的獎勵等級。每次呼叫都會查詢
accounts資料表並更新內部快取欄位;查詢失敗時回傳上次的快取值。- Returns:
- 獎勵等級
-
sendPacket
public void sendPacket(byte[] packet) 將已組裝完成的封包寫入此連線並送出。透過底層 Netty session 的
writeAndFlush立即送出(編碼/加密由MaplePacketEncoder處理)。- Parameters:
packet- 由tools.packet.*建構器組裝出的封包位元組
-
banSingleMacs
將單一 MAC 位址加入封鎖名單。會校驗格式:全零位址
00-00-00-00-00-00或長度非 17 的字串一律拒絕;通過後寫入macbans資料表(資料庫副作用)。- Parameters:
macData- 欲封鎖的 MAC 位址(格式XX-XX-XX-XX-XX-XX)- Returns:
- 成功封鎖回傳
true;格式無效或寫入失敗回傳false
-
Fullyunban
對指定角色的帳號執行完整解封(帳號封鎖 + IP/MAC 封鎖)。依序呼叫
unban(String)與unbanIPMacs(String),兩者皆達預期結果才視為成功 (unban須為0,unbanIPMacs須為1或2)。- Parameters:
charname- 角色名稱- Returns:
- 全部解封成功回傳
true,否則回傳false
-
getCloseSession
public boolean getCloseSession()判斷此連線是否已被標記為待關閉。- Returns:
- 已標記關閉則回傳
true
-
loadCharacterNamesByAccId
-
loadNecessaryAccInfoByCharID
public void loadNecessaryAccInfoByCharID(int charid) 依角色編號回填此連線所需的基本帳號資訊。分兩次查詢(皆透過共用
ThreadLocal連線):先由characters取得accountid, 再由accounts取得帳號名稱與 MAC,並就地更新本物件的accId/accountName/mac欄位(狀態變更)。任一階段查詢失敗僅記錄錯誤、不拋出例外。- Parameters:
charid- 角色編號(cid)
-