May 26, 2015

製作艦隊收藏(艦これ)外掛 (四) 解析 API part I


目錄


(零) 聲明

此程式僅為個人學習 Python 的實作練習,並藉由此遊戲來分析與驗證網路傳輸行為,所有程式及文章僅為程式學習目的,架設於 Bitbucket 的私人 repository 中,無任何公開、散佈或任何營利行為,

不正ツール使用は規約違反です。お辞め頂けますようお願い申し上げます。 – 艦これ開発/運営 公式ツイート

本人不鼓勵也不贊同於艦これ使用任何形式的外掛或任何不正的工具,使用此類工具違反 艦これ 的 利用規約,並可能導致帳號被永久刪除。

The program was built for Python learning purpose only. Both the source codes and the program are stored in Bitbucket’s private repository. They are not disclosed to anyone in any form. Using such programs violates kancolle’s Terms of Use and may result in a permanent account ban.


(一) 艦これ遊戲 API

0. 影片展示、說明

在 Youtube 可選擇 HD 高畫質。

1. 艦これ運作機制

艦これ的遊戲本體 Flash 放在一個 iframe 內,該 iframe 則嵌在遊戲網頁內。

當 Flash 讀取完畢時,伺服器會透過 AJAX 方式傳送許多資料至瀏覽器端,大部分的「資料」都是 JSON 格式。

舉例來說,當遊戲進入 Start 頁面時,伺服器會傳來下列 JSON:

  • api_start2
  • get_incentive
  • basic
  • furniture
  • slot_item
  • useitem

除了 JSON 資料外,艦娘頭像與艦娘語音也都是以 AJAX 的方式向 Server 請求,其中圖像包在 flash swf 內,而語音則是 mp3 檔。

# 例如
Remote Address:125.6.189.103:80
Request URL:http://125.6.189.103/kcs/resources/swf/ships/icwowutxbvgh.swf?VERSION=5
Request Method:GET
Status Code:200 OK (from cache)
# 發光的 霧島
Request URL:http://125.6.189.103/kcs/resources/swf/ships/icwowutxbvgh.swf?VERSION=5
# 發光的 多摩
Request URL:http://125.6.189.103/kcs/resources/swf/ships/jiftwdxqwtin.swf?VERSION=1
# 一般的 摩耶
Request URL:http://125.6.189.103/kcs/resources/swf/ships/gpshoozxgutk.swf?VERSION=5

艦これ的伺服器位置、圖像 swf 對照表、mp3 對照表等等都可以在 Resouce 的檔案內找到。另外,幾乎所有 javascript 都沒有使用 scrambler,並且都很好心的附上日文註解,包含付款資訊的 js 也是。有興趣的可以開啟瀏覽器的 Developer Tool 觀察。

艦娘頭像與語音在網路上都找的到,沒有必要從遊戲中擷取,因此我們只專注在 JSON 的解析。


(二) 心理建設

艦これ除了資訊介面為人詬病外,深入觀察後,會發現其 API 的設計也有很多問題。

建議有心想要 dig 進來的玩家先有一定的心理建設。

網路上其他開發者也有著共同的批判,例如:

1. 艦これAPIを叩く

世間一般で「XXを叩く」といえば、「XXを非難する」という意味の比喩表現です。 この本も、人類史上稀に見る「クソAPI」である艦これのAPIを「非難」し、 艦これAPIを悪いAPIの題材とし、よりよいAPI設計を解説することを目的としています。
艦これAPIを叩く by masarakki

這本 gitbook 的作者表示艦これ的 API 是人類史上少見的爛 API。

這本 gitbook 是 2014 年 1 月寫的,有些 API 已經更新過,跟以前完全不一樣了。

舉例來說,我已經攔截不到戰鬥過程的 JSON,導致無法分析是否該夜戰或是撤退,必須用其他方法來判斷,相信這項 API 的變動應該就是為了防止自動練功的程式。

2. Kan Colle Tool

KanColle’s API is a messy REST API that takes the word “redundant” to a new level.
– Kan Colle Tool 的 API Documentation

艦これ的 API 把 “redundant” 這個字推向了一個新的境界。

3. 其他例子

想看以前艦これ API 有多醜的,可以參考下列資料:

  • slotitem.json @Feb 26, 2014
    現在有好一點了,但其實差不多。

  • masterShip.json @Dec 24, 2013
    現在似乎已沒有這個資料,已經整合進 api_start2 了?

