Class PlayerHandler

java.lang.Object
handling.channel.handler.PlayerHandler

public class PlayerHandler extends Object
頻道伺服器中「玩家自身動作」的封包處理器,由 MapleServerHandler 的封包分派表呼叫。

本類別為一組 static 方法的集合,將 RecvPacketOpcode 解出的玩家行為 封包(以 LittleEndianAccessor 讀取)轉換為對 MapleCharacter 的狀態變更, 並透過 CFieldCWvsContext 等建構器回送結果。涵蓋範圍包括:

  • 移動、坐椅、表情、改快捷鍵/技能巨集(MovePlayerUseChairChangeKeymap);
  • 近距離/遠距離/魔法攻擊與技能施放(closeRangeAttackrangedAttackMagicDamageSpecialMove);
  • 受傷扣血、恢復、換地圖與傳送(TakeDamageHealChangeMapTrockAddMap);
  • 掉錢、機甲/勳章/技能教學等雜項動作。

關鍵協作者:MapleStatEffect(技能效果計算)、CheatingOffenseMapleCharacter#getCheatTracker(作弊偵測)、MapleMonster(攻擊目標)、 DamageParse(傷害套用)、MapleQuestMapleEventWorld(跨伺服器廣播)。

  • Constructor Details

    • PlayerHandler

      public PlayerHandler()
  • Method Details

    • isFinisher

      public static int isFinisher(int skillid)
      判斷指定技能是否為「終結技」(連擊系終結招),並回傳其所需消耗的連擊珠類型。

      closeRangeAttack(LittleEndianAccessor, MapleClient, MapleCharacter, boolean) 在處理近距離攻擊時判定是否需呼叫 chr.handleOrbconsume(...) 消耗連擊珠(如十字斬/三段斬)。

      Parameters:
      skillid - 技能 ID
      Returns:
      終結技類型(1 或 2);非終結技回傳 0
    • ChangeSkillMacro

      public static void ChangeSkillMacro(LittleEndianAccessor slea, MapleCharacter chr)
      處理玩家設定/更新「技能巨集」(最多三招的快捷組合)的封包。

      自封包逐筆讀出巨集名稱、是否喊話旗標與三個技能 ID,建立 SkillMacro 並以 chr.updateMacros 寫回角色狀態。若巨集名稱為保留字 @存檔 則 以 chr.dropMessage 提示無法保存並中止迴圈。

      Parameters:
      slea - 待讀取的封包存取器(含巨集數量與各巨集欄位)
      chr - 設定巨集的角色
    • ChangeKeymap

      public static final void ChangeKeymap(LittleEndianAccessor slea, MapleCharacter chr)
      處理玩家變更「快捷鍵配置」的封包,並兼作寵物自動藥水設定的入口。

      當封包資料足夠(available() > 8)時逐筆套用按鍵綁定:跳過無法綁定的隱藏/ 非初心者四轉技與未習得技能、以及未持有的道具,否則以 chr.changeKeybinding 寫入。 反之(資料較短)則視為寵物自動補 HP/MP/藥水設定,將數值寫入對應任務 (GameConstants.HP_ITEMMP_ITEMPOT_ITEM)的自訂資料。

      Parameters:
      slea - 待讀取的封包存取器
      chr - 變更設定的角色;為 null 時不處理
    • UseTitle

      public static final void UseTitle(int itemId, MapleClient c, MapleCharacter chr)
      處理玩家裝備/取消「稱號」(setup 類道具,ID 前綴 370)的請求。

      itemId 為 0 表示取消稱號;否則驗證該道具確實存在於裝飾道具欄且為合法稱號, 通過後以 chr.setTitleEffect 設定並向同地圖廣播 CField.showTitle。 驗證失敗則僅回送 CWvsContext.enableActions() 解除動作鎖。

      Parameters:
      itemId - 稱號道具 ID,0 表示取消
      c - 發出請求的客戶端連線
      chr - 對應角色;為 null 或不在地圖時不處理
    • UseChair

      public static final void UseChair(int itemId, MapleClient c, MapleCharacter chr)
      處理玩家使用「椅子」道具(含釣魚椅)坐下的請求。

      先驗證該椅子存在於裝飾道具欄,否則登記 CheatingOffense.USING_UNAVAILABLE_ITEM 作弊紀錄並中止。若位於釣魚地圖 (MapConstants.isFishingMap(int)),依魚餌/釣竿/椅子組合判定啟動普通或高級 (VIP)釣魚(chr.startFishingTask);條件不符則提示。最後以 chr.setChair 設定坐椅、向同地圖廣播 CField.showChair,並回送 CWvsContext.enableActions()

      Parameters:
      itemId - 椅子道具 ID
      c - 發出請求的客戶端連線
      chr - 對應角色;為 null 或不在地圖時不處理
    • CancelChair

      public static final void CancelChair(short id, MapleClient c, MapleCharacter chr)
      處理玩家起身或使用「地圖內固定椅子」的請求。

      id 為 -1 表示起身:若先前坐的是釣魚椅則取消釣魚任務,清除坐椅狀態、 回送 CField.cancelChair(-1) 並向同地圖廣播取消坐椅。其餘值表示坐上地圖內 指定椅子,設定坐椅後回送 CField.cancelChair(id)

      Parameters:
      id - 椅子識別碼;-1 表示起身
      c - 發出請求的客戶端連線
      chr - 對應角色
    • TrockAddMap

      public static final void TrockAddMap(LittleEndianAccessor slea, MapleClient c, MapleCharacter chr)
      處理玩家在「世界傳送石」(Teleport Rock)名單中新增/刪除目前地圖的請求。

      依封包讀出的傳送石類型(普通/VIP/Hyper)與動作(新增或刪除)對應呼叫角色的 增刪方法。新增前以 FieldLimitType.VipRock 檢查目前地圖是否允許登錄,不允許則 提示。最後回送 MTSCSPacket.OnMapTransferResult 通知結果。

      Parameters:
      slea - 待讀取的封包存取器(含 addrem 動作、vip 類型,刪除時另含地圖 ID)
      c - 發出請求的客戶端連線
      chr - 對應角色
    • CharInfoRequest

      public static final void CharInfoRequest(int objectid, MapleClient c, MapleCharacter chr)
      處理玩家點選他人角色以查看「角色資訊」的請求。

      依物件 ID 於目前地圖尋找目標角色,回送 CWvsContext.enableActions() 後, 若目標存在且非分身、且(非 GM 或請求者本身為 GM)則回送 CWvsContext.charInfo(會標示是否為查看自己)。

      Parameters:
      objectid - 目標角色的地圖物件 ID
      c - 發出請求的客戶端連線
      chr - 發出請求的角色(方法內以 c.getPlayer() 為準)
    • TakeDamage

      public static final void TakeDamage(LittleEndianAccessor slea, MapleClient c, MapleCharacter chr)
      處理玩家「受到傷害」的封包,套用扣血並向同地圖廣播受傷動畫。

      自封包讀出傷害類型(-4 為毒霧、-3/-2 為地圖傷害)、元素、傷害值與來源怪物等資訊, 計入怪物攻擊/反射、毒霧、地圖傷害等情形,扣減 HP/MP 並處理魔法護盾、致命一擊等狀態, 視情況登記作弊紀錄,最後以 CField.damagePlayer 廣播給其他玩家。

      Parameters:
      slea - 待讀取的封包存取器(含傷害類型、元素、傷害值與來源資料)
      c - 發出請求的客戶端連線
      chr - 受傷的角色
    • AranCombo

      public static final void AranCombo(MapleClient c, MapleCharacter chr, int toAdd)
      累加「狂狼勇士(Aran)連擊數」並套用對應的連擊增益與成就勳章。

      僅對狂狼勇士職業(job 2000–2112)生效。連擊逾時(超過 7 秒)會歸零後重新累加, 上限 30000。達到 10 的倍數時依連擊技能等級套用 applyComboBuff;達到 5000/15000/30000 里程碑時,透過一次性紀錄(getOneTimeLog)發放對應的 連擊勳章並提示。同時回送 CField.testCombo 更新客戶端連擊顯示。

      Parameters:
      c - 對應客戶端連線
      chr - 累加連擊的角色;為 null 或非狂狼勇士時不處理
      toAdd - 本次新增的連擊數
    • UseItemEffect

      public static final void UseItemEffect(int itemId, MapleClient c, MapleCharacter chr)
      處理玩家使用「道具特效」(CASH 類炫耀/特效道具)的請求。

      驗證該道具確實存在於現金道具欄且數量足夠,否則回送 CWvsContext.enableActions() 並中止。通過後(除 5510000 外)以 chr.setItemEffect 設定特效,並向同地圖廣播 CField.itemEffect

      Parameters:
      itemId - 特效道具 ID
      c - 發出請求的客戶端連線
      chr - 對應角色
    • CancelItemEffect

      public static final void CancelItemEffect(int id, MapleCharacter chr)
      取消由道具施加的增益效果。

      -idMapleItemInformationProvider 取得對應道具效果, 呼叫 chr.cancelEffect 移除之。

      Parameters:
      id - 道具效果來源 ID(封包傳入的負值之相反數)
      chr - 對應角色
    • CancelBuffHandler

      public static final void CancelBuffHandler(int sourceid, MapleCharacter chr)
      處理玩家主動取消「技能增益」的請求。

      若來源為蓄力技(isChargeSkill),清除蓄力起始時間並向同地圖廣播 CField.skillCancel;否則以 chr.cancelEffect 移除該技能第 1 級效果。

      Parameters:
      sourceid - 增益來源技能 ID
      chr - 對應角色;為 null 或不在地圖時不處理
    • CancelMech

      public static final void CancelMech(LittleEndianAccessor slea, MapleCharacter chr)
      處理機械師(Mechanic)相關技能取消的封包。

      自封包讀出來源技能 ID(必要時補正 +1000 以對應實際技能),若為蓄力技則清除蓄力 起始時間並廣播 CField.skillCancel,否則讀取等級後以 chr.cancelEffect 移除對應效果。

      Parameters:
      slea - 待讀取的封包存取器(含來源技能 ID 與等級)
      chr - 對應角色;為 null 或技能不存在時不處理
    • QuickSlot

      public static final void QuickSlot(LittleEndianAccessor slea, MapleCharacter chr)
      處理玩家儲存「快捷欄(Quick Slot)配置」的封包。

      當封包長度符合(available() == 32)時讀出 8 個整數鍵位,組成逗號分隔字串 後寫入 GameConstants.QUICK_SLOT 任務的自訂資料以持久化。

      Parameters:
      slea - 待讀取的封包存取器(8 個 int 快捷欄項)
      chr - 對應角色;為 null 時不處理
    • SkillEffect

      public static final void SkillEffect(LittleEndianAccessor slea, MapleCharacter chr)
      處理蓄力/持續性技能的「施放特效」封包,向同地圖廣播技能動畫。

      讀出技能 ID、等級、方向等欄位(≥ 91000000 的公會/配方類直接回送 CWvsContext.enableActions() 略過);當伺服器端技能等級與封包一致且屬蓄力技 (或特定技能 33101005)時,記錄蓄力起始時間並廣播 CField.skillEffect

      Parameters:
      slea - 待讀取的封包存取器(含技能 ID、等級、方向等)
      chr - 施放技能的角色;為 null、技能不存在或不在地圖時不處理
    • SpecialMove

      public static final void SpecialMove(LittleEndianAccessor slea, MapleClient c, MapleCharacter chr)
      處理玩家施放「特殊技能/增益技」(buff、召喚、武陵道場等非攻擊技能)的封包。

      讀出技能 ID 與等級並嚴格驗證:≥ 91000000 的公會/配方類略過;天使祝福需與所配召喚一致; PVP 中受限技能不可施放;伺服器端未習得或等級不符的非特例技能會直接關閉連線(反作弊)。 通過後依技能套用增益效果、扣除消耗(如武陵道場精力 getMulungEnergy)、設定冷卻並向 同地圖廣播施放效果,必要時對分身(clone)排程同步施放。

      Parameters:
      slea - 待讀取的封包存取器(含技能 ID、等級與附帶參數)
      c - 發出請求的客戶端連線
      chr - 施放技能的角色;為 null、道具欄被鎖或不在地圖時僅回送 CWvsContext.enableActions()
    • closeRangeAttack

      public static final void closeRangeAttack(LittleEndianAccessor slea, MapleClient c, MapleCharacter chr, boolean energy)
      處理玩家「近距離(近戰)攻擊」的封包,計算傷害、廣播動作並對怪物套用攻擊。

      DamageParse.parseDmgM(LittleEndianAccessor, MapleCharacter) 解析攻擊資訊,驗證技能(含天使/連犽突進等特例與 活動地圖技能限制)後計算最大傷害與攻擊次數,處理影分身(SHADOWPARTNER)倍數、 連擊珠消耗(isFinisher(int))、技能冷卻(chr.addCooldown)與雪球地圖判定。 接著向同地圖(或 GM 隱身時)廣播 CField.closeRangeAttack,並以 DamageParse.applyAttack(AttackInfo, Skill, MapleCharacter, int, double, MapleStatEffect, AttackType) 實際結算傷害;若角色有分身則透過 Timer.CloneTimer 排程延遲同步攻擊。

      Parameters:
      slea - 待讀取的封包存取器(攻擊資料)
      c - 發出請求的客戶端連線
      chr - 攻擊者角色
      energy - true 表示能量充電(衝拳)系攻擊,需具備對應增益狀態方可施放
    • rangedAttack

      public static final void rangedAttack(LittleEndianAccessor slea, MapleClient c, MapleCharacter chr)
      處理玩家「遠距離(弓弩/拳套/標槍等)攻擊」的封包,含消耗彈藥與傷害結算。

      DamageParse.parseDmgR(LittleEndianAccessor, MapleCharacter) 解析攻擊資訊並驗證技能後,處理彈藥(箭矢/子彈/飛鏢) 的尋找與消耗、無消耗系(如靈魂箭、不滅之魂)特例、影分身倍數與技能冷卻,向同地圖(或 GM 隱身時)廣播 CField.rangedAttack,再以 DamageParse.applyAttack(AttackInfo, Skill, MapleCharacter, int, double, MapleStatEffect, AttackType) 結算傷害; 角色有分身時透過 Timer.CloneTimer 排程延遲同步。

      Parameters:
      slea - 待讀取的封包存取器(攻擊資料)
      c - 發出請求的客戶端連線
      chr - 攻擊者角色;為 null、道具欄被鎖或不在地圖時不處理
    • MagicDamage

      public static final void MagicDamage(LittleEndianAccessor slea, MapleClient c, MapleCharacter chr)
      處理玩家「魔法攻擊」的封包,計算魔法傷害並對怪物套用攻擊。

      DamageParse.parseDmgMa(LittleEndianAccessor, MapleCharacter) 解析攻擊資訊並驗證技能後計算最大傷害(金字塔/初心者 技能有固定上限),套用活動地圖技能限制與技能冷卻,向同地圖(或 GM 隱身時)廣播 CField.magicAttack,再以 DamageParse.applyAttackMagic(AttackInfo, Skill, MapleCharacter, MapleStatEffect, double) 結算傷害;角色有分身 時透過 Timer.CloneTimer 排程延遲同步。

      Parameters:
      slea - 待讀取的封包存取器(攻擊資料)
      c - 發出請求的客戶端連線
      chr - 施法者角色;為 null、道具欄被鎖或不在地圖時不處理
    • DropMeso

      public static final void DropMeso(int meso, MapleCharacter chr)
      處理玩家「丟出楓幣」的請求,扣除金額並於地圖上生成楓幣掉落物。

      驗證角色存活、金額介於 10–50000 且不超過持有量,否則回送 CWvsContext.enableActions() 中止。通過後以 chr.gainMeso 扣款, 並以 chr.getMap().spawnMesoDrop 生成可拾取的楓幣堆。

      Parameters:
      meso - 欲丟出的楓幣數量(須介於 10–50000)
      chr - 丟出楓幣的角色
    • ChangeAndroidEmotion

      public static final void ChangeAndroidEmotion(int emote, MapleCharacter chr)
      處理玩家機器人(Android)做出「表情」的請求,向同地圖廣播表情動畫。

      僅在表情編號合法(1–17)、角色存在且擁有機器人、且未隱身時,廣播 CField.showAndroidEmotion

      Parameters:
      emote - 表情編號(1–17)
      chr - 對應角色
    • MoveAndroid

      public static final void MoveAndroid(LittleEndianAccessor slea, MapleClient c, MapleCharacter chr)
      處理玩家機器人(Android)「移動」的封包,更新位置並向同地圖廣播。

      MovementParse.parseMovement(LittleEndianAccessor, int) 解析移動片段,於資料合法且角色擁有機器人時, 以 updatePosition 更新機器人座標並廣播 CField.moveAndroid(含防地圖崩潰 的有效性檢查)。

      Parameters:
      slea - 待讀取的封包存取器(移動片段)
      c - 發出請求的客戶端連線
      chr - 對應角色
    • ChangeEmotion

      public static final void ChangeEmotion(int emote, MapleCharacter chr)
      處理玩家做出「表情(臉部表情)」的請求,向同地圖廣播並同步分身。

      表情編號 > 7 屬須持有對應道具(ID 5159992 + emote)的特殊表情,未持有時 登記 CheatingOffense.USING_UNAVAILABLE_ITEM 作弊紀錄並中止。合法且未隱身時廣播 CField.facialExpression,並透過 Timer.CloneTimer 對分身排程延遲同步表情。

      Parameters:
      emote - 表情編號(> 7 須持有對應道具)
      chr - 對應角色
    • Heal

      public static final void Heal(LittleEndianAccessor slea, MapleCharacter chr)
      處理玩家自然「恢復 HP/MP」的封包(站樁回復/回復系技能)。

      更新心跳計時後讀出本次回復的 HP/MP 量,並以 stats.getHealHP()getHealMP() 為上限夾鉗(防止過量回復作弊),再經 chr.canHP 速率檢查後 套用 addMP 等回復。角色已死亡(HP ≤ 0)時不處理。

      Parameters:
      slea - 待讀取的封包存取器(含心跳與 HP/MP 回復量)
      chr - 回復的角色;為 null 時不處理
    • MovePlayer

      public static final void MovePlayer(LittleEndianAccessor slea, MapleClient c, MapleCharacter chr)
      處理玩家「角色移動」的封包,更新座標、廣播移動並處理跟隨與墜落保護。

      MovementParse.parseMovement(LittleEndianAccessor, int) 解析移動片段(解析失敗時記錄 AIOBE 並中止), 向同地圖(或 GM 隱身時)廣播 CField.movePlayer、更新角色與地圖位置;若啟用跟隨 (follow)則同步帶動被跟隨者,並透過 Timer.CloneTimer 排程分身移動。另含「墜落計數器」 防穿地保護:連續落到地圖底部以下達門檻時將角色傳回出生點,以及黃光環(YELLOW_AURA) 的位移觸發。

      Parameters:
      slea - 待讀取的封包存取器(移動片段)
      c - 發出請求的客戶端連線
      chr - 移動的角色;為 null 時不處理
    • ChangeMapSpecial

      public static final void ChangeMapSpecial(String portal_name, MapleClient c, MapleCharacter chr)
      處理玩家踩到「腳本傳送點」(特殊入口)的請求,觸發該傳送點腳本。

      依名稱取得 MaplePortal,標記角色進入傳送狀態後(且道具欄未被鎖時)呼叫 portal.enterPortal 執行腳本;找不到傳送點或道具欄被鎖時回送 CWvsContext.enableActions()

      Parameters:
      portal_name - 傳送點名稱
      c - 發出請求的客戶端連線
      chr - 對應角色;為 null 或不在地圖時不處理
    • ChangeMap

      public static final void ChangeMap(LittleEndianAccessor slea, MapleClient c, MapleCharacter chr)
      處理玩家「換地圖」的封包,涵蓋死亡復活、特定劇情解鎖傳送與一般傳送點進入。

      讀出來源類型、目標地圖 ID 與傳送點名稱後,依情境分流:

      • 角色死亡(!chr.isAlive())時的復活:優先交由活動實例 (revivePlayer)或金字塔地鐵處理,否則依安全的旅人之輪(5510000)、VIP/強效 護身符回復 HP/MP 並傳回返回地圖;
      • 實習生(intern)GM 可直接傳送至任意目標地圖;
      • 一般玩家僅允許白名單內的劇情/序章地圖傳送(其餘視為作弊不予傳送),必要時關閉序章 UI 鎖;
      • 其餘情況經指定傳送點 portal.enterPortal 進入(道具欄被鎖則僅回送 CWvsContext.enableActions())。
      Parameters:
      slea - 待讀取的封包存取器(含來源類型、目標地圖 ID、傳送點名稱與旅人之輪旗標)
      c - 發出請求的客戶端連線
      chr - 換地圖的角色;為 null 或不在地圖時不處理
    • InnerPortal

      public static final void InnerPortal(LittleEndianAccessor slea, MapleClient c, MapleCharacter chr)
      處理玩家使用「同地圖內傳送點」(地圖內位移入口)移動的封包。

      標記角色正使用傳送點後,依名稱取得 MaplePortal 與目標座標;若傳送點不存在則 中止,若距離過遠(且非 GM)則登記 CheatingOffense.USING_FARAWAY_PORTAL 作弊紀錄 並中止。通過後以 chr.getMap().movePlayer 將角色移至目標座標並重新檢查跟隨狀態。

      Parameters:
      slea - 待讀取的封包存取器(含傳送點名稱與目標座標)
      c - 發出請求的客戶端連線
      chr - 對應角色;為 null 或不在地圖時不處理
    • snowBall

      public static final void snowBall(LittleEndianAccessor slea, MapleClient c)
      處理雪球(雪人推球)小遊戲的攻擊封包;本實作僅回送動作解鎖。

      實際推球邏輯在近距離攻擊(closeRangeAttack(LittleEndianAccessor, MapleClient, MapleCharacter, boolean)MapleSnowballs.hitSnowball) 中處理,故此處僅回送 CWvsContext.enableActions()

      Parameters:
      slea - 待讀取的封包存取器(隊伍/位置/關卡等欄位,此處未使用)
      c - 發出請求的客戶端連線
    • leftKnockBack

      public static final void leftKnockBack(LittleEndianAccessor slea, MapleClient c)
      處理雪球小遊戲中的「向左擊退」封包。

      僅在角色位於雪球地圖(map ID 前綴 10906)時生效,回送 CField.leftKnockBackCWvsContext.enableActions();否則忽略以避免在其他地圖被當成無限後退(FJ)外掛。

      Parameters:
      slea - 待讀取的封包存取器(此處未使用)
      c - 發出請求的客戶端連線
    • ReIssueMedal

      public static final void ReIssueMedal(LittleEndianAccessor slea, MapleClient c, MapleCharacter chr)
      處理玩家向勳章任務 NPC「重新領取勳章」的請求。

      依封包讀出的任務取得對應勳章道具,依序檢查並以 UIPacket.reissueMedal 回送對應結果碼:任務未完成或道具不符(4)、已持有該勳章(3)、 道具欄空間不足(2)、楓幣不足 100(1)。全部通過則扣除 100 楓幣、以 MapleInventoryManipulator.addById(MapleClient, int, short, String) 補發勳章並回送成功(0)。

      Parameters:
      slea - 待讀取的封包存取器(含任務 ID 與勳章道具 ID)
      c - 發出請求的客戶端連線
      chr - 領取勳章的角色
    • TeachSkill

      public static void TeachSkill(LittleEndianAccessor slea, MapleClient c, MapleCharacter chr)
      處理玩家「傳授職業核心技能(Core Aura)給同帳號其他角色」的請求。

      要求等級 ≥ 70 且自身已習得來源技能;依施術者職業對應可傳授的核心技能 ID (重砲指揮官/惡魔/精靈遊俠/蒼龍俠客/米哈逸),並驗證目標角色屬同一帳號 (getAccountID)。成功時透過 chr.teachSkillchangeTeachSkill 寫入並完成任務 7783,必要時更新核心氣場(updateCoreAura),回送 InfoPacket.teachMessage;失敗則以 chr.dropMessage 提示原因。

      Parameters:
      slea - 待讀取的封包存取器(含來源技能 ID 與目標角色 ID)
      c - 發出請求的客戶端連線
      chr - 傳授技能的角色;為 null、不在地圖或道具欄被鎖時僅回送 CWvsContext.enableActions()