在開始分析前,要知道GM指令的指令效果與使用方式,才方便開啟除錯(Debug)進行分析。
效果:產生金幣。
範例:
.adena ${金幣數量}
1.分析資料表:
先進入commands表,找到adena的指令。
class_name是L1Adena。
2.分析程式碼:
透過搜尋L1Adena開啟程式碼。
src/l1j/server/server/command/executor/L1Adena.java
登入遊戲稍微確認一下目前物品欄內的物品和數量。
使用除錯模式,斷點在38行。
38~39行單純取得指令所帶的金幣數量參數,放於count變數中。
41行可以特別分析一下pc.getInventory()。
使用評估表達式Evaluate Expression來分析。
可發現物品欄的物件是L1PcInventory.class。
而_owner是L1PcInstance.class;這個之前就分析過此為客戶端的完整資料。
_items可以發現數量與人物物品欄內的數量一致,將其展開並點開其中一個的_item。
這邊可以發現_item是L1Weapon,說明是武器的物品,裡面的_name是歐西斯匕首。
接著在方法storeItem上,按下Ctrl + 左鍵。
會直接跳轉到該方法位置。
src/l1j/server/server/model/L1PcInventory.java
設定斷點在142繼續分析。
142~148行,是在判斷數量是否大於0、物品資料是否合法存在。
150行,40312物品查看資料庫後可以發現是旅館鑰匙;這一段判斷就先不分析。
160行,是判斷該物品是否是可堆疊的物品。
163~166行,判斷該物品是否已經在物品欄內存在,如果不存在則直接新增,
168行,物品已存在的狀態,會將數量相加,並更新物品資訊。
最後Return該新增的物品L1ItemInstance資訊。
註:部分程式碼沒有特別分析到,可自行深入分析。
回到L1Adena。
42~44行,根據Return回來的L1ItemInstance資訊,可以做一些判斷或是組合回傳回客戶端的數據。
修改
目前指令只有針對自己,希望將此指令修改程可以指定玩家做查詢。
以下是修改後所使用的指令方式:
.desc me|${玩家名稱} ${金幣數量}
修改前
@Override
public void execute(L1PcInstance pc, String cmdName, String arg) {
try {
StringTokenizer stringtokenizer = new StringTokenizer(arg);
int count = Integer.parseInt(stringtokenizer.nextToken());
L1ItemInstance adena = pc.getInventory().storeItem(L1ItemId.ADENA, count);
if (adena != null) {
pc.sendPackets(new S_SystemMessage((new StringBuilder()).append(count).append(" 金幣產生。").toString()));
}
}
catch (Exception e) {
pc.sendPackets(new S_SystemMessage((new StringBuilder()).append("請輸入 .adena 數量||.金幣 數量。").toString()));
}
}
修改後
@Override
public void execute(L1PcInstance pc, String cmdName, String arg) {
try {
StringTokenizer stringtokenizer = new StringTokenizer(arg);
String char_name = stringtokenizer.nextToken();
int count = Integer.parseInt(stringtokenizer.nextToken());
L1PcInstance target = null;
if (char_name.equalsIgnoreCase("me")) {
target = pc;
}
else {
target = L1World.getInstance().getPlayer(char_name);
}
if (target == null) {
pc.sendPackets(new S_ServerMessage(73, char_name));
return;
}
L1ItemInstance adena = target.getInventory().storeItem(L1ItemId.ADENA, count);
if (adena != null) {
pc.sendPackets(new S_SystemMessage((new StringBuilder()).append("贈與 ").append(target.getName()).append(" ").append(count).append(" 金幣。").toString()));
}
}
catch (Exception e) {
pc.sendPackets(new S_SystemMessage((new StringBuilder()).append("請輸入 .adena 玩家名稱|me 數量。").toString()));
}
}
修改後儲存,啟動模擬器。
啟動天堂登入遊戲,登入GM帳號與另一個帳號。
GM使用指令贈與另一位玩家金幣,該玩家金幣確實已經增加。
結論
程式碼:
src/l1j/server/server/command/executor/L1Adena.java
處理客戶端來的GM指令desc的處理。
src/l1j/server/server/model/L1PcInventory.java
物品欄的相關資訊與方法。
|
|
|
|
|
|