經過幾年的改進後,艦これ的 API 應該已經進步許多,但還是有不少讓人覺得莫名其妙的部分。有了這樣的心理建設(?)後,我們就來解析一下遊戲中重要的 API 吧。


(三) 使用的工具

我使用 Sublime Text 3 配上 SublimePrettyJson Package 來處理 JSON。

1. 範例流程

譬如進入補給畫面後,會發出這個 Request:

Remote Address:125.6.189.103:80
Request URL:http://125.6.189.103/kcs/scenes/SupplyMain.swf?version=2.0.19
Request Method:GET
Status Code:200 OK (from cache)

補給某隻艦娘後,艦これ回傳的 JSON 如下:

svdata={"api_result":1,"api_result_msg":"\u6210\u529f","api_data":{
"api_ship":[{"api_id":7,"api_fuel":15,"api_bull":15,"api_onslot":[0,0,0,0,0]}],
"api_material":[4241,6894,4075,5872],"api_use_bou":0}}

將開頭的 svdata= 刪掉後,用 SublimePrettyJson 排版,排版完後大概長這個樣子:

{
  "api_result": 1,
  "api_result_msg": "成功",
  "api_data": {
    "api_ship": [
      {
        "api_id": 7,
        "api_fuel": 15,
        "api_bull": 15,
        "api_onslot": [
          0,
          0,
          0,
          0,
          0
        ]
      }
    ],
    "api_material": [
      4241,
      6894,
      4075,
      5872
    ],
    "api_use_bou": 0
  }
}

排版只是方便我們觀察而已,寫程式時只要刪掉前面的 svdata= 即可直接處理 JSON 了。

2. 實驗分析

下面的 API 是我在 2015/04/02 左右做多次實驗分析後的結果,2015/05/28 更新過後我也稍微比對了一下,基本上 API 都大同小異。

這只我做實驗分析的結果,不保證完全正確,有興趣的可以自己研究看看。

(但大致上應該都正確啦,不然我的外掛就不會 work 惹。)


(四) Python 的 Unicode 編碼問題

使用 Python 處理 Unicode 字元時,可能會遇到一些編碼問題。

我自己遇到了很多問題,並將其這些經驗寫成文章。

建議讀者詳細看完這兩篇:


(五) Port API

每次切換到遊戲主畫面(如上圖)時,會從伺服器要求 port API。

Remote Address:125.6.189.103:80
Request URL:http://125.6.189.103/kcsapi/api_port/port
Request Method:POST
Status Code:200 OK

回傳的 JSON 如下圖:

利用 SublimePrettyJson 排版後如下:

實驗分析後,各項數值意義如下:

1. Overview

  • api_material
    • api_id 1~4 分別是 燃料、彈藥、鋼鐵、ボーキサイト 的數量。
    • api_id 5~8 分別是 高速建造、高速修復、建造資材、改修資材的數量。
  • api_deck_port
    • 參見下方。
  • api_ndock
    • 參見下方。
  • api_ship
    • 參見下方。
  • api_basic 包含了提督ID、名稱、等級、經驗值、最大可擁有船艦數、裝備數、目前佈置的家具、造船渠道數量、維修渠道數量、遠征勝敗場、出征勝敗場、演習勝敗場、徽章數量、可否大型建造等等資訊。
  • api_log 紀錄主畫面下方按下”表示”按鈕時會跑出來的資訊(艦隊最新消息)。
  • api_p_bgm_id 背景音樂的 ID。

2. api_deck_port

api_deck_port 紀錄著玩家第一艦隊到第四艦隊的艦隊資訊:

  • api_member_id 提督 ID。
  • api_id 第幾個艦隊(1~4)。
  • api_name 艦隊名稱。
  • api_name_id 不知道,待研究。
  • api_mission 此艦隊目前在進行哪個任務
    • 第一個值,應該是遠征第 N 個頁面?
    • 第二個值,應該是該頁面的第 N 個任務?
    • 第三個值,遠征任務完成時間的 Epoch time
    • 第四個值,不知道,待研究。
  • api_flagship 第幾艘船是旗艦,除非遊戲規則更改,否則這個值應該不會更改,多餘的?
  • api_ship 這支艦隊是由哪些船艦所組成,船艦的數值是 local ID。也就是”此帳號中,第幾隻入手的艦娘”(意即下方 api_shipapi_id)。

