您当前位置: 天堂123 > 天堂架設 > 天堂私服創NPC指令分析

天堂私服創NPC指令分析

2021/12/7

在開始分析前,請務必先將以下文章閱讀完畢。

GM指令分析 (前往怪物)
了解spawnlist資料表用途與欄位說明。
了解spawnlist_npc資料表用途與欄位說明。
GM指令分析 (召喚怪物)
了解L1SpawnUtil的spawn方法行為,有助於了解這邊的分析。
分析
效果:創建怪物或NPC並寫入資料庫中的spawnlist或spawnlist_npc資料表。
範例:

.insert mob ${npcid}
.insert npc ${npcid}
1.分析資料表:

先進入commands表,找到insert的指令。
class_name是L1InsertSpawn。

2.分析資料表:

再進入npc表,這邊先分析一個impl欄位。
先列出impl的清單。(下面兩個SQL語法效果一樣)
SELECT DISTINCT impl FROM npc;
SELECT impl FROM npc GROUP BY impl;

資料分析,可以透過這些impl去抓取資料判斷對應的分類。
SELECT * FROM npc WHERE impl = 'L1Scarecrow';
SELECT * FROM npc WHERE impl = 'L1Monster';
SELECT * FROM npc WHERE impl = 'L1Teleporter';
SELECT * FROM npc WHERE impl = 'L1Merchant';
SELECT * FROM npc WHERE impl = 'L1Housekeeper';
SELECT * FROM npc WHERE impl = 'L1Dwarf';
SELECT * FROM npc WHERE impl = 'L1Guard';
SELECT * FROM npc WHERE impl = 'L1Npc';
SELECT * FROM npc WHERE impl = 'L1Guardian';
SELECT * FROM npc WHERE impl = 'L1Quest';
SELECT * FROM npc WHERE impl = 'L1Board';
SELECT * FROM npc WHERE impl = 'L1FieldObject';
SELECT * FROM npc WHERE impl = 'L1Doll';
SELECT * FROM npc WHERE impl = 'L1Furniture';
SELECT * FROM npc WHERE impl = 'L1Effect';
SELECT * FROM npc WHERE impl = '';
SELECT * FROM npc WHERE impl = 'L1Tower';
SELECT * FROM npc WHERE impl = 'L1Crown';
SELECT * FROM npc WHERE impl = 'L1Door';
SELECT * FROM npc WHERE impl = 'L1AuctionBoard';
SELECT * FROM npc WHERE impl = 'L1Signboard';
SELECT * FROM npc WHERE impl = 'L1DragonPortal';
SELECT * FROM npc WHERE impl = 'L1Fish';
這邊已經將資料取出,並去對應過後的對應表如下:
L1Scarecrow = 新手村的木頭人。
L1Monster = 怪物。
L1Teleporter = 競技場管理員、守門人、傳送師。(皆屬於傳送類型的NPC)
L1Merchant = 商人、強化師。(基本上為有金錢交易的NPC)
L1Housekeeper = 血盟小屋的女僕。
L1Dwarf = 侏儒倉庫、角色專屬侏儒倉庫。
L1Guard = 警衛、城堡守衛。
L1Npc = 沒什麼作用的NPC。
L1Guardian = 潘、精靈、精靈女皇..等等。(妖精森林裡面的守護者)
L1Quest = 任務。(任務型的NPC)
L1Board = 佈告欄。
L1FieldObject = 火把、曙光、海音村莊的風車、奇岩的競技場的旗幟…等等。(各種地圖的物件)
L1Doll = 魔法娃娃。
L1Furniture = 家具。
L1Effect = 火牢、精準目標、冰矛圍籬、衝擊之暈、治癒能量風暴。(魔法效果)
`` = 純粹沒定義的。(垃圾資料?)
L1Tower = 守護者之塔。(攻城的守護者之塔)
L1Crown = 王冠。
L1Door = 門。(好像沒什麼定義)
L1AuctionBoard = 拍賣佈告欄。(血盟小屋的拍賣佈告欄)
L1Signboard = 招牌。(古魯丁各個商店前的招牌)
L1DragonPortal = 龍之副本的門。
L1Fish = 魚。(釣魚池裡面會動魚或影子)
基本上上面分析這麼多種,主要大為分兩類L1Monster、非 L1Monster`。
3.分析資料表:

再進入npc表,
再找到安塔瑞斯的編號 = 45682,用於待會創怪用。
SELECT * FROM `npc` WHERE `name` = '安塔瑞斯' AND impl = 'L1Monster';
再騎士村商店的梅林的編號 = 70074,用於待會NPC用。
SELECT * FROM `npc` WHERE `name` = '梅林' AND impl = 'L1Merchant';
多找一個釣魚池的魚兒的編號 = 81308來測試效果。
SELECT * FROM `npc` WHERE impl = 'L1Fish';
2.指令的分析:

啟動模擬器除錯模式,並啟動天堂遊戲登入。
基本上都是在騎士村內執行以下指令。(同一個地方,後面好確認伺服器重啟後的效果)
使用創怪的GM指令,參數為mob表示為怪物,並帶入45682 = 安塔瑞斯。
.insert mob 45682

人物稍微往下移動換個位置。
使用創NPC的GM指令,參數為npc表示為怪物,並帶入70074 = 梅林。
.insert npc 70074

人物再次稍微往下移動換個位置。
使用創NPC的GM指令,參數為npc表示為怪物,並帶入81308 = 釣魚池的魚兒。
.insert npc 81308

這時候可以將模擬器關閉做重啟。
再次登入遊戲。
這時候可以看到安塔瑞斯、梅林、釣魚池的魚兒依舊是在設定的出生位置。
3.分析程式碼:

透過搜尋L1InsertSpawn開啟程式碼。
src/l1j/server/server/command/executor/L1InsertSpawn.java

45~53行,判斷輸入的參數並去取得type與npcid。
並判斷是否有找到npcid,如無則傳送數據回客戶端做顯示找不到符合條件的NPC。。
54~62行:
第一個判斷type是否為mob。
進入後再次判斷該npc的impl是否為L1Monster。
如不為L1Monster,則傳送數據回客戶端做顯示指定的NPC不是L1Monster類型。。
如斷無誤,則使用SpawnTable的storeSpawn方法。
該方法就是使用將相關對應的資料寫入到資料表spawnlist中。
INSERT INTO spawnlist 
SET location =?,
count =?,
npc_templateid =?,
group_id =?,
locx =?,
locy =?,
randomx =?,
randomy =?,
heading =?,
min_respawn_delay =?,
max_respawn_delay =?,
mapid =?
第二個判斷type是否為npc。
則使用NpcSpawnTable的storeSpawn方法。
該方法就是使用將相關對應的資料寫入到資料表spawnlist_npc中。
INSERT INTO spawnlist_npc 
SET location =?,
count =?,
npc_templateid =?,
locx =?,
locy =?,
heading =?,
mapid =?
63行,使用L1SpawnUtil的spawn方法,將對應的npc立刻創建出來。
註:此部分已經有在GM指令分析 (召喚怪物)分析,這邊就不在特別分析。

剩下的程式碼都滿基礎的就不特別說明。
結論
資料表:

資料表及欄位,可於上方分析中有說明。
程式碼:

src/l1j/server/server/command/executor/L1InsertSpawn.java
處理客戶端來的GM指令insert的處理。
src/l1j/server/server/datatables/NpcSpawnTable.java
storeSpawn產生NPC並寫入資料庫。
src/l1j/server/server/datatables/SpawnTable.java
storeSpawn產生怪物並寫入資料庫。