3. api_ndock

api_ndock 紀錄著玩家維修場的資訊:

  • api_member_id 提督 ID。
  • api_id 第幾個維修廠,總共 1~4 個維修廠。
  • api_state
    • 1 代表此維修廠正在維修船艦
    • 0 代表閒置
    • -1 代表未開放(需課金開放)。
  • api_ship_id 正在維修的艦娘的 local ID。(即下方 api_shipapi_id)。
  • api_complete_time 維修完成時間的 Epoch time
  • api_complete_time_str 將上述 Epoch 轉成 strf 格式,時區是 JST, GMT +9
  • api_item1 ~ 4 應該是維修時使用的鋼材、燃料等等(待驗證)。

4. api_ship

api_ship 紀錄著玩家所擁有的艦娘(船艦)的資訊:

  • api_id 這艘船是此帳號的”第幾隻艦娘”,下面會解釋。
  • api_sortno 這隻艦娘在圖鑑上的 ID,要注意的是,有些艦娘改造之後(ex: 電改) 沒有獨自的圖鑑,但此數值依然會更改,通常是跳到 3XX。
    例如:
    電(いなづま) 的圖鑑 ID 是:074
    電改 是:337,而圖鑑頁面 337 是空的

  • api_lv 艦娘目前等級。

  • api_exp 艦娘目前經驗、下一級所需經驗。
  • api_nowhp 目前血量(耐久度)。
  • api_maxhp 最大血量。
  • api_slot 目前裝備,-1 代表未開放。
  • api_kyouka 已強化的數值。
  • api_backs 可搭載艦上機的數量。
  • api_fuel 燃料量。
  • api_bull 彈藥量。
  • api_slotnum 可用之裝備欄位。
  • api_cond 疲勞值。
  • api_karyoku 火力(かりょく),這邊開始以日文羅馬拼音命名變數。
  • api_raisou 雷装(らいそう)。
  • api_taiku 対空(たいくう)。
  • api_soukou 装甲(そうこう)。
  • api_kaihi 回避(かいひ)。
  • api_taisen 対潜(たいせん)。
  • api_sakuteki 索敵(さくてき)。
  • api_lucky 運(lucky),靠杯為什麼運氣就是用英文 XD

5. 補充說明

艦娘在 api_shipapi_id 對我們而言是很重要的值,每隻艦娘都有不同且唯一的 api_id。用資料庫的概念來比喻,api_id 就是該艦娘的 Primary Key

api_id 所代表的意義是:「此帳號中,第幾隻入手的艦娘。」

api_id 從 1 開始往上累加,一次加一,不會往後退。

舉例來說:

第一次登入遊戲時,玩家要從吹雪叢雲五月雨這五隻艦娘中選一個老婆…不是,是選一個初始艦。所以所有玩家的 api_id 為 1 的艦娘一定是這五隻其中一隻。

另一個例子:

假設你目前有 4 隻艦娘,下一隻艦娘的 api_id 就是 5,再下一隻就是 6。

如果你將 api_id 為 5 的艦娘給解體,則 6 的依然是 6,不會改變。

此時再抓到下一隻的 api_id 會是 7。也就是說api_id 為 5 的艦娘就此從缺了。

這個機制可以保證每個艦娘都有一個獨特的 api_id,即使有兩個名稱、等級、裝備、所有屬性都相同的艦娘,由於其入手時間一定有前後順序,故我們依然可以由 api_id 來分辨兩者。

另一個例子,假設 api_deck_portapi_ship 為:

"api_ship": [
  1,
  2,
  3,
  4,
  10,
  150
]

代表這隻艦隊是由你開始遊戲以來得到的第 1 隻艦娘、第 2 隻、第 3 隻、第 4 隻、第 10 隻跟第 110 隻艦娘所組成。

這個概念不只適用於「目前擁有的船艦」的 API,同樣也適用於「目前擁有的裝備」的 API,之後會再詳述。

這樣聽起來 api_id 應該是很重要的值,但是艦これ API 爛就爛在,「幾乎所有 API 都有 api_id 這個欄位,而且代表的意義都不一樣」。

為了避免混淆,我在之後的文章會以 艦娘的 local ID 稱呼這邊的 api_id


(六) 延伸閱